-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.js
More file actions
350 lines (286 loc) · 10.5 KB
/
Copy pathcontent.js
File metadata and controls
350 lines (286 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// === 增量追加:监听前端 URL 路由变化(支持 SPA) ===
(function() {
const notifyUrlChange = () => {
chrome.runtime.sendMessage({
type: 'url_change',
url: location.href
});
};
['pushState', 'replaceState'].forEach(method => {
const original = history[method];
history[method] = function () {
const result = original.apply(this, arguments);
notifyUrlChange();
return result;
};
});
window.addEventListener('hashchange', notifyUrlChange);
})();
/*
// 内容脚本模块
const ContentScript = (() => {
// 私有变量
let lastUrl = location.href;
// 创建悬浮按钮
const createFloatingButton = () => {
// 检查是否已存在按钮
if (document.getElementById('search-switcher-btn')) {
return;
}
// 创建按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.id = 'search-switcher-btn';
buttonContainer.className = 'search-switcher-container';
// 初始位置设置 - 从存储中获取或使用默认值
chrome.storage.local.get('buttonPosition', (data) => {
const position = data.buttonPosition || { right: '20px', bottom: '80px' };
// 确保位置总是在右侧边缘
position.right = '0px';
position.left = 'auto';
// 应用位置
Object.assign(buttonContainer.style, position);
// 设置右侧边缘类
buttonContainer.classList.add('edge-right');
});
// 创建按钮
const button = document.createElement('div');
button.className = 'search-switcher-icon';
button.setAttribute('role', 'button');
button.setAttribute('aria-label', '搜索切换');
// 获取当前系统是否为暗色模式
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
// 根据暗色模式设置颜色
if (isDarkMode) {
button.style.backgroundColor = '#222222';
button.style.borderColor = '#444444';
} else {
button.style.backgroundColor = '#ffffff';
button.style.borderColor = '#eeeeee';
}
// 创建图标
const iconImg = document.createElement('img');
iconImg.src = chrome.runtime.getURL('icon/icon48.png');
iconImg.style.width = '20px';
iconImg.style.height = '20px';
iconImg.alt = '搜索切换';
button.appendChild(iconImg);
// 添加点击事件
button.addEventListener('click', togglePopup);
// 添加拖拽功能
makeDraggable(buttonContainer, button);
// 将按钮添加到容器
buttonContainer.appendChild(button);
// 创建弹出窗口容器
const popupContainer = document.createElement('div');
popupContainer.id = 'search-switcher-popup';
popupContainer.className = 'search-switcher-popup';
popupContainer.style.display = 'none';
// 添加弹出窗口内嵌框架
const popupFrame = document.createElement('iframe');
popupFrame.id = 'search-switcher-iframe';
popupFrame.src = chrome.runtime.getURL('popup.html');
popupFrame.className = 'search-switcher-iframe';
// 将框架添加到弹出窗口
popupContainer.appendChild(popupFrame);
// 将按钮和弹出窗口添加到页面
buttonContainer.appendChild(popupContainer);
document.body.appendChild(buttonContainer);
// 添加全局点击事件,用于关闭弹出窗口
document.addEventListener('click', (e) => {
const container = document.getElementById('search-switcher-btn');
const popup = document.getElementById('search-switcher-popup');
if (container && !container.contains(e.target) && popup && popup.style.display === 'block') {
popup.style.display = 'none';
}
});
};
// 使元素可拖拽
const makeDraggable = (container, handle) => {
// 拖拽状态
let isDragging = false;
let startX, startY;
let startRight, startBottom;
let lastClick = 0;
// 保存最后的位置
function savePosition() {
const position = {
right: container.style.right,
bottom: container.style.bottom
};
chrome.storage.local.set({ buttonPosition: position });
}
// 限制位置在窗口边缘
function constrainToWindowEdge(el) {
// 强制固定在右侧边缘
container.style.right = '0px';
container.style.left = 'auto';
// 移除所有其他边缘样式类,只保留右侧边缘类
container.classList.remove('edge-left', 'edge-top', 'edge-bottom');
container.classList.add('edge-right');
// 保存当前位置
savePosition();
}
// 鼠标按下事件
handle.addEventListener('mousedown', (e) => {
// 检测是否是双击(双击不触发拖动)
const now = new Date().getTime();
if (now - lastClick < 300) {
// 双击,不处理拖动
lastClick = 0;
return;
}
lastClick = now;
// 如果弹出窗口打开,则不开始拖动
const popup = document.getElementById('search-switcher-popup');
if (popup && popup.style.display === 'block') {
return;
}
e.preventDefault();
isDragging = true;
// 记录起始位置
startX = e.clientX;
startY = e.clientY;
const rect = container.getBoundingClientRect();
startRight = window.innerWidth - rect.right;
startBottom = window.innerHeight - rect.bottom;
// 添加拖动样式
container.classList.add('dragging');
});
// 鼠标移动事件(全局)
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
e.preventDefault();
// 计算Y轴的变化,只允许上下移动
const deltaY = startY - e.clientY;
const newBottom = startBottom + deltaY;
// 更新位置,只修改垂直位置,保持右侧固定
container.style.bottom = `${Math.max(20, Math.min(window.innerHeight - 60, newBottom))}px`;
// 确保始终在右侧
container.style.right = '0px';
container.style.left = 'auto';
});
// 鼠标释放事件(全局)
document.addEventListener('mouseup', () => {
if (isDragging) {
isDragging = false;
// 移除拖动样式
container.classList.remove('dragging');
// 吸附到边缘
constrainToWindowEdge(container);
}
});
// 鼠标离开窗口事件
document.addEventListener('mouseleave', () => {
if (isDragging) {
isDragging = false;
container.classList.remove('dragging');
constrainToWindowEdge(container);
}
});
};
// 切换弹出窗口显示状态
const togglePopup = () => {
const popup = document.getElementById('search-switcher-popup');
// 直接设置显示状态,不使用过渡动画
if (popup.style.display === 'none') {
popup.style.display = 'block';
// 确保无动画效果
popup.style.transition = 'none';
// 在下一帧恢复过渡效果(用于关闭时)
requestAnimationFrame(() => {
popup.style.transition = '';
});
} else {
popup.style.display = 'none';
}
};
// 检测搜索平台
const detectSearchPlatform = () => {
const url = window.location.href;
console.log("当前URL:", url);
const supportedPlatforms = [
// 各种搜索平台配置
{ name: 'Google', pattern: /google\.com\/(search|imghp|images|videos)/, param: 'q' },
{ name: 'Google HK', pattern: /google\.com.hk\/(search|imghp|images|videos)/, param: 'q' },
{ name: 'Bing', pattern: /bing\.com\/(search|images|videos|news)/, param: 'q' },
{ name: 'Bing CN', pattern: /bing\.com\/(search|images|videos|news)/, param: 'q' },
{ name: 'Baidu', pattern: /baidu\.com\/s/, param: 'wd' },
{ name: 'Baidu Images', pattern: /image\.baidu\.com/, param: 'word' },
{ name: 'Baidu Videos', pattern: /video\.baidu\.com/, param: 'word' },
{ name: '360', pattern: /so\.com\/s/, param: 'q' },
{ name: 'Sogou', pattern: /sogou\.com\/web/, param: 'query' },
{ name: 'Yahoo', pattern: /yahoo\.com\/search/, param: 'p' },
{ name: 'DuckDuckGo', pattern: /duckduckgo\.com\//, param: 'q' },
];
for (const platform of supportedPlatforms) {
if (platform.pattern.test(url)) {
console.log(`匹配成功: [${platform.name}] ${url} 匹配到模式: ${platform.pattern}`);
return true;
}
}
console.log(`未匹配到任何平台: ${url}`);
return false;
};
// 监听系统暗色模式变化
const setupDarkModeListener = () => {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
const button = document.querySelector('.search-switcher-icon');
if (button) {
if (e.matches) {
// 切换到暗色模式
button.style.backgroundColor = '#222222';
button.style.borderColor = '#444444';
} else {
// 切换到亮色模式
button.style.backgroundColor = '#ffffff';
button.style.borderColor = '#eeeeee';
}
}
});
};
// 初始化
const initialize = () => {
console.log("初始化扩展...");
// 立即检测一次
const isSearchPage = detectSearchPlatform();
console.log("是否为搜索页面:", isSearchPage);
if (isSearchPage) {
console.log("创建悬浮按钮...");
createFloatingButton();
setupDarkModeListener();
} else {
// 再尝试延迟检测一次,处理某些网站的异步加载
setTimeout(() => {
const isSearchPageDelayed = detectSearchPlatform();
console.log("延迟检测是否为搜索页面:", isSearchPageDelayed);
if (isSearchPageDelayed && !document.getElementById('search-switcher-btn')) {
console.log("延迟创建悬浮按钮...");
createFloatingButton();
setupDarkModeListener();
}
}, 2000);
}
};
// 设置URL变化监听器
const setupUrlChangeListener = () => {
// 监听URL变化,用于SPA
new MutationObserver(() => {
const currentUrl = location.href;
if (currentUrl !== lastUrl) {
lastUrl = currentUrl;
initialize();
}
}).observe(document, { subtree: true, childList: true });
};
// 公开接口
return {
initialize,
setupUrlChangeListener
};
})();
// 当页面加载完成后初始化
window.addEventListener('load', () => {
ContentScript.initialize();
ContentScript.setupUrlChangeListener();
});
*/