// ==UserScript== // @name 多重搜索MultipleSearch // @name:zh-CN 多重搜索 // @name:zh-TW 多重搜索 // @name:zh-HK 多重搜索 // @author Cassius0924 // @namespace http://tampermonkey.net/ // @version 0.4.0 // @description 携带搜索词快捷切换搜索引擎、视频网站或博客网站。Quickly switch between search engines, video sites or blog sites with search words. // @description:zh-CN 携带搜索词快捷切换搜索引擎、视频网站或博客网站。 // @description:zh-TW 攜帶搜索詞快捷切換搜索引擎、視頻網站或博客網站。 // @description:zh-HK 攜帶搜索詞快捷切換搜索引擎、視頻網站或博客網站。 // @license MIT // @icon https://i.imgur.com/oqVZgBY.png // @match https://www.bing.com/search* // @match https://www.baidu.com/s?* // @match https://www.google.com/search?* // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== (function () { //已经适配网页 const handlers = { baidu: { //网页预处理 preprocess: function () { let head = selectElement('#head'); head.style = "height: 140px; transition:height 0.3s ease-in-out;"; let div = createElement('div', 'ms-cover', 'background-color: white; height: 50px'); let hw = selectElement('#head .head_wrapper'); let u = selectElement('#u'); let u1 = selectElement('#u1'); let skt = selectElement('#head .search-keyboard-toast'); div.appendChild(hw); div.appendChild(u); div.appendChild(u1); div.appendChild(skt); head.appendChild(div); selectElement('#s_tab').style = 'padding-top: 140px; transition: all 0.3s ease-in-out;'; //TODO-1: 解决输入框无法使用快捷键的问题,难搞 }, //添加多重搜索组件 addMSComponent: function () { let head = selectElement('#head'); let div = createElement('div', 'ms-container', 'margin-left: 120px;'); let css = "@media screen and (min-width: 1921px) { .ms-container { width: 1055px; margin: 0 auto !important;} }\n #ms-component .ms-dragging {opacity: 0.5; transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s}\n#ms-component .ms-crowded {transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s;}"; let style = createElement("style", '', '', css); div.appendChild(style); let msComponent = makeMSComponent(); msComponent.style = 'bottom: 8px; position: absolute;'; div.appendChild(msComponent); head.appendChild(div); addShortcutKeys(); }, //添加滚动监听 addScrollListener: function () { window.onscroll = function () { let head = selectElement('#head'); let searchTab = selectElement('#s_tab'); let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop > 12) { selectElement('.cr-title').style.marginTop = '20px'; } if (scrollTop > 0) { head.style.height = '103px'; searchTab.style.paddingTop = '115px'; } else { head.style.height = '140px'; searchTab.style.paddingTop = '140px'; } toggleMSComponent(scrollTop, 0, 0); turnOffToggleSortMode(); } }, //切换排序模式预处理 preToggleSortMode: function () { if (GM_getValue('sortMode') === 'off') { selectElement('#head').style.height = '155px'; selectElement('#s_tab').style.paddingTop = '155px'; } else { selectElement('#head').style.height = '140px'; selectElement('#s_tab').style.paddingTop = '140px'; } }, //获取搜索内容 getSearchContent: function () { return selectElement('#kw').value; } }, google: { preprocess: function () { let bg = selectElement('.sfbg'); setTimeout(() => { bg.style = 'height:190px; z-index:-100;'; bg.style.transition = 'height 0.3s ease-in-out'; }, 0); let dodTBe = selectElement('.dodTBe'); dodTBe.style.height = '125px'; dodTBe.style.transition = 'all, 0.3s ease-in-out'; }, addMSComponent: function () { let head = selectElement('.CvDJxb'); head.style = "display:flex; flex-direction: column; justify-content: center;"; let css = "#ms-component{--ms-margin:165px;margin-left: calc(var(--ms-margin) - 15px);} @media(prefers-color-scheme:light){#ms-component{background:#fff !important;}} @media(prefers-color-scheme:dark){.ms-item {background: #303134 !important; color:#e8eaed !important; box-shadow: none !important; box-sizing: content-box ;border: 1px solid rgb(95,99,104);} .ms-item svg path:nth-child(2){fill: #e8eaed}.mss-content, .mss-icon-content{border: 1px solid rgb(95,99,104); background-color: #202124;}.mss-icon-close svg path:nth-child(2), .mss-del-btn svg path:nth-child(2){fill: #e8eaed;}.mss-title, .mss-icon-title {color: #e8eaed; border-bottom: 1px solid rgb(95,99,104);}.mss-item {background: #303134; border: 1px solid rgb(95,99,104); box-shadow: none;}.mss-item-name, .mss-item-url, .mss-del-btn, .mss-name-input, .mss-url-input, .mss-icon-input, .mss-add-btn, .mss-icon-cancel-btn, .mss-icon-confirm-btn {background: #303134; border: 1px solid rgb(95,99,104); box-shadow: none;}}@media (max-width: 1300px) {#ms-component{--ms-margin: 28px;}}@media (min-width: 1121px) and (max-width: 1300px) {#ms-component{--ms-margin: calc((100vw - 1065px)/2);}}\n @media (min-width: 1459px) and (max-width: 1659px) {#ms-component{--ms-margin: calc(25vw + -200px);}}\n@media (min-width: 1659px) {#ms-component{--ms-margin: 215px;}}\n#ms-component .ms-dragging {opacity: 0.5; transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s}\n#ms-component .ms-crowded {transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s;} .pin{z-index: 1000}"; let style = createElement("style", '', '', css); let msComponent = makeMSComponent(); msComponent.style = 'bottom: 8px; position: absolute; top: 60px;'; msComponent.appendChild(style); head.appendChild(msComponent); addShortcutKeys(); }, addScrollListener: function () { window.onscroll = function () { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop > 120) { selectElement('.sfbg').style.height = '135px'; selectElement('#ms-component').style.top = '52px'; selectElement('.dodTBe').style.height = '90px'; } else if (scrollTop <= 0) { selectElement('.sfbg').style.height = '210px';selectElement('.dodTBe').style.height = '125px'; } else { selectElement('#ms-component').style.top = '60px'; } toggleMSComponent(scrollTop, 120, 0); turnOffToggleSortMode(); } }, preToggleSortMode: function () { if (GM_getValue('sortMode') === 'off') { selectElement('.sfbg').style.height = '240px'; selectElement('.dodTBe').style.height = '140px'; } else { selectElement('.sfbg').style.height = '210px'; selectElement('.dodTBe').style.height = '125px'; } }, getSearchContent: function () { return selectElement('.i4ySpb ~ .gLFyf').value; } }, bing: { preprocess: function () { let head = selectElement('#b_header'); head.style = 'transform: translateY(-75px);z-index: 10; transition:all, 0.3s ease-in-out;'; let content = selectElement('#b_content'); content.style = 'position: relative;z-index:9; top: -70px; transition:top, 0.3s ease-in-out;'; let searchBox = selectElement('#sb_form_q'); searchBox.onfocus = () => { selectElement('#ms-component').classList.remove('top'); }; searchBox.onblur = () => { selectElement('#ms-component').classList.add('top'); } }, addMSComponent: function () { let head = selectElement('#b_header'); let body = selectElement('.b_respl'); let css = ".ms-dragging {opacity: 0.5; transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s} #ms-component .ms-crowded {transition: all 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) 0s;} .top{z-index:100} .pin{z-index: 1000;}"; let style = createElement("style", '', '', css); document.head.appendChild(style); let msComponent = makeMSComponent(); msComponent.classList.add('top'); msComponent.style = 'position: sticky; top: 0; height: 0px; margin-top:75px; padding-left: 150px;'; let scopeBar = selectElement('.b_scopebar'); scopeBar.style = 'margin-top: 70px; transition:all, 0.3s ease-in-out;'; body.insertBefore(msComponent, head); addShortcutKeys(); }, addScrollListener: function () { window.onscroll = function () { let msComponent = selectElement('#ms-component'); let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop > 60) { msComponent.style.paddingBlock = '10px'; } if (scrollTop <= 130) { msComponent.style.paddingBlock = '0px'; } if (scrollTop > 110) { msComponent.style.height = '30px'; msComponent.style.boxShadow = '0 2px 10px 0 rgb(0 0 0 / 10%)'; } if (scrollTop <= 140) { msComponent.style.height = '0px'; msComponent.style.boxShadow = ''; } toggleMSComponent(scrollTop, 70, 70); turnOffToggleSortMode(); } }, preToggleSortMode: function () { let msComponent = selectElement('#ms-component'); let scopeBar = selectElement('.b_scopebar'); if (GM_getValue('sortMode') === 'off') { scopeBar.style.marginTop = '85px'; } else { msComponent.style.marginTop = '75px'; scopeBar.style.marginTop = '70px'; } }, getSearchContent: function () { return selectElement('#sb_form_q').value; } }, cnbing: { //TODO-2: 中国版bing preprocess: function () { }, addMSComponent: function () { }, addScrollListener: function () { }, preToggleSortMode: function () { }, getSearchContent: function () { }, } } const hostToHandler = { 'www.baidu.com': 'baidu', 'www.google.com': 'google', 'www.bing.com': 'bing', 'cn.bing.com': 'cnbing' }; function getHandler() { const host = window.location.host; if (hostToHandler[host] === undefined) { return 'other'; } return handlers[hostToHandler[host]]; } function main() { if (GM_getValue('searchEngines') === null) { const searchEngines = [ { name: '百度', url: 'https://www.baidu.com/s?wd=', icon: 'https://icon.horse/icon/www.baidu.com' }, { name: '谷歌', url: 'https://www.google.com/search?q=', icon: 'https://icon.horse/icon/www.google.com' }, { name: '必应', url: 'https://www.bing.com/search?q=', icon: 'https://icon.horse/icon/www.bing.com' }, { name: 'YouTube', url: 'https://www.youtube.com/results?search_query=', icon: 'https://icon.horse/icon/www.youtube.com' }, { name: '哔哩哔哩', url: 'https://search.bilibili.com/all?keyword=', icon: 'https://icon.horse/icon/www.bilibili.com' }, { name: '知乎', url: 'https://www.zhihu.com/search?type=content&q=', icon: 'https://icon.horse/icon/www.zhihu.com' }, { name: 'CSDN', url: 'https://so.csdn.net/so/search/s.do?q=', icon: 'https://icon.horse/icon/so.csdn.net' }, { name: 'DuckDuckGo', url: 'https://duckduckgo.com/?q=', icon: 'https://icon.horse/icon/www.duckduckgo.com' }, { name: 'Setting', toggleSortIcon: `<svg class='ms-toggle-sort-icon' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="19" height="19"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.05 12.05L21 17l-4.95 4.95-1.414-1.414 2.536-2.537L4 18v-2h13.172l-2.536-2.536 1.414-1.414zm-8.1-10l1.414 1.414L6.828 6 20 6v2H6.828l2.536 2.536L7.95 11.95 3 7l4.95-4.95z"/></svg>`, plusIcon: `<svg class='ms-plus-icon' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20"><path fill="none" d="M0 0h24v24H0z"/><path d="M2 12c0-.865.11-1.703.316-2.504A3 3 0 0 0 4.99 4.867a9.99 9.99 0 0 1 4.335-2.505 3 3 0 0 0 5.348 0 9.99 9.99 0 0 1 4.335 2.505 3 3 0 0 0 2.675 4.63c.206.8.316 1.638.316 2.503 0 .865-.11 1.703-.316 2.504a3 3 0 0 0-2.675 4.629 9.99 9.99 0 0 1-4.335 2.505 3 3 0 0 0-5.348 0 9.99 9.99 0 0 1-4.335-2.505 3 3 0 0 0-2.675-4.63C2.11 13.704 2 12.866 2 12zm4.804 3c.63 1.091.81 2.346.564 3.524.408.29.842.541 1.297.75A4.993 4.993 0 0 1 12 18c1.26 0 2.438.471 3.335 1.274.455-.209.889-.46 1.297-.75A4.993 4.993 0 0 1 17.196 15a4.993 4.993 0 0 1 2.77-2.25 8.126 8.126 0 0 0 0-1.5A4.993 4.993 0 0 1 17.195 9a4.993 4.993 0 0 1-.564-3.524 7.989 7.989 0 0 0-1.297-.75A4.993 4.993 0 0 1 12 6a4.993 4.993 0 0 1-3.335-1.274 7.99 7.99 0 0 0-1.297.75A4.993 4.993 0 0 1 6.804 9a4.993 4.993 0 0 1-2.77 2.25 8.126 8.126 0 0 0 0 1.5A4.993 4.993 0 0 1 6.805 15zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg> ` } ]; GM_setValue('searchEngines', searchEngines); } GM_setValue('themeColor', '#4e6ef2'); GM_setValue('sortMode', 'off'); let handler = getHandler(); handler.preprocess.call(); handler.addMSComponent.call(); handler.addScrollListener.call(); } //添加拖拽功能 function addElementDragListener(element) { element.ondragover = function (e) { e.preventDefault(); //阻止默认事件 } element.ondragstart = function (e) { e.target.parentNode.childNodes.forEach(element => { if (element === e.target) { element.classList.toggle("ms-dragging"); } else { element.classList.toggle("ms-crowded"); } }); dragging = e.target; e.dataTransfer.effectAllowed = 'move'; } element.ondragend = function (e) { setTimeout(() => { e.target.parentNode.childNodes.forEach(element => { if (element === e.target) { element.classList.toggle("ms-dragging"); } else { element.classList.toggle("ms-crowded"); } }); }, 0); } element.ondrop = function (e) { let delay = 0.5; //延迟 e.preventDefault(); let target = e.target; let targetIndex = 0; if (!target.classList.contains('ms-dragging') && target.getAttribute('droppable') === 'true') { let draggingIndex = Array.prototype.indexOf.call(dragging.parentNode.children, dragging); if (target.classList.contains('ms-item')) { // 啥也不干 } else if (target.parentNode.classList.contains('ms-item')) { target = target.parentNode; } else { target = target.parentNode.parentNode; } targetIndex = Array.prototype.indexOf.call(target.parentNode.children, target); if (draggingIndex !== targetIndex) { reorderElements(draggingIndex, targetIndex, dragging, target, delay); } } } // 插入元素 function reorderElements(draggingIndex, targetIndex, dragging, target, delay) { let startPosition = dragging.getBoundingClientRect(); let endPosition = target.getBoundingClientRect(); if (draggingIndex < targetIndex) { addAnimation(draggingIndex, targetIndex, startPosition, endPosition, dragging, 1); setTimeout(() => { dragging.parentNode.childNodes.forEach(element => { element.style.transform = ''; }); target.parentNode.insertBefore(dragging, target.nextSibling); }, delay * 1000); } else { addAnimation(draggingIndex, targetIndex, startPosition, endPosition, dragging, -1); setTimeout(() => { dragging.parentNode.childNodes.forEach(element => { element.style.transform = ''; }); target.parentNode.insertBefore(dragging, target); }, delay * 1000); } updateData(draggingIndex, targetIndex); } // 添加动画 function addAnimation(draggingIndex, targetIndex, startPosition, endPosition, dragging, direction) { let deltaX = 0; let component = dragging.parentNode; if (direction === 1) { //往右 deltaX = endPosition.right - startPosition.right; console.log(draggingIndex, targetIndex); for (let i = draggingIndex + 1; i <= targetIndex; i++) { let element = component.children[i]; let deltaX2 = startPosition.left - dragging.nextSibling.getBoundingClientRect().left; element.style.transition = ''; element.style.transform = `translateX(${deltaX2}px)`; element.offsetWidth; element.style.transition = 'all 0s'; } } else if (direction === -1) { //往左 deltaX = endPosition.left - startPosition.left; for (let i = targetIndex; i < draggingIndex; i++) { let element = component.children[i]; let deltaX2 = startPosition.right - dragging.previousSibling.getBoundingClientRect().right; element.style.transition = ''; element.style.transform = `translateX(${deltaX2}px)`; element.offsetWidth; element.style.transition = 'all 0s'; } } dragging.style.transition = ''; dragging.style.transform = `translateX(${deltaX}px)`; dragging.offsetWidth; dragging.style.transition = 'all 0s'; } // 更新数据 function updateData(draggingIndex, targetIndex) { let engines = GM_getValue('searchEngines'); let draggingEngine = engines.splice(draggingIndex, 1)[0]; engines.splice(targetIndex, 0, draggingEngine); GM_setValue('searchEngines', engines); } } function makeMSComponent() { let msComponent = createElementWithId('div', 'ms-component'); let searchEngines = GM_getValue('searchEngines'); //添加元素 searchEngines.forEach((searchEngine, index) => { let element = makeElement(searchEngine, index); msComponent.appendChild(element); }); //添加样式 let allStyle = getAllStyle(); msComponent.appendChild(allStyle); //添加快捷键 return msComponent; } //组件添加元素 function makeElement(searchEngine) { let element = createElement('div', 'ms-item'); element.setAttribute('droppable', true) if (searchEngine.name === 'Setting') { element.style.justifyContent = 'center'; element.innerHTML = searchEngine.toggleSortIcon + searchEngine.plusIcon; let items = element.childNodes; items.forEach(item => { item.onmouseover = function () { item.childNodes[1].style = `fill:${GM_getValue('themeColor')};`; } item.onmouseout = function () { item.childNodes[1].style = ``; } }) //切换排序模式 items[0].onclick = function () { toggleSortMode(); } //点击后弹出设置面板 items[1].onclick = function () { popUpSettingPanel(); } } else { element.onclick = function () { search(searchEngine.url); } let div = createElement('div', 'ms-item-content'); div.setAttribute('droppable', true); let sortIcon = createElement('div', 'ms-sort-icon') sortIcon.setAttribute('droppable', true); let img = createElement('img', 'ms-icon'); img.src = searchEngine.icon; img.draggable = ''; img.setAttribute('droppable', true); let text = createElement('span', 'ms-text', '', searchEngine.name) text.setAttribute('droppable', true); let url = createInput('', 'ms-url', 'display:none', searchEngine.url); addElementDragListener(element); div.appendChild(sortIcon); div.appendChild(img); div.appendChild(text); div.appendChild(url); element.appendChild(div); } return element; } //切换排序模式 function toggleSortMode() { let component = selectElement('#ms-component') let handler = getHandler(); handler.preToggleSortMode(); if (GM_getValue('sortMode') === 'off') { component.childNodes.forEach((element, index) => { if (index !== component.childNodes.length - 1) { element.style.height = '63.5px'; element.draggable = 'true'; } }); GM_setValue('sortMode', 'on'); } else { component.childNodes.forEach((element, index) => { if (index !== component.childNodes.length - 1) { element.style.height = '48.5px'; element.draggable = ''; element.style.transition = ''; } }); GM_setValue('sortMode', 'off'); } } function turnOnToggleSortMode() { if (GM_getValue('sortMode') === 'off') { toggleSortMode(); } } function turnOffToggleSortMode() { if (GM_getValue('sortMode') === 'on') { toggleSortMode(); } } //弹出添加面板 function popUpSettingPanel() { let panel = createElementWithId('div', 'ms-setting-panel'); let content = createElement('div', 'mss-content'); let title = createElement('div', 'mss-title', '', '多重搜索设置'); let container = createElement('div', 'mss-container'); let left = createElement('div', 'mss-left'); let list = createElement('div', 'mss-list'); function listSearchEngines() { list.innerHTML = ''; let searchEngines = GM_getValue('searchEngines'); searchEngines.forEach((searchEngine, index) => { if (index !== searchEngines.length - 1) { appendItem(searchEngine, index); } }); } function appendItem(searchEngine, index) { index = index ? index : list.childNodes.length; let item = createElement('div', 'mss-item'); let icon = createElement('img', 'mss-item-icon'); icon.src = searchEngine.icon; icon.addEventListener('click', () => { popUpIconPanel(searchEngine, index); }); let center = createElement('div', 'mss-center'); let name = createInput('', 'mss-item-name', '', searchEngine.name, '名称'); let url = createInput('', 'mss-item-url', '', searchEngine.url, '网址'); let icon_ = createInput('', 'mss-item-icon_', '', searchEngine.icon); let delBtn = createElement('button', 'mss-del-btn', '', `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20"><path fill="none" d="M0 0h24v24H0z"/><path d="M7 4V2h10v2h5v2h-2v15a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6H2V4h5zM6 6v14h12V6H6zm3 3h2v8H9V9zm4 0h2v8h-2V9z"/></svg>`); delBtn.addEventListener('click', (e) => { list.childNodes[index].style.display = 'none'; }); center.appendChild(name); center.appendChild(url); center.appendChild(icon_); item.appendChild(icon); item.appendChild(center); item.appendChild(delBtn); list.appendChild(item); } function popUpIconPanel(searchEngine, index) { let panel = createElement('div', 'mss-icon-panel'); let content = createElement('div', 'mss-icon-content'); let title = createElement('div', 'mss-icon-title', '', '修改图标'); let container = createElement('div', 'mss-icon-container'); let form = createElement('form', 'mss-icon-form'); let iconInput = createInput('', 'mss-icon-input', '', selectElementAll('#ms-setting-panel .mss-item-icon_')[index].value, '图标地址(留空自动生成)'); let close = createElement('div', 'mss-icon-close', '', `<svg class=\'mss-icon-editor-close-icon\' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20"><path fill="none" d="M0 0h24v24H0z"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>`); close.addEventListener('click', () => { panel.remove(); }); let cancelBtn = createElement('button', 'mss-icon-cancel-btn', '', '取消'); cancelBtn.addEventListener('click', (e) => { panel.remove(); }); let confirmBtn = createElement('button', 'mss-icon-confirm-btn', '', '确定'); confirmBtn.addEventListener('click', (e) => { selectElementAll('#ms-setting-panel .mss-item-icon')[index].src = iconInput.value; selectElementAll('#ms-setting-panel .mss-item-icon_')[index].value = iconInput.value; panel.remove(); }); form.appendChild(iconInput); container.appendChild(form); content.appendChild(title); content.appendChild(container); content.appendChild(close); content.appendChild(cancelBtn); content.appendChild(confirmBtn); panel.appendChild(content); document.body.appendChild(panel); } listSearchEngines(); let right = createElement('div', 'mss-right'); let form = createElement('form', 'mss-form'); let nameInput = createInput('', 'mss-name-input', '', '', '搜索引擎名称'); let urlInput = createInput('', 'mss-url-input', '', '', '搜索引擎地址'); let iconInput = createInput('', 'mss-icon-input', '', '', '图标地址(留空自动生成)'); let addBtn = createElement('button', 'mss-add-btn', '', '添加'); addBtn.addEventListener('click', (e) => { e.preventDefault(); let name = nameInput.value; let url = urlInput.value; let hostname = ''; try { hostname = new URL(url).hostname; } catch (e) { alert('网址格式错误'); return; } let icon = iconInput.value ? iconInput.value : `https://icon.horse/icon/${hostname}`; if (name && url && icon) { let searchEngine = { name: name, url: url, icon: icon }; appendItem(searchEngine); } }); let close = createElement('div', 'mss-icon-close', '', `<svg class='mss-close-icon' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20"><path fill="none" d="M0 0h24v24H0z"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>`); close.addEventListener('click', () => { panel.remove(); }); let cancelBtn = createElement('button', 'mss-icon-cancel-btn', '', '取消'); cancelBtn.addEventListener('click', (e) => { panel.remove(); }); let confirmBtn = createElement('button', 'mss-icon-confirm-btn', '', '确定'); confirmBtn.addEventListener('click', (e) => { let newSearchEngines = []; let setting = GM_getValue('searchEngines').pop(); let list = selectElement('#ms-setting-panel .mss-list'); list.childNodes.forEach((item,index) => { if (item.style.display !== 'none') { let name = selectElementAll('.mss-item-name')[index].value; let url = selectElementAll('.mss-item-url')[index].value; let icon = selectElementAll('.mss-item-icon_')[index].value; newSearchEngines.push({ name: name, url: url, icon: icon }); } }); newSearchEngines.push(setting); GM_setValue('searchEngines', newSearchEngines); panel.remove(); window.location.reload(); }); form.appendChild(nameInput); form.appendChild(urlInput); form.appendChild(iconInput); form.appendChild(addBtn); left.appendChild(list); right.appendChild(form); container.appendChild(left); container.appendChild(right); content.appendChild(close); content.appendChild(title); content.appendChild(container); content.appendChild(cancelBtn) content.appendChild(confirmBtn); panel.appendChild(content); document.body.appendChild(panel); } function getAllStyle() { let css = `#ms-component {background: white;border-radius: 10px;display: flex;flex-wrap: nowrap;flex-direction: row; transition: padding-block 0.3s ease-in-out 0s, box-shadow 0.3s ease-in-out 0s, height 0.3s ease-in-out, 0s margin-top 0.3s ease-in-out;} .ms-container {margin-left: 120px;} .ms-item {height: 48.5px;overflow-y: hidden;min-width: 30px;margin-inline: 10px;display: flex;padding: 6px 10px;flex-direction: column;align-items: center;justify-content: flex-end;cursor: pointer;background: linear-gradient(135deg, rgba(245, 245, 245, 1) 0%, rgba(255, 255, 255, 1) 100%);box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);border-radius: 8px;color: black;text-decoration: none; transition: height 0.3s ease-in-out 0s}\n.ms-item:hover{color: #4e6ef2 !important;}\n .ms-item-content {display: flex;flex-direction: column;align-items: center;justify-content: flex-end;} .ms-sort-icon {width: 10px;height: 3px;margin-bottom: 10px;border-radius: 3px;background: #909eb0;transition: height 0.3s ease-in-out;} .ms-icon {width: 30px;height: 30px;border-radius: 5px;transition: all 0.3s ease-in-out;} .ms-toggle-sort-icon {transition: all 0.3s ease-in-out;} .ms-text {min-width: 36px;margin-top: 2px;font-size: 12px;font-weight: bold;white-space: nowrap;overflow: hidden; text-align: center;} #ms-setting-panel {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.2);z-index: 1000;display: flex;justify-content: center;align-items: center;} .mss-content {position: relative;width: 800px;height: 500px;border-radius: 10px;display: flex;flex-direction: column;justify-content: flex-start;align-items: center;background: #EFEFEFFF;} .mss-title {width: 100%;height: 15%;display: flex;justify-content: center;align-items: center;font-size: 20px;font-weight: bold;border-bottom: 1px solid #e5e5e5;} .mss-container {width: 100%;height: 85%;display: flex;flex-direction: row;justify-content: flex-start;align-items: center;} .mss-left {width: 100%;height: 100%;display: flex;flex-direction: column;justify-content: flex-start;align-items: center;} .mss-list {width: 400px;height: 100%;display: flex;flex-direction: column;justify-content: flex-start;align-items: center;overflow-y: scroll;overflow-x: hidden;} .mss-list::-webkit-scrollbar {} .mss-item {width: auto;height: 60px;margin-block: 10px;padding-block: 10px;padding-inline: 10px;display: flex;flex-direction: row;justify-content: flex-start;align-items: center;border-radius: 10px;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-item-icon {width: 45px;height: 45px;margin: 0 0;border-radius: 10px;cursor: pointer;} .mss-center {margin: 0 10px;height: 100%;display: flex;flex-direction: column;justify-content: space-around;align-items: stretch;} .mss-item-name {width: 80px;border: none;outline: none;border-radius: 3px;padding: 3px 10px 1px;font-weight: bold;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-item-url {width: 185px;border: none;outline: none;border-radius: 3px;padding: 3px 10px 1px;font-weight: bold;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-item-icon_ {display: none;} .mss-del-btn {width: 45px;height: 45px;border: 1px solid #e5e5e5;border-radius: 10px;cursor: pointer;} .mss-icon-panel {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.2);z-index: 1000;display: flex;justify-content: center;align-items: center;} .mss-icon-content {position: relative;width: 400px;height: 300px;border-radius: 10px;display: flex;flex-direction: column;justify-content: flex-start;align-items: center;background: #EFEFEFFF;} .mss-icon-title {width: 100%;height: 20%;display: flex;justify-content: center;align-items: center;font-size: 20px;font-weight: bold;border-bottom: 1px solid #e5e5e5;} .mss-icon-container {width: 100%;height: 80%;display: flex;flex-direction: row;justify-content: flex-start;align-items: center;} .mss-icon-form {width: 100%;height: 90px;display: flex;margin-bottom: 30px;flex-direction: column;justify-content: center;align-items: center;} .mss-icon-input {width: 280px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;margin-bottom: 10px;padding: 0 10px;font-weight: bold;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-icon-close {position: absolute;top: 20px;right: 10px;width: 30px;display: flex;flex-direction: row;justify-content: center;align-items: center;height: 30px;margin: 0 10px;cursor: pointer;} .mss-icon-cancel-btn {position: absolute;bottom: 10px;right: 100px;width: 80px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;background: #e5e5e5;cursor: pointer;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-icon-confirm-btn {position: absolute;bottom: 10px;right: 10px;width: 80px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;background: #e5e5e5;cursor: pointer;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-right {width: 100%;height: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;} .mss-form {width: 100%;height: 200px;display: flex;flex-direction: column;justify-content: center;align-items: center;} .mss-name-input {width: 300px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;margin-bottom: 10px;padding: 0 10px;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-url-input {width: 300px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;margin-bottom: 10px;padding: 0 10px;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-icon-input {width: 300px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;margin-bottom: 10px;padding: 0 10px;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset, 4px 4px 10px -8px rgba(0, 0, 0, .3) inset;background: linear-gradient(135deg, rgba(240, 240, 240, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-add-btn {width: 300px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;margin-bottom: 10px;padding: 0 10px;background: #e5e5e5;cursor: pointer;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-close {position: absolute;top: 22.5px;right: 10px;width: 30px;display: flex;flex-direction: row;justify-content: center;align-items: center;height: 30px;margin: 0 10px;cursor: pointer;} .mss-cancel-btn {position: absolute;bottom: 10px;right: 100px;width: 80px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;background: #e5e5e5;cursor: pointer;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} .mss-button-btn {position: absolute;bottom: 10px;right: 10px;width: 80px;height: 40px;border: 1px solid #e5e5e5;border-radius: 10px;background: #e5e5e5;cursor: pointer;box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1), 4px 4px 10px -8px rgba(0, 0, 0, .3);background: linear-gradient(135deg, rgba(230, 230, 230, 1) 0%, rgba(246, 246, 246, 1) 100%);} input{box-sizing:border-box;-webkit-box-sizing: border-box;}`; return createElement('style', '', '', css); } // 展开或折叠组件 function toggleMSComponent(scrollTop, expandCritical, collapseCritical) { let items = selectElementAll('.ms-item'); let sortIcons = selectElementAll('.ms-sort-icon'); let icons = selectElementAll('.ms-icon'); let toggleSortIcon = selectElement('.ms-toggle-sort-icon'); items.forEach((item, index) => { if (scrollTop > expandCritical) { if (index !== items.length - 1) { sortIcons[index].style.height = '0px'; sortIcons[index].style.opacity = '0'; sortIcons[index].style.marginBottom = '0px'; icons[index].style.height = '0px'; icons[index].style.width = '0px'; icons[index].style.opacity = '0'; } item.style.height = '18px'; toggleSortIcon.style.height = '0px'; toggleSortIcon.style.width = '0px'; toggleSortIcon.style.opacity = '0'; } else if (scrollTop <= collapseCritical) { if (index !== items.length - 1) { sortIcons[index].style.height = '3px'; sortIcons[index].style.opacity = '1'; sortIcons[index].style.marginBottom = '10px'; icons[index].style.height = '30px'; icons[index].style.width = '30px'; icons[index].style.opacity = '1'; } item.style.height = '48.5px'; toggleSortIcon.style.height = '20px'; toggleSortIcon.style.width = '20px'; toggleSortIcon.style.opacity = '1'; } }); } function search(url) { let handler = getHandler(); window.open(url + handler.getSearchContent.call()); } // 添加快捷键 function addShortcutKeys() { let urlInputs = selectElementAll('.ms-url'); let texts = selectElementAll('.ms-text'); let system = getSystem(); let modifier = (system === 'mac' || system === 'ipad') ? '⌥' : 'Alt'; let originalTexts = []; texts.forEach((text) => { originalTexts.push(text.innerHTML); }); document.body.addEventListener('keydown', (event) => { event.altKey && ( selectElement('#ms-component').classList.add('pin'), [...Array(9)].forEach((_, i) => { let keyCode = 'Digit' + (i + 1); texts.forEach((text, index) => { text.style.width = text.offsetWidth + 'px'; text.innerHTML = `${modifier} + ${index + 1}`; }); event.code === keyCode && ( event.preventDefault(), //阻止键盘输入 search(urlInputs[i].value) ) })); }); document.body.addEventListener('keyup', (event) => { !event.altKey && ( selectElement('#ms-component').classList.remove('pin'), texts.forEach((text, index) => { text.style.width = ''; text.innerHTML = originalTexts[index]; }) ) }); } // 获取系统类型 function getSystem() { let userAgent = navigator.userAgent; let isMac = userAgent.indexOf('Mac') > -1; let isIpad = userAgent.indexOf('iPad') > -1; if (isMac) { return 'mac'; } else if (isIpad) { return 'ipad'; } else { return 'win'; } } function createElement(tag, className, style, content) { let element = document.createElement(tag); className && (element.className = className); style && (element.style = style); content && (element.innerHTML = content); return element; } function createElementWithId(tag, id, style, content) { let element = document.createElement(tag); id && (element.id = id); style && (element.style = style); content && (element.innerHTML = content); return element; } function createInput(type, className, style, value, placeholder) { let input = document.createElement('input'); type && (input.type = type); className && (input.className = className); style && (input.style = style); value && (input.value = value); placeholder && (input.placeholder = placeholder); return input; } function selectElement(element) { return document.querySelector(element); } function selectElementAll(element) { return document.querySelectorAll(element); } main(); })();