// ==UserScript==
// @name SearchJumper
// @name:zh-CN 搜索酱
// @name:zh-TW 搜尋醬
// @name:ja SearchJumper
// @name:ru SearchJumper
// @namespace hoothin
// @version 1.9.32
// @description Instantly search selected text across multiple search engines. Highlight keywords and boost your research efficiency.
// @description:zh-CN 一键即时搜索选定文本或在多个搜索引擎之间快速切换,支持关键词高亮、拖拽搜索、以图搜图、页内查找与自定义引擎。
// @description:zh-TW 一鍵即時搜尋選定文字或在多個搜尋引擎之間快速切換,支援關鍵字高亮、拖曳搜尋、以圖搜圖、頁內尋找與自訂引擎。
// @description:ja 選択したテキストをワンクリックで即座に検索したり、キーワードの強調表示、ドラッグアンドドロップ検索、画像検索、ページ内検索、カスタムエンジンをサポートする複数の検索エンジン間で素早く切り替えたりできます。
// @description:ru Легко проводите поиск по выбранному тексту/изображению/ссылке. Быстро переходите к любому поисковому движку. Выделяйте искомый текст.
// @author hoothin
// @license MPL-2.0
// @match *://*/*
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAclBMVEUAAAD+/v7////+/v7+/v7////+/v79/f3////////+/v7////////////+/v79/f3////+/v7/rP8zMzP/2f/R0dHAwMD/zf+vr69ZWVlKSkry8vL/vv/+5/7r6+uRkZGcnJx8fHxwcHD+7/7f39+kpKTMxXKjAAAAEXRSTlMA4wrL9ICvkxk56nVVI9WgZNxdEUkAAAE2SURBVDjLfdPZloMgDAZgFtHR2uU3LnWrXd//FUfIHKRT7XfhUYIkhINYqPyoM0SZTnIlPu2PEbwo2f8LqwTvIvMW/9H4oH+WeCqxQu79/xKr5N8aSmOD5gkGm3YuQYRNkU3CG+ynCYH6VsEycwW8wJXoDK8narlOIXI4Z6IKi47ucNI5A6vCOC41mBEaX8VCAuVQFEXzQODRzENDaVsRoSwYAgUrIecJI38MCAw8NkLaFCibphyDMusKox0DoJci+6615fcA2q5fikz8b/QC0HWuKTX8NnM/wbWSyL86qW01u1D3xEQ04dLSE0z6w3ILz9rWPq/hefslUN3uL+B6v/kKMiVmO2w6CSfGhqNg6oBVWvlbxTO+XAy1kiVWInTK8EZyfQFlZBDeKbEiNfFBSh2bNBj8BZ8mNsZysMSsAAAAAElFTkSuQmCC
// @grant GM.getValue
// @grant GM_getValue
// @grant GM.setValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM.addStyle
// @grant GM.deleteValue
// @grant GM_deleteValue
// @grant GM.registerMenuCommand
// @grant GM_registerMenuCommand
// @grant GM.xmlHttpRequest
// @grant GM_xmlhttpRequest
// @grant GM.notification
// @grant GM_notification
// @grant GM.setClipboard
// @grant GM_setClipboard
// @grant GM.openInTab
// @grant GM_openInTab
// @grant GM.info
// @grant GM_info
// @grant unsafeWindow
// @compatible edge tested with tm
// @compatible Chrome tested with tm
// @compatible Firefox tested with tm
// @compatible Opera untested
// @compatible Safari untested
// @compatible ios tested with userscript
// @compatible android tested with kiwi
// @supportURL https://github.com/hoothin/SearchJumper/issues
// @homepage https://github.com/hoothin/SearchJumper
// @require https://update.greasyfork.org/scripts/484118/searchJumperDefaultConfig.js
// @connect global.bing.com
// @connect suggestqueries.google.com
// @connect api.bing.com
// @connect suggestion.baidu.com
// @connect webdav.hoothin.com
// @connect search.hoothin.com
// @connect *
// @run-at document-start
// ==/UserScript==
(async function() {
'use strict';
const ext = false;
const _unsafeWindow = (typeof unsafeWindow == 'undefined') ? window : unsafeWindow;
if (_unsafeWindow.searchJumperInited) return;
_unsafeWindow.searchJumperInited = true;
const clipboard = navigator && navigator.clipboard;
const inIframe = window.top !== window.self;
if (inIframe) {
try {
if (window.self.innerWidth === 0 && window.self.innerHeight === 0) {
let ignore = await new Promise(resolve => {
window.addEventListener('load', e => {
setTimeout(() => {
resolve(window.self.innerWidth < 300 || window.self.innerHeight < 300);
}, 500);
});
});
if (ignore) return;
} else if (window.self.innerWidth < 300 || window.self.innerHeight < 300) {
return;
}
} catch(e) {
return;
}
}
const importPageReg = /^https:\/\/github\.com\/hoothin\/SearchJumper(\/(issue|discussions)|\/?$|#|\?)|^https:\/\/greasyfork\.org\/.*\/scripts\/445274[\-\/].*\/discussions/i;
const mobileUa = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
const homePage = 'https://search.hoothin.com/';
const githubPage = 'https://hoothin.github.io/SearchJumper';
const firstRunPage = homePage + "firstRun";
let configPage = homePage + 'config/';
let isAllPage = false;
let searchData = {};
searchData.sitesConfig = sitesConfig;
searchData.prefConfig = {
position: {
x: "left",
y: "top"
},
offset: {
x: "0",
y: "0"
},
firstRun: true,
openInNewTab: false,
enableInPage: true,
altKey: false,
ctrlKey: true,
shiftKey: false,
metaKey: false,
autoClose: false,
autoDelay: 1000,
shortcut: true,
initShow: false,
alwaysShow: false,
customSize: 100,
tilesZoom: 100,
tipsZoom: 100,
typeOpenTime: 250,
longPressTime: 500,
noIcons: false,
showSiteLists: true,
alwaysShowSiteLists: false,
cacheSwitch: false,
noAni: false,
quickAddRule: true,
multiline: 2,
multilineGap: 1000,
historyLength: 0,
dragToSearch: true,
hideDragHistory: false,
sortType: false,
sortSite: false,
autoHide: false,
autoHideAll: false,
showCurrent: true,
shortcutKey: 'Backquote',
showInSearchEngine: false,
showInSearchJumpPage: true,
limitInPageLen: 1,
limitPopupLen: 1,
ignoreWords: ["a", "in", "into", "the", "to", "on", "among", "between", "and", "an", "of", "by", "with", "about", "under", "or", "at", "as"],
inPageRule: {},
firstFiveWordsColor: [],
inPageWordsStyles: [],
altToHighlight: true,
defaultPicker: false,
disableInputOnWords: false,
disableTypeOpen: false,
callBarAlt: false,
callBarCtrl: false,
callBarShift: false,
callBarMeta: false,
defaultFindTab: false,
disableAutoOpen: false,
hideOnSearchEngine: false,
minSizeMode: false,
hidePopup: false,
minPopup: 0,
selectToShow: ext,
expandType: false,
rightMouse: true,
shiftLastUsedType: true,
mouseLeaveToHide: true,
currentTypeFirst: true,
switchSitesPreKey: 'ArrowLeft',
switchSitesNextKey: 'ArrowRight',
switchSitesCtrl: true,
switchSitesAlt: false,
switchSitesShift: true,
switchSitesMeta: false
};
function run() {
let lang = navigator.appName === "Netscape" ? navigator.language : navigator.userLanguage;
let config = {};
function setLang() {
switch (lang) {
case "zh-CN":
case "zh-SG":
config = {
import: '导入',
filter: '筛选',
selectAll: '全选',
importOrNot: '是否导入配置?',
settings: '配置脚本',
batchOpen: '批量打开',
batchOpenConfirm: '确定要批量打开吗?',
postOver: '发送成功:',
postError: '发送失败:',
copyOver: '复制成功',
keywords: '请输入搜索词',
targetUrl: '请输入搜索URL',
siteName: '站名',
siteDesc: '描述',
siteUrl: '地址',
siteIcon: '图标',
siteTest: '测试',
siteCancel: '取消',
siteAdd: '添加',
siteType: '分类',
siteExist: '已存在相同规则,是否添加为克隆项?',
siteAddOver: '站点添加成功',
multiline: '是否以换行符分隔多行搜索?',
multilineTooMuch: '行数超过10行,是否继续搜索?',
inputPlaceholder: '筛选引擎',
inputTitle: '筛选引擎,支持 * ? 通配符,$代表末尾,^代表开头,分组**站点 可筛选指定分组,例如 图片**baidu,tab 下一项',
inputKeywords: '输入搜索关键词',
inPageTips: '自定义分隔符:$c 加分隔符,例如 $c| search | jumper,默认空格作为分隔符\n原始文本不分隔:$o 加文本,例如$oopai liked by hero\n正则表达式:/re/,例如 $c, /google/i , /aPPle/\n添加提示文本:搜索文本$t{提示文本},例如 linux$t{linux is not unix}\n添加自定义样式:搜索文本$s{背景;其他},例如 google$s{#333333;color:red;}\n左键点击关键词跳转至下一个,右键点击关键词跳转至上一个',
inPagePlaceholder: '输入文字,按下回车进行页内查找',
pickerBtn: '抓取元素',
multiPickerBtn: '抓取元素,按住 Ctrl 或 Command 连续抓取',
editBtn: '编辑查找文字',
emptyBtn: '清空查找文字',
copyInPageBtn: '复制查找文字',
wordModeBtn: '单词模式',
copyEleBtn: '复制选中元素',
openLinkBtn: '打开选中链接',
maxEleBtn: '展开选中元素',
minEleBtn: '收起选中元素',
expandAll: '全部展开',
collapseAll: '全部合起',
rename: '重命名',
recoverBtn: '恢复查找文字',
pinBtn: '固定查找文字,在所有标签页中搜索',
locBtn: '定位侧边栏',
filterSites: '筛选搜索引擎',
searchInPage: '页内查找',
removeBtn: '移除搜索词',
saveRuleBtn: '保存当前站点的搜索词',
wordContent: '搜索词内容',
wordHide: '隐藏父级元素',
wordHideTips: '元素深度,0为当前父级',
wordStyle: '搜索词样式',
wordTitle: '搜索词注释',
re: '正则',
ignoreCase: '不区分大小写',
filterLink: '筛选链接',
modify: '修改',
cancel: '取消',
modifyWord: '修改页内搜索词',
addSearchEngine: '添加搜索引擎',
noValidItemAsk: '未找到有效元素,是否手动编辑规则并添加?',
expand: '展开剩余站点',
add: '添加',
addWord: '添加新词语',
wordRange: '生效范围',
customInputFrame: '自定义搜索参数',
customSubmit: '提交搜索',
finalSearch: '目标搜索字串',
search: '搜索此项',
siteKeywords: '关键词(多个关键词以|分隔)',
siteMatch: '站点 URL 匹配正则',
openSelect: '打开选项',
openInDefault: '默认',
openInNewTab: '新标签页打开',
openInCurrent: '当前页打开',
currentType: '当前分类',
maxAddSiteBtn: '最大化',
minAddSiteBtn: '还原',
addAction: '添加操作',
crawlInfo: '模拟输入搜索',
inputAction: '输入',
clickAction: '点击',
sleepAction: '等待',
copyAction: '📄复制元素',
submitCrawl: '☑️完成操作',
inputOutput: '在元素<span title="#t1#" class="element">#t1#</span>内输入<span title="#t2#">#t2#</span>',
clickOutput: '点击元素<span title="#t#" class="element">#t#</span>',
dblclickOutput: '双击元素<span title="#t#" class="element">#t#</span>',
rclickOutput: '右击元素<span title="#t#" class="element">#t#</span>',
copyOutput: '复制元素<span title="#t#" class="element">#t#</span>',
sleepOutput: '休眠<span title="#t#">#t#</span>毫秒',
inputNewValue: '请输入新值',
deleteConfirm: '确定要删除此项吗?',
sleepPrompt: '等待时间(毫秒)',
startCache: '开始缓存,请耐心等待缓存完毕,勿关闭配置页!',
cacheOver: '所有图标都已缓存完毕!',
cspDisabled: '脚本样式被当前站点的 CSP 阻止,因此无法显示,请尝试安装 Allow CSP: Content-Security-Policy 扩展获取权限',
Sunday: '星期日 (日)',
Monday: '星期一 (月)',
Tuesday: '星期二 (火)',
Wednesday: '星期三 (水)',
Thursday: '星期四 (木)',
Friday: '星期五 (金)',
Saturday: '星期六 (土)',
template: '请设置【#t#】的值',
recordAction: '⏺️录制操作',
startRecord: '开始录制操作,按回车键结束录制',
loopAction: '🔁开始循环',
loopActionEnd: '⏹️循环结束',
loopStart: '开始循环,循环次数为<span title="#t#">#t#</span>',
loopEnd: '结束循环',
loopTimes: '循环次数,将遍历所有匹配元素并顺序执行',
loadingCollection: '正在加载合集,请稍候……',
emuInputTips: '在指定页面元素(例如输入框)内输入搜索词',
emuClickTips: '单击指定页面元素(例如按钮)',
emuWaitTips: '等待一段时间后继续执行,当某个操作需要一段时间才能完成时很有用',
emuCopyTips: '复制指定元素的文本到剪贴板',
emuRecordTips: '录制接下来的点击和输入操作',
emuLoopTips: '开始循环,接下来的操作将遍历所有找到的元素并且重复指定次数',
emuStopTips: '结束操作并生成规则'
};
break;
case "zh":
case "zh-TW":
case "zh-HK":
config = {
import: '導入',
filter: '篩選',
selectAll: '全選',
importOrNot: '是否導入配置?',
settings: '配置脚本',
batchOpen: '批量打開',
batchOpenConfirm: '確定要批量打開嗎?',
postOver: '發送成功:',
postError: '發送失敗:',
copyOver: '複製成功',
keywords: '請輸入搜尋詞',
targetUrl: '請輸入搜尋URL',
siteName: '站名',
siteDesc: '描述',
siteUrl: '地址',
siteIcon: '圖標',
siteTest: '測試',
siteCancel: '取消',
siteAdd: '添加',
siteType: '分類',
siteExist: '已存在相同規則,是否添加為克隆項?',
siteAddOver: '站點添加成功',
multiline: '是否以換行符分隔多行搜尋?',
multilineTooMuch: '行數超過10行,是否繼續搜尋?',
inputPlaceholder: '篩選引擎',
inputTitle: '篩選引擎,支援 * ? 通配符,$代表末尾,^代表開頭,分組**站點 可篩選指定分組,例如 圖片**google,tab 下一項',
inputKeywords: '輸入搜尋關鍵詞',
inPageTips: '自定義分隔符:$c 加分隔符,例如 $c| search | jumper,默認空格作為分隔符\n原始文本不分隔:$o 加文本,例如$oopai liked by hero\n正則表達式:/re/,例如 $c, /google/i , /aPPle/\n添加提示文本:搜尋文本$t{提示文本},例如 linux$t{linux is not unix}\n添加自定義樣式:搜尋文本$s{背景;其他},例如 google$s{#333333;color:red;}\n左鍵點擊關鍵詞跳轉至下一個,右鍵點擊關鍵詞跳轉至上一個',
inPagePlaceholder: '輸入文字,按下回車進行頁內查找',
pickerBtn: '抓取元素',
multiPickerBtn: '抓取元素,按住 Ctrl 或 Command 連續抓取',
editBtn: '編輯查找文字',
emptyBtn: '清空查找文字',
copyInPageBtn: '複製查找文字',
wordModeBtn: '單詞模式',
copyEleBtn: '複製選中元素',
openLinkBtn: '打開選中連結',
maxEleBtn: '展開選中元素',
minEleBtn: '收起選中元素',
expandAll: '全部展開',
collapseAll: '全部合起',
rename: '重命名',
recoverBtn: '恢復查找文字',
pinBtn: '固定查找文字,在所有標籤頁中搜尋',
locBtn: '定位側邊欄',
filterSites: '篩選搜尋引擎',
searchInPage: '頁內查找',
removeBtn: '移除搜尋詞',
saveRuleBtn: '保存當前站點的搜尋詞',
wordContent: '搜尋詞內容',
wordHide: '隱藏父級元素',
wordHideTips: '元素深度,0為當前父級',
wordStyle: '搜尋詞樣式',
wordTitle: '搜尋詞注釋',
re: '正則',
ignoreCase: '不區分大小寫',
filterLink: '篩選鏈接',
modify: '修改',
cancel: '取消',
modifyWord: '修改頁內搜尋詞',
addSearchEngine: '添加搜尋引擎',
noValidItemAsk: '未找到有效元素,是否手動編輯規則並添加?',
expand: '展開剩餘站點',
add: '添加',
addWord: '添加新詞語',
wordRange: '生效範圍',
customInputFrame: '自定義搜尋參數',
customSubmit: '提交搜尋',
finalSearch: '目標搜尋字串',
search: '搜尋此項',
siteKeywords: '關鍵詞(多個關鍵詞以|分隔)',
siteMatch: '站點 URL 匹配正則',
openSelect: '打開選項',
openInDefault: '默認',
openInNewTab: '新標籤頁打開',
openInCurrent: '當前頁打開',
currentType: '當前分類',
maxAddSiteBtn: '最大化',
minAddSiteBtn: '還原',
addAction: '添加操作',
crawlInfo: '模擬輸入搜尋',
inputAction: '輸入',
clickAction: '點擊',
sleepAction: '等待',
copyAction: '📄複製元素',
submitCrawl: '☑️完成操作',
inputOutput: '在元素<span title="#t1#" class="element">#t1#</span>內輸入<span title="#t2#">#t2#</span>',
clickOutput: '點擊元素<span title="#t#" class="element">#t#</span>',
dblclickOutput: '雙擊元素<span title="#t#" class="element">#t#</span>',
rclickOutput: '右擊元素<span title="#t#" class="element">#t#</span>',
copyOutput: '複製元素<span title="#t#" class="element">#t#</span>',
sleepOutput: '休眠<span title="#t#">#t#</span>毫秒',
inputNewValue: '請輸入新值',
deleteConfirm: '確定要刪除此項嗎? ',
sleepPrompt: '等待時間(毫秒)',
startCache: '開始緩存,請耐心等待緩存完畢,勿關閉配置頁!',
cacheOver: '所有圖標都已緩存完畢!',
cspDisabled: '腳本樣式被當前站點的 CSP 阻止,因此無法顯示,請嘗試安裝 Allow CSP: Content-Security-Policy 擴展獲取權限',
Sunday: '星期日 (日)',
Monday: '星期一 (月)',
Tuesday: '星期二 (火)',
Wednesday: '星期三 (水)',
Thursday: '星期四 (木)',
Friday: '星期五 (金)',
Saturday: '星期六 (土)',
template: '請設置【#t#】的值',
recordAction: '⏺️錄製動作',
startRecord: '開始錄製操作,按下回車鍵結束錄製',
loopAction: '🔁開始循環',
loopActionEnd: '⏹️循環結束',
loopStart: '開始循環,循環次數為<span title="#t#">#t#</span>',
loopEnd: '結束循環',
loopTimes: '循環次數,將遍歷所有匹配元素並順序執行',
loadingCollection: '正在載入合集,請稍候……',
emuInputTips: '在指定頁面元素(例如輸入框)內輸入搜尋字詞',
emuClickTips: '點擊指定頁面元素(例如按鈕)',
emuWaitTips: '等待一段時間後繼續執行,當某個操作需要一段時間才能完成時很有用',
emuCopyTips: '複製指定元素的文字到剪貼簿',
emuRecordTips: '錄製接下來的點擊和輸入操作',
emuLoopTips: '開始循環,接下來的操作將遍歷所有找到的元素並且重複指定次數',
emuStopTips: '結束操作並產生規則'
};
break;
case 'ja':
config = {
import: 'インポート',
filter: 'フィルター',
selectAll: 'すべて選択',
importOrNot: '設定をインポートしますか? ',
settings: '構成スクリプト',
batchOpen: 'バッチオープン',
batchOpenConfirm: 'バッチオープンしてもよろしいですか? ',
postOver: '正常に送信されました:',
postError: '送信に失敗しました:',
copyOver: 'コピーに成功しました',
keywords: '検索語を入力してください',
targetUrl: '検索 URL を入力してください',
siteName: 'サイト名',
siteDesc: '説明',
siteUrl: 'アドレス',
siteIcon: 'アイコン',
siteTest: 'テスト',
siteCancel: 'キャンセル',
siteAdd: '追加',
siteType: 'カテゴリ',
siteExist: '同じルールがすでに存在します。クローンとして追加しますか? ',
siteAddOver: 'サイトは正常に追加されました',
multiline: '複数行の検索は改行で区切るべきですか? ',
multilineTooMuch: '行数が 10 行を超えています。検索を続けますか? ',
inputPlaceholder: 'フィルタリング エンジン',
inputTitle: 'フィルタリング エンジン、*? ワイルドカードをサポート、$ は終わりを表し、^ は始まりを表します、グループ ** サイトは写真などの指定されたグループをフィルターできます ** Google、次の項目をタブします',
inputKeywords: '検索キーワードを入力してください',
inPageTips: 'カスタム区切り文字: $c と区切り文字 ($c| 検索 | ジャンパーなど)、デフォルトのスペースを区切り文字として使用\n元のテキストは分離されていません: $o と文字 (ヒーローが好んだ $oopai など)\n正規表現 :/re/ 、$c、/google/i、/aPPle/ など\nプロンプト テキストの追加: 検索テキスト $t{プロンプト テキスト}、たとえば linux$t{Linux は Unix ではありません}\nカスタム スタイルの追加: 検索テキスト $s{背景;other}、例: google$s{#333333;color:red;}\nキーワードを左クリックすると次のキーワードにジャンプし、キーワードを右クリックすると前のキーワードにジャンプします',
inPagePlaceholder: 'ページ内を検索するには、テキストを入力して Enter キーを押してください',
pickerBtn: '要素の取得',
multiPickerBtn: '要素を取得するには、Ctrl または Command を押したまま継続的に取得します',
editBtn: '検索テキストを編集',
emptyBtn: '空の検索テキスト',
copyInPageBtn: '検索テキストをコピー',
wordModeBtn: 'ワードモード',
copyEleBtn: '選択した要素をコピー',
openLinkBtn: '選択したリンクを開く',
maxEleBtn: '選択した要素を展開',
minEleBtn: '選択した要素を折りたたむ',
expandAll: 'すべて展開',
collapseAll: 'すべて折り',
rename: '名前を変更',
reverseBtn: '検索テキストを復元',
pinBtn: '検索テキストを修正、すべてのタブで検索',
locBtn: 'サイドバーを検索',
filterSites: '検索エンジンをフィルタリング',
searchInPage: 'ページ内を検索',
removeBtn: '検索語を削除',
saveRuleBtn: '現在のサイトの検索語を保存',
wordContent: '単語の内容を検索',
wordHide: '親要素を非表示',
wordHideTips: '要素の深さ、0 が現在の親',
wordStyle: '検索ワードスタイル',
wordTitle: '検索単語の注釈',
re: 'RegExp',
ignoreCase: '大文字と小文字は区別されません',
filterLink: 'フィルターリンク',
modify: '変更',
cancel: 'キャンセル',
modifyWord: 'ページ上の検索ワードを変更します',
addSearchEngine: '検索エンジンを追加',
noValidItemAsk: '有効な要素が見つかりません。ルールを手動で編集して追加しますか? ',
expand: '残りのサイトを展開します',
add: '追加',
addWord: '新しい単語を追加',
wordRange: '有効範囲',
customInputFrame: 'カスタム検索パラメータ',
customSubmit: '検索を送信',
finalSearch: '対象の検索文字列',
search: 'このアイテムを検索',
siteKeywords: 'キーワード (| で区切られた複数のキーワード)',
siteMatch: '通常のサイト URL と一致',
openSelect: 'オプションを開く',
openInDefault: 'デフォルト',
openInNewTab: '新しいタブが開きます',
openInCurrent: '現在のページが開いています',
currentType: '現在のカテゴリ',
maxAddSiteBtn: '最大化',
minAddSiteBtn: '復元',
addAction: 'アクションを追加',
rollInfo: '入力検索をシミュレート',
inputAction: '入力',
clickAction: 'クリック',
sleepAction: '待機',
copyAction: '📄要素のコピー',
submitCrawl: '☑️操作を完了',
inputOutput: '要素 <span title="#t1#" class="element">#t1#</span> 内に <span title="#t2#">#t2#</span> を入力します',
clickOutput: 'クリック<span title="#t#" class="element">#t#</span>',
dblclickOutput: 'ダブルクリック<span title="#t#" class="element">#t#</span>',
rclickOutput: '右クリック<span title="#t#" class="element">#t#</span>',
copyOutput: 'コピー要素<span title="#t#" class="element">#t#</span>',
sleepOutput: 'スリープ<span title="#t#">#t#</span> ミリ秒',
inputNewValue: '新しい値を入力してください',
deleteconfirm: 'この項目を削除してもよろしいですか? ',
sleepPrompt: '待機時間 (ミリ秒)',
startCache: 'キャッシュを開始します。キャッシュが完了するまで辛抱強く待ってください。設定ページは閉じないでください。 ',
cacheOver: 'すべてのアイコンがキャッシュされました! ',
cspDisabled: 'スクリプト スタイルは現在のサイトの CSP によってブロックされているため、表示できません。許可を取得するには、Allow CSP: Content-Security-Policy 拡張機能をインストールしてみてください',
Sunday: '日曜日',
Monday: '月曜日',
Tuesday: '火曜日',
Wednesday: '水曜日',
Thursday: '木曜日',
Friday: '金曜日',
Saturday: '土曜日',
template: '[#t#]の値を設定してください',
recordAction: '⏺️記録操作',
startRecord: '記録操作を開始します。記録を終了するには Enter キーを押してください',
loopAction: '🔁ループの開始',
loopActionEnd: '⏹️ループの終了',
loopStart: 'ループを開始。ループ数は <span title="#t#">#t#</span> です',
loopEnd: 'ループの終了',
loopTimes: 'ループの数。一致するすべての要素が走査され、順番に実行されます',
loadingCollection: 'コレクションを読み込み中...',
emuInputTips: '指定されたページ要素 (入力ボックスなど) に検索語を入力します',
emuClickTips: '指定されたページ要素 (ボタンなど) をクリックします',
emuWaitTips: '続行する前にしばらく待ってください。操作が完了するまでに時間がかかる場合に便利です',
emuCopyTips: '指定された要素のテキストをクリップボードにコピーします',
emuRecordTips: '次のクリックと入力操作を記録します',
emuLoopTips: 'ループを開始します。次の操作は見つかったすべての要素を走査し、指定された回数だけ繰り返します',
emuStopTips: '操作を終了してルールを生成'
};
break;
case 'ru':
config = {
import: 'Импортировать', //????????????????????????????????????????????????????????????
filter: 'Фильтровать', //????????????????????????????????????????????????????????????
selectAll: 'Выбрать всё', //????????????????????????????????????????????????????????????
importOrNot: 'Импортировать эту конфигурацию?',
settings: 'Настройки',
batchOpen: 'Групповой поиск',
batchOpenConfirm: 'Искать с помощью всех движков группы?',
postOver: 'Post over: ',
postError: 'Post fail: ',
copyOver: 'Скопировано успешно',
keywords: 'Input keywords',
targetUrl: 'Input URL',
siteName: 'Название',
siteDesc: 'Описание',
siteUrl: 'URL',
siteIcon: 'Иконка',
siteTest: 'Тест',
siteCancel: 'Отменить',
siteAdd: 'Добавить',
siteType: 'Группа',
siteExist: 'Движок уже существует. Добавить его как клон?',
siteAddOver: 'Движок успешно добавлен',
multiline: 'Использовать многострочный поиск?',
multilineTooMuch: 'Количество строк превышает 10. Продолжить поиск?', //????????????????????????????????????????????????????????????
inputPlaceholder: 'Фильтры',
inputTitle: 'Filter engines, support * ? wildcards, $ means end, ^ means start, type name**site name to filter type like "image**google", tab to next. ',
inputKeywords: 'Ввести ключевые слова поиска',
inPageTips: 'Custom delimiter: $c + delimiter, such as $c| search | jumper, space as delimiter by default\nOriginal text without delimited: $o + text, such as $oopai liked by hero\nRegular expression: /re/, such as $c, /google/i , /aPPle/\nTips text: search text$t{tips text}, such as linux$t{linux is not unix}\nCustom style: Search text$s{background;other}, such as google$s{#333333;color:red;}\nLeft-click keyword to jump to the next, right-click keyword to jump to the previous',
inPagePlaceholder: 'Для поиска введите текст и нажмите Enter',
pickerBtn: 'Выбрать область',
multiPickerBtn: 'Выбрать элемент или выбрать несколько элементов с помощью Ctrl или Command',
editBtn: 'Редактировать текст поиска',
emptyBtn: 'Очистить поле ввода',
copyInPageBtn: 'Скопировать текст поика',
wordModeBtn: 'Режим поиска по словам. В поле ввода можно ввести целое предложение, после чего на странице будут искаться все слова по отдельности из которого состоит предложение',
copyEleBtn: 'Скопировать выбранные элементы',
openLinkBtn: 'Открыть выбранные ссылки',
maxEleBtn: 'Расширить выбранные элементы',
minEleBtn: 'Сжать выбранные элементы',
expandAll: 'Развернуть всё',
collapseAll: 'Свернуть всё',
rename: 'Rename',
recoverBtn: 'Recover find text',
pinBtn: 'Выделить цветом текущие ключевые слова поиска по странице во всех открытых вкладках',
locBtn: 'Отображать совпадения справа на панели',
filterSites: 'Фильтровать движки',
searchInPage: 'Искать на странице',
removeBtn: 'Удалить правило поиска',
saveRuleBtn: 'Сохранить правило поиска текущего сайта',
wordContent: 'Слово или фраза для поиска',
wordHide: 'Hide parent element',
wordHideTips: 'Глубина элемента, 0 - это текущее значение', //????????????????????????????????????????????????????????????
wordStyle: 'Стиль выделения слова',
wordTitle: 'Аннотация к искомому слову',
re: 'RegExp',
ignoreCase: 'Игнорировать регистр',
filterLink: 'Фильтровать ссылку', //????????????????????????????????????????????????????????????
modify: 'Готово',
cancel: 'Отменить',
modifyWord: 'Изменить параметры',
addSearchEngine: 'Добавить движок',
noValidItemAsk: 'Не найден подходящий элемент. Хотите вручную добавить сайт?',
expand: 'Развернуть другие сайты', //????????????????????????????????????????????????????????????
add: 'Добавить',
addWord: 'Добавить новое слово',
wordRange: 'Выделить область поиска',
customInputFrame: 'Пользовательские параметры поиска',
customSubmit: 'Принять',
finalSearch: 'Целевая строка поиска',
search: 'Искать это', //????????????????????????????????????????????????????????????
siteKeywords: 'Ключевые слова (разделитель |)',
siteMatch: 'Regexp для соответствия URL сайта',
openSelect: 'Открыть в',
openInDefault: 'По умолчанию',
openInNewTab: 'Открыть в новой вкладке',
openInCurrent: 'Открыть в текущей вкладке',
currentType: 'Current',
maxAddSiteBtn: 'Развернуть',
minAddSiteBtn: 'Свернуть',
addAction: 'Добавить действия',
crawlInfo: 'Симуляция действий на сайте',
inputAction: 'Ввод',
clickAction: 'Клик мыши',
sleepAction: 'Ожидание',
copyAction: '📄Копировать элемент',
submitCrawl: '☑️Завешить действие',
inputOutput: 'Ввод <span title="#t2#">#t2#</span> в элемент <span title="#t1#" class="element">#t1#</span>',
clickOutput: 'Клик по элементу <span title="#t#" class="element">#t#</span>',
dblclickOutput: 'Двойной клик <span title="#t#" class="element">#t#</span>',
rclickOutput: 'щелкните ПКМ <span title="#t#" class="element">#t#</span>',
copyOutput: 'Копировать элемент <span title="#t#" class="element">#t#</span>',
sleepOutput: 'Ждать <span title="#t#">#t#</span> миллисекунд',
inputNewValue: 'Введите новое значение',
deleteConfirm: 'Хотите удалить этот элемент? ',
sleepPrompt: 'Время ожидания (в миллисекундах)',
startCache: 'Началось кширование закрывайте страницу!',
cacheOver: 'Все иконки кэшированы!',
cspDisabled: 'The style of SearchJumper is blocked by the CSP of current site, please try to install the Allow CSP: Content-Security-Policy extension to obtain permission',
template: 'Установите значение "#t#"',
recordAction: '⏺️Записать действие',
startRecord: 'Сейчас начнется запись действия. После завершения нажмите Enter, чтобы вернуться в окно редактирования.',
loopAction: '🔁Начать цикл',
loopActionEnd: '⏹️Остановить цикл',
loopStart: 'Начать цикл <span title="#t#">#t#</span> раз',
loopEnd: 'Остановить цикл',
loopTimes: 'Количество циклов, все совпадающие элементы будут пройдены и выполнены последовательно',
loadingCollection: 'Preparing collection for SearchJumper...',
emuInputTips: 'Ввести поисковые запросы в указанные элементы страницы (например, в поля ввода).',
emuClickTips: 'Кликнуть по указанному элементу страницы (например, по кнопке)',
emuWaitTips: 'Подождите некоторое время, прежде чем продолжить. Полезно, когда операция требует некоторого времени для завершения',
emuCopyTips: 'Копирование текста указанного элемента в буфер обмена',
emuRecordTips: 'Записать следующие нажатия и операции ввода',
emuLoopTips: 'Запустить цикл, следующая операция будет обходить все найденные элементы и повторяться указанное количество раз',
emuStopTips: 'Завершить операцию и создать правило'
};
break;
default:
config = {
import: 'Import',
filter: 'Filter',
selectAll: 'SelectAll',
importOrNot: 'Do you want to import this config?',
settings: 'Settings',
batchOpen: 'Batch open',
batchOpenConfirm: 'Batch open urls?',
postOver: 'Post over: ',
postError: 'Post fail: ',
copyOver: 'Copied successfully',
keywords: 'Input keywords',
targetUrl: 'Input URL',
siteName: 'Site Name',
siteDesc: 'Description',
siteUrl: 'Site Url',
siteIcon: 'Site Icon',
siteTest: 'Test',
siteCancel: 'Cancel',
siteAdd: 'Add',
siteType: 'Category',
siteExist: 'Site is already exist, add it as clone?',
siteAddOver: 'Site added successfully',
multiline: 'Search as multilines?',
multilineTooMuch: 'The number of lines exceeds 10, do you want to continue searching?',
inputPlaceholder: 'Filter engines',
inputTitle: 'Filter engines, support * ? wildcards, $ means end, ^ means start, type name**site name to filter type like "image**google", tab to next. ',
inputKeywords: 'Enter search keywords',
inPageTips: 'Custom delimiter: $c + delimiter, such as $c| search | jumper, space as delimiter by default\nOriginal text without delimited: $o + text, such as $oopai liked by hero\nRegular expression: /re/, such as $c, /google/i , /aPPle/\nTips text: search text$t{tips text}, such as linux$t{linux is not unix}\nCustom style: Search text$s{background;other}, such as google$s{#333333;color:red;}\nLeft-click keyword to jump to the next, right-click keyword to jump to the previous',
inPagePlaceholder: 'Input text, press Enter to find in the page',
pickerBtn: 'Pick a element',
multiPickerBtn: 'Pick a element, pick multi elements with Ctrl or Command',
editBtn: 'Edit search text',
emptyBtn: 'Empty search text',
copyInPageBtn: 'Copy search text',
wordModeBtn: 'Word mode',
copyEleBtn: 'Copy selected elements',
openLinkBtn: 'Open selected links',
maxEleBtn: 'Expand selected elements',
minEleBtn: 'Collapse selected elements',
expandAll: 'Expand All',
collapseAll: 'Collapse All',
rename: 'Rename',
recoverBtn: 'Recover find text',
pinBtn: 'Pin search text to search in all tabs',
locBtn: 'Sidebar to locate',
filterSites: 'Filter search engines',
searchInPage: 'Find in page',
removeBtn: 'Remove search term',
saveRuleBtn: 'Save the search term of the current site',
wordContent: 'Search word content',
wordHide: 'Hide parent element',
wordHideTips: 'Element depth, 0 means the current',
wordStyle: 'Search word style',
wordTitle: 'Search word annotation',
re: 'RegExp',
ignoreCase: 'Ignore case',
filterLink: 'Filter link',
modify: 'Modify',
cancel: 'Cancel',
modifyWord: 'Modify search word',
addSearchEngine: 'Add search engine',
noValidItemAsk: 'No valid element found, do you want to manually edit the rule and add it?',
expand: 'Expand other sites',
add: 'Add',
addWord: 'Add new word',
wordRange: 'Effective range',
customInputFrame: 'Custom search parameters',
customSubmit: 'Submit',
finalSearch: 'Target search string',
search: 'Search this',
siteKeywords: 'Keywords(split by |)',
siteMatch: 'Regexp to match site URL',
openSelect: 'Open option',
openInDefault: 'Default',
openInNewTab: 'Open a new tab',
openInCurrent: 'Open in current',
currentType: 'Current',
maxAddSiteBtn: 'Maximize',
minAddSiteBtn: 'Restore',
addAction: 'Add Actions',
crawlInfo: 'Analog input search',
inputAction: 'Input',
clickAction: 'Click',
sleepAction: 'Wait',
copyAction: '📄Copy element',
submitCrawl: '☑️Complete operation',
inputOutput: 'Input <span title="#t2#">#t2#</span> in the element <span title="#t1#" class="element">#t1#</span>',
clickOutput: 'Click on element <span title="#t#" class="element">#t#</span>',
dblclickOutput: 'Double click <span title="#t#" class="element">#t#</span>',
rclickOutput: 'Right click <span title="#t#" class="element">#t#</span>',
copyOutput: 'Copy element <span title="#t#" class="element">#t#</span>',
sleepOutput: 'Sleep for <span title="#t#">#t#</span> milliseconds',
inputNewValue: 'Please enter a new value',
deleteConfirm: 'Are you sure you want to delete this item? ',
sleepPrompt: 'Wait time (milliseconds)',
startCache: 'Start cache icons of engines, do not close this page!',
cacheOver: 'All icons cached!',
cspDisabled: 'The style of SearchJumper is blocked by the CSP of current site, please try to install the Allow CSP: Content-Security-Policy extension to obtain permission',
template: 'Please set the value of "#t#"',
recordAction: '⏺️Record operation',
startRecord: 'Start to record operation, press Enter to end',
loopAction: '🔁Start loop',
loopActionEnd: '⏹️Stop loop',
loopStart: 'Start loop <span title="#t#">#t#</span> times',
loopEnd: 'Stop loop',
loopTimes: 'Number of loops, all matching elements will be traversed and executed sequentially',
loadingCollection: 'Preparing collection for SearchJumper...',
emuInputTips: 'Enter search terms in specified page elements (such as input boxes)',
emuClickTips: 'Click on a specified page element (such as a button)',
emuWaitTips: 'Wait for a while before continuing, useful when an operation takes a while to complete',
emuCopyTips: 'Copy the text of the specified element to the clipboard',
emuRecordTips: 'Record the next clicks and input operations',
emuLoopTips: 'Start the loop, the next operation will traverse all found elements and repeat the specified number of times',
emuStopTips: 'End the operation and generate rules'
};
break;
}
}
function i18n(name, param) {
return config[name] ? (param ? config[name].replace(/#t#/g, param).replace(/#t1#/g, param[0]).replace(/#t2#/g, param[1]) : config[name]) : name;
};
const isMobile = ('ontouchstart' in document.documentElement);
var enableDebug = true;
var debug = (str, title) => {
if(enableDebug) {
console.log(
`%c【SearchJumper v.${_GM_info.script.version}】 ${title ? title : 'debug'}`,
'color: orange;font-size: large;font-weight: bold;',
str
);
}
};
var disabled = false;
var isInConfigPage = false;
var lastRequestUrl;
function createHTML(html = "") {
return escapeHTMLPolicy ? escapeHTMLPolicy.createHTML(html) : html;
}
var _GM_xmlhttpRequest, _GM_registerMenuCommand, _GM_notification, _GM_setClipboard, _GM_openInTab, _GM_addStyle, _GM_info, GM_fetch;
if (typeof GM_xmlhttpRequest != 'undefined') {
_GM_xmlhttpRequest = GM_xmlhttpRequest;
GM_fetch = true;
} else if (typeof GM != 'undefined' && typeof GM.xmlHttpRequest != 'undefined') {
_GM_xmlhttpRequest = GM.xmlHttpRequest;
GM_fetch = true;
} else {//will not cross csp, it's safe!
let res;
_GM_xmlhttpRequest = (f) => {fetch(f.url, {method: f.method || 'GET', body: f.data, headers: f.headers}).then(response => {
res = response;
if (f.responseType === "blob") {
return response.blob();
}
return response.text();
}).then(data => {f.onload && f.onload({status: res.status, response: data})}).catch(e => f.onerror && f.onerror(e))};
}
if (GM_fetch) {
GM_fetch = async (url, option) => {
if (!url) return null;
lastRequestUrl = url;
return new Promise((resolve, reject) => {
let isPost = option && /^post$/i.test(option.method);
let requestOption = {
method: (option && option.method) || 'GET',
url: url,
headers: (option && option.headers) || {
referer: url,
origin: url,
"Content-Type": (isPost ? "application/x-www-form-urlencoded" : ""),
'X-Requested-With': (isPost ? 'XMLHttpRequest' : '')
},
onload: function(d) {
if (lastRequestUrl != url) return;
let response = d.response;
if (d.status >= 400 || !response) response = "";
let text = () => new Promise((r) => {
r(response);
});
let json = () => new Promise((r) => {
try {
r(JSON.parse(response));
} catch (e) {
r(null);
}
});
resolve({text: text, json: json, finalUrl: (d.finalUrl || url)});
},
onerror: function(e) {
debug(e);
reject(e);
},
ontimeout: function(e) {
debug(e);
reject(e);
}
};
if (option && option.body) {
requestOption.data = option.body;
}
if (option && option.responseType === "stream") {
requestOption.responseType = "stream";
delete requestOption.onload;
requestOption.onloadstart = d => {
if (!d || !d.response || !d.response.getReader) return;
let bytes = [], callBack, buffer;
const reader = d.response.getReader();
let json = () => {
let result = "";
try {
if (buffer) {
result = buffer.trim();
if (/^data:/.test(result)) {
result = "[" + result.replace(/^data:\s+\[DONE\]\s*/m, "").trim().replace(/\n+/g, "\n").split("\n").map(line => line.replace(/^data:/, "")).join(",") + "]";
} else if (/^({.*} *\n)* *{.*}$/.test(result)) {
result = result.split("\n").pop();
} else if (/^\[[\s\S]+[^\]]$/.test(result)) {
result = result + "]";
}
}
return JSON.parse(result);
} catch (e) {
return null;
}
};
reader.read().then(function readBytes({done, value}) {
if (lastRequestUrl != url) return;
if (done) {
resolve({text: buffer, json: json, finalUrl: (d.finalUrl || url)});
return;
}
bytes = option.streamMode === "standalone" ? Array.from(value) : bytes.concat(Array.from(value));
try {
buffer = new TextDecoder('utf-8').decode(new Uint8Array(bytes));
option.onstream({text: buffer, json: json, finalUrl: (d.finalUrl || url)});
} catch (e) {
console.log(e);
}
return reader.read().then(readBytes);
});
};
}
_GM_xmlhttpRequest(requestOption);
});
}
} else GM_fetch = fetch;
if (inIframe) {
_GM_registerMenuCommand = (s, f) => {};
} else if (typeof GM_registerMenuCommand != 'undefined') {
_GM_registerMenuCommand = GM_registerMenuCommand;
} else if (typeof GM != 'undefined' && typeof GM.registerMenuCommand != 'undefined') {
_GM_registerMenuCommand = GM.registerMenuCommand;
} else {
_GM_registerMenuCommand = (s, f) => {};
}
if (ext) {
_GM_openInTab = (s, t) => {
chrome.runtime.sendMessage({action: "openInTab", detail: {url: s, incognito: t && t.incognito, active: t && t.active, close: t && t.close}});
};
} else if (typeof GM_openInTab != 'undefined') {
_GM_openInTab = GM_openInTab;
} else if (typeof GM != 'undefined' && typeof GM.openInTab != 'undefined') {
_GM_openInTab = GM.openInTab;
} else {
_GM_openInTab = (s, t) => {window.open(s)};
}
if (ext) {
_GM_notification = s => {
chrome.runtime.sendMessage({action: "notification", detail: {message: s}});
}
} else if (typeof GM_notification != 'undefined') {
_GM_notification = s => GM_notification({text: s, onclick: e => _GM_openInTab(configPage, {active: true})});
} else if (typeof GM != 'undefined' && typeof GM.notification != 'undefined') {
_GM_notification = s => GM.notification({text: s, onclick: e => _GM_openInTab(configPage, {active: true})});
} else {
_GM_notification = (s) => {};
}
if (typeof GM_setClipboard != 'undefined') {
_GM_setClipboard = GM_setClipboard;
} else if (typeof GM != 'undefined' && typeof GM.setClipboard != 'undefined') {
_GM_setClipboard = GM.setClipboard;
} else {
_GM_setClipboard = (s, i) => {
try {
clipboard.writeText(s)
.then(() => {
console.log('Text copied to clipboard');
})
.catch((error) => {
document.execCommand('copy');
console.error('Failed to copy text: ', error);
});
} catch (e) {
document.execCommand('copy');
}
};
}
_GM_addStyle = cssStr => {
cssStr = cssStr.replace(/\n\s*/g, "");
if (typeof GM_addStyle != 'undefined') {
return GM_addStyle(cssStr);
} else {
let styleEle = document.createElement("style");
styleEle.innerHTML = createHTML(cssStr);
document.head.appendChild(styleEle);
return styleEle;
}
};
if (typeof GM_info != 'undefined') {
_GM_info = GM_info;
} else if (typeof GM != 'undefined' && typeof GM.info != 'undefined') {
_GM_info = GM.info;
} else {
_GM_info = { script: {name: 'SearchJumper', version: 0} };
}
if (!_unsafeWindow.searchJumperAddons) _unsafeWindow.searchJumperAddons = [];
const curRef = document.referrer;
let href = location.href.slice(0, 500);
var storage = {
supportGM: typeof GM_getValue == 'function' && typeof GM_getValue('a', 'b') != 'undefined',
supportGMPromise: typeof GM != 'undefined' && typeof GM.getValue == 'function' && typeof GM.getValue('a','b') != 'undefined',
supportCrossSave: function() {
return this.supportGM || this.supportGMPromise;
},
listItemCache: [],
mxAppStorage: (function() {
try {
return window.external.mxGetRuntime().storage;
} catch(e) {
}
})(),
operaUJSStorage: (function() {
try {
return window.opera.scriptStorage;
} catch(e) {
}
})(),
setItem: function (key, value) {
if (ext) {
chrome.storage.local.set({ [key]: value }, () => {});
} else if (this.supportGMPromise) {
GM.setValue(key, value);
if(value === "" && typeof GM != 'undefined' && typeof GM.deleteValue != 'undefined'){
GM.deleteValue(key);
}
} else if (this.supportGM) {
GM_setValue(key, value);
if(value === "" && typeof GM_deleteValue != 'undefined'){
GM_deleteValue(key);
}
} else if (this.operaUJSStorage) {
this.operaUJSStorage.setItem(key, value);
} else if (this.mxAppStorage) {
this.mxAppStorage.setConfig(key, value);
} else if (window.localStorage) {
window.localStorage.setItem(key, value);
}
},
getItem: async function (key, cb) {
var value;
if (ext) {
let result = await chrome.storage.local.get([key]);
value = result && result[key];
} else if (this.supportGMPromise) {
value = await GM.getValue(key);
} else if (this.supportGM) {
value = GM_getValue(key);
} else if (this.operaUJSStorage) {
value = this.operaUJSStorage.getItem(key);
} else if (this.mxAppStorage) {
value = this.mxAppStorage.getConfig(key);
} else if (window.localStorage) {
value = window.localStorage.getItem(key);
};
if(cb) cb(value);
return value;
},
getListItem: async function(list, key) {
var listData = this.listItemCache[list];
if (typeof listData === 'undefined') {
listData = await this.getItem(list);
this.listItemCache[list] = listData || null;
}
if (!listData) return null;
for(var i = 0; i < listData.length; i++) {
let data = listData[i];
if (data.k == key) {
return data.v;
}
}
return null;
},
setListItem: async function(list, key, value) {
var listData = this.listItemCache[list];
if (typeof listData === 'undefined') {
listData = await this.getItem(list);
}
if (!listData) listData = [];
listData = listData.filter(data => data && data.k != key);
if (value) {
listData.unshift({k: key, v: value});
if (listData.length > 50) listData.pop();
}
this.setItem(list, listData);
this.listItemCache[list] = listData;
}
};
class WebDAV {
constructor(webDAVUrl, username, password) {
this.webDAVUrl = webDAVUrl;
this.username = username;
this.password = password;
}
init() {
if (this.inited) return;
this.inited = true;
this.auth = btoa(`${this.username}:${this.password}`);
}
request(action, data, path, type, callback, headers) {
if (ext) {
chrome.runtime.sendMessage({action: "webDAV", detail: {method: action, body: data, path: path, type: type, headers: headers}}, function(r) {
callback && callback(r);
});
} else {
this.init();
let url = this.webDAVUrl + path;
let _headers = {
referer: url,
origin: url,
"Content-Type": "text/xml; charset=UTF-8",
"Authorization": `Basic ${this.auth}`
};
for (let header in headers) {
_headers[header] = headers[header];
}
_GM_xmlhttpRequest({
method: action,
url: url,
data: data,
headers: _headers,
onload: function(d) {
let response = d.response;
if (d.status >= 400 || !response) response = "";
if (type == 'xml') {
var xml = d.responseXML;
if(xml) {
response = xml.firstChild.nextSibling ? xml.firstChild.nextSibling : xml.firstChild;
}
}
callback && callback(response);
},
onerror: function(e) {
debug(e);
callback && callback(e);
},
ontimeout: function(e) {
debug(e);
callback && callback(e);
}
});
}
}
GET(path, callback) {
return this.request('GET', null, path, 'text', callback, {});
}
PROPFIND(path, callback) {
return this.request('PROPFIND', null, path, 'xml', callback, {Depth: "1"});
}
MKCOL(path, callback) {
return this.request('MKCOL', null, path, 'text', callback, {});
}
DELETE(path, callback) {
return this.request('DELETE', null, path, 'text', callback, {});
}
PUT(path, data, callback) {
return this.request('PUT', data, path, 'text', callback, {});
}
async read(path) {
let self = this;
return new Promise((resolve) => {
self.GET(path, resolve);
});
}
async write(path, data) {
let self = this;
return new Promise((resolve) => {
self.PUT(path, data, resolve);
});
}
async rm(path) {
let self = this;
return new Promise((resolve) => {
self.DELETE(path, resolve);
});
}
}
var webDAV;
async function dataChanged(callback, override) {
if (shareEngines) return;
let _searchData = await storage.getItem("searchData");
if (_searchData) searchData = _searchData;
if (!webDAV) return callback && callback();
if (!override) {
let _lastModified = await webDAV.read("lastModified");
if (_lastModified) {
_lastModified = parseFloat(_lastModified);
}
if (_lastModified && (!searchData.lastModified || _lastModified > searchData.lastModified)) {
searchData.lastModified = _lastModified;
lastModified = searchData.lastModified;
let sitesConfig = await webDAV.read("sitesConfig.json");
if (sitesConfig) {
try {
sitesConfig = JSON.parse(sitesConfig);
searchData.sitesConfig = sitesConfig;
} catch (e) {
debug(e);
}
}
let inPageRule = await webDAV.read("inPageRule.json");
if (inPageRule) {
try {
inPageRule = JSON.parse(inPageRule);
searchData.prefConfig.inPageRule = inPageRule;
} catch (e) {
debug(e);
}
}
}
}
callback && callback();
await webDAV.write("lastModified", "" + searchData.lastModified);
await webDAV.write("sitesConfig.json", JSON.stringify(searchData.sitesConfig));
await webDAV.write("inPageRule.json", JSON.stringify(searchData.prefConfig.inPageRule));
}
var escapeHTMLPolicy;
if (_unsafeWindow.trustedTypes && _unsafeWindow.trustedTypes.createPolicy) {
escapeHTMLPolicy = _unsafeWindow.trustedTypes.createPolicy('searchjumper_default', {
createHTML: (string, sink) => string
});
}
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
if (typeof String.prototype.replaceAll != 'function') {
String.prototype.replaceAll = function(search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
}
if (typeof String.prototype.endsWith != 'function') {
String.prototype.endsWith = function(search, this_len) {
if (this_len === undefined || this_len > this.length) {
this_len = this.length;
}
return this.substring(this_len - search.length, this_len) === search;
};
}
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function(search, pos){
return this.slice(pos || 0, search.length) === search;
};
}
function getBody(doc) {
return doc.body || doc.querySelector('body');
}
function clientX(e) {
if (e.type.indexOf('touch') === 0) {
return e.changedTouches ? e.changedTouches[0].clientX : 0;
} else {
return e.clientX;
}
}
function clientY(e) {
if (e.type.indexOf('touch') === 0) {
return e.changedTouches ? e.changedTouches[0].clientY : 0;
} else {
return e.clientY;
}
}
function pageX(e) {
if (e.type.indexOf('touch') === 0) {
return e.changedTouches ? e.changedTouches[0].pageX : 0;
} else {
return e.pageX;
}
}
function pageY(e) {
if (e.type.indexOf('touch') === 0) {
return e.changedTouches ? e.changedTouches[0].pageY : 0;
} else {
return e.pageY;
}
}
function getAllElementsByXpath(xpath, contextNode, doc) {
doc = doc || document;
contextNode = contextNode || doc;
var result = [];
try {
var query = doc.evaluate(xpath, contextNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < query.snapshotLength; i++) {
var node = query.snapshotItem(i);
if (node.nodeType === 1) result.push(node);
}
} catch (err) {
debug(`Invalid xpath: ${xpath}`);
}
return result;
}
function getElementByXpath(xpath, contextNode, doc) {
doc = doc || document;
contextNode = contextNode || doc;
try {
let xpathNode = (s, d, n) => {
let result = d.evaluate(s, n, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null);
return result.singleNodeValue && result.singleNodeValue.nodeType === 1 && result.singleNodeValue;
};
let selSplit = xpath.split(" =>> ");
if (selSplit.length === 2) {
let ele = xpathNode(selSplit[0], doc, contextNode);
if (ele && ele.shadowRoot) {
return xpathNode(selSplit[1], ele.shadowRoot, ele.shadowRoot);
}
} else {
return xpathNode(xpath, doc, contextNode);
}
} catch (err) {
debug(`Invalid xpath: ${xpath}`);
return false;
}
}
function isXPath(xpath) {
if (!xpath) return false;
return /^\(*(descendant::|\.\/|\/\/|id\()/.test(xpath);
}
function getAllElements(sel, doc, contextNode) {
if (!doc) doc = document;
try {
if (!isXPath(sel)) {
return doc.querySelectorAll(sel);
}
} catch(e) {
debug(e, 'Error selector');
}
return getAllElementsByXpath(sel, contextNode, doc);
}
function getElement(sel, doc) {
if (!doc) doc = document;
try {
if (!isXPath(sel)) {
let selSplit = sel.split(" =>> ");
if (selSplit.length === 2) {
let ele = doc.querySelector(selSplit[0]);
return ele && ele.shadowRoot && ele.shadowRoot.querySelector(selSplit[1]);
} else return doc.querySelector(sel);
}
} catch(e) {
debug(e);
}
return getElementByXpath(sel, doc, doc);
}
function getElementTop(ele, targetIframe) {
var actualTop = ele.offsetTop;
var current = ele.offsetParent;
while (current) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
if (targetIframe) {
current = targetIframe;
while (current) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
try {
let currentWindow = targetIframe.contentWindow.parent;
targetIframe = currentWindow.frameElement;
while (targetIframe) {
current = targetIframe;
while (current) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
currentWindow = currentWindow.parent;
targetIframe = currentWindow.frameElement;
}
} catch(e) {}
}
return actualTop;
}
function getElementLeft(ele) {
var actualLeft = ele.offsetLeft;
var current = ele.offsetParent;
while (current) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
if (!document.isSameNode(ele.ownerDocument)) {
let iframes = document.getElementsByTagName("iframe");
for (let i = 0; i < iframes.length; i++) {
let iframe = iframes[i];
let iframeDoc;
try {
iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
} catch(e) {
break;
}
if (iframeDoc.isSameNode(ele.ownerDocument)) {
current = iframe;
while (current) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
break;
}
}
}
return actualLeft;
}
function getActiveElement(root) {
const activeEl = root.activeElement;
if (!activeEl) {
return null;
}
if (activeEl.shadowRoot) {
return getActiveElement(activeEl.shadowRoot);
} else {
return activeEl;
}
}
function isInput(ele) {
if (ele &&
((/INPUT|TEXTAREA/i.test(ele.nodeName) &&
ele.getAttribute("aria-readonly") != "true"
) ||
ele.contentEditable == 'true'
)
) {
return true;
} else {
while (ele && ele.nodeName) {
if (ele.contentEditable == 'true') return true;
if (ele.nodeName.toUpperCase() == 'BODY') {
break;
}
ele = ele.parentNode;
}
}
return false;
}
function inputActive(doc) {
let activeEl = getActiveElement(doc);
return isInput(activeEl);
}
async function waitForFontAwesome(callback) {
while (document.hidden) {
await sleep(500);
}
var retries = 100;
var text = '\uf0c8';
var checkReady = function() {
var canvas, context;
retries -= 1;
canvas = document.createElement('canvas');
canvas.width = 20;
canvas.height = 20;
context = canvas.getContext('2d', { willReadFrequently: true });
context.fillStyle = 'rgba(0,0,0,1.0)';
context.fillRect( 0, 0, 20, 20 );
context.font = '16pt FontAwesome';
context.textAlign = 'center';
context.fillStyle = 'rgba(255,255,255,1.0)';
context.fillText(text, 10, 18 );
var data = context.getImageData( 2, 10, 1, 1 ).data;
if ( data[0] == 0 && data[1] == 0 && data[2] == 0 ) {
context.font = '16pt "Font Awesome 6 Free"';
context.fillText(text, 10, 18 );
data = context.getImageData( 2, 10, 1, 1 ).data;
if ( data[0] == 0 && data[1] == 0 && data[2] == 0 ) {
if ( retries > 0 ) {
setTimeout( checkReady, 150 );
}
} else if ( typeof callback === 'function' ) {
callback();
}
} else {
if ( typeof callback === 'function' ) {
callback();
}
}
}
setTimeout( checkReady, 100 );
}
var logoBtn, searchBar, searchTypes = [], currentSite = false, disableState = false, cacheKeywords, cacheFilter, tipsStorage, localKeywords, lastSign, inPagePostParams, cacheIcon, historySites, historyType, sortTypeNames, sortSiteNames, cachePool = [], cacheFontPool = [], currentFormParams, globalInPageWords, navEnable, referrer, disableHighlight, lastHighlight, lastAddType, allPageNewMode = false, lastModified = 0, allPageBgUrl;
const logoBtnSvg = `<svg class="search-jumper-logoBtnSvg" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><title>${_GM_info.script.name}</title><path d="M.736 510.464c0-281.942 228.335-510.5 510-510.5 135.26 0 264.981 53.784 360.625 149.522 95.643 95.737 149.375 225.585 149.375 360.978 0 281.94-228.335 510.5-510 510.5-281.665 0-510-228.56-510-510.5zm510-510.5v1021m-510-510.5h1020" fill="#fefefe"/><path d="M237.44 346.624a48.64 48.64 0 1 0 97.28 0 48.64 48.64 0 1 0-97.28 0zM699.904 346.624a48.64 48.64 0 1 0 97.28 0 48.64 48.64 0 1 0-97.28 0zM423.296 759.296c-64 0-115.712-52.224-115.712-115.712 0-26.624 9.216-52.224 25.6-72.704 9.216-11.776 26.112-13.312 37.888-4.096s13.312 26.112 4.096 37.888c-9.216 11.264-13.824 24.576-13.824 38.912 0 34.304 27.648 61.952 61.952 61.952s61.952-27.648 61.952-61.952c0-4.096-.512-8.192-1.024-11.776-2.56-14.848 6.656-28.672 21.504-31.744 14.848-2.56 28.672 6.656 31.744 21.504 1.536 7.168 2.048 14.336 2.048 22.016-.512 63.488-52.224 115.712-116.224 115.712z" fill="#333"/><path d="M602.08 760.296c-64 0-115.712-52.224-115.712-115.712 0-14.848 12.288-27.136 27.136-27.136s27.136 12.288 27.136 27.136c0 34.304 27.648 61.952 61.952 61.952s61.952-27.648 61.952-61.952c0-15.36-5.632-30.208-15.872-41.472-9.728-11.264-9.216-28.16 2.048-37.888 11.264-9.728 28.16-9.216 37.888 2.048 19.456 21.504 29.696 48.64 29.696 77.824 0 62.976-52.224 115.2-116.224 115.2z" fill="#333"/><ellipse ry="58" rx="125" cy="506.284" cx="201.183" fill="#faf"/><ellipse ry="58" rx="125" cy="506.284" cx="823.183" fill="#faf"/></svg>`;
const logoBase64 = "data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ic2VhcmNoLWp1bXBlci1sb2dvQnRuU3ZnIiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0uNzM2IDUxMC40NjRjMC0yODEuOTQyIDIyOC4zMzUtNTEwLjUgNTEwLTUxMC41IDEzNS4yNiAwIDI2NC45ODEgNTMuNzg0IDM2MC42MjUgMTQ5LjUyMiA5NS42NDMgOTUuNzM3IDE0OS4zNzUgMjI1LjU4NSAxNDkuMzc1IDM2MC45NzggMCAyODEuOTQtMjI4LjMzNSA1MTAuNS01MTAgNTEwLjUtMjgxLjY2NSAwLTUxMC0yMjguNTYtNTEwLTUxMC41em01MTAtNTEwLjV2MTAyMW0tNTEwLTUxMC41aDEwMjAiIGZpbGw9IiNmZWZlZmUiLz48cGF0aCBkPSJNMjM3LjQ0IDM0Ni42MjRhNDguNjQgNDguNjQgMCAxIDAgOTcuMjggMCA0OC42NCA0OC42NCAwIDEgMC05Ny4yOCAwek02OTkuOTA0IDM0Ni42MjRhNDguNjQgNDguNjQgMCAxIDAgOTcuMjggMCA0OC42NCA0OC42NCAwIDEgMC05Ny4yOCAwek00MjMuMjk2IDc1OS4yOTZjLTY0IDAtMTE1LjcxMi01Mi4yMjQtMTE1LjcxMi0xMTUuNzEyIDAtMjYuNjI0IDkuMjE2LTUyLjIyNCAyNS42LTcyLjcwNCA5LjIxNi0xMS43NzYgMjYuMTEyLTEzLjMxMiAzNy44ODgtNC4wOTZzMTMuMzEyIDI2LjExMiA0LjA5NiAzNy44ODhjLTkuMjE2IDExLjI2NC0xMy44MjQgMjQuNTc2LTEzLjgyNCAzOC45MTIgMCAzNC4zMDQgMjcuNjQ4IDYxLjk1MiA2MS45NTIgNjEuOTUyczYxLjk1Mi0yNy42NDggNjEuOTUyLTYxLjk1MmMwLTQuMDk2LS41MTItOC4xOTItMS4wMjQtMTEuNzc2LTIuNTYtMTQuODQ4IDYuNjU2LTI4LjY3MiAyMS41MDQtMzEuNzQ0IDE0Ljg0OC0yLjU2IDI4LjY3MiA2LjY1NiAzMS43NDQgMjEuNTA0IDEuNTM2IDcuMTY4IDIuMDQ4IDE0LjMzNiAyLjA0OCAyMi4wMTYtLjUxMiA2My40ODgtNTIuMjI0IDExNS43MTItMTE2LjIyNCAxMTUuNzEyeiIgZmlsbD0iIzMzMyIvPjxwYXRoIGQ9Ik02MDIuMDggNzYwLjI5NmMtNjQgMC0xMTUuNzEyLTUyLjIyNC0xMTUuNzEyLTExNS43MTIgMC0xNC44NDggMTIuMjg4LTI3LjEzNiAyNy4xMzYtMjcuMTM2czI3LjEzNiAxMi4yODggMjcuMTM2IDI3LjEzNmMwIDM0LjMwNCAyNy42NDggNjEuOTUyIDYxLjk1MiA2MS45NTJzNjEuOTUyLTI3LjY0OCA2MS45NTItNjEuOTUyYzAtMTUuMzYtNS42MzItMzAuMjA4LTE1Ljg3Mi00MS40NzItOS43MjgtMTEuMjY0LTkuMjE2LTI4LjE2IDIuMDQ4LTM3Ljg4OCAxMS4yNjQtOS43MjggMjguMTYtOS4yMTYgMzcuODg4IDIuMDQ4IDE5LjQ1NiAyMS41MDQgMjkuNjk2IDQ4LjY0IDI5LjY5NiA3Ny44MjQgMCA2Mi45NzYtNTIuMjI0IDExNS4yLTExNi4yMjQgMTE1LjJ6IiBmaWxsPSIjMzMzIi8+PGVsbGlwc2Ugcnk9IjU4IiByeD0iMTI1IiBjeT0iNTA2LjI4NCIgY3g9IjIwMS4xODMiIGZpbGw9IiNmYWYiLz48ZWxsaXBzZSByeT0iNTgiIHJ4PSIxMjUiIGN5PSI1MDYuMjg0IiBjeD0iODIzLjE4MyIgZmlsbD0iI2ZhZiIvPjwvc3ZnPg==";
const noImgBase64 = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIxMDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNDI5LjAxMzMzMyA2NDBBMzIgMzIgMCAwIDEgMzg0IDU5NC45ODY2NjdsMzcuNzYtMzcuNzYtMjIuODI2NjY3LTIyLjYxMzMzNC0xMzUuNjggMTM1LjY4IDkwLjQ1MzMzNCA5MC40NTMzMzQgMTM1LjY4LTEzNS42OC0yMi42MTMzMzQtMjIuNjEzMzM0ek01MzQuNjEzMzMzIDM5OC45MzMzMzNsMjIuNjEzMzM0IDIyLjYxMzMzNEw1OTQuOTg2NjY3IDM4NEEzMiAzMiAwIDAgMSA2NDAgNDI5LjAxMzMzM2wtMzcuNzYgMzcuNzYgMjIuNjEzMzMzIDIyLjYxMzMzNCAxMzUuNjgtMTM1LjY4LTkwLjQ1MzMzMy05MC40NTMzMzR6IiBmaWxsPSIjNUU1QzVDIj48L3BhdGg+PHBhdGggZD0iTTUxMiAyMS4zMzMzMzNhNDkwLjY2NjY2NyA0OTAuNjY2NjY3IDAgMSAwIDQ5MC42NjY2NjcgNDkwLjY2NjY2N0E0OTAuNjY2NjY3IDQ5MC42NjY2NjcgMCAwIDAgNTEyIDIxLjMzMzMzM3ogbTMxNi44IDM1NC45ODY2NjdsLTE4MS4xMiAxODEuMTJhMzIgMzIgMCAwIDEtNDUuMjI2NjY3IDBMNTU3LjIyNjY2NyA1MTIgNTEyIDU1Ny4yMjY2NjdsNDUuMjI2NjY3IDQ1LjIyNjY2NmEzMiAzMiAwIDAgMSAwIDQ1LjIyNjY2N2wtMTgxLjEyIDE4MS4xMmEzMiAzMiAwIDAgMS00NS4yMjY2NjcgMGwtMTM1LjY4LTEzNS42OGEzMiAzMiAwIDAgMSAwLTQ1LjIyNjY2N2wxODEuMTItMTgxLjEyYTMyIDMyIDAgMCAxIDQ1LjIyNjY2NyAwTDQ2Ni43NzMzMzMgNTEyIDUxMiA0NjYuNzczMzMzbC00NS4yMjY2NjctNDUuMjI2NjY2YTMyIDMyIDAgMCAxIDAtNDUuMjI2NjY3bDE4MS4xMi0xODEuMTJhMzIgMzIgMCAwIDEgNDUuMjI2NjY3IDBsMTM1LjY4IDEzNS42OGEzMiAzMiAwIDAgMSAwIDQ1LjIyNjY2N3oiIGZpbGw9IiM1RTVDNUMiPjwvcGF0aD4KPC9zdmc+";
const closePath = '<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m165.4 618.2l-66-0.3L512 563.4l-99.3 118.4-66.1 0.3c-4.4 0-8-3.5-8-8 0-1.9 0.7-3.7 1.9-5.2l130.1-155L340.5 359c-1.2-1.5-1.9-3.3-1.9-5.2 0-4.4 3.6-8 8-8l66.1 0.3L512 464.6l99.3-118.4 66-0.3c4.4 0 8 3.5 8 8 0 1.9-0.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path>';
const wordParam = "%s[lurest]?\\b";
const wordParamReg = new RegExp(wordParam);
var targetElement, hoverElement, cssText, mainStyleEle;
var inMinMode = false;
function sloarToLunar(sy, sm, sd) {
if (!sy && !sm && !sd) {
let now = new Date();
let year = now.getFullYear(), month = now.getMonth(), date = now.getDate();
sy = now.getFullYear();
sm = now.getMonth() + 1;
sd = now.getDate();
}
let firstYear = 2000;
let firsrMonth = 2;
let firstDay = 5;
let lunarYearArr = [
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, //2050-2059
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099
0x0d520 //2100
],
lunarMonth = '正二三四五六七八九十冬臘',
lunarDay = '一二三四五六七八九十初廿',
tianGan = '甲乙丙丁戊己庚辛壬癸',
diZhi = '子丑寅卯辰巳午未申酉戌亥',
shengxiao = '鼠牛虎兔龍蛇馬羊猴雞狗豬';
function sloarToLunar(sy, sm, sd) {
sm -= 1;
let daySpan = (Date.UTC(sy, sm, sd) - Date.UTC(firstYear, firsrMonth - 1, firstDay)) / (24 * 60 * 60 * 1000) + 1;
let ly, lm, ld;
let lunarData;
for (let j = 0; j < lunarYearArr.length; j++) {
daySpan -= lunarYearDays(lunarYearArr[j]);
if (daySpan <= 0) {
ly = firstYear + j;
lunarData = lunarYearArr[j];
daySpan += lunarYearDays(lunarData);
break
}
}
if (!lunarData) return null;
for (let k = 0; k < lunarYearMonths(lunarData).length; k++) {
daySpan -= lunarYearMonths(lunarData)[k];
if (daySpan <= 0) {
if (hasLeapMonth(lunarData) && hasLeapMonth(lunarData) <= k) {
if (hasLeapMonth(lunarData) < k) {
lm = k;
} else if (hasLeapMonth(lunarData) === k) {
lm = '闰' + k;
} else {
lm = k + 1;
}
} else {
lm = k + 1;
}
daySpan += lunarYearMonths(lunarData)[k];
break
}
}
ld = daySpan;
if (hasLeapMonth(lunarData) && (typeof (lm) === 'string' && lm.indexOf('闰') > -1)) {
lm = `闰${lunarMonth[/\d/.exec(lm) - 1]}`
} else {
lm = lunarMonth[lm - 1];
}
ly = getTianGan(ly) + getDiZhi(ly);
if (ld < 11) {
ld = `${lunarDay[10]}${lunarDay[ld-1]}`
} else if (ld > 10 && ld < 20) {
ld = `${lunarDay[9]}${lunarDay[ld-11]}`
} else if (ld === 20) {
ld = `${lunarDay[1]}${lunarDay[9]}`
} else if (ld > 20 && ld < 30) {
ld = `${lunarDay[11]}${lunarDay[ld-21]}`
} else if (ld === 30) {
ld = `${lunarDay[2]}${lunarDay[9]}`
}
return {
lunarYear: ly,
lunarMonth: lm,
lunarDay: ld,
}
}
function hasLeapMonth(ly) {
if (ly & 0xf) {
return ly & 0xf
} else {
return false
}
}
function leapMonthDays(ly) {
if (hasLeapMonth(ly)) {
return (ly & 0xf0000) ? 30 : 29
} else {
return 0
}
}
function lunarYearDays(ly) {
let totalDays = 0;
for (let i = 0x8000; i > 0x8; i >>= 1) {
let monthDays = (ly & i) ? 30 : 29;
totalDays += monthDays;
}
if (hasLeapMonth(ly)) {
totalDays += leapMonthDays(ly);
}
return totalDays
}
function lunarYearMonths(ly) {
let monthArr = [];
for (let i = 0x8000; i > 0x8; i >>= 1) {
monthArr.push((ly & i) ? 30 : 29);
}
if (hasLeapMonth(ly)) {
monthArr.splice(hasLeapMonth(ly), 0, leapMonthDays(ly));
}
return monthArr
}
function getTianGan(ly) {
let tianGanKey = (ly - 3) % 10;
if (tianGanKey === 0) tianGanKey = 10;
return tianGan[tianGanKey - 1]
}
function getDiZhi(ly) {
let diZhiKey = (ly - 3) % 12;
if (diZhiKey === 0) diZhiKey = 12;
diZhiKey--;
return diZhi[diZhiKey] + ` (${shengxiao[diZhiKey]}) `
}
return sloarToLunar(sy, sm, sd)
}
class SearchBar {
constructor() {
let self = this;
this.scale = searchData.prefConfig.customSize / 100;
this.tilesZoom = searchData.prefConfig.tilesZoom / 100;
this.tipsZoom = searchData.prefConfig.tipsZoom / 100;
cssText = `
#search-jumper {
font-size: 16px;
}
#search-jumper-root {
font-size: initial;
}
#search-jumper.search-jumper-showall {
overflow-y: hidden;
pointer-events: all;
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
flex-direction: unset;
max-width: unset;
max-height: unset;
text-align: center;
top: 0;
bottom: unset;
height: 100%;
}
#search-jumper.search-jumper-showall>.search-jumper-searchBar {
display: none;
}
#search-jumper>.search-jumper-searchBar.grabbing>.search-jumper-type {
display: none!important;
}
#search-jumper.search-jumper-showall #filterSites {
background-color: #f5f5f5e0;
border: none;
height: 40px;
margin-bottom: 0;
padding: 5px;
margin: 0 10px;
box-shadow: #ddd 0px 0px 3px;
outline: none;
box-sizing: border-box;
cursor: default;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-ms-user-select: none;
position: fixed;
width: 80%;
left: calc(10% - 10px);
top: 1%;
border-radius: 20px;
pointer-events: all;
}
#search-jumper.search-jumper-showall #filterSites>input,
#search-jumper.search-jumper-showall #filterSites>textarea {
background-color: white;
color: black;
border: none;
outline: none;
box-sizing: border-box;
font-size: 20px;
cursor: text;
}
#search-jumper.search-jumper-showall #filterSites>span {
display: none;
}
#search-jumper.search-jumper-showall #search-jumper-alllist .sitelist {
visibility: visible!important;
opacity: 1!important;
pointer-events: all;
text-align: left;
position: static;
display: block!important;
height: fit-content;
max-height: calc(100vh - 130px);
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
}
#search-jumper.search-jumper-showall #search-jumper-alllist .sitelist>.sitelistCon {
opacity: 1;
}
#search-jumper.search-jumper-showall #search-jumper-alllist .sitelist>.sitelistCon>p {
pointer-events: all;
cursor: pointer;
margin: 0 auto;
}
#search-jumper.search-jumper-showall.searching #search-jumper-alllist .sitelist>.sitelistCon a {
display: flex!important;
}
#search-jumper.search-jumper-showall #search-jumper-alllist .sitelist:hover {
z-index: 1;
}
#search-jumper.search-jumper-showall.search-jumper-searchBarCon {
-ms-overflow-style: unset;
scrollbar-width: unset;
overflow: hidden;
}
#search-jumper-alllist {
display: none;
top: 101px;
position: absolute;
width: 100%;
overflow-x: auto;
overflow-y: hidden;
height: calc(100% - 101px);
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
}
#search-jumper-alllist>.search-jumper-btn {
position: fixed;
top: 1%;
right: 10%;
filter: drop-shadow(1px 1px 3px #00000060);
cursor: pointer;
pointer-events: all;
z-index: 1;
width: 32px;
height: 32px;
}
#search-jumper-alllist>.search-jumper-btn>svg {
cursor: pointer;
width: 32px;
height: 32px;
}
.search-jumper-showallBg {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
transform: translateZ(0);
${searchData.prefConfig.noAni ? "background-color: rgba(0, 0, 0, 0.1);" : (
"background-color: rgba(0, 0, 0, 0.1);" +
//"backdrop-filter: blur(5px);" +
//"-webkit-backdrop-filter: blur(5px);" +
"transition:background-color .6s ease;")}
}
#search-jumper.search-jumper-showall>#search-jumper-alllist:hover~.search-jumper-showallBg {
background-color: rgba(0, 0, 0, 0.8);
}
#search-jumper.search-jumper-showall>.search-jumper-showallBg {
display: block;
}
#search-jumper>.groupTab {
position: fixed;
background: #ffffffee !important;
left: 0;
top: 0;
overflow: hidden;
height: 100%;
overflow: auto;
scrollbar-width: none;
padding: 20px 0;
box-sizing: border-box;
display: none;
z-index: 1;
}
#search-jumper.search-jumper-showall>#search-jumper-alllist.new-mode+.groupTab {
display: block;
}
#search-jumper.search-jumper-showall>.groupTab::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
#search-jumper.search-jumper-showall>.groupTab>span {
display: block;
width: ${42 * this.scale}px;
transition: all 0.25s ease;
cursor: pointer;
}
#search-jumper.search-jumper-showall>.groupTab>span>span.search-jumper-word {
opacity: 0.8;
}
#search-jumper.search-jumper-showall>.groupTab:hover>span {
width: ${42 * this.scale + 150}px;
}
#search-jumper.search-jumper-showall>.groupTab>span:hover{
background: #f5f7fa !important;
}
#search-jumper.search-jumper-showall>.groupTab:hover>span::after {
content: attr(data-type);
color: #6b6e74;
position: absolute;
margin-top: -${21 * this.scale + 10}px;
left: ${42 * this.scale + 5}px;
white-space: nowrap;
font-weight: bold;
}
.search-jumper-historylistcon {
display: flex;
position: fixed;
width: 100%;
max-width: 100%;
overflow: auto;
justify-content: center;
left: 0;
top: 60px;
background: #ffffffee;
border-bottom: 1px solid #ddd;
pointer-events: all;
min-height: 40px;
-ms-overflow-style: unset;
scrollbar-width: unset;
}
.search-jumper-historylistcon::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
.search-jumper-historylist {
display: flex;
max-width: 100%;
}
#search-jumper.search-jumper-showall #search-jumper-alllist {
display: block;
}
#search-jumper-alllist>.sitelistBox {
display: flex;
min-width: 100%;
justify-content: center;
width: fit-content;
min-height: 100%;
position: initial;
transition: all 0.3s ease;
}
#search-jumper-alllist>.timeInAll,
#search-jumper-alllist>.dayInAll {
position: fixed;
bottom: 0;
line-height: 1.5;
color: white;
opacity: 0.45;
font-weight: bold;
font-family: Arial,sans-serif,微软雅黑;
overflow-wrap: normal;
white-space: nowrap;
margin: 20px;
pointer-events: none;
text-shadow: 0 0 5px black;
background-image: initial;
}
#search-jumper-alllist>.dayInAll {
left: 50px;
font-size: ${lang.indexOf("zh") == 0 ? '1.5' : '2'}vw;
}
#search-jumper-alllist>.timeInAll {
right: 50px;
font-size: 2vw;
}
#search-jumper-alllist>.modeSwitch {
position: fixed;
top: 5px;
right: 5px;
width: 45px;
height: 45px;
border-radius: 50%;
box-shadow: 0px 0px 5px 0px #7a7a7a;
cursor: pointer;
transition: transform 0.25s ease;
}
#search-jumper-alllist>.modeSwitch>* {
pointer-events: none;
}
#search-jumper-alllist>.modeSwitch:hover {
transform: scale(1.1);
}
#search-jumper-alllist.new-mode {
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: none;
}
#search-jumper-alllist.new-mode>.sitelistBox {
flex-wrap: wrap;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 78%;
max-height: unset;
}
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist>.sitelistCon {
display: flex;
flex-wrap: wrap;
padding: 0;
}
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist>.sitelistCon>p {
text-align: left;
font-size: large;
padding: 10px 30px;
display: table-caption;
width: 100%;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a {
width: 240px;
height: 100px;
display: block!important;
padding: 10px 8%;
box-sizing: border-box;
}
#search-jumper.search-jumper-showall.searching #search-jumper-alllist.new-mode .sitelist>.sitelistCon a {
display: block!important;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist>.sitelistCon>div {
padding: 0 10px;
border-radius: 5px;
transition: transform 0.25s ease, box-shadow 0.25s ease;
box-shadow: 0 0 #0000, 0 0 #0000, 0 1px 3px #9e9e9e1a, 0 1px 2px -1px #9e9e9e1a;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist>.sitelistCon>div:hover {
transform: translateY(-6px);
-webkit-transform: translateY(-6px);
-moz-transform: translateY(-6px);
box-shadow: 0 0 #0000, 0 0 #0000, 0 1px 3px #0000001a, 0 1px 2px -1px #0000001a;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist>.sitelistCon>div:before {
content: attr(title);
margin-left: 41px;
color: #abb0bd;
font-size: 12px;
height: 3em;
line-height: 1.5em;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-left: 62px;
margin-top: 35px;
width: 185px;
position: absolute;
pointer-events: none;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a>img {
width: 48px;
height: 48px;
float: left;
margin-left: -20px;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a>p {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: block;
font-size: 16px;
height: 21px;
line-height: 21px;
margin-bottom: 8px;
margin-top: 0px;
margin-left: 40px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#search-jumper .sitelist a+p {
display: none;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a+p {
position: absolute;
margin-top: -28px;
color: white;
width: 250px;
max-width: calc(100% - 20px);
display: flex;
justify-content: space-evenly;
overflow: hidden;
opacity: 0;
transition: .3s;
border-top: 1px solid rgba(136,136,136,.2);
padding-top: 3px;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a+p>span {
flex-shrink: 0;
font-size: 14px;
padding: 2px 6px;
background: rgb(160 160 160 / 10%);
color: #888;
border-radius: 10px;
transition: .3s;
cursor: pointer;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a+p>span:hover {
color: white;
background: rgb(160 160 160 / 30%);
}
#search-jumper #search-jumper-alllist.new-mode .sitelistCon>div:hover>p {
opacity: 1;
}
#search-jumper #search-jumper-alllist.showbg>.inputGroup,
#search-jumper #search-jumper-alllist.showbg>.search-jumper-btn,
#search-jumper #search-jumper-alllist.showbg>.search-jumper-historylistcon,
#search-jumper #search-jumper-alllist.showbg+.groupTab,
#search-jumper #search-jumper-alllist.showbg>.sitelistBox {
transition: .3s;
opacity: 0;
}
#search-jumper.search-jumper-showall>#search-jumper-alllist.showbg:hover~.search-jumper-showallBg {
background: unset;
}
.search-jumper-searchBarCon {
all: unset;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2147483646;
pointer-events: none;
text-align: center;
overflow: scroll;
display: block;
-ms-overflow-style: none;
scrollbar-width: none;
box-sizing: border-box;
z-index: 2147483647;
user-select: none;
}
.search-jumper-searchBar {
z-index: 2147483647;
overflow-wrap: break-word;
background: #505050cc;
border-radius: ${this.scale * 21}px!important;
border: 1px solid #b3b3b3;
display: inline-flex;
pointer-events: all;
margin-top: -${this.scale * 25}px;
vertical-align: top;
${searchData.prefConfig.noAni ? "" : "opacity: 0.8;"}
${searchData.prefConfig.noAni ? "" : "transition:margin-top 1s ease, margin-left 1s, right 1s, opacity 1s, transform 1s;"}
user-select: none;
text-align: center;
position: relative;
box-sizing: border-box;
}
.hideAll>.search-jumper-searchBar {
margin-top: -${this.scale * 40}px;
}
.search-jumper-searchBarCon:not(.search-jumper-showall)::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
.search-jumper-searchBarCon.search-jumper-scroll {
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
}
.search-jumper-searchBarCon.search-jumper-scroll>.search-jumper-searchBar {
pointer-events: all;
}
.search-jumper-scroll.search-jumper-bottom {
overflow-y: hidden;
}
.search-jumper-scroll.search-jumper-right>.search-jumper-searchBar {
position: absolute !important;
top: 0;
}
.search-jumper-scroll.search-jumper-bottom>.search-jumper-searchBar {
margin-top: 0px;
}
.search-jumper-scroll.search-jumper-bottom>.search-jumper-searchBar:hover,
.search-jumper-scroll.search-jumper-bottom>.search-jumper-searchBar.initShow,
.resizePage.search-jumper-scroll.search-jumper-bottom>.search-jumper-searchBar,
.search-jumper-scroll.search-jumper-bottom.funcKeyCall>.search-jumper-searchBar,
#search-jumper.in-input.search-jumper-scroll.search-jumper-bottom>.search-jumper-searchBar {
margin-top: 0px;
}
.search-jumper-searchBar:hover {
margin-top: 0;
opacity: 1;
${searchData.prefConfig.noAni ? "" : "transition:margin-top 0.1s ease, margin-left 0.1s, right 0.1s, opacity 0.1s, transform 0.1s;"}
}
.search-jumper-searchBar.initShow,
.resizePage>.search-jumper-searchBar {
margin-top: 0;
${searchData.prefConfig.noAni ? "" : "transition:margin-top 0.25s ease, margin-left 0.25s, right 0.25s, opacity 0.25s, transform 0.25s;"}
}
.funcKeyCall>.search-jumper-searchBar.initShow {
${searchData.prefConfig.noAni ? "" : "transition:opacity 0.15s ease-out;"}
}
#search-jumper.funcKeyCall {
overflow: visible;
position: absolute;
max-width: 100%;
width: 100%;
top: 0;
}
.funcKeyCall>.search-jumper-searchBar {
position: absolute!important;
background: none;
border: none;
max-width: unset!important;
margin: unset;
${searchData.prefConfig.minPopup && !searchData.prefConfig.noAni ? 'transition: transform 0.25s ease;' : ''}
${searchData.prefConfig.minPopup ? 'transform: scale(0.7);' : ''}
}
.funcKeyCall>.search-jumper-searchBar:hover {
${searchData.prefConfig.minPopup ? 'transform: scale(1);' : ''}
}
.in-input>.search-jumper-searchBar,
.funcKeyCall>.search-jumper-searchBar {
opacity: 1;
display: inline-flex!important;
}
.in-input.in-find {
pointer-events: none;
}
.in-input.in-find>.searchJumperNavBar,
.in-input.in-find>.search-jumper-input {
pointer-events: all;
}
.in-input.in-find>.search-jumper-searchBar, .in-input>.rectSelecting.search-jumper-searchBar {
opacity: 0!important;
pointer-events: none;
transition: none;
}
.in-input.in-find>.search-jumper-searchBar:hover {
opacity: 1!important;
}
.in-input.in-find>.search-jumper-input {
opacity: 0.6;
transition:opacity 0.25s ease;
}
.in-input.in-find>.search-jumper-input:hover,
.in-input.in-find>.search-jumper-input.active {
opacity: 1;
}
.funcKeyCall>.search-jumper-searchBar {
flex-direction: column;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type {
height: ${searchData.prefConfig.minPopup ? (24 * this.tilesZoom + 'px') : 'auto'}!important;
max-width: ${searchData.prefConfig.minPopup ? (24 * this.tilesZoom) : (40 * (searchData.prefConfig.numPerLine || 7) * this.tilesZoom)}px!important;
width: auto!important;
width: max-content!important;
max-height: ${108 * this.tilesZoom + 10}px;
flex-wrap: wrap!important;
flex-direction: row;
padding: 5px;
box-shadow: #000000 0px 0px 10px;
overflow: auto;
scrollbar-width: none;
transition: none;
background: #d0d0d0d0;
box-sizing: content-box;
}
${searchData.prefConfig.hideTileType ? `
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:before {
content: attr(data-type);
position: absolute;
background: #ffffffd0;
color: black;
margin-top: -${22 * this.tilesZoom}px;
line-height: 1.2;
font-size: ${13 * this.tilesZoom}px;
font-weight: bold;
border-radius: ${20 * this.tilesZoom}px;
padding: 3px 6px;
box-shadow: #000000 0px 0px 10px;
opacity: 0;
pointer-events: none;
transition: all 0.5s ease;
left: 50%;
transform: translate(-50%, 0);
z-index: 1;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>span.search-jumper-btn:first-child {
display: none;
}
#search-jumper.funcKeyCall .search-jumper-type.search-jumper-open.not-expand>a:nth-of-type(${(searchData.prefConfig.expandTypeLength || 12)+1}) {
display: grid!important;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:hover:before {
opacity: 1;
}
` : ''}
#search-jumper>.search-jumper-searchBar>.search-jumper-type.search-jumper-open {
overflow: visible;
}
#search-jumper>.search-jumper-searchBar>.search-jumper-type.search-jumper-open.search-jumper-move:hover {
width: fit-content!important;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type.search-jumper-open:not(.not-expand) {
overflow: auto;
}
#search-jumper.search-jumper-left>.search-jumper-searchBar>.search-jumper-type.search-jumper-open.search-jumper-move:hover,
#search-jumper.search-jumper-right>.search-jumper-searchBar>.search-jumper-type.search-jumper-open.search-jumper-move:hover {
width: 100%!important;
height: fit-content!important;
}
#search-jumper.search-jumper-bottom>.search-jumper-searchBar>.search-jumper-type.search-jumper-open.search-jumper-move:hover {
align-items: flex-end;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type.search-jumper-open {
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
overflow: auto;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist {
border-radius: 10px;
box-shadow: 0px 0px 10px 0px #7a7a7a;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist>.sitelistCon {
margin: 0;
padding: 5px;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist>.sitelistCon>div {
display: none;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist>.sitelistCon>div:nth-of-type(${searchData.prefConfig.expandTypeLength || 12})~div {
display: block;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist>.sitelistCon>p {
display: none;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.sitelist>.sitelistCon a>img {
width: 20px;
height: 20px;
}
${searchData.prefConfig.minPopup && !searchData.prefConfig.hideTileType ? `
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>a.search-jumper-btn,
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>.searchJumperExpand {
display: none;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:hover>a.search-jumper-btn,
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:hover>.searchJumperExpand {
display: grid;
}
` : ''}
${searchData.prefConfig.minPopup == 2 ? `
.funcKeyCall:not(.targetInput)>.search-jumper-searchBar {
transform: scale(1);
}
#search-jumper.funcKeyCall:not(.targetInput)>.search-jumper-searchBar>.search-jumper-type {
height: auto!important;
width: auto!important;
width: max-content!important;
max-width: ${40 * (searchData.prefConfig.numPerLine || 7) * this.tilesZoom}px!important;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type>a.search-jumper-btn {
display: grid;
}
#search-jumper.funcKeyCall.targetInput>.search-jumper-searchBar>.search-jumper-type>a.search-jumper-btn {
display: none;
}
#search-jumper.funcKeyCall.targetInput>.search-jumper-searchBar>.search-jumper-type:hover>a.search-jumper-btn {
display: grid;
}
` : ''}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:hover {
height: auto!important;
width: auto!important;
width: max-content!important;
max-width: ${40 * (searchData.prefConfig.numPerLine || 7) * this.tilesZoom}px!important;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-type::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
.search-jumper-left,
.search-jumper-left .search-jumper-type,
.search-jumper-left>.search-jumper-searchBar,
.search-jumper-right,
.search-jumper-right .search-jumper-type,
.search-jumper-right>.search-jumper-searchBar {
flex-direction: column;
max-width: ${42 * this.scale}px;
max-height: unset;
}
.search-jumper-left .search-jumper-type,
.search-jumper-right .search-jumper-type {
max-width: ${40 * this.scale}px;
}
.search-jumper-left,
.search-jumper-left>.search-jumper-searchBar,
.search-jumper-right,
.search-jumper-right>.search-jumper-searchBar {
max-width: 100%;
}
.search-jumper-searchBar.grabbing {
max-width: ${42 * this.scale}px;
}
.search-jumper-right .search-jumper-type {
align-items: flex-end;
}
.search-jumper-left {
height: 100%;
text-align: initial;
}
.search-jumper-left:not(.search-jumper-showall) {
width: initial;
width: -webkit-fill-available;
}
.search-jumper-right {
left: unset;
right: 0;
height: 100%;
}
.searchJumperExpand {
opacity: 0.8;
}
.searchJumperExpand:hover {
opacity: 1;
}
.searchJumperExpand>svg {
transform: rotate(-90deg);
border-radius: 20px;
filter: drop-shadow(0px 0px 2px black);
width: unset;
height: unset;
color: black;
fill: black;
}
.search-jumper-type.search-jumper-open>span.search-jumper-word,
#search-jumper.funcKeyCall .search-jumper-type>span.search-jumper-word {
filter: drop-shadow(0px 0px 2px black);
}
.search-jumper-left .searchJumperExpand>svg,
.search-jumper-right .searchJumperExpand>svg {
transform: unset;
}
.search-jumper-bottom {
top: unset;
bottom: 0;
height: ${this.scale * 42 * 2}px;
max-height: ${this.scale * 43 * 2}px;
overflow-y: hidden;
}
.search-jumper-left>.search-jumper-searchBar {
width: fit-content;
margin-top: 0;
margin-left: -${this.scale * 20}px;
}
.hideAll.search-jumper-left>.search-jumper-searchBar {
margin-left: -${this.scale * 40}px;
}
.search-jumper-right>.search-jumper-searchBar {
margin-top: 0;
right: -${this.scale * 20}px;
position: fixed;
}
.hideAll.search-jumper-right>.search-jumper-searchBar {
right: -${this.scale * 40}px;
}
.search-jumper-left>.search-jumper-searchBar:hover,
.search-jumper-left>.search-jumper-searchBar.initShow,
.resizePage.search-jumper-left>.search-jumper-searchBar,
.search-jumper-left.funcKeyCall>.search-jumper-searchBar,
#search-jumper.in-input.search-jumper-left>.search-jumper-searchBar {
margin-top: unset;
margin-left: 0;
opacity: 1;
}
.search-jumper-right>.search-jumper-searchBar:hover,
.search-jumper-right>.search-jumper-searchBar.initShow,
.resizePage.search-jumper-right>.search-jumper-searchBar,
.search-jumper-right.funcKeyCall>.search-jumper-searchBar,
#search-jumper.in-input.search-jumper-right>.search-jumper-searchBar {
margin-top: unset;
right: 0;
opacity: 1;
}
.search-jumper-bottom>.search-jumper-searchBar {
position: relative;
margin-top: 0px;
top: ${this.scale * 42}px;
}
.hideAll.search-jumper-bottom>.search-jumper-searchBar {
opacity: 0;
}
.search-jumper-bottom>.search-jumper-searchBar:hover,
.search-jumper-bottom>.search-jumper-searchBar.initShow,
.resizePage.search-jumper-bottom>.search-jumper-searchBar,
.search-jumper-bottom.funcKeyCall>.search-jumper-searchBar,
#search-jumper.in-input.search-jumper-bottom>.search-jumper-searchBar {
margin-top: 0px;
opacity: 1;
}
.search-jumper-btn {
position: relative;
display: grid;
--scale: 1;
padding: ${1 * this.scale}px!important;
margin: ${3 * this.scale}px!important;
cursor: pointer;
box-sizing: content-box;
${searchData.prefConfig.noAni ? "" : "transition:margin-left 0.25s ease, width 0.25s, height 0.25s, transform 0.25s, background 0.25s;"}
width: calc(${32 * this.scale}px * var(--scale));
height: calc(${32 * this.scale}px * var(--scale));
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-decoration:none;
min-width: ${32 * this.scale}px;
min-height: ${32 * this.scale}px;
text-align: center;
background-image: initial;
filter: drop-shadow(1px 1px 3px #00000030);
}
#search-jumper.funcKeyCall .search-jumper-btn {
padding: ${1 * this.tilesZoom}px!important;
margin: ${3 * this.tilesZoom}px!important;
width: ${32 * this.tilesZoom}px;
height: ${32 * this.tilesZoom}px;
min-width: ${32 * this.tilesZoom}px;
min-height: ${32 * this.tilesZoom}px;
border-radius: ${10 * this.tilesZoom}px;
filter: drop-shadow(1px 1px 3px #00000060);
}
#search-jumper.funcKeyCall a.search-jumper-btn {
background: #f7f7f7a0;
}
a.search-jumper-btn:not(.search-jumper-word)>span {
position: absolute;
text-align: center;
width: 100%;
bottom: 0px;
color: black!important;
font-family: Arial, sans-serif;
text-shadow: 0 1px white, 1px 0 white, -1px 0 white, 0 -1px white;
font-size: ${12 * this.scale}px;
font-weight: normal;
opacity: 0.8;
}
#search-jumper.funcKeyCall a.search-jumper-btn:not(.search-jumper-word)>span {
font-size: ${12 * this.tilesZoom}px;
}
.search-jumper-type>a.search-jumper-btn.historySite {
box-shadow: 0px 0px 8px 0px #00000080;
}
.search-jumper-btn>img {
width: ${32 * this.scale}px;
height: ${32 * this.scale}px;
border: unset;
}
#search-jumper.funcKeyCall .search-jumper-btn>img {
width: ${32 * this.tilesZoom}px;
height: ${32 * this.tilesZoom}px;
border-radius: unset;
}
.search-jumper-btn>b {
line-height: ${32 * this.scale}px;
font-size: ${14 * this.scale}px;
letter-spacing: 0;
color: white;
opacity: 0.9;
text-shadow: 0 0 1px #d9d9d9cc;
}
#search-jumper.funcKeyCall .search-jumper-btn>b {
line-height: ${32 * this.tilesZoom}px;
font-size: ${14 * this.tilesZoom}px;
}
.search-jumper-btn:hover>b {
opacity: 1;
}
.search-jumper-btn>div {
position: absolute;
width: 100%;
height: 100%;
line-height: ${32 * this.scale}px;
background: black;
border-radius: ${20 * this.scale}px;
font-size: ${30 * this.scale}px;
color: wheat;
display: none;
}
#search-jumper.funcKeyCall .search-jumper-btn>div {
line-height: ${32 * this.tilesZoom}px;
border-radius: ${20 * this.tilesZoom}px;
font-size: ${30 * this.tilesZoom}px;
}
.search-jumper-isInPage .search-jumper-btn>div,
.search-jumper-isTargetImg .search-jumper-btn>div,
.search-jumper-isTargetAudio .search-jumper-btn>div,
.search-jumper-isTargetVideo .search-jumper-btn>div,
.search-jumper-isTargetLink .search-jumper-btn>div,
.search-jumper-isTargetPage .search-jumper-btn>div {
animation-name: changeOpacity;
animation-duration: 2s;
animation-iteration-count: 3;
animation-delay: 0.1s;
display: block;
opacity: 0;
}
@keyframes changeOpacity {
0% {opacity: 0;}
10% {opacity: 0;}
50% {opacity: 0.75;}
80% {opacity: 0;}
100% {opacity: 0;}
}
@-webkit-keyframes loader-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes loader-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.search-jumper-tips>.loader {
border-width: 5px;
border-style: solid;
border-color: gainsboro gainsboro dodgerblue gainsboro;
border-radius: 50%;
display: block;
width: 25px;
float: left;
height: 25px;
margin-right: 10px;
margin-top: 5px;
-webkit-animation: loader-rotate 1.5s linear infinite;
animation: loader-rotate 1.5s linear infinite;
}
.search-jumper-tips>.loader+font {
font-size: 25px;
line-height: 40px;
}
.search-jumper-tips>div {
font-size: initial;
line-height: initial;
font-weight: normal;
padding: 5px;
cursor: initial;
}
.search-jumper-tips>div [data-read],
.search-jumper-tips>div [data-close],
.search-jumper-tips>div [data-paste],
.search-jumper-tips>div [data-copy] {
cursor: pointer;
}
.search-jumper-tips>div [data-search] {
cursor: help;
}
.search-jumper-tips>div [data-close] {
position: absolute;
top: 0px;
right: 0px;
width: 20px;
height: 20px;
color: white;
transition:all 0.2s ease;
}
.search-jumper-tips>div [data-close]:hover {
color: red;
}
.search-jumper-tips>div [data-read] {
color: #f9690e;
}
.search-jumper-tips>div [data-drag] {
cursor: grab;
}
.search-jumper-tips.draging {
cursor: grabbing;
transition: none;
}
.search-jumper-tips.draging * {
pointer-events: none;
}
.search-jumper-logoBtnSvg {
width: ${32 * this.scale}px;
height: ${32 * this.scale}px;
overflow: hidden;
vertical-align: top;
cursor: grab;
}
#search-jumper.funcKeyCall .search-jumper-logoBtnSvg {
height: ${32 * this.tilesZoom}px;
width: ${32 * this.tilesZoom}px;
}
.search-jumper-type.search-jumper-targetImg,
.search-jumper-type.search-jumper-targetAudio,
.search-jumper-type.search-jumper-targetVideo,
.search-jumper-type.search-jumper-targetLink,
.search-jumper-type.search-jumper-targetPage,
.search-jumper-isTargetImg>.search-jumper-type,
.search-jumper-isTargetAudio>.search-jumper-type,
.search-jumper-isTargetVideo>.search-jumper-type,
.search-jumper-isTargetLink>.search-jumper-type,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetImg,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetAudio,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetVideo,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetLink,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetPage,
.search-jumper-searchBar.search-jumper-isTargetImg:hover>.search-jumper-type,
.search-jumper-searchBar.search-jumper-isTargetAudio:hover>.search-jumper-type,
.search-jumper-searchBar.search-jumper-isTargetVideo:hover>.search-jumper-type,
.search-jumper-searchBar.search-jumper-isTargetLink:hover>.search-jumper-type {
display: none;
}
#search-jumper.in-input .search-jumper-type.search-jumper-open {
width: auto!important;
height: auto!important;
}
#search-jumper.in-input .sitelistCon>div:not(.input-hide)>a {
display: flex!important;
}
#search-jumper .input-hide,
#search-jumper.search-jumper-showall #search-jumper-alllist .sitelist.input-hide {
display: none!important;
}
#search-jumper.in-input .search-jumper-type:not(.input-hide) {
display: inline-flex!important;
flex-wrap: nowrap!important;
}
#search-jumper.in-input .search-jumper-btn:not(.input-hide) {
display: grid!important;
}
#search-jumper>.search-jumper-searchBar>.search-jumper-logo {
display: inline-flex;
background: unset;
padding: 0px;
}
#search-jumper.funcKeyCall>.search-jumper-searchBar>.search-jumper-logo {
display: none;
}
.search-jumper-searchBar>.search-jumper-type.search-jumper-targetAll,
.search-jumper-searchBar:hover>.search-jumper-type.search-jumper-targetAll {
display: inline-flex;
}
.search-jumper-isInPage>.search-jumper-type.search-jumper-needInPage,
.search-jumper-isTargetImg>.search-jumper-type.search-jumper-targetImg,
.search-jumper-isTargetAudio>.search-jumper-type.search-jumper-targetAudio,
.search-jumper-isTargetVideo>.search-jumper-type.search-jumper-targetVideo,
.search-jumper-isTargetLink>.search-jumper-type.search-jumper-targetLink,
.search-jumper-isTargetPage>.search-jumper-type,
.search-jumper-searchBar.search-jumper-isInPage:hover>.search-jumper-type.search-jumper-needInPage,
.search-jumper-searchBar.search-jumper-isTargetImg:hover>.search-jumper-type.search-jumper-targetImg,
.search-jumper-searchBar.search-jumper-isTargetAudio:hover>.search-jumper-type.search-jumper-targetAudio,
.search-jumper-searchBar.search-jumper-isTargetVideo:hover>.search-jumper-type.search-jumper-targetVideo,
.search-jumper-searchBar.search-jumper-isTargetLink:hover>.search-jumper-type.search-jumper-targetLink,
.search-jumper-searchBar.search-jumper-isTargetPage:hover>.search-jumper-type.search-jumper-targetPage,
.search-jumper-searchBar.search-jumper-isTargetPage:hover>.search-jumper-type {
display: inline-flex;
}
.search-jumper-type,
.search-jumper-logo {
display: inline-flex;
box-sizing: border-box;
background: #d0d0d0;
border-radius: ${20 * this.scale}px!important;
overflow: hidden;
padding: 0.2px;
height: ${40 * this.scale}px;
width: ${40 * this.scale}px;
max-height: ${this.scale * 40}px;
min-height: ${this.scale * 40}px;
min-width: ${this.scale * 40}px;
${searchData.prefConfig.noAni ? "" : `transition:width ${searchData.prefConfig.typeOpenTime}ms ease, height ${searchData.prefConfig.typeOpenTime}ms;`}
}
#search-jumper.funcKeyCall .search-jumper-type,
#search-jumper.funcKeyCall .search-jumper-logo {
border-radius: ${20 * this.tilesZoom}px!important;
height: ${40 * this.tilesZoom}px;
width: ${40 * this.tilesZoom}px;
max-height: ${this.tilesZoom * 40}px;
min-height: ${this.tilesZoom * 40}px;
min-width: ${this.tilesZoom * 40}px;
}
.search-jumper-right>.searchJumperNavBar {
right: unset;
left: 0;
}
.search-jumper-right>.searchJumperNavBar>#navMarks+div.navPointer {
right: unset;
left: 20px;
transform: rotate(180deg);
}
.search-jumper-bottom>.search-jumper-input {
bottom: unset;
top: 80px;
}
#search-jumper .search-jumper-type.search-jumper-open.not-expand>a:nth-of-type(${searchData.prefConfig.expandTypeLength || 12})~a {
display: none!important;
}
#search-jumper .sitelist {
position: fixed;
text-align: left;
background: #00000000;
max-height: calc(100vh - ${this.scale * 42}px);
overflow: scroll;
border: 0;
pointer-events: none;
opacity: 0;
${searchData.prefConfig.noAni ? "" : "transition:opacity 0.25s ease;"}
scrollbar-width: none;
box-sizing: content-box;
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
z-index: 1;
}
#search-jumper .search-jumper-type:hover>.sitelist {
pointer-events: all;
opacity: 1;
}
#search-jumper .sitelist>.sitelistCon {
margin: 10px;
border-radius: 10px;
box-shadow: 0px 0px 10px 0px #7a7a7a;
padding: 0 0 10px 0;
background: #ffffffee;
opacity: 1;
border: 0;
}
#search-jumper .sitelist>.sitelistCon:hover {
opacity: 1;
}
#search-jumper .sitelist::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
#search-jumper .sitelist>.sitelistCon>div {
padding: 0 10px;
}
#search-jumper .sitelist>.sitelistCon>div:hover {
background: #f5f7fa;
}
#search-jumper .sitelist a {
display: flex;
align-items: center;
text-decoration: none;
cursor: pointer;
}
#search-jumper .sitelist a>img {
width: 20px;
height: 20px;
margin-right: 10px;
margin-top: unset;
max-width: unset;
-moz-transition: transform 0.3s ease;
-webkit-transition: transform 0.3s ease;
transition: transform 0.3s ease;
}
#search-jumper .sitelist a>p {
display: inline-block;
font-size: 15px;
font-family: Arial, sans-serif;
line-height: 25px;
margin: 5px auto;
color: #6b6e74;
flex: 1;
text-align: left;
white-space: nowrap;
transform-origin: left;
-moz-transition: transform 0.3s ease;
-webkit-transition: transform 0.3s ease;
transition: transform 0.3s ease;
}
#search-jumper .sitelist a.dragTarget>img {
-webkit-transform:scale(1.5);
-moz-transform:scale(1.5);
transform:scale(1.5);
}
#search-jumper .sitelist a.dragTarget>p {
-webkit-transform:scale(1.2);
-moz-transform:scale(1.2);
transform: scale(1.2);
}
#search-jumper .sitelist a * {
pointer-events: none;
}
#search-jumper .sitelist>.sitelistCon>p {
color: #565656;
text-align: center;
font-size: 16px;
font-family: Arial, sans-serif;
font-weight: bold;
background: #f6f6f6;
border-radius: 10px 10px 0 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 3px 10px;
position: sticky;
top: 0;
pointer-events: none;
margin: -1px 0 0 0;
}
.search-jumper-searchBar.disable-pointer>.search-jumper-type {
pointer-events: none;
}
.search-jumper-word {
background: black;
color: #ffffff!important;
font-family: Arial, sans-serif;
font-weight: 500;
font-size: ${13 * this.scale}px;
line-height: calc(${32 * this.scale}px * var(--scale));
min-width: ${32 * this.scale}px;
min-height: ${32 * this.scale}px;
letter-spacing: 0px;
text-shadow: unset;
text-decoration: none;
}
span.search-jumper-word {
border-radius: ${20 * this.scale}px!important;
}
a.search-jumper-word>span {
border-radius: 50%!important;
min-width: ${32 * this.tilesZoom}px;
min-height: ${32 * this.tilesZoom}px;
background: white;
}
#search-jumper.funcKeyCall .search-jumper-word {
border-radius: ${10 * this.tilesZoom}px!important;
font-size: ${14 * this.tilesZoom}px;
line-height: ${32 * this.tilesZoom}px;
width: ${32 * this.tilesZoom}px;
height: ${32 * this.tilesZoom}px;
min-width: ${32 * this.tilesZoom}px;
min-height: ${32 * this.tilesZoom}px;
}
#search-jumper.funcKeyCall .search-jumper-word>span {
background: unset;
}
.search-jumper-word:hover {
font-weight: bold;
text-shadow: 0px 0px 5px #d0d0d0;
}
a.search-jumper-word {
color: #111111!important;
background: unset;
}
.funcKeyCall a.search-jumper-word {
background: #f7f7f7a0;
}
a.search-jumper-word>span {
color: #222!important;
border-radius: 20px;
line-height: unset;
text-align: center;
text-shadow: 0 0 0.7px #787878dd;
background-image: initial;
}
.search-jumper-type img {
width: 100%;
height: 100%;
margin-top: unset;
}
#search-jumper.funcKeyCall .search-jumper-type img {
width: ${32 * this.tilesZoom}px;
height: ${32 * this.tilesZoom}px;
}
.funcKeyCall>.search-jumper-tips {
position: absolute;
}
.search-jumper-tips {
z-index: 2147483647;
pointer-events: none;
position: fixed;
font-size: ${35 * this.tipsZoom}px;
background: #f5f5f5f0;
border-radius: ${10 * this.tipsZoom}px!important;
padding: 6px;
box-shadow: 0px 0px 10px 0px #000;
font-weight: bold;
${searchData.prefConfig.noAni ? "" : "transition: all 0.2s ease;"}
color: black;
white-space: normal;
max-width: 640px;
max-width: min(80vw,640px);
width: max-content;
line-height: ${35 * this.tipsZoom}px;
word-break: break-all;
text-align: center;
box-sizing: content-box;
overflow: hidden;
font-family: Roboto,arial,sans-serif;
cursor: grab;
max-height: 80vh;
overscroll-behavior: contain;
-ms-scroll-chaining: contain;
}
.search-jumper-tips:hover {
overflow: auto;
}
.search-jumper-tips * {
max-width: 640px;
max-width: min(80vw,640px);
margin: auto;
}
.search-jumper-tips .markdown {
white-space: pre-wrap;
line-height: 1.2;
text-align: initial;
margin: 10px;
display: block;
user-select: text;
cursor: auto;
}
.search-jumper-tips iframe {
border: unset;
display: block;
}
.search-jumper-searchBar>.search-jumper-type {
padding: 0px;
${searchData.prefConfig.disableTypeOpen ? "background: unset;" : ""}
}
.search-jumper-searchBar>.search-jumper-type:not(.search-jumper-open) {
background: unset;
border-radius: unset!important;
}
.minSizeMode.search-jumper-searchBar>.search-jumper-type:not(.search-jumper-open),
.minSizeMode.search-jumper-searchBar:hover>.search-jumper-type:not(.search-jumper-open) {
display: none;
}
.minSizeModeClose.minSizeMode.search-jumper-searchBar:hover>.search-jumper-type:not(.search-jumper-targetImg,.search-jumper-targetLink,.search-jumper-targetPage,.search-jumper-targetVideo,.search-jumper-targetAudio) {
display: inline-flex;
}
.funcKeyCall>.search-jumper-searchBar>.search-jumper-type:not(.search-jumper-open) {
display: none;
border-radius: ${20 * this.tilesZoom}px!important;
}
span.search-jumper-word>img {
width: ${20 * this.scale}px;
height: ${20 * this.scale}px;
margin: auto;
}
#search-jumper.funcKeyCall span.search-jumper-word>img {
width: ${20 * this.tilesZoom}px;
height: ${20 * this.tilesZoom}px;
}
.search-jumper-btn:hover {
-webkit-transform:scale(1.1);
-moz-transform:scale(1.1);
transform:scale(1.1);
color: white;
text-decoration:none;
filter: drop-shadow(1px 1px 3px #00000050);
}
.search-jumper-btn:active {
-webkit-transform:scale(1.1);
-moz-transform:scale(1.1);
transform:scale(1.1);
transition:unset;
filter: drop-shadow(1px 1px 5px #000000a0);
}
.search-jumper-searchBar .search-jumper-btn.current {
overflow: visible;
}
.search-jumper-searchBar .search-jumper-btn.current::before {
content: '';
position: absolute;
right: -2px;
top: -2px;
border: 1px solid #00000099;
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background: white;
box-shadow: 0px 0px 3px 0px rgb(0 0 0 / 80%);
${searchData.prefConfig.noAni ? "" : "opacity: 0.8;"}
}
.in-input .search-jumper-input {
display: block;
box-sizing: content-box;
}
.lock-input .search-jumper-lock-input {
float: left;
font-size: 20px;
top: 14px;
left: 25px;
color: darkgrey;
position: absolute;
border-right: 2px solid #32373a;
padding-right: 10px;
display: block;
}
.search-jumper-input {
width: 50%;
min-width: 500px;
bottom: 2%;
left: 50%;
margin: 0 0 0 -25%;
margin-left: min(-25%, -250px);
position: fixed;
font-family: Arial, sans-serif;
text-align: left;
box-shadow: 0px 2px 10px rgb(0 0 0 / 80%);
border: 1px solid rgb(179 179 179 / 10%);
border-radius: 28px;
background-color: rgb(51 56 59 / 90%);
padding: 5px;
display: none;
z-index: 2139999999;
font-size: 20px;
height: 36px;
touch-action: none;
}
.inputGroup {
cursor: grab;
display: flex;
}
.inputGroup * {
cursor: default;
}
.search-jumper-input input,
.search-jumper-input textarea {
background-color: #212022;
color: #adadad;
border: none;
font-size: 16px;
height: 35px;
margin-bottom: 0;
padding: 5px;
margin: 0 10px;
border-radius: 3px;
box-shadow: #333 0px 0px 2px;
width: calc(100% - 20px);
outline: none;
box-sizing: border-box;
cursor: text;
}
#searchJumperInput,
#searchJumperInputKeyWords {
width: calc(100% - 11px);
float: left;
transition: 0.25s width ease;
}
#searchJumperInput {
margin: 0 5px 0 10px;
}
#searchJumperInputKeyWords {
margin: 0 10px 0 1px;
}
#searchJumperInputKeyWords:disabled {
opacity: 0.5;
max-width: 20%;
min-width: 20%;
}
#filterSites>input:focus,
#filterSites>textarea:focus {
width: calc(400% - 20px);
color: white;
}
.search-jumper-input * {
box-sizing: border-box;
}
.search-jumper-input input[type="radio"] {
display: none;
}
.search-jumper-input input:checked + label {
background: #3a444add;
opacity: 0.9;
color: white;
font-size: 14px;
}
.search-jumper-input input#filterSitesTab:checked ~ .line {
left: 27px;
}
.search-jumper-input input#filterSitesTab:checked ~ .content-container #filterSites {
opacity: 1;
pointer-events: all;
}
.search-jumper-input input#searchInPageTab:checked ~ .line {
left: 233px;
}
.search-jumper-input input#searchInPageTab:checked ~ .content-container #searchInPage {
opacity: 1;
pointer-events: all;
}
.search-jumper-input label {
display: inline-block;
font-size: 12px;
height: 32px;
line-height: 32px;
width: 200px;
text-align: center;
background: #2a343acc;
color: #959595;
position: relative;
transition: 0.25s background ease, 0.25s opacity ease;
cursor: pointer;
position: relative;
top: -38px;
left: 22px;
border-radius: 5px 5px 0 0;
user-select: none;
pointer-events: all;
max-width: 40%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
opacity: 0.6;
}
.search-jumper-input input:checked + label:hover,
.search-jumper-input label:hover {
background: #3a444a;
opacity: 1;
}
.search-jumper-input label::after {
content: "";
height: 1px;
width: 100%;
position: absolute;
display: block;
background: #ccc;
bottom: 0;
opacity: 0;
left: 0;
transition: 0.25s ease;
}
.search-jumper-input label:hover::after {
opacity: 1;
}
.search-jumper-input .line {
background: #1E88E5;
width: 200px;
height: 1px;
top: -2px;
left: 0;
transition: 0.25s ease;
position: absolute;
}
.inputGroup>.svgBtns {
right: 16px;
top: 5px;
height: 35px;
position: absolute;
user-select: none;
background: #212022;
white-space: nowrap;
overflow: hidden;
display: flex;
align-items: center;
}
.inputGroup>#addons {
position: absolute;
bottom: 41px;
right: 110px;
display: none;
flex-direction: column;
background: #212022;
border-radius: 10px;
opacity: 0;
transition: 0.5s opacity ease;
}
.inputGroup>#addons>div {
padding: 10px;
}
.inputGroup>#addons>div>input {
float: left;
width: 20px;
height: 20px;
margin: 0 10px 0 0;
cursor: pointer;
}
.inputGroup:hover>#addons {
display: flex;
}
.inputGroup>#addons:hover {
opacity: 1;
}
.inputGroup>.svgBtns:hover+#addons {
opacity: 1;
}
.inputGroup>#addons>div>label {
color: white;
display: inline;
background: none;
top: unset;
left: unset;
font-size: unset;
line-height: 20px;
max-width: unset;
}
.inputGroup>.svgBtns:hover {
width: auto;
}
.inputGroup>.svgBtns>svg {
margin: 0 2px;
}
.inputGroup svg.checked {
fill: #1E88E5;
}
@media screen and (max-width: 2048px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 1580px;
}
}
@media screen and (max-width: 1920px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 1320px;
}
}
@media screen and (max-width: 1600px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 1060px;
}
}
@media screen and (max-width: 1300px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 800px;
}
}
@media screen and (max-width: 900px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 540px;
}
}
@media screen and (max-width: 600px) {
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist {
width: 95vw;
}
#search-jumper.search-jumper-showall #search-jumper-alllist.new-mode .sitelist>.sitelistCon {
width: calc(100% - 20px);
}
#search-jumper-alllist>.timeInAll, #search-jumper-alllist>.dayInAll {
margin: 10px;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a {
width: calc(50vw - 45px);
}
#search-jumper #search-jumper-alllist.new-mode .sitelist>.sitelistCon>div:before {
width: 100px;
margin-left: 68px;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a>img {
margin-left: 0;
}
}
@media screen and (max-width: 380px) {
#search-jumper #search-jumper-alllist.new-mode .sitelist a {
width: calc(100vw - 60px);
}
#search-jumper #search-jumper-alllist.new-mode .sitelist>.sitelistCon>div:before {
width: calc(100vw - 150px);
margin-left: 85px;
}
#search-jumper #search-jumper-alllist.new-mode .sitelist a+p {
width: calc(100vw - 60px);
}
}
@media screen and (max-width: 800px) {
.search-jumper-input .line {
display: none;
}
.search-jumper-input {
min-width: 300px;
margin-left: min(-25%, -150px);
}
.inputGroup>.svgBtns {
width: 25px;
}
#search-jumper-alllist>.modeSwitch {
width: 36px;
height: 36px;
right: 2px;
top: 10px;
}
}
@media screen and (max-width: 650px) {
#search-jumper.search-jumper-showall>#search-jumper-alllist.new-mode+.groupTab {
display: none;
}
}
.search-jumper-input .content-container {
background: #eee;
position: static;
font-size: 16px;
}
.search-jumper-input .content-container .inputGroup {
position: absolute;
padding: 5px;
width: 100%;
top: 0;
left: 0;
opacity: 0;
pointer-events: none;
transition: 0.25s ease;
color: #333;
}
.search-jumper-input svg,
.searchJumperNavBar svg {
width: 25px;
height: 25px;
fill: white;
cursor: pointer;
opacity: 0.8;
transition: 0.25s all ease;
font-size: 0px;
}
.search-jumper-input .inputGroup:hover svg,
.searchJumperNavBar.sjNavShow svg {
pointer-events: all;
}
.search-jumper-input svg *,
.searchJumperNavBar svg * {
cursor: pointer;
}
.search-jumper-input svg:hover,
.searchJumperNavBar svg:hover,
.search-jumper-input>.closeBtn:hover,
.searchJumperNavBar>div.minNavBtn:hover,
.searchJumperNavBar>div.maxNavBtn:hover {
-webkit-transform:scale(1.2);
-moz-transform:scale(1.2);
transform:scale(1.2);
opacity: 1;
}
#search-jumper.selectedEle #filterSites>.svgBtns>svg {
display: inline-block!important;
}
.search-jumper-input>.closeBtn {
position: absolute;
right: 0px;
top: -35px;
width: 30px;
height: 30px;
vertical-align: middle;
overflow: hidden;
background: rgb(51 56 59 / 90%);
color: white;
text-align: center;
line-height: 30px;
border-radius: 20px;
pointer-events: all;
transition: 0.25s all ease;
opacity: 0.6;
font-size: 26px;
box-shadow: 0px 0px 2px rgb(0 0 0 / 80%);
border: 1px solid rgb(179 179 179 / 20%);
cursor: pointer;
user-select: none;
}
#searchInPage>.lockWords {
max-width: 50%;
position: absolute;
bottom: 4px;
left: 16px;
color: white;
font-size: 18px;
display: flex;
flex-wrap: wrap-reverse;
max-height: 38px;
overflow: hidden;
}
#searchInPage>.lockWords:hover {
overflow-y: auto;
height: auto;
max-height: 90vh;
}
#searchInPage>.lockWords>span {
position: relative;
padding: 5px;
cursor: pointer;
user-select: none;
background: yellow;
color: black;
border: 1px solid;
margin: 2px;
display: flex;
align-items: center;
white-space: nowrap;
max-width: 100%;
line-height: initial;
}
#searchInPage>.lockWords>span>em {
cursor: alias;
}
#searchInPage>.lockWords .lockWordTool {
position: absolute;
right: 0;
top: 0;
display: none;
opacity: 0.3;
height: 15px;
width: 15px;
text-align: center;
line-height: 15px;
border-radius: 50%;
background: black;
color: white;
}
#searchInPage>.lockWords .lockWordTool>span {
cursor: pointer;
font-size: 15px;
}
#searchInPage>.lockWords .modifyBtn {
top: unset;
bottom: 0;
}
#searchInPage>.lockWords .lockWordTool:hover {
opacity: 1;
}
#searchInPage>.lockWords>span:hover .lockWordTool {
display: block;
pointer-events: all;
}
#searchInPage>.lockWords .lockWordTool>svg {
width: 15px;
height: 15px;
fill: black;
color: black;
border: 1px solid white;
border-radius: 10px;
background: white;
}
#searchInPage>.lockWords>span>em {
font-size: 12px;
margin-right: 5px;
color: unset;
}
.searchJumperNavBar {
all: unset;
top: 0px;
bottom: 0px;
right: 0px;
position: fixed;
width: 20px;
z-index: 2147483647;
background: #00000026;
text-align: center;
pointer-events: none;
font-size: 0px;
opacity: 0;
transition: width 0.3s, background 0.3s;
}
.searchJumperNavBar:hover {
width: 25px;
background: #00000066;
}
.searchJumperNavBar.sjNavShow {
pointer-events: all;
opacity: 1;
}
.search-jumper-showall > .searchJumperNavBar.sjNavShow {
opacity: 0;
}
.searchJumperNavBar>.closeNavBtn {
width: 16px;
height: 16px;
fill: white;
cursor: pointer;
display: inline-block;
}
.searchJumperNavBar>.minNavBtn,
.searchJumperNavBar>.maxNavBtn {
font-size: 12px;
font-weight: bold;
font-family: system-ui;
line-height: 16px;
opacity: 0.1;
background: white;
color: black;
border-radius: 10px;
width: 16px;
height: 16px;
display: inline-block;
cursor: pointer;
transition: 0.25s opacity ease, 0.25s transform ease;
}
.searchJumperNavBar:hover>.minNavBtn,
.searchJumperNavBar:hover>.maxNavBtn {
opacity: 0.8;
}
#search-jumper>.searchJumperNavBar.minimize {
background: transparent;
pointer-events: none;
}
.searchJumperNavBar.minimize>.closeNavBtn,
.searchJumperNavBar.minimize>.navPointer,
.searchJumperNavBar.minimize>.maxNavBtn,
.searchJumperNavBar.minimize>#navMarks {
display: none;
}
.searchJumperNavBar.minimize>.minNavBtn {
opacity: 1;
box-shadow: 0px 0px 3px 1px #000;
margin-left: -50px;
margin-top: 5px;
pointer-events: all;
}
.search-jumper-right>.searchJumperNavBar.minimize>.minNavBtn {
margin-left: unset;
margin-right: -50px;
}
#navMarks+.navPointer {
pointer-events: none;
position: absolute;
right: 20px;
text-shadow: #fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0;
font-size: 30px;
font-family: system-ui;
line-height: 0px;
border: 0;
margin-top: 0;
opacity: 0.8;
color: black;
transition: top 0.25s ease;
animation-name: changeHor;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
@keyframes changeHor {
0% {right: 20px;}
10% {right: 18px;}
80% {right: 25px;}
100% {right: 20px;}
}
#navMarks {
height: calc(100% - 50px);
width: 100%;
position: relative;
}
#navMarks>span {
height: 0.5vh;
width: 100%;
position: absolute;
border: 1px solid #cccccc;
min-height: 5px;
box-sizing: border-box;
left: 0;
border-radius: 0px!important;
cursor: alias;
}
.searchJumperPosBar {
background: rgba(29, 93, 163, 0.3);
position: absolute;
min-height: 10px;
min-width: 10px;
animation-duration: 2s;
z-index: 2147483647;
margin: 0;
opacity: 0;
pointer-events: none;
transition: 0.25s all ease;
}
.searchJumperPosBar.searchJumperPosW {
width: 100%;
left: 0;
}
.searchJumperPosBar.searchJumperPosH {
height: 100%;
top: 0;
position: fixed;
}
@keyframes fadeit {
0% {opacity: 1;}
50% {opacity: 0.8;}
100% {opacity: 0;}
}
#rightSizeChange {
top: 0;
opacity: 0;
height: 45px;
width: 15px;
position: absolute;
cursor: e-resize;
right: 0;
pointer-events: all;
}
.searchJumper-hide {
display: none!important;
}
.search-jumper-historylist>a.search-jumper-btn {
filter: drop-shadow(0px 0px 3px #00000050);
width: 32px;
height: 32px;
line-height: 32px;
min-width: auto;
min-height: auto;
flex-shrink: 0;
}
.search-jumper-historylist>a.search-jumper-btn>img {
width: 32px;
height: 32px;
}
.search-jumper-historylist>a.search-jumper-btn:not(.search-jumper-word)>span {
font-size: 12px;
line-height: normal;
}
#search-jumper .listArrow {
width: 0;
height: 0;
border: 10px solid transparent;
pointer-events: none;
border-bottom-color: white;
position: fixed;
opacity: 0;
visibility: hidden;
z-index: 2147483647;
transition: opacity .3s ease, top .15s, bottom .15s, left .15s, right .15s;
}
#search-jumper.search-jumper-left .listArrow {
border-bottom-color: transparent;
border-right-color: white;
}
#search-jumper.search-jumper-right .listArrow {
border-bottom-color: transparent;
border-left-color: white;
}
#search-jumper.search-jumper-bottom .listArrow {
border-bottom-color: transparent;
border-top-color: white;
}
@media (prefers-color-scheme: dark) {
/* 站点列表 */
#search-jumper .sitelist > .sitelistCon > p {
background-color: #252B32 !important;
}
#search-jumper.search-jumper-showall #filterSites {
background-color: #2a282cc0;
}
#search-jumper.search-jumper-showall #filterSites>input,
#search-jumper.search-jumper-showall #filterSites>textarea {
background-color: #000000;
color: white;
}
#search-jumper .sitelist > .sitelistCon {
background-color: #1C2127ee !important;
}
#search-jumper .sitelist > .sitelistCon > div:hover {
background-color: #283C57 !important;
}
#search-jumper .sitelist > .sitelistCon > p,
#search-jumper .sitelist a > p {
color: #DADADA !important;
}
#search-jumper .listArrow {
border-bottom-color: #1C2127;
}
#search-jumper.search-jumper-left .listArrow {
border-bottom-color: transparent;
border-right-color: #1C2127;
}
#search-jumper.search-jumper-right .listArrow {
border-bottom-color: transparent;
border-left-color: #1C2127;
}
#search-jumper.search-jumper-bottom .listArrow {
border-bottom-color: transparent;
border-top-color: #1C2127;
}
/* 历史列表 */
.search-jumper-historylistcon {
background-color: #181C20e0 !important;
}
.search-jumper-historylist>a.search-jumper-btn {
filter: drop-shadow(0px 0px 3px #ffffff50);
}
.search-jumper-showall a.search-jumper-word,
.search-jumper-showall a.search-jumper-word > span {
background-color: #292A2D !important;
border-radius: 20px !important;
}
.search-jumper-tips {
background-color: #3F4042f0;
color: #DADADA;
}
.search-jumper-tips>*:not(font) {
color: white;
}
.search-jumper-showall a.search-jumper-word > span {
color: #DADADA !important;
}
.search-jumper-showall .search-jumper-word:hover {
text-shadow: 0px 0px 5px #2374FF !important;
}
/* 类别 */
.search-jumper-showall .search-jumper-type,
.search-jumper-showall .search-jumper-logo {
background-color: #181C20 !important;
}
#search-jumper.search-jumper-showall>.groupTab {
background: #1C2127ee !important;
}
#search-jumper.search-jumper-showall>.groupTab>span:hover{
background: #283C57 !important;
}
#search-jumper.search-jumper-showall>.groupTab:hover>span::after {
color: white;
}
}
`;
this.inPageCss = `
mark.searchJumper,
a.searchJumper {
visibility: inherit;
font-style: normal;
box-shadow: rgba(0, 0, 0, 0.3) 1px 1px 3px;
border-radius: 3px;
text-decoration: none;
padding: 1px 0;
-webkit-text-fill-color: initial;
text-shadow: initial;
min-width: initial;
display: inline;
}
mark.searchJumper:before,
a.searchJumper:before,
mark.searchJumper:after,
a.searchJumper:after {
all: unset;
content: none!important;
}
mark.searchJumper[data-current=true],
a.searchJumper[data-current=true] {
border-bottom: 0.2em solid;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
animation: 0.5s linear 0s 5 normal none running currentMark;
}
@keyframes currentMark {
from {border-color: unset}
to {border-color: transparent;}
}
`;
if (searchData.prefConfig.cssText) cssText += searchData.prefConfig.cssText;
let logoCon = document.createElement("span");
logoCon.className = "search-jumper-logo";
logoBtn = document.createElement("span");
logoBtn.innerHTML = createHTML(logoBtnSvg);
logoBtn.className = "search-jumper-btn";
logoCon.addEventListener('mouseenter', e => {
if (this.preList) {
this.preList.style.visibility = "hidden";
this.listArrow.style.cssText = "";
}
});
logoCon.appendChild(logoBtn);
let bar = document.createElement("span");
bar.className = "search-jumper-searchBar";
bar.appendChild(logoCon);
let searchBarCon = document.createElement("div");
searchBarCon.id = "search-jumper";
searchBarCon.style.display = "none";
searchBarCon.className = "search-jumper-searchBarCon";
searchBarCon.appendChild(bar);
searchBarCon.setAttribute("translate", "no");
let alllist = document.createElement("div");
alllist.id = "search-jumper-alllist";
searchBarCon.appendChild(alllist);
this.alllist = alllist;
let groupTab = document.createElement("span");
groupTab.className = "groupTab";
searchBarCon.appendChild(groupTab);
this.groupTab = groupTab;
let showallBg = document.createElement("div");
showallBg.className = "search-jumper-showallBg";
searchBarCon.appendChild(showallBg);
let sitelistBox = document.createElement("div");
sitelistBox.className = "sitelistBox";
alllist.appendChild(sitelistBox);
this.sitelistBox = sitelistBox;
const tagReg = /#[^\s#]+/g;
sitelistBox.addEventListener("mouseover", e => {
if (!alllist.classList.contains("new-mode")) return;
let target = e.target;
if (target.parentNode && target.parentNode.dataset.name) {
target = target.parentNode;
}
let title = target.title;
if (!target.dataset.name || !title || target.initedTag) return;
let tags = document.createElement("p");
let tagMatch = title.match(tagReg);
if (tagMatch) {
tagMatch.forEach(tag => {
let tagEle = document.createElement("span");
tagEle.innerText = tag.slice(1);
tagEle.addEventListener("click", e => {
self.searchInput.value = tag;
self.searchInput.dispatchEvent(new CustomEvent("input"));
});
tags.appendChild(tagEle);
});
target.appendChild(tags);
}
target.initedTag = true;
});
let timeInAll = document.createElement("span");
timeInAll.className = "timeInAll";
alllist.appendChild(timeInAll);
this.timeInAll = timeInAll;
this.modeSwitch = document.createElement("div");
this.modeSwitch.className = "modeSwitch";
this.modeSwitch.innerHTML = createHTML(`<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" version="1.1"><rect height="450" width="520" y="287" x="253" fill="#fff"></rect><path d="m511.8,64.2c-247.5,0 -448.2,200.7 -448.2,448.2s200.7,448.2 448.2,448.2s448.2,-200.6 448.2,-448.2s-200.7,-448.2 -448.2,-448.2zm-260.4,353.9c0,-7.8 6.3,-14.2 14.2,-14.2l315.6,0l0,-102.5c0,-12.3 14.7,-18.8 23.7,-10.4l165.1,151.7c9.5,8.7 3.3,24.6 -9.6,24.6l-495,0c-7.8,0 -14.2,-6.3 -14.2,-14.2l0,-35l0.2,0zm523.2,188.5c0,7.8 -6.3,14.2 -14.2,14.2l-315.5,0l0,102.6c0,12.3 -14.7,18.8 -23.7,10.4l-165.2,-151.8c-9.5,-8.7 -3.3,-24.6 9.6,-24.6l495,0c7.8,0 14.2,6.3 14.2,14.2l0,35l-0.2,0z"></path></svg>`);
alllist.appendChild(this.modeSwitch);
this.modeSwitch.addEventListener("click", e => {
e.preventDefault();
e.stopPropagation();
alllist.classList.toggle("new-mode");
alllist.classList.remove("showbg");
storage.setItem("allPageNewMode", alllist.classList.contains("new-mode"));
});
this.modeSwitch.addEventListener("mouseenter", e => {
if (allPageBgUrl) {
e.preventDefault();
e.stopPropagation();
alllist.classList.add("showbg");
}
});
this.modeSwitch.addEventListener("mouseleave", e => {
if (allPageBgUrl) {
e.preventDefault();
e.stopPropagation();
alllist.classList.remove("showbg");
}
});
this.modeSwitch.addEventListener("contextmenu", e => {
if (allPageBgUrl) {
e.preventDefault();
e.stopPropagation();
alllist.classList.remove("showbg");
_GM_openInTab(allPageBgUrl, {active: true, insert: true});
}
});
if (allPageNewMode) alllist.classList.add("new-mode");
let dayInAll = document.createElement("span");
dayInAll.className = "dayInAll";
alllist.appendChild(dayInAll);
this.dayInAll = dayInAll;
alllist.addEventListener(getSupportWheelEventName(), e => {
self.tips.style.display = "none";
clearTimeout(self.requestShowTipsTimer);
if (e.target != alllist && e.target != showallBg && e.target != sitelistBox) return;
if (alllist.classList.contains("new-mode")) return;
var deltaX, deltaY;
if(e.type !== 'wheel'){
var x = 0, y = 0;
if (typeof e.axis == 'number') {
if (e.axis == 2) {
y = e.detail;
} else {
x = e.detail;
}
} else {
if (typeof e.wheelDeltaY == 'undefined' || e.wheelDeltaY != 0) {
y = -e.wheelDelta / 40;
} else {
x = -e.wheelDelta / 40;
};
};
deltaY = y;
deltaX = x;
} else {
deltaX = e.deltaX;
deltaY = e.deltaY;
}
e.preventDefault();
e.stopPropagation();
alllist.scrollLeft += deltaY;
}, { passive: false, capture: false });
let logoConfigBtn = document.createElement("span");
logoConfigBtn.innerHTML = createHTML(logoBtnSvg);
logoConfigBtn.className = "search-jumper-btn";
logoConfigBtn.addEventListener('click', e => {
_GM_openInTab(configPage, {active: true, insert: true});
});
alllist.appendChild(logoConfigBtn);
let historylistCon = document.createElement("div");
historylistCon.className = "search-jumper-historylistcon";
alllist.appendChild(historylistCon);
let historylist = document.createElement("div");
historylist.className = "search-jumper-historylist";
historylistCon.appendChild(historylist);
this.historylist = historylist;
bar.addEventListener('mouseenter', e => {
if (bar.classList.contains("grabbing")) return;
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
}
this.checkScroll(true);
if (searchData.prefConfig.mouseLeaveToHide) {
bar.classList.remove("initShow");
}
}, false);
bar.addEventListener('mouseleave', e => {
if (searchData.prefConfig.mouseLeaveToHide) {
if (bar.classList.contains("grabbing")) return;
self.waitForHide();
}
if (self.preList) {
self.preList.style.visibility = "hidden";
self.listArrow.style.cssText = "";
}
}, false);
this.touched = true;
if (searchData.prefConfig.initShow) {
bar.classList.add("initShow");
} else {
this.touched = false;
}
if (searchData.prefConfig.minSizeMode) {
bar.classList.add("minSizeMode");
bar.classList.add("minSizeModeClose");
}
if (isMobile && !searchData.prefConfig.resizePage) {
let touchBodyHandler = e => {
this.touched = false;
bar.classList.remove("initShow");
};
let touchHandler = e => {
if (this.touched || this.funcKeyCall) return;
this.touched = true;
bar.classList.add('disable-pointer');
e.stopPropagation();
setTimeout(() => {
bar.classList.remove('disable-pointer');
}, 250);
};
getBody(document).addEventListener("touchstart", touchBodyHandler, { passive: true, capture: false });
bar.addEventListener('touchstart', touchHandler, { passive: false, capture: true });
}
this.bar = bar;
this.con = searchBarCon;
let tips = document.createElement("span");
tips.className = "search-jumper-tips";
tips.style.opacity = 0;
searchBarCon.appendChild(tips);
tips.addEventListener('mouseenter', e => {
if (self.hideTimeout) {
clearTimeout(self.hideTimeout);
}
}, false);
tips.addEventListener('click', e => {
let dataset = e.target.dataset;
let text = e.target.innerText;
if (!dataset) return;
if (typeof dataset.read !== 'undefined') {
let msg = new SpeechSynthesisUtterance("");
msg.volume = dataset.volume || 1;
msg.rate = dataset.rate || 1;
msg.pitch = dataset.pitch || 1;
msg.lang = dataset.lang || "";
msg.text = dataset.read || text;
window.speechSynthesis.speak(msg);
}
if (typeof dataset.copy !== 'undefined') {
_GM_setClipboard(dataset.copy || text);
}
if (dataset.search) {
extSelectionText = text;
self.searchBySiteName(dataset.search);
}
if (typeof dataset.paste !== 'undefined') {
if (targetElement &&
((/INPUT|TEXTAREA/i.test(targetElement.nodeName) &&
targetElement.getAttribute("aria-readonly") != "true"
) ||
targetElement.contentEditable == 'true'
)
) {
triggerPaste(targetElement, dataset.paste || text);
}
}
if (typeof dataset.close !== 'undefined') {
self.tips.style.opacity = 0;
self.tips.style.display = "none";
self.tips.innerHTML = createHTML("");
}
}, false);
let startMouse, startPos, mouseMoveHandler = e => {
let curX = clientX(e) - startMouse.x;
let curY = clientY(e) - startMouse.y;
if (Math.abs(curX) + Math.abs(curY) < 5) return;
if (tips.style.right === "") {
tips.style.setProperty("left", (startPos.left + curX) + "px", "important");
//tips.style.left = (startPos.left + curX) + "px!important";
} else {
tips.style.setProperty("right", (startPos.right - curX) + "px", "important");
//tips.style.right = (startPos.right - curX) + "px!important";
}
if (tips.style.bottom === "") {
tips.style.setProperty("top", (startPos.top + curY) + "px", "important");
//tips.style.top = (startPos.top + curY) + "px!important";
} else {
tips.style.setProperty("bottom", (startPos.bottom - curY) + "px", "important");
//tips.style.bottom = (startPos.bottom - curY) + "px!important";
}
tips.classList.add("draging");
};
let mouseUpHandler = e => {
document.removeEventListener('mouseup', mouseUpHandler, false);
document.removeEventListener('mousemove', mouseMoveHandler, false);
document.removeEventListener('touchend', mouseUpHandler, false);
document.removeEventListener('touchmove', mouseMoveHandler, false);
tips.classList.remove("draging");
};
let dragTips = (e, cb) => {
if (!e.target) return;
if (e.target !== tips && typeof e.target.dataset.drag === 'undefined') return;
e.preventDefault();
e.stopPropagation();
startMouse = {x: clientX(e), y: clientY(e)};
let tipsStyle = getComputedStyle(tips);
startPos = {
left: parseFloat(tipsStyle.left),
right: parseFloat(tipsStyle.right),
top: parseFloat(tipsStyle.top),
bottom: parseFloat(tipsStyle.bottom)
};
cb && cb();
};
tips.addEventListener('mousedown', e => {
dragTips(e, () => {
document.addEventListener('mouseup', mouseUpHandler, false);
document.addEventListener('mousemove', mouseMoveHandler, false);
});
}, false);
tips.addEventListener('touchstart', e => {
dragTips(e, () => {
document.addEventListener('touchend', mouseUpHandler, false);
document.addEventListener('touchmove', mouseMoveHandler, false);
});
}, { passive: false, capture: false });
this.tips = tips;
//this.appendBar();
let searchJumperNavBar = document.createElement("div");
searchJumperNavBar.className = "searchJumperNavBar";
searchJumperNavBar.style.display = "none";
searchJumperNavBar.innerHTML = createHTML(`
<svg class="closeNavBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>Close navigation</title>${closePath}</svg>
<div class="minNavBtn" title="Minimize navigation">-</div>
<div id="navMarks"></div>
<div class="maxNavBtn" title="Restore input"><img src="${logoBase64}" /></div>
<div class="navPointer">></div>
`);
searchBarCon.appendChild(searchJumperNavBar);
let searchJumperExpand = document.createElement("span");
searchJumperExpand.title = i18n('expand');
searchJumperExpand.className = "searchJumperExpand search-jumper-btn";
searchJumperExpand.innerHTML = createHTML(`
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><rect height="450" width="600" y="300" x="200" fill="#fff"></rect><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64z m0 640L240 432l45.6-45.6L512 613.6l226.4-226.4 45.6 45.6L512 704z"></path></svg>
`);
this.searchJumperExpand = searchJumperExpand;
this.navMarks = searchJumperNavBar.querySelector("#navMarks");
this.closeNavBtn = searchJumperNavBar.querySelector(".closeNavBtn");
this.minNavBtn = searchJumperNavBar.querySelector(".minNavBtn");
this.maxNavBtn = searchJumperNavBar.querySelector(".maxNavBtn");
this.searchJumperNavBar = searchJumperNavBar;
this.navPointer = searchJumperNavBar.querySelector(".navPointer");
this.navPointer.style.display = "none";
let searchInputDiv = document.createElement("div");
searchInputDiv.className = "search-jumper-input";
searchInputDiv.innerHTML = createHTML(`<span class="closeBtn">×</span>
<input type="radio" id="filterSitesTab" name="tab" ${searchData.prefConfig.defaultFindTab? "" : "checked=\"checked\""} />
<label for="filterSitesTab">${i18n("filterSites")}</label>
<input type="radio" id="searchInPageTab" name="tab" ${searchData.prefConfig.defaultFindTab? "checked=\"checked\"" : ""} />
<label for="searchInPageTab">${i18n("searchInPage")}</label>
<div class="line"></div>
<div class="content-container">
<div class="inputGroup" id="filterSites">
<input spellcheck="false" id="searchJumperInput" autocomplete="on" title="${i18n("inputTitle")}" placeholder="${i18n("inputPlaceholder")}" list="filterGlob" />
<input spellcheck="false" id="searchJumperInputKeyWords" autocomplete="on" placeholder="${i18n("inputKeywords")}" list="suggest" />
<datalist id="filterGlob">
</datalist>
<datalist id="suggest">
</datalist>
<span class="search-jumper-lock-input"></span>
<span class="svgBtns">
<svg id="copyEleBtn" style="display:none;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("copyEleBtn")}</title><path d="M706.5 188.4H190.2c-29.8 0-54 24.2-54 54v662.9c0 29.8 24.2 54 54 54h516.3c29.8 0 54-24.2 54-54V242.4c0-29.8-24.2-54-54-54z m-18 698.9H208.2V260.4h480.3v626.9zM313.7 512.2h275.2c19.9 0 36-16.1 36-36s-16.1-36-36-36H313.7c-19.9 0-36 16.1-36 36s16.1 36 36 36zM313.7 715.2h201.6c19.9 0 36-16.1 36-36s-16.1-36-36-36H313.7c-19.9 0-36 16.1-36 36s16.1 36 36 36zM837.2 64.7H302.9c-19.9 0-36 16.1-36 36s16.1 36 36 36h516.3v662.9c0 19.9 16.1 36 36 36s36-16.1 36-36V118.7c0-29.8-24.2-54-54-54z"></path></svg>
<svg id="openLinkBtn" style="display:none;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("openLinkBtn")}</title><path d="M429.013333 640A32 32 0 0 1 384 594.986667l37.76-37.76-22.826667-22.613334-135.68 135.68 90.453334 90.453334 135.68-135.68-22.613334-22.613334zM534.613333 398.933333l22.613334 22.613334L594.986667 384A32 32 0 0 1 640 429.013333l-37.76 37.76 22.613333 22.613334 135.68-135.68-90.453333-90.453334z"/><path d="M512 21.333333a490.666667 490.666667 0 1 0 490.666667 490.666667A490.666667 490.666667 0 0 0 512 21.333333z m316.8 354.986667l-181.12 181.12a32 32 0 0 1-45.226667 0L557.226667 512 512 557.226667l45.226667 45.226666a32 32 0 0 1 0 45.226667l-181.12 181.12a32 32 0 0 1-45.226667 0l-135.68-135.68a32 32 0 0 1 0-45.226667l181.12-181.12a32 32 0 0 1 45.226667 0L466.773333 512 512 466.773333l-45.226667-45.226666a32 32 0 0 1 0-45.226667l181.12-181.12a32 32 0 0 1 45.226667 0l135.68 135.68a32 32 0 0 1 0 45.226667z"/></svg>
<svg id="maxEleBtn" style="display:none;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("maxEleBtn")}</title><path d="M192 832h160a32 32 0 0 1 0 64H160a32 32 0 0 1-32-32V672a32 32 0 0 1 64 0zM182.72 886.72a32 32 0 0 1-45.44-45.44l224-224a32 32 0 0 1 45.44 45.44zM832 832V672a32 32 0 0 1 64 0v192a32 32 0 0 1-32 32H672a32 32 0 0 1 0-64zM886.72 841.28a32 32 0 0 1-45.44 45.44l-224-224a32 32 0 0 1 45.44-45.44zM192 192v160a32 32 0 0 1-64 0V160a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64zM137.28 182.72a32 32 0 0 1 45.44-45.44l224 224a32 32 0 0 1-45.44 45.44zM832 192H672a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0zM841.28 137.28a32 32 0 1 1 45.44 45.44l-224 224a32 32 0 0 1-45.44-45.44z"></path></svg>
<svg id="minEleBtn" style="display:none;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("minEleBtn")}</title><path d="M672 352h160a32 32 0 0 1 0 64H640a32 32 0 0 1-32-32V192a32 32 0 0 1 64 0zM662.72 406.72a32 32 0 0 1-45.44-45.44l224-224a32 32 0 1 1 45.44 45.44zM352 352V192a32 32 0 0 1 64 0v192a32 32 0 0 1-32 32H192a32 32 0 0 1 0-64zM406.72 361.28a32 32 0 0 1-45.44 45.44l-224-224a32 32 0 0 1 45.44-45.44zM672 672v160a32 32 0 0 1-64 0V640a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64zM617.28 662.72a32 32 0 0 1 45.44-45.44l224 224a32 32 0 0 1-45.44 45.44zM192 672a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V672zM361.28 617.28a32 32 0 0 1 45.44 45.44l-224 224a32 32 0 0 1-45.44-45.44z"></path></svg>
<svg id="pickerBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("multiPickerBtn")}</title><path d="M874.048 533.333333C863.424 716.629333 716.629333 863.424 533.333333 874.048V917.333333a21.333333 21.333333 0 0 1-42.666666 0v-43.285333C307.370667 863.424 160.576 716.629333 149.952 533.333333H106.666667a21.333333 21.333333 0 0 1 0-42.666666h43.285333C160.576 307.370667 307.370667 160.576 490.666667 149.952V106.666667a21.333333 21.333333 0 0 1 42.666666 0v43.285333c183.296 10.624 330.090667 157.418667 340.714667 340.714667h42.816a21.333333 21.333333 0 1 1 0 42.666666H874.026667z m-42.752 0h-127.786667a21.333333 21.333333 0 0 1 0-42.666666h127.786667C820.778667 330.922667 693.056 203.221333 533.333333 192.704V320a21.333333 21.333333 0 0 1-42.666666 0V192.704C330.922667 203.221333 203.221333 330.944 192.704 490.666667H320a21.333333 21.333333 0 0 1 0 42.666666H192.704c10.517333 159.744 138.24 287.445333 297.962667 297.962667V704a21.333333 21.333333 0 0 1 42.666666 0v127.296c159.744-10.517333 287.445333-138.24 297.962667-297.962667zM512 554.666667a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z"></path></svg>
</span>
</div>
<div class="inputGroup" id="searchInPage">
<span class="lockWords"></span>
<input spellcheck="false" id="searchJumperInPageInput" autocomplete="on" title="${i18n("inPageTips")}" placeholder="${i18n("inPagePlaceholder")}" />
<span class="svgBtns">
<svg id="editBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("editBtn")}</title><path d="M928 365.664a32 32 0 0 0-32 32V864a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V160a32 32 0 0 1 32-32h429.6a32 32 0 0 0 0-64H160a96 96 0 0 0-96 96v704a96 96 0 0 0 96 96h704a96 96 0 0 0 96-96V397.664a32 32 0 0 0-32-32z"></path><path d="M231.616 696.416a38.4 38.4 0 0 0 44.256 53.792l148-38.368L950.496 185.248 814.72 49.472 290.432 573.76l-58.816 122.656z m111.808-85.12L814.72 140l45.248 45.248-468.992 468.992-77.824 20.16 30.272-63.104z"></path></svg>
<svg id="addWord" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("addWord")}</title><path d="M821.364 962h-618.75C123.864 962 62 900.114 62 821.364v-618.75c0-78.75 61.864-140.635 140.614-140.635h618.75c78.75 0 140.636 61.885 140.636 140.635v618.75C962 900.114 900.114 962 821.364 962z m79.265-756.814c0-46.586-35.25-81.815-81.815-81.815H205.186c-46.843-0.214-84.557 34.758-83.165 82.393-0.128 14.4 1.35 613.05 1.35 613.05 0 46.565 35.25 81.815 81.815 81.815h613.628c46.565 0 81.815-35.25 81.815-81.815V205.186z m-173.55 347.657H552.843v174.236c0 16.95-13.736 30.685-30.686 30.685h-0.236a30.686 30.686 0 0 1-30.685-30.685V552.843H296.92a30.686 30.686 0 0 1-30.685-30.686v-0.236c0-16.95 13.735-30.685 30.685-30.685h194.315V296.92c0-16.95 13.735-30.685 30.685-30.685h0.236c16.95 0 30.686 13.735 30.686 30.685v194.315h174.236c16.95 0 30.685 13.735 30.685 30.685v0.236c0 16.95-13.735 30.686-30.685 30.686z"></path></svg>
<svg id="emptyBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("emptyBtn")}</title><path d="m159.45829,231.40004l-48.83334,0a36.625,34.1375 0 0 1 0,-68.275l805.75004,0a36.625,34.1375 0 0 1 0,68.275l-683.6667,0l0,603.09581a61.04167,56.89583 0 0 0 61.04167,56.89584l439.50002,0a61.04167,56.89583 0 0 0 61.04167,-56.89584l0,-500.68332a36.625,34.1375 0 0 1 73.25,0l0,500.68332c0,69.12844 -60.12604,125.17084 -134.29167,125.17084l-439.50002,0c-74.16563,0 -134.29167,-56.0424 -134.29167,-125.17084l0,-603.09581zm256.37501,-113.79167a36.625,34.1375 0 0 1 0,-68.275l195.33334,0a36.625,34.1375 0 0 1 0,68.275l-195.33334,0zm-36.625,307.23749a36.625,34.1375 0 0 1 73.25,0l0,273.09999a36.625,34.1375 0 0 1 -73.25,0l0,-273.09999zm195.33334,0a36.625,34.1375 0 0 1 73.25,0l0,273.09999a36.625,34.1375 0 0 1 -73.25,0l0,-273.09999z"/></svg>
<svg id="copyInPageBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("copyInPageBtn")}</title><path d="M706.5 188.4H190.2c-29.8 0-54 24.2-54 54v662.9c0 29.8 24.2 54 54 54h516.3c29.8 0 54-24.2 54-54V242.4c0-29.8-24.2-54-54-54z m-18 698.9H208.2V260.4h480.3v626.9zM313.7 512.2h275.2c19.9 0 36-16.1 36-36s-16.1-36-36-36H313.7c-19.9 0-36 16.1-36 36s16.1 36 36 36zM313.7 715.2h201.6c19.9 0 36-16.1 36-36s-16.1-36-36-36H313.7c-19.9 0-36 16.1-36 36s16.1 36 36 36zM837.2 64.7H302.9c-19.9 0-36 16.1-36 36s16.1 36 36 36h516.3v662.9c0 19.9 16.1 36 36 36s36-16.1 36-36V118.7c0-29.8-24.2-54-54-54z"></path></svg>
<svg id="wordModeBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("wordModeBtn")}</title><path d="M832 128c38.4 0 64 25.6 64 64v640c0 38.4-25.6 64-64 64H192c-38.4 0-64-25.6-64-64V192c0-38.4 25.6-64 64-64h640m0-64H192c-70.4 0-128 57.6-128 128v640c0 70.4 57.6 128 128 128h640c70.4 0 128-57.6 128-128V192c0-70.4-57.6-128-128-128z"></path><path d="M736 812.8h-448c-19.2 0-32-12.8-32-32s12.8-32 32-32h448c19.2 0 32 12.8 32 32 0 12.8-12.8 32-32 32zM320 704c-19.2-6.4-25.6-25.6-19.2-44.8l185.6-454.4c6.4-12.8 25.6-19.2 38.4-12.8 19.2 6.4 25.6 25.6 19.2 44.8l-185.6 454.4c-6.4 12.8-25.6 19.2-38.4 12.8z"></path><path d="M704 691.2c19.2-6.4 25.6-25.6 19.2-44.8L544 211.2c-6.4-19.2-25.6-25.6-38.4-19.2-19.2 6.4-25.6 25.6-19.2 38.4l179.2 441.6c6.4 19.2 25.6 25.6 38.4 19.2z"></path><path d="M371.2 492.8h256v64h-256z"></path></svg>
<svg id="recoverBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("recoverBtn")}</title><path d="M502.26 289.06c-0.02 16.95 13.26 30.94 30.18 31.8 123.47 8.79 236.97 70.94 310.89 170.21 73.92 99.28 100.91 225.84 73.93 346.65-41.65-181.74-195.38-316.12-381.05-333.08-8.89-0.6-17.63 2.55-24.09 8.7a31.798 31.798 0 0 0-9.86 23.64v85.15a32.343 32.343 0 0 1-50.67 26.41L114.21 413.02a32.341 32.341 0 0 1-14.46-26.95c0-10.84 5.43-20.96 14.46-26.95L451.6 124.68a32.358 32.358 0 0 1 33.28-2.03 32.355 32.355 0 0 1 17.39 28.44v137.97h-0.01z"></path></svg>
<svg id="saveRuleBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("saveRuleBtn")}</title><path d="M579.7 291.4c18.8 0 34.1-15.3 34.1-34.1v-34.1c0-18.8-15.4-34.1-34.1-34.1-18.8 0-34.1 15.3-34.1 34.1v34.1c0 18.7 15.4 34.1 34.1 34.1zM944.7 216.3L808.2 79.9c-6.8-6.8-15.3-10.2-23.9-10.2H170.4c-56.3 0-102.3 46-102.3 102.3v682.1c0 56.3 46 102.3 102.3 102.3H852.5c56.3 0 102.3-46 102.3-102.3V240.2c0.1-8.5-3.3-17-10.1-23.9zM358 137.9h307v182.5c0 11.9-10.2 22.2-22.2 22.2H380.2c-11.9 0-22.2-10.2-22.2-22.2V137.9z m358.1 750.3H306.9V652.9c0-20.5 17.1-37.5 37.5-37.5h334.2c20.5 0 37.5 17 37.5 37.5v235.3z m170.6-34.1c0 18.8-15.3 34.1-34.1 34.1h-66.5V652.9c0-58-47.7-105.7-105.7-105.7h-336c-58 0-105.7 47.7-105.7 105.7v235.3h-68.2c-18.8 0-34.1-15.3-34.1-34.1V172c0-18.8 15.3-34.1 34.1-34.1h119.4v182.5c0 49.5 40.9 90.4 90.4 90.4h262.6c49.5 0 90.4-40.9 90.4-90.4V137.9h37.5l116 116v600.2z"></path></svg>
<svg id="pinBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("pinBtn")}</title><path d="m674.8822,92.83803a81.61801,81.04246 0 0 1 25.30158,17.09996l213.75757,212.46631a81.61801,81.04246 0 0 1 -24.70304,131.36982l-75.74151,33.30845l-142.09696,141.257l-11.26329,155.3854a81.61801,81.04246 0 0 1 -139.13151,51.46196l-137.98885,-137.15085l-235.14149,234.56388l-57.83996,-57.18896l235.27751,-234.69896l-142.7499,-141.85131a81.61801,81.04246 0 0 1 51.6642,-138.09635l160.95072,-11.94025l139.5668,-138.74469l32.78324,-75.09935a81.61801,81.04246 0 0 1 107.35489,-42.14208zm-32.45675,74.36997l-38.95901,89.22775l-171.94193,170.99958l-191.25821,14.1284l338.46989,336.3262l13.43977,-185.47917l174.33607,-173.32279l89.69819,-39.44067l-213.78477,-212.43929z"></path></svg>
<svg id="locBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("locBtn")}</title><path d="M357.6 832l-255.2 56c-20 4.8-39.2-10.4-39.2-31.2V569.6c0-15.2 10.4-28 24.8-31.2L243.2 504l53.6 53.6L139.2 592c-7.2 1.6-12.8 8-12.8 16v188c0 10.4 9.6 17.6 19.2 16l192.8-42.4 12.8-3.2 12.8 2.4 306.4 60.8 210.4-47.2c7.2-1.6 12.8-8 12.8-16V580c0-10.4-9.6-17.6-19.2-16L688 606.4l-12 2.4L760 524.8l160.8-36c20-4.8 39.2 10.4 39.2 31.2v286.4c0 15.2-10.4 28-24.8 31.2L672.8 896M512 128c-115.2 0-206.4 101.6-190.4 220 5.6 41.6 26.4 80 56 109.6l0.8 0.8L512 591.2l133.6-132.8 0.8-0.8c29.6-29.6 49.6-68 56-109.6C719.2 229.6 627.2 128 512 128m0-64c141.6 0 256 114.4 256 256 0 70.4-28 133.6-74.4 180L512 681.6 330.4 500C284.8 453.6 256 390.4 256 320 256 178.4 371.2 64 512 64z m64.8 193.6c0-35.2-28.8-64-64-64s-64 28.8-64 64 28.8 64 64 64 64-28 64-64z"></path></svg>
</span>
<div id="addons"></div>
</div>
</div>
<div id="rightSizeChange"></div>
`);
searchBarCon.appendChild(searchInputDiv);
this.searchInputDiv = searchInputDiv;
this.searchInput = searchInputDiv.querySelector("#searchJumperInput");
this.searchJumperInputKeyWords = searchInputDiv.querySelector("#searchJumperInputKeyWords");
this.searchLockInput = searchInputDiv.querySelector(".search-jumper-lock-input");
this.searchJumperInPageInput = searchInputDiv.querySelector("#searchJumperInPageInput");
this.pickerBtn = searchInputDiv.querySelector("#pickerBtn");
this.minEleBtn = searchInputDiv.querySelector("#minEleBtn");
this.maxEleBtn = searchInputDiv.querySelector("#maxEleBtn");
this.copyEleBtn = searchInputDiv.querySelector("#copyEleBtn");
this.openLinkBtn = searchInputDiv.querySelector("#openLinkBtn");
this.editBtn = searchInputDiv.querySelector("#editBtn");
this.addWord = searchInputDiv.querySelector("#addWord");
this.recoverBtn = searchInputDiv.querySelector("#recoverBtn");
this.wordModeBtn = searchInputDiv.querySelector("#wordModeBtn");
this.saveRuleBtn = searchInputDiv.querySelector("#saveRuleBtn");
this.pinBtn = searchInputDiv.querySelector("#pinBtn");
this.locBtn = searchInputDiv.querySelector("#locBtn");
this.emptyBtn = searchInputDiv.querySelector("#emptyBtn");
this.copyInPageBtn = searchInputDiv.querySelector("#copyInPageBtn");
this.closeBtn = searchInputDiv.querySelector(".closeBtn");
this.filterSites = searchInputDiv.querySelector("#filterSites");
this.filterSitesTab = searchInputDiv.querySelector("#filterSitesTab");
this.searchInPageTab = searchInputDiv.querySelector("#searchInPageTab");
this.searchInPageLockWords = searchInputDiv.querySelector("#searchInPage>.lockWords");
this.contentContainer = searchInputDiv.querySelector(".content-container");
this.rightSizeChange = searchInputDiv.querySelector("#rightSizeChange");
this.filterGlob = searchInputDiv.querySelector("#filterGlob");
this.suggestDatalist = searchInputDiv.querySelector("#suggest");
this.addonsList = searchInputDiv.querySelector("#addons");
this.fakeTextareas = new Map();
this.addonCheckboxDict = {};
}
showInPageSearch() {
this.searchInPageTab.checked = true;
this.showSearchInput();
this.initSetInPageWords();
this.searchJumperInPageInput.value = "";
this.initShowSearchInput = true;
}
showFilterSearch() {
this.filterSitesTab.checked = true;
this.showSearchInput();
}
initSetInPageWords() {
if (this.searchInPageTab.checked && !this.searchJumperInPageInput.value) {
let words = getSelectStr() || this.searchJumperInputKeyWords.value.replace(/^\*/, "") || getKeywords();
if (words) {
try {
words = decodeURIComponent(words);
} catch (e) {}
}
if (this.lockWords && this.lockWords.indexOf(words) !== -1) return;
this.searchJumperInPageInput.value = words || globalInPageWords;
if (!this.lockWords) {
this.submitIgnoreSpace(this.searchJumperInPageInput.value);
//this.submitInPageWords();
}
}
}
anylizeInPageWords(words, init) {
if (!words) return [];
let self = this;
let result = [];
if (!this.lockWords) {
if (words.indexOf("$c") === 0 && words.length > 2) {
words = words.substr(3).trim();
} else if (words.indexOf("$o") === 0) {
words = words.substr(2).trim();
}
}
if (this.splitSep) {
let inWordMode = this.wordModeBtn.classList.contains("checked");
let splitSep = inWordMode ? new RegExp(`[\\${this.splitSep} ]`) : this.splitSep;
words.split(splitSep).sort((a, b) => b.length - a.length).forEach(word => {
let oriWord = word;
word = word.trim();
if (!word) return;
if (init) {
if (word.length < (searchData.prefConfig.limitInPageLen || 1)) return;
if ((searchData.prefConfig.ignoreWords || []).includes(word.toLowerCase())) return;
}
let title = "";
let style = "";
let popup = false;
let hideParent;
let link;
let inRange;
let isRe = false;
let reCase = "";
let titleReg = /\$t{(.*?)}($|\$)/;
let titleMatch = word.match(titleReg);
let showTips = 0;
if (titleMatch) {
title = titleMatch[1];
word = word.replace(titleReg, "$2");
if (title == "\\$popup") title = "$popup";
else if (title == "\\@popup") title = "@popup";
else {
let popupMatch = title.match(/^[\$@]popup(\((.*)\))?$/);
if (popupMatch) {
title = "";
popup = true;
if (popupMatch[1]) {
showTips = popupMatch[2] || "1";
}
}
}
}
let hideParentReg = /\$p{(.*?)}($|\$)/;
let hideParentMatch = word.match(hideParentReg);
if (hideParentMatch) {
hideParent = parseInt(hideParentMatch[1]) || 0;
word = word.replace(hideParentReg, "$2");
}
let inRangeReg = /\$in{(.*?)}($|\$)/;
let inRangeMatch = word.match(inRangeReg);
if (inRangeMatch) {
inRange = inRangeMatch[1] || '';
word = word.replace(inRangeReg, "$2");
}
let styleReg = /\$s{(.*?)}($|\$)/;
let styleMatch = word.match(styleReg);
if (styleMatch) {
let bg = styleMatch[1], otherCss = "";
styleMatch = styleMatch[1].match(/(.*?);(.*)/);
if (styleMatch) {
bg = styleMatch[1];
otherCss = styleMatch[2];
}
style = self.getHighlightStyle(self.curWordIndex, bg, otherCss);
word = word.replace(styleReg, "$2");
} else {
style = self.getHighlightStyle(self.curWordIndex, "", "");
}
let showWords = "";
if (word.indexOf("@") === 0) {
showWords = word;
let wordTemp = searchData.prefConfig.inPageRule && searchData.prefConfig.inPageRule[word];
if (wordTemp) word = wordTemp;
//else return;
} else {
word = word.replace(/^\\@/, "@");
}
let reMatch = word.match(/^\/(.*)\/([il]*)($|\$)/);
if (reMatch) {
isRe = true;
word = reMatch[1];
reCase = reMatch[2].indexOf("i") != -1 ? "i" : "";
link = reMatch[2].indexOf("l") != -1;
}
if (!showWords) showWords = word;
if (self.highlightSpans[showWords]) return;
result.push({content: word, showWords: showWords, isRe: isRe, link: link, reCase: reCase, title: title, style: style, oriWord: oriWord, hideParent: hideParent, inRange: inRange, popup: popup, showTips: showTips, init: init});
self.curWordIndex++;
});
} else {
this.curWordIndex = 0;
let word = (this.lockWords || "").replace(/^\$o/, "") + words;
result = [{content: word, showWords: word, isRe: false, reCase: "", title: "", style: self.getHighlightStyle(self.curWordIndex, "", ""), init: init}];
}
return result;
}
submitInPageWords(init) {
let self = this;
let words = this.searchJumperInPageInput.value;
let wordSpans = [];
if (!words) {
if (!this.lockWords) {
this.highlight("");
} else {
this.highlight("insert");
for (let i in this.highlightSpans) {
let span = this.highlightSpans[i];
let curList = this.marks[i];
this.setHighlightSpan(span, 0, curList);
}
}
return wordSpans;
}
this.initHighlight = !!init;
if (this.initHighlight) {
setTimeout(() => {
this.initHighlight = false;
}, 500);
}
if (!this.lockWords) {
if (words.indexOf("$c") === 0 && words.length > 2) {
this.splitSep = words.substr(2, 1);
} else if (words.indexOf("$o") === 0) {
this.splitSep = null;
} else this.splitSep = "◎";
this.curWordIndex = 0;
}
this.searchJumperInPageInput.value = "";
let targetWords = this.anylizeInPageWords(words, this.initHighlight);
if (!targetWords || targetWords.length == 0) return wordSpans;
if (this.lockWords) {
this.lockWords += (this.lockWords.indexOf(this.splitSep) === this.lockWords.length - this.splitSep.length ? "" : this.splitSep) + words;
} else this.lockWords = words;
if (!this.splitSep) {
this.searchInPageLockWords.innerHTML = createHTML();
this.highlight("");
}
this.highlight(targetWords);
targetWords.forEach(word => {
if (!word) return;
let wordSpan = document.createElement("span");
wordSpan.innerHTML = createHTML(word.showWords);
wordSpan.title = word.title ? JSON.parse('"' + word.title + '"') : word.showWords;
let background = word.style.match(/background: *(#?\w+)/);
if (background && background[1].indexOf('unset') === -1) wordSpan.style.background = background[1];
let color = word.style.match(/color: *(#?\w+)/);
if (color) wordSpan.style.color = color[1];
wordSpan.addEventListener("click", e => {
e.stopPropagation();
e.preventDefault();
return false;
});
wordSpan.oncontextmenu = e => {
e.preventDefault();
};
wordSpan.addEventListener('dblclick', e => {
e.stopPropagation();
e.preventDefault();
if (e.target.nodeName.toUpperCase() === 'EM') return;
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) return;
if (this.lockWords.indexOf(word.oriWord) === -1) {
return;
}
this.showModifyWindow(word, wordSpan);
}, true);
wordSpan.addEventListener("mousedown", e => {
if (e.button === 0) {
this.focusHighlightByText(word.showWords, true, wordSpan);
} else if (e.button === 2){
this.focusHighlightByText(word.showWords, false, wordSpan);
}
});
let wheelScrolling = false;
wordSpan.addEventListener(getSupportWheelEventName(), e => {
e.preventDefault();
e.stopPropagation();
if (wheelScrolling) return;
wheelScrolling = true;
setTimeout(() => {
wheelScrolling = false;
}, 100);
let deltaY;
if(e.type !== 'wheel'){
let y = 0;
if (typeof e.axis == 'number') {
if (e.axis == 2) {
y = e.detail;
}
} else {
if (typeof e.wheelDeltaY == 'undefined' || e.wheelDeltaY != 0) {
y = -e.wheelDelta / 40;
}
};
deltaY = y;
} else {
deltaY = e.deltaY;
}
this.focusHighlightByText(word.showWords, deltaY > 0, wordSpan);
}, { passive: false, capture: false });
wordSpan.addEventListener("editword", e => {
wordSpan.parentNode.removeChild(wordSpan);
this.removeHighlightWord(word);
this.searchJumperInPageInput.value = word.content;
});
let removeBtn = document.createElement("div");
removeBtn.addEventListener("mousedown", e => {
e.stopPropagation();
e.preventDefault();
/*if (this.wordModeBtn.classList.contains("checked")) {
this.wordModeBtn.classList.remove("checked");
if (this.lockWords) {
this.refreshPageWords(this.lockWords);
}
return;
}*/
wordSpan.parentNode.removeChild(wordSpan);
this.removeHighlightWord(word);
});
removeBtn.className = "lockWordTool";
removeBtn.innerHTML = createHTML(`<span title="${i18n("removeBtn")}">×</span>`);
wordSpan.appendChild(removeBtn);
let modifyBtn = document.createElement("div");
modifyBtn.addEventListener("mousedown", e => {
e.stopPropagation();
e.preventDefault();
if (this.lockWords.indexOf(word.oriWord) === -1) {
return;
}
this.showModifyWindow(word, wordSpan);
});
modifyBtn.className = "lockWordTool modifyBtn";
modifyBtn.innerHTML = createHTML(`<span>+</span>`);
wordSpan.appendChild(modifyBtn);
let curList = this.marks[word.showWords];
this.setHighlightSpan(wordSpan, -1, curList);
this.highlightSpans[word.showWords] = wordSpan;
this.searchInPageLockWords.appendChild(wordSpan);
wordSpans.push(wordSpan);
});
if (this.searchInPageLockWords.scrollTop <= 0) this.searchInPageLockWords.scrollTop = this.searchInPageLockWords.scrollHeight;
this.searchJumperInPageInput.style.paddingLeft = this.searchInPageLockWords.clientWidth + 3 + "px";
if (this.navMarks.innerHTML && this.con.style.display === "none") this.con.style.display = "";
return wordSpans;
}
async showCustomInputWindow(url, callback) {
return new Promise((resolve) => {
this.customInputCallback = callback;
let geneFinalUrl = () => {
let finalValue = this.finalSearch.dataset.url;
[].forEach.call(this.customGroup.children, ele => {
let value = ele.value;
if (ele.className == "select") {
value = ele.children[0].value;
} else if (/^DIV$/i.test(ele.nodeName)) return;
finalValue = finalValue.replace('◎', value || '');
});
this.finalSearch.value = finalValue;
};
if (!this.customInputFrame) {
let customInputCssText = `
.customInputFrame-body {
width: 300px;
min-height: 200px;
position: fixed;
text-align: left;
left: 50%;
top: 50%;
margin-top: -160px;
margin-left: -150px;
z-index: 2147483647;
background-color: #ffffff;
border: 1px solid #afb3b6;
border-radius: 10px;
opacity: 0.95;
filter: alpha(opacity=95);
box-shadow: 5px 5px 20px 0px #000;
color: #6e7070;
font-size: initial;
}
.customInputFrame-body #customGroup {
max-height: 50vh;
overflow: auto;
scrollbar-width: none;
}
.customInputFrame-body #customGroup::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
.customInputFrame-title {
background: #458bd1!important;
display: flex!important;
align-items: center!important;
justify-content: center!important;
color: white!important;
font-weight: bold;
font-size: 18px!important;
border-radius: 10px 10px 0 0!important;
}
.customInputFrame-title>img {
margin: 5px;
height: 32px;
width: 32px;
}
.customInputFrame-input-title {
font-size: 9pt;
font-family: Arial, sans-serif;
display: inline-block;
background-color: white;
position: relative;
left: 20px;
padding: 0px 4px;
text-align: left;
color: #646464;
word-break: break-all;
max-width: 85%;
z-index: 1;
}
.customInputFrame-body input[type=text],
.customInputFrame-body input[type=number],
.customInputFrame-body textarea,
.customInputFrame-body .select {
resize: both;
font-size: 11pt;
font-weight: normal;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.23);
margin: 4px;
font-family: inherit;
background-color: #FFF;
width: calc(100% - 8px);
color: #4A4A4A;
margin-top: -8px;
padding: 4px;
padding-top: 8px;
box-sizing: border-box;
}
.customInputFrame-buttons {
text-align: center;
margin-bottom: 5px;
display: flex;
justify-content: space-evenly;
}
.customInputFrame-buttons>button {
width: 32%;
font-size: 16px;
cursor: pointer;
border: 1px solid #1976d2;
border-radius: 4px;
transition: all .3s;
color: #fff;
background-color: #458bd1;
line-height: 25px;
}
.customInputFrame-buttons>button:hover {
color: #e3f2fd;
}
.customInputFrame-body .select {
height: 30px;
position: relative;
}
.customInputFrame-body .select>input[type=text] {
top: 0px;
left: -7px;
position: relative;
border: unset!important;
width: calc(100% - 25px);
padding-bottom: 3px;
margin-bottom: -30px;
float: left;
background: unset;
height: 28px;
}
.customInputFrame-body .select>p {
padding: 0;
margin: 0;
position: absolute;
pointer-events: none;
}
.customInputFrame-body .select>.options {
position: absolute;
visibility: hidden;
opacity: 0;
transition: opacity .1s;
background-color: #FFF;
color: #4A4A4A;
border: 1px solid rgba(0, 0, 0, 0.23);
border-radius: 4px;
z-index: 10;
width: auto;
max-width: 35%;
right: calc(50% - 147px);
margin-top: -10px;
position: fixed;
}
.customInputFrame-body .select>input:focus+p {
display: none;
}
.customInputFrame-body .select:hover>.options {
visibility: visible;
opacity: 1;
}
.customInputFrame-body .select>.options>p {
cursor: pointer;
min-height: 20px;
padding: 3px 0;
margin: 0;
}
.customInputFrame-body .select>.options>p:hover {
background: aliceblue;
}
.customInputFrame-body div.select:after {
content: "▼";
position: absolute;
right: 6px;
top: 8px;
font-size: 9px;
}
@media (prefers-color-scheme: dark) {
.customInputFrame-body,
.customInputFrame-input-title,
.customInputFrame-body input,
.customInputFrame-body textarea,
.customInputFrame-body .select {
background-color: black!important;
color: #d5d5d5!important;
}
.customInputFrame-body input:focus,
.customInputFrame-body textarea:focus,
.customInputFrame-body .select:focus {
background-color: #1e1e1e!important;
}
.customInputFrame-body input,
.customInputFrame-body textarea,
.customInputFrame-body .select {
border: 1px solid rgb(255 255 255 / 36%)!important;
background-color: #0c0c0c!important;
}
.customInputFrame-title,
.customInputFrame-buttons>button {
background: #245d8f!important;
}
.customInputFrame-body .select>.options {
border: 1px solid rgb(255 255 255 / 36%)!important;
background-color: black;
color: #d5d5d5;
}
.customInputFrame-body .select>.options>p:hover {
background: #1e1e1e;
}
}
`;
let customInputCssEle = _GM_addStyle(customInputCssText);
let customInputFrame = document.createElement("div");
this.customInputFrame = customInputFrame;
customInputFrame.innerHTML = createHTML(`
<div class="customInputFrame-body">
<a href="${configPage}" class="customInputFrame-title" target="_blank">
<img width="32px" height="32px" src="${logoBase64}" />${i18n("customInputFrame")}
</a>
<div id="customGroup">
</div>
<div class="customInputFrame-input-title">${i18n("finalSearch")}</div>
<textarea name="finalSearch" type="text"></textarea>
<div class="customInputFrame-buttons">
<button id="cancel" type="button">${i18n("cancel")}</button>
<button id="customSubmit" type="button">${i18n("customSubmit")}</button>
</div>
</div>
`);
if (!disabled) customInputFrame.appendChild(customInputCssEle);
let cancelBtn = customInputFrame.querySelector("#cancel");
cancelBtn.addEventListener("click", e => {
if (customInputFrame.parentNode) {
customInputFrame.parentNode.removeChild(customInputFrame);
}
resolve("");
});
customInputFrame.addEventListener("keydown", e => {
if (e.keyCode == 13) {
customSubmit.click();
}
});
let customGroup = this.customInputFrame.querySelector("#customGroup");
this.customGroup = customGroup;
let finalSearch = this.customInputFrame.querySelector("[name='finalSearch']");
this.finalSearch = finalSearch;
finalSearch.addEventListener("click", e => {
geneFinalUrl();
});
let customSubmit = customInputFrame.querySelector("#customSubmit");
customSubmit.addEventListener("click", e => {
geneFinalUrl();
if (finalSearch.value) {
if (this.customInputCallback) this.customInputCallback(finalSearch.value);
}
resolve(finalSearch.value);
if (customInputFrame.parentNode) {
customInputFrame.parentNode.removeChild(customInputFrame);
}
});
}
if (this.customInputFrame.parentNode) {
this.customInputFrame.parentNode.removeChild(this.customInputFrame);
}
this.customGroup.innerHTML = createHTML();
let tempUrl = url;
let inputMatch = tempUrl.match(/%input{(.*?[^\\])}/);
while (inputMatch) {
let param = inputMatch[1];
if (/^".*","/.test(param)) {
param = param.substr(1, param.length - 2).split('","');
} else {
param = param.replace(/\\,/g, "◎SJ").split(",").map(str => str.replace(/◎SJ/g, ","));
}
if (param.length === 1) {//input
param = param[0].replace(/\\\|/g, "◎SJ").split("|").map(str => str.replace(/◎SJ/g, "|"));
let inputTitle = document.createElement('div');
inputTitle.className = 'customInputFrame-input-title';
inputTitle.innerText = param[0];
this.customGroup.appendChild(inputTitle);
let paramInput = document.createElement('input');
paramInput.type = 'text';
if (param.length > 1) paramInput.title = param[1];
this.customGroup.appendChild(paramInput);
} else if (param.length >= 2) {//select
let titleSplit = param[0].replace(/\\}/g, "}");
if (/^'.*'\/'/.test(titleSplit)) {
titleSplit = titleSplit.substr(1, titleSplit.length - 2).split("'/'");
} else {
titleSplit = titleSplit.replace(/\\\//g, "◎SJ").split("/").map(str => str.replace(/◎SJ/g, "/"));
}
let optionSplit = param.slice(1).join(",");
if (/^'.*'\/'/.test(optionSplit)) {
optionSplit = optionSplit.substr(1, optionSplit.length - 2).split("'/'");
} else {
optionSplit = optionSplit.replace(/\\\//g, "◎SJ").split("/").map(str => str.replace(/◎SJ/g, "/"));
}
let singleTitle = titleSplit.length === optionSplit.length + 1;
let inputTitle = document.createElement('div');
inputTitle.className = 'customInputFrame-input-title';
inputTitle.innerText = titleSplit[0];
this.customGroup.appendChild(inputTitle);
let paramSelectInput = document.createElement('input');
paramSelectInput.type = "text";
let paramSelect = document.createElement('div');
paramSelect.className = "select";
paramSelect.appendChild(paramSelectInput);
let selectTips = document.createElement('p');
selectTips.innerText = 'Select option';
paramSelect.appendChild(selectTips);
let options = document.createElement('div');
options.className = "options";
paramSelect.appendChild(options);
let option = document.createElement("p");
option.setAttribute("value", "");
option.innerHTML = createHTML('<b>Select option</b>');
options.appendChild(option);
option.addEventListener("click", e => {
options.style.visibility = "hidden";
setTimeout(() => {
options.style.visibility = "";
}, 0);
paramSelectInput.value = "";
selectTips.innerText = 'Select option';
geneFinalUrl();
});
for (let i = 0; i < optionSplit.length; i++) {
let value = optionSplit[i];
let option = document.createElement("p");
option.setAttribute("value", value);
if (singleTitle) {
let title = titleSplit[i + 1];
title = title.replace(/\\\|/g, "◎SJ").split("|").map(str => str.replace(/◎SJ/g, "|"));
option.innerText = title[0];
if (title.length > 1) {
option.title = title[1];
}
} else {
option.innerText = value;
}
option.addEventListener("click", e => {
options.style.visibility = "hidden";
setTimeout(() => {
options.style.visibility = "";
}, 0);
paramSelectInput.value = option.getAttribute("value");
selectTips.innerText = '';
geneFinalUrl();
});
options.appendChild(option);
}
paramSelectInput.addEventListener("change", e => {
selectTips.innerText = '';
});
paramSelect.addEventListener("mouseenter", e => {
paramSelect.focus();
options.style.marginTop = - this.customGroup.scrollTop + 20 + "px";
});
this.customGroup.appendChild(paramSelect);
}
tempUrl = tempUrl.replace(inputMatch[0], '◎');
inputMatch = tempUrl.match(/%input{(.*?[^\\])}/);
}
this.finalSearch.dataset.url = tempUrl;
this.finalSearch.value = tempUrl.replace(/◎/g, '');
this.addToShadow(this.customInputFrame);
let frameBody = this.customInputFrame.children[0];
frameBody.style.marginTop = -frameBody.offsetHeight / 2 + "px";
});
}
showModifyWindow(word, wordSpan) {
let oriWord;
this.modifyWord = {};
this.addNew = !word && !wordSpan;
if (!this.addNew) {
oriWord = word.oriWord;
if (!oriWord) return;
this.modifyWord = word;
this.modifySpan = wordSpan;
}
if (!this.modifyFrame) {
let modifyCssText = `
.searchJumperModify-body {
width: 300px;
min-height: 200px;
position: fixed;
text-align: left;
left: 50%;
top: 50%;
margin-top: -160px;
margin-left: -150px;
z-index: 100000;
background-color: #ffffff;
border: 1px solid #afb3b6;
border-radius: 10px;
opacity: 0.95;
filter: alpha(opacity=95);
box-shadow: 5px 5px 20px 0px #000;
color: #6e7070;
}
.searchJumperModify-title {
background: #458bd1!important;
display: flex!important;
align-items: center!important;
justify-content: center!important;
color: white!important;
font-weight: bold;
font-size: 18px!important;
border-radius: 10px 10px 0 0!important;
}
.searchJumperModify-title>img {
margin: 5px;
height: 32px;
width: 32px;
}
.searchJumperModify-input-title {
font-size: 9pt;
font-family: Arial, sans-serif;
display: inline-block;
background-color: white;
position: relative;
left: 20px;
padding: 0px 4px;
text-align: left;
color: #646464;
}
.searchJumperModify-body>input[type=text],
.searchJumperModify-body>input[type=number],
.searchJumperModify-body>textarea {
resize: both;
font-size: 11pt;
font-weight: normal;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.23);
margin: 4px;
font-family: inherit;
background-color: #FFF;
width: calc(100% - 8px);
color: #4A4A4A;
margin-top: -8px;
padding: 4px;
padding-top: 8px;
box-sizing: border-box;
}
.searchJumperModify-buttons {
text-align: center;
margin-bottom: 5px;
display: flex;
justify-content: space-evenly;
}
.searchJumperModify-buttons>button {
width: 32%;
font-size: 16px;
cursor: pointer;
border: 1px solid #1976d2;
border-radius: 4px;
transition: all .3s;
color: #fff;
background-color: #458bd1;
line-height: 25px;
}
.searchJumperModify-buttons>button:hover {
color: #e3f2fd;
}
#rangePickerBtn {
width: 28px;
float: right;
margin-top: -33px;
margin-right: 6px;
position: sticky;
display: block;
cursor: pointer;
background: rgb(255 255 255 / 80%);
}
.searchJumperModify-checkGroup {
margin: 5px;
}
#searchJumperModify-re + label ~ * {
display: none;
}
#searchJumperModify-re:checked + label ~ * {
display: inline;
}
@media (prefers-color-scheme: dark) {
.searchJumperModify-body,
.searchJumperModify-input-title,
.searchJumperModify-body>input[type=text],
.searchJumperModify-body>input[type=number],
.searchJumperModify-body>textarea,
.searchJumperModify-body>select {
background-color: black!important;
color: #d5d5d5!important;
}
.searchJumperModify-body>input:focus,
.searchJumperModify-body>textarea:focus,
.searchJumperModify-body>select:focus {
background-color: #1e1e1e!important;
}
.searchJumperModify-body>input[type=text],
.searchJumperModify-body>input[type=number],
.searchJumperModify-body>textarea {
border: 1px solid rgb(255 255 255 / 36%)!important;
}
.searchJumperModify-title,
.searchJumperModify-buttons>button {
background: #245d8f!important;
}
#rangePickerBtn {
background: rgb(0 0 0 / 80%);
fill: white;
}
}
`;
let modifyCssEle = _GM_addStyle(modifyCssText);
let modifyFrame = document.createElement("div");
this.modifyFrame = modifyFrame;
modifyFrame.id = "searchJumperModifyWord";
modifyFrame.innerHTML = createHTML(`
<div class="searchJumperModify-body">
<a href="${configPage}" class="searchJumperModify-title" target="_blank">
<img onerror="this.style.display='none'" width="32px" height="32px" src="${logoBase64}" />${i18n("modifyWord")}
</a>
<div class="searchJumperModify-input-title">${i18n("wordContent")}</div>
<input id="searchJumperHighlightWord" name="wordContent" placeholder="words" type="text"/>
<div class="searchJumperModify-checkGroup">
<input id="searchJumperModify-re" type="checkbox"/>
<label for="searchJumperModify-re">${i18n("re")}</label>
<input id="searchJumperModify-case" type="checkbox"/>
<label for="searchJumperModify-case">${i18n("ignoreCase")}</label>
<input id="searchJumperModify-link" type="checkbox"/>
<label for="searchJumperModify-link">${i18n("filterLink")}</label>
</div>
<div class="searchJumperModify-input-title">${i18n("wordHide")}</div>
<input name="wordHide" min="0" placeholder="${i18n("wordHideTips")}" type="number" />
<div class="searchJumperModify-input-title">${i18n("wordRange")}</div>
<input name="wordRange" placeholder="#main" type="text" />
<svg id="rangePickerBtn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("pickerBtn")}</title><path d="M874.048 533.333333C863.424 716.629333 716.629333 863.424 533.333333 874.048V917.333333a21.333333 21.333333 0 0 1-42.666666 0v-43.285333C307.370667 863.424 160.576 716.629333 149.952 533.333333H106.666667a21.333333 21.333333 0 0 1 0-42.666666h43.285333C160.576 307.370667 307.370667 160.576 490.666667 149.952V106.666667a21.333333 21.333333 0 0 1 42.666666 0v43.285333c183.296 10.624 330.090667 157.418667 340.714667 340.714667h42.816a21.333333 21.333333 0 1 1 0 42.666666H874.026667z m-42.752 0h-127.786667a21.333333 21.333333 0 0 1 0-42.666666h127.786667C820.778667 330.922667 693.056 203.221333 533.333333 192.704V320a21.333333 21.333333 0 0 1-42.666666 0V192.704C330.922667 203.221333 203.221333 330.944 192.704 490.666667H320a21.333333 21.333333 0 0 1 0 42.666666H192.704c10.517333 159.744 138.24 287.445333 297.962667 297.962667V704a21.333333 21.333333 0 0 1 42.666666 0v127.296c159.744-10.517333 287.445333-138.24 297.962667-297.962667zM512 554.666667a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z"></path></svg>
<div class="searchJumperModify-input-title">${i18n("wordStyle")}</div>
<input name="wordStyle" placeholder="orange or #333333;color:red;" type="text" />
<div class="searchJumperModify-input-title">${i18n("wordTitle")}</div>
<textarea name="wordTitle" type="text" placeholder="Text comment, or @popup to popup, @popup(1) to popup 1st showTips, @popup(name) to popup showTips of target engine"></textarea>
<div class="searchJumperModify-buttons">
<button id="cancel" type="button">${i18n("cancel")}</button>
<button id="modify" type="button">${i18n("modify")}</button>
</div>
</div>
`);
if (!disabled) modifyFrame.appendChild(modifyCssEle);
let cancelBtn = modifyFrame.querySelector("#cancel");
cancelBtn.addEventListener("click", e => {
if (modifyFrame.parentNode) {
modifyFrame.parentNode.removeChild(modifyFrame);
}
});
let rangePickerBtn = modifyFrame.querySelector("#rangePickerBtn");
rangePickerBtn.addEventListener("click", e => {
picker.getSelector(selector => {
wordRange.value = selector;
modifyFrame.style.display = '';
});
modifyFrame.style.display = 'none';
});
let modifyBtn = modifyFrame.querySelector("#modify");
this.modifyBtn = modifyBtn;
modifyBtn.addEventListener("click", e => {
let newWord = wordContent.value;
if (this.splitSep) newWord = newWord.replaceAll(this.splitSep, "");
if (!newWord) return;
let contentChange = newWord !== this.modifyWord.showWords || wordReCase.checked !== this.modifyWord.isRe || wordLink.checked !== this.modifyWord.link;
if (wordIsRe.checked && newWord.indexOf("@") !== 0) {
newWord = `/${newWord}/${wordReCase.checked ? "i" : ""}${wordLink.checked ? "l" : ""}`;
}
let hide = wordHide.value;
if (hide) {
if (this.splitSep) hide = hide.replaceAll(this.splitSep, "");
hide = hide >= 0 ? hide : 0;
newWord += `$p{${hide}}`;
}
let style = wordStyle.value;
if (style) {
if (this.splitSep) style = style.replaceAll(this.splitSep, "");
newWord += `$s{${style}}`;
}
let title = JSON.stringify(wordTitle.value).replace(/^"|"$/g, "");
if (title) {
if (this.splitSep) title = title.replaceAll(this.splitSep, "");
newWord += `$t{${title}}`;
}
let range = wordRange.value;
if (range) {
if (this.splitSep) range = range.replaceAll(this.splitSep, "");
if (range !== this.modifyWord.inRange) contentChange = true;
newWord += `$in{${range}}`;
}
if (this.addNew) {
if (this.wordModeBtn.classList.contains("checked")) {
this.wordModeBtn.classList.remove("checked");
if (this.lockWords) {
this.refreshPageWords(this.lockWords);
}
}
this.searchJumperInPageInput.value = newWord;
this.submitInPageWords();
} else {
this.replaceWord(this.modifyWord, newWord, this.modifySpan, contentChange);
}
if (modifyFrame.parentNode) {
modifyFrame.parentNode.removeChild(modifyFrame);
}
});
}
let wordContent = this.modifyFrame.querySelector("[name='wordContent']"),
wordStyle = this.modifyFrame.querySelector("[name='wordStyle']"),
wordTitle = this.modifyFrame.querySelector("[name='wordTitle']"),
wordRange = this.modifyFrame.querySelector("[name='wordRange']"),
wordHide = this.modifyFrame.querySelector("[name='wordHide']"),
wordIsRe = this.modifyFrame.querySelector("#searchJumperModify-re"),
wordReCase = this.modifyFrame.querySelector("#searchJumperModify-case"),
wordLink = this.modifyFrame.querySelector("#searchJumperModify-link");
if (this.addNew) {
wordContent.value = "";
wordStyle.value = "";
wordRange.value = "";
wordHide.value = "";
wordTitle.value = "";
wordIsRe.checked = false;
wordReCase.checked = false;
wordLink.checked = false;
this.modifyBtn.innerText = i18n('add');
} else {
this.modifyBtn.innerText = i18n('modify');
let style = "";
let styleReg = /\$s{(.*?)}($|\$)/;
let styleMatch = oriWord.match(styleReg);
if (styleMatch) {
style = styleMatch[1];
}
wordContent.value = word.showWords || "";
wordStyle.value = style || "";
wordRange.value = word.inRange || "";
wordIsRe.checked = !!word.isRe;
wordReCase.checked = !!word.reCase;
wordLink.checked = !!word.link;
if (typeof word.hideParent !== 'undefined') wordHide.value = word.hideParent;
try {
if (word.popup) {
wordTitle.value = "@popup";
if (word.showTips) {
wordTitle.value = `@popup(${word.showTips})`;
}
} else {
wordTitle.value = word.title !== word.showWords ? JSON.parse('"' + word.title + '"') : "";
}
} catch (e) {
debug(e);
}
}
this.addToShadow(this.modifyFrame);
}
replaceWord(word, newWord, modifySpan, contentChange) {
if (contentChange) {
if (modifySpan.parentNode) modifySpan.parentNode.removeChild(modifySpan);
this.removeHighlightWord(word);
this.searchJumperInPageInput.value = newWord;
this.submitInPageWords();
} else {
let title = "";
let style = "";
let hideParent = -1;
let titleReg = /\$t{(.*?)}($|\$)/;
let titleMatch = newWord.match(titleReg);
if (titleMatch) {
title = titleMatch[1];
title = JSON.parse('"' + title + '"');
}
word.title = title;
modifySpan.title = title;
let styleReg = /\$s{(.*?)}($|\$)/;
let styleMatch = newWord.match(styleReg);
if (styleMatch) {
let bg = styleMatch[1], otherCss = "";
styleMatch = styleMatch[1].match(/(.*?);(.*)/);
if (styleMatch) {
bg = styleMatch[1];
otherCss = styleMatch[2];
}
style = this.getHighlightStyle(this.curWordIndex, bg, otherCss);
word.style = style;
modifySpan.style = style;
}
let hideChange = false;
let hideParentReg = /\$p{(.*?)}($|\$)/;
let hideParentMatch = newWord.match(hideParentReg);
if (hideParentMatch) {
hideParent = parseInt(hideParentMatch[1]) || 0;
hideChange = hideParent != word.hideParent;
} else hideChange = typeof word.hideParent !== 'undefined';
if (hideChange) {
[].forEach.call(document.querySelectorAll(".searchJumper-hide"), hide => {
if (hide.dataset.content === word.showWords) {
hide.classList.remove("searchJumper-hide");
hide.style.display = "";
hide.removeAttribute('data-content');
}
});
}
this.marks[word.showWords].forEach(mark => {
if (mark) {
mark.title = title;
if (style) mark.style = style;
if (hideChange && hideParent != -1) {
let parentDepth = hideParent;
let parent = mark.parentElement;
while(parentDepth-- > 0 && parent) {
parent = parent.parentElement;
}
if (parent) {
parent.dataset.content = word.showWords;
parent.classList.add("searchJumper-hide");
parent.innerHTML = createHTML("");
}
}
}
});
if (hideParent == -1) {
delete word.hideParent;
} else word.hideParent = hideParent;
this.lockWords = this.lockWords.replace(word.oriWord, newWord);
word.oriWord = newWord;
}
}
removeHighlightWord(word) {
if (!this.lockWords) return;
if (!this.splitSep) this.emptyInPageWords();
if (!word.oriWord) return;
if (this.lockWords.indexOf(word.oriWord) === -1) return;
let preStr = this.lockWords.match(/^\$(c.|o)/), findIndex, findNum = 0;
preStr = preStr ? preStr[0] : "";
let targetArr = this.lockWords.replace(preStr, "").split(this.splitSep);
findIndex = targetArr.indexOf(word.oriWord);
if (this.wordModeBtn.classList.contains("checked")) {
if (findIndex != -1) {
targetArr.splice(findIndex, 1);
findNum = 1;
}
for (let i = 0; i < targetArr.length; i++) {
let wordArr = targetArr[i].split(/[ ]/);
findIndex = wordArr.indexOf(word.oriWord);
if (findIndex != -1) {
findNum++;
if (findNum == 1) {
wordArr.splice(findIndex, 1);
targetArr[i] = wordArr.join(" ");
} else {
break;
}
}
}
this.lockWords = preStr + targetArr.join(this.splitSep);
} else {
if (findIndex < 0) return;
targetArr.splice(findIndex, 1);
findNum = targetArr.indexOf(word.oriWord) != -1 ? 2 : 1;
this.lockWords = preStr + targetArr.join(this.splitSep);
}
delete this.highlightSpans[word.showWords];
findIndex = this.curHighlightWords.indexOf(word);
if (findIndex < 0) return;
this.curHighlightWords.splice(findIndex, 1);
this.searchJumperInPageInput.style.paddingLeft = this.searchInPageLockWords.clientWidth + 3 + "px";
if (findNum > 1) return;
this.marks[word.showWords].forEach(mark => {
if (mark.parentNode) {
if (mark.dataset.block) {
mark.parentNode && mark.parentNode.removeChild(mark);
} else if (!/^MARK$/i.test(mark.nodeName)) {
mark.classList.remove("searchJumper");
mark.style.cssText = mark.dataset.css || "";
delete mark.dataset.css;
} else {
let newNode = document.createTextNode(mark.firstChild.data);
mark.parentNode.replaceChild(newNode, mark);
newNode.parentNode.normalize();
}
}
});
delete this.marks[word.showWords];
let children = [].slice.call(this.navMarks.children);
[].forEach.call(children, nav => {
if (nav.dataset.content == word.showWords) {
nav.parentNode.removeChild(nav);
}
});
}
emptyInPageWords() {
this.searchInPageLockWords.innerHTML = createHTML();
this.highlight("");
}
focusHighlightByText(text, fw, span) {
let curList = this.marks[text];
if (!curList || curList.length === 0) return;
if (text != this.focusText) {
this.focusIndex = 0;
this.focusText = text;
} else {
if (fw) {
if (this.focusIndex != curList.length - 1) {
this.focusIndex = this.focusIndex + 1;
} else this.focusIndex = 0;
} else {
if (this.focusIndex != 0) {
this.focusIndex = this.focusIndex - 1;
} else this.focusIndex = curList.length - 1;
}
}
let newIndex = this.focusIndex;
if (newIndex >= curList.length) newIndex = 0;
if (fw) {
while (!curList[newIndex].offsetParent || curList[newIndex].dataset.type) {
if (newIndex != curList.length - 1) {
newIndex = newIndex + 1;
} else newIndex = 0;
if (newIndex == this.focusIndex) break;
}
} else {
while (!curList[newIndex].offsetParent || curList[newIndex].dataset.type) {
if (newIndex != 0) {
newIndex = newIndex - 1;
} else newIndex = curList.length - 1;
if (newIndex == this.focusIndex) break;
}
}
this.focusIndex = newIndex;
this.focusHighlight(curList[this.focusIndex]);
this.setHighlightSpan(span, this.focusIndex, curList);
}
getRect(ele) {
let eleBCR = ele.getBoundingClientRect();
let rect = {
left: eleBCR.left,
top: eleBCR.top,
width: eleBCR.width,
height: eleBCR.height
};
let currentWindow = ele.ownerDocument && ele.ownerDocument.defaultView;
let currentFrame = currentWindow && currentWindow.frameElement;
while (currentFrame) {
const frameRect = currentFrame.getBoundingClientRect();
rect.left += frameRect.left;
rect.top += frameRect.top;
currentWindow = currentWindow.parent;
currentFrame = currentWindow.frameElement;
}
return rect;
}
focusHighlight(ele) {
if (!ele) return;
if (this.focusMark) this.focusMark.removeAttribute('data-current');
this.focusMark = ele;
if (!this.wPosBar) {
this.wPosBar = document.createElement("div");
this.hPosBar = document.createElement("div");
this.wPosBar.className = "searchJumperPosBar searchJumperPosW";
this.hPosBar.className = "searchJumperPosBar searchJumperPosH";
}
if (!this.wPosBar.parentNode) {
this.addToShadow(this.wPosBar);
this.addToShadow(this.hPosBar);
}
let rect = this.getRect(ele);
this.wPosBar.style.top = rect.top + document.documentElement.scrollTop + getBody(document).scrollTop + "px";
this.wPosBar.style.height = rect.height + "px";
this.hPosBar.style.left = rect.left + "px";
this.hPosBar.style.width = rect.width + "px";
this.wPosBar.style.animationName = "";
this.hPosBar.style.animationName = "";
let self = this;
setTimeout(async () => {
ele.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
ele.dataset.current = true;
self.wPosBar.style.animationName = "fadeit";
self.hPosBar.style.animationName = "fadeit";
self.fixTimes = 0;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
function fixPosBar() {
if (self.focusMark != ele) return;
let rect = self.getRect(ele);
self.wPosBar.style.top = rect.top + document.documentElement.scrollTop + getBody(document).scrollTop + "px";
self.hPosBar.style.left = rect.left + "px";
if (rect.top > viewHeight / 3 && rect.top < viewHeight / 3 * 2) return;
if (++self.fixTimes == 5) {
ele.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
} else if (self.fixTimes > 10) {
ele.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
self.wPosBar.style.animationName = "";
self.hPosBar.style.animationName = "";
return;
}
setTimeout(() => {
fixPosBar();
}, 200);
}
fixPosBar();
}, 0);
}
getHighlightSpanByText(text) {
return this.highlightSpans[text];
}
setHighlightSpan(span, index, list) {
if (!span) return;
let numEle = span.querySelector("em");
if (!numEle) {
numEle = document.createElement("em");
span.insertBefore(numEle, span.firstChild);
}
index++;
let len = 0;
if (list && list.length) {
len = 0;
list.forEach(e => {
if (!e.dataset.type) len++;
});
}
numEle.innerHTML = createHTML("[" + index + "/" + len + "]");
}
getHighlightStyle(index, background, addCssText) {
if (!background && !addCssText) {
let setCss = searchData.prefConfig.inPageWordsStyles[index];
if (setCss) return setCss;
}
addCssText = addCssText || "";
function geneRandomColor() {
let r, g, b;
r = Math.floor(256 * Math.random());
g = Math.floor(256 * Math.random());
b = Math.floor(256 * Math.random());
r = r.toString(16);
if (r.length === 1) r = "0" + r;
g = g.toString(16);
if (g.length === 1) g = "0" + g;
b = b.toString(16);
if (b.length === 1) b = "0" + b;
return "#" + r + g + b;
}
function getWordColor(bg) {
if (bg.indexOf("#") !== 0) return "";
if (bg === "#ffff00") return "black";
bg = bg.substr(1);
let r, g, b;
r = parseInt(bg.substr(0, 2), 16);
g = parseInt(bg.substr(2, 2), 16);
b = parseInt(bg.substr(4, 2), 16);
let bgBrightness = r * 0.299 + g * 0.587 + b * 0.114;
r = 255 - r;
g = 255 - g;
b = 255 - b;
let wordBrightness = r * 0.299 + g * 0.587 + b * 0.114;
let diff = Math.abs(wordBrightness - bgBrightness);
if (diff <= 128) {
if (bgBrightness > 158) {
return "#000000";
} else {
return "#FFFFFF";
}
}
r = r.toString(16);
if (r.length === 1) r = "0" + r;
g = g.toString(16);
if (g.length === 1) g = "0" + g;
b = b.toString(16);
if (b.length === 1) b = "0" + b;
return "#" + r + g + b;
}
if (!background) {
background = searchData.prefConfig.firstFiveWordsColor[index];
}
if (!background) {
switch (index) {
case 0:
background = "#ffff00";
break;
case 1:
background = "#e91e63";
break;
case 2:
background = "#00bcd4";
break;
case 3:
background = "#008000";
break;
case 4:
background = "#800080";
break;
default:
background = geneRandomColor();
break;
}
}
if (background) {
let color = getWordColor(background);
if (color) color = "color:" + color + "!important;";
background = `background:${background}!important;${color}`;
}
return `${background}${addCssText}`;
}
createNavMark(node, word, index, curList, scrollHeight) {
let self = this;
let navMark = document.createElement("span");
let top = getElementTop(node, self.targetIframe);
navMark.title = word.title || word.showWords;
navMark.dataset.top = top;
navMark.dataset.content = word.showWords;
navMark.style.top = top / scrollHeight * 100 + "%";
navMark.style.background = node.style.background || "yellow";
navMark.addEventListener("click", e => {
e.stopPropagation();
e.preventDefault();
self.focusIndex = index;
self.focusHighlight(node);
self.setHighlightSpan(self.getHighlightSpanByText(word.showWords), index, curList);
self.navPointer.style.display = "";
self.navPointer.style.top = navMark.offsetTop + 33 + "px";
return false;
}, true);
self.navMarks.appendChild(navMark);
}
anylizeDomWithTextPos(dom, result) {
if (!result) result = {text: "", data:{}};
if (!dom || !dom.childNodes || !dom.childNodes.length || (dom.nodeType == 1 && !dom.offsetParent && !dom.offsetHeight)) {
return result;
}
dom.childNodes.forEach(ele => {
if ((ele.classList && ele.classList.contains("searchJumper")) || /^(img|svg|picture|br|hr|textarea)$/i.test(ele.nodeName)) {
const start = result.text.length;
result.text += "\n";
result.data[start] = {node: ele, text: "\n"};
} else if (ele.offsetParent || ele.offsetHeight) {
if (/^(div|h\d|p|form|ul|li|ol|dl|address|menu|table|fieldset|td)$/i.test(ele.nodeName)) {
let start = result.text.length;
result.text += "\n";
result.data[start] = {node: {}, text: "\n"};
result = this.anylizeDomWithTextPos(ele, result);
start = result.text.length;
result.text += "\n";
result.data[start] = {node: {}, text: "\n"};
} else {
result = this.anylizeDomWithTextPos(ele, result);
}
} else if (ele.nodeType === 3) {
let textData;
if (ele.parentNode.nodeType == 1 && ele.parentNode.childNodes.length == 1) {
textData = ele.parentNode.innerText || ele.data;
} else {
textData = ele.data;
}
if (!textData || !textData.trim()) return;
const start = result.text.length;
result.text += textData;
result.data[result.text.length - 1] = {node: ele, text: textData};
}
});
return result;
}
highlightPopup(spannode, word) {
let self = this;
let targetShowTipsSite;
let mouseMoveHandler = e => {
if (targetShowTipsSite) {
self.clingPos(spannode, self.tips);
}
};
spannode.addEventListener("mouseenter", e => {
spannode.addEventListener("mousemove", mouseMoveHandler);
if (targetElement != spannode || !self.funcKeyCall) {
targetShowTipsSite = null;
targetElement = spannode;
if (word.showTips) {
if (/^\d+$/.test(word.showTips)) {
let firstType = self.autoGetFirstType();
let targetSites = firstType.querySelectorAll('a.search-jumper-btn[data-show-tips]:not(.notmatch)');
let index = parseInt(word.showTips) - 1;
targetShowTipsSite = targetSites[index];
} else {
targetShowTipsSite = self.getTargetSitesByName([word.showTips])[0];
}
}
self.setFuncKeyCall(true);
if (targetShowTipsSite) {
self.bar.style.setProperty("display", "none", "important");
targetShowTipsSite.dispatchEvent(new CustomEvent('showTips'));
} else {
self.showInPage(true, e);
}
}
});
spannode.addEventListener("mouseleave", e => {
spannode.removeEventListener("mousemove", mouseMoveHandler);
});
}
createHighlightMark(word, index, curList) {
let self = this;
let spannode = document.createElement("mark");
spannode.className = "searchJumper";
if (word.title) spannode.title = JSON.parse('"' + word.title + '"');
if (word.popup) {
this.highlightPopup(spannode, word);
}
spannode.style.cssText = word.style;
spannode.addEventListener("click", e => {
if (!e.altKey) return;
e.stopPropagation();
e.preventDefault();
return false;
});
spannode.dataset.content = word.showWords;
spannode.addEventListener("mousedown", e => {
if (!e.altKey) return;
let target;
let newIndex = index;
while (!target || target.dataset.type) {
if (e.button === 0) {
if (newIndex != curList.length - 1) {
newIndex++;
self.focusIndex = newIndex;
} else self.focusIndex = 0;
} else if (e.button === 2){
if (newIndex != 0) {
newIndex--;
self.focusIndex = newIndex;
} else self.focusIndex = curList.length - 1;
}
target = curList[self.focusIndex];
if (newIndex == index) break;
}
self.focusHighlight(target);
self.setHighlightSpan(self.getHighlightSpanByText(word.showWords), self.focusIndex, curList);
self.focusText = word.showWords;
});
return spannode;
}
createAddonSpan(name, data) {
let index = "addon_" + this.addonsList.children.length, self = this;
let con = document.createElement("div");
let checkbox = document.createElement("input");
checkbox.type = 'checkbox';
checkbox.id = index;
checkbox.checked = !data.disable;
checkbox.addEventListener("change", e => {
searchData.prefConfig.disableAddon[name] = !checkbox.checked;
data.disable = !checkbox.checked;
if (checkbox.checked) {
self.findInpageAddons.forEach(addon => {
if (addon != data && addon.sort == data.sort) {
addon.disable = true;
let _name = addon.name || ("addon" + index++);
self.addonCheckboxDict[_name].checked = false;
searchData.prefConfig.disableAddon[_name] = true;
}
});
}
storage.setItem("searchData", searchData);
if (self.lockWords) {
self.refreshPageWords(self.lockWords);
}
});
con.appendChild(checkbox);
con.title = data.title || "";
let label = document.createElement("label");
label.setAttribute("for", index);
label.innerText = name;
con.appendChild(label);
this.addonCheckboxDict[name] = checkbox;
this.addonsList.appendChild(con);
}
findAccentedWord(text, searchWord, normalizeArray) {
const searchLength = searchWord.length;
let normalizedIndex = 0;
let startIndex = -1;
for (let i = 0; i < text.length; i++) {
const normalized = normalizeArray[i];
if (normalized === "") {
continue;
}
if (normalized === searchWord[normalizedIndex]) {
if (normalizedIndex === 0) startIndex = i;
normalizedIndex++;
if (normalizedIndex === searchLength) {
return {
pos: startIndex,
len: i - startIndex + 1
};
}
} else {
normalizedIndex = 0;
startIndex = -1;
if (normalized === searchWord[0]) {
startIndex = i;
normalizedIndex = 1;
}
}
}
startIndex = text.indexOf(searchWord);
return {len: searchWord.length, pos: startIndex};
}
findPosInStr(content, kw, contentUp, wordUp, normalizeArray) {
if (!content) {
return {len: 0, pos: -1};
}
let len = 0, pos = -1, hasAddon = false;
if (this.findInpageAddons.length) {
for (let i = 0; i < this.findInpageAddons.length; i++) {
let curAddon = this.findInpageAddons[i];
if (!curAddon || !curAddon.run || curAddon.disable) continue;
hasAddon = true;
let curData = curAddon.run(content, kw);
if (curData && curData.matched) {
len = curData.len;
pos = curData.pos;
break;
}
}
}
if (pos == -1 && !hasAddon) {
return this.findAccentedWord(contentUp, wordUp, normalizeArray);
}
return {len: len, pos: pos};
}
highlight(words, ele, root, iframe) {
if (!words && (!this.curHighlightWords || this.curHighlightWords.length === 0)) return;
if (!ele) {
this.highlight(words, getBody(document), root);
return;
}
[].forEach.call(ele.getElementsByTagName("iframe"), iframe => {
if (!iframe.offsetParent) return;
if (iframe.offsetHeight < 100 || iframe.offsetWidth < 100) return;
let iframeDoc;
try {
iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
} catch(e) {
return;
}
if (iframeDoc && getBody(iframeDoc)) {
this.highlight(words, getBody(iframeDoc), root, iframe);
}
});
this.targetIframe = iframe || false;
if (ele.id == "searchJumperModifyWord") return;
ele = ele || getBody(document);
let inWordMode = this.wordModeBtn.classList.contains("checked");
let preEles = [];
let searchingPre = false;
let self = this;
if (words === "") {
this.highlightSpans = {};
Object.values(this.marks).forEach(async markList => {
if (!markList) return;
let normalizeSet = new Set();
for (let mark of markList) {
if (!mark.parentNode) continue;
if (mark.dataset.block) {
mark.parentNode && mark.parentNode.removeChild(mark);
} else if (!/^MARK$/i.test(mark.nodeName)) {
mark.classList.remove("searchJumper");
mark.style.cssText = mark.dataset.css || "";
delete mark.dataset.css;
} else {
let newNode = document.createTextNode(mark.firstChild.data);
mark.parentNode.replaceChild(newNode, mark);
normalizeSet.add(newNode.parentNode);
}
}
normalizeSet.forEach(node => {node.normalize();});
});
[].forEach.call(ele.querySelectorAll(".searchJumper-hide"), hide => {
hide.classList.remove("searchJumper-hide");
hide.style.display = "";
hide.removeAttribute('data-content');
});
this.navMarks.innerHTML = createHTML();
this.marks = {};
this.curHighlightWords = [];
return;
}
if (!this.inPageStyle) {
this.inPageStyle = _GM_addStyle(this.inPageCss);
}
if (!this.inPageStyle.parentNode) {
document.head.appendChild(this.inPageStyle);
}
let insert = (words === "insert");
if (insert) {
words = this.curHighlightWords;
this.refreshNavMarks();
} else {
this.curHighlightWords = (this.curHighlightWords || []).concat(words);
}
this.fakeTextareas = new Map();
let scrollHeight = Math.max(document.documentElement.scrollHeight, getBody(document).scrollHeight);
this.navMarks.style.display = "none";
let navMarkParams = [];
function searchWithinNode(node, word, start) {
let len, pos = -1, skip, spannode, middlebit, middleclone;
skip = 0;
let pa = node.parentNode;
if (node.nodeType == 1 && node.className && node.className.indexOf && node.className.indexOf("searchJumper") != -1) return 0;
if (start && (node.nodeType == 1 || node.nodeType == 11)) {
let domTextResult = self.anylizeDomWithTextPos(node);
let textRes = domTextResult.text;
let textResUp = textRes.toUpperCase();
let normalizeArray = [];
for (let i = 0; i < textResUp.length; i++) {
const normalized = textResUp[i].normalize("NFD").replace(/[\u0300-\u036f]/g, "");
normalizeArray.push(normalized);
}
let wordUp = word.content.toUpperCase();
let dataRes = domTextResult.data;
let index = 0;
let nodeAndPos = [];
let validWord = (word.init || inWordMode) && /^[a-z]+$/i.test(word.content);
function getNodePos(pos, len, matchedText) {
let keys = Object.keys(domTextResult.data);
let findNodes = [], leftLen = len;
let pre = "", after = "", after2 = "";
for (let i = 0; i < keys.length; i++) {
let end = parseInt(keys[i]);
let curnode = domTextResult.data[end];
if (pos > end) continue;
let curpos = pos - (end - curnode.text.length) - 1;
let type = "full";
if (curpos < 0) {
if (curnode.text.length < leftLen) {
type = "middle";
} else {
type = "end";
}
} else {
if (curnode.text.length - curpos < leftLen) {
type = "start";
}
}
if (type === "full") matchedText = "";
if (validWord) {
if (type == "full") {
pre = curpos == 0 ? "\n" : curnode.text[curpos - 1];
after = (curpos + leftLen) == curnode.text.length ? "\n" : curnode.text[curpos + leftLen];
if (after !== "\n") {
after2 = (curpos + leftLen + 1) == curnode.text.length ? "\n" : curnode.text[curpos + leftLen + 1];
}
} else if (type == "start" && !pre) {
pre = curpos == 0 ? "\n" : curnode.text[curpos - 1];
} else if ((type == "end" || type == "full") && !after) {
after = (curpos + leftLen) == curnode.text.length ? "\n" : curnode.text[curpos + leftLen];
if (after !== "\n") {
after2 = (curpos + leftLen + 1) == curnode.text.length ? "\n" : curnode.text[curpos + leftLen + 1];
}
}
if (pre && after) {
if (/[a-z]/i.test(pre) || /[a-rt-z]/i.test(after) || (after.toLowerCase() == 's' && /[a-z]/i.test(after2))) {
break;
}
}
}
if (curpos < 0) curpos = 0;
let curlen = Math.min(leftLen, curnode.text.length - curpos);
leftLen -= curlen;
if (!curnode.text.trim()) {
if (type === "start") pos += curnode.text.length;
continue;
}
let nodeInfo;
for (let j = 0; j < nodeAndPos.length; j++) {
if (nodeAndPos[j].node == curnode.node) {
nodeInfo = nodeAndPos[j];
break;
}
}
if (!nodeInfo) nodeAndPos.push({node: curnode.node, text: curnode.text, match:[{pos: curpos, len: curlen, type: type, matched: matchedText}]});
else nodeInfo.match.push({pos: curpos, len: curlen, type: type, matched: matchedText});
if (leftLen <= 0) break;
}
}
function getIndex() {
pos = -1;
if (word.isRe) {
let wordMatch = textRes.match(new RegExp(word.content, word.reCase));
if (wordMatch) {
let content = wordMatch[0];
len = content.length;
pos = wordMatch.index;
}
} else {
let result = self.findPosInStr(textRes, word.content, textResUp, wordUp, normalizeArray);
len = result.len;
pos = result.pos;
}
if (pos > -1) {
let matchedText = textRes.slice(pos, pos + len);
textRes = textRes.slice(pos + len);
textResUp = textResUp.slice(pos + len);
normalizeArray = normalizeArray.slice(pos + len);
pos += index;
index = pos + len;
getNodePos(pos, len, matchedText);
getIndex();
}
}
getIndex();
if (nodeAndPos.length) {
nodeAndPos.forEach(data => {
if (typeof word.hideParent !== 'undefined') {
let parentDepth = word.hideParent;
let parent = data.node.parentElement;
while(parentDepth-- > 0 && parent) {
parent = parent.parentElement;
}
if (parent && parent.classList && !parent.classList.contains("searchJumper-hide")) {
parent.innerHTML = createHTML("");
parent.dataset.content = word.showWords;
parent.classList.add("searchJumper-hide");
}
} else {
let curList = self.marks[word.showWords];
let index = curList.length;
let spannode;
let newTextNodeCon;
let parentDisplay = "";
if (data.node.parentNode.nodeType == 1) {
let parentStyle = getComputedStyle(data.node.parentNode);
parentDisplay = parentStyle.display;
}
if (parentDisplay.indexOf("flex") != -1 || parentDisplay.indexOf("grid") != -1 || parentDisplay.indexOf("layer") != -1) {
newTextNodeCon = document.createElement("span");
newTextNodeCon.style.all = "unset";
} else {
newTextNodeCon = document.createDocumentFragment();
}
let newTextNode = document.createTextNode(data.text);
newTextNodeCon.appendChild(newTextNode);
let matches = data.match.reverse();
let spannodes = [];
matches.forEach(d => {
spannode = self.createHighlightMark(word, index, curList);
switch (d.type) {
case "start":
spannode.style.borderTopRightRadius = 0;
spannode.style.borderBottomRightRadius = 0;
break;
case "middle":
spannode.style.borderRadius = 0;
break;
case "end":
spannode.style.borderTopLeftRadius = 0;
spannode.style.borderBottomLeftRadius = 0;
break;
default:
break;
}
middlebit = newTextNode.splitText(d.pos);
if (d.type != 'start' && d.type != 'middle' && middlebit.data.length) {
middlebit.splitText(d.len);
}
middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
if (d.type != "full" && d.type != "start") {
spannode.dataset.type = d.type;
}
if (d.matched) {
spannode.dataset.matched = d.matched;
}
newTextNodeCon.replaceChild(spannode, middlebit);
spannodes.unshift(spannode);
});
data.node.parentNode.replaceChild(newTextNodeCon, data.node);
self.marks[word.showWords].push(...spannodes);
spannodes.forEach(n => {
if (!n.dataset.type) {
navMarkParams.push([n, word, index, curList, scrollHeight]);
}
});
}
});
}
}
let checkChildren = true;
if (word.link) {
if (node.nodeType == 1 && node.href && node.href.match) {
checkChildren = false;
let wordMatch = node.href.match(new RegExp(word.content, word.reCase));
if (wordMatch) {
if (typeof word.hideParent !== 'undefined') {
let parentDepth = word.hideParent;
let parent = node;
while(parentDepth-- > 0 && parent) {
parent = parent.parentElement;
}
if (parent) {
parent.innerHTML = createHTML("");
parent.dataset.content = word.showWords;
parent.classList.add("searchJumper-hide");
return 0;
}
} else {
let curList = self.marks[word.showWords];
let index = curList.length;
node.classList.add("searchJumper");
if (word.title) node.title = JSON.parse('"' + word.title + '"');
if (word.popup) {
self.highlightPopup(node, word);
}
if (!node.dataset.css) node.dataset.css = node.style.cssText;
if (word.style) {
node.style.cssText += word.style;
}
node.addEventListener("click", e => {
if (!e.altKey) return;
e.stopPropagation();
e.preventDefault();
return false;
});
node.dataset.content = word.showWords;
node.addEventListener("mousedown", e => {
if (!e.altKey) return;
let target;
if (e.button === 0) {
if (index != curList.length - 1) {
self.focusIndex = index + 1;
} else self.focusIndex = 0;
} else if (e.button === 2){
if (index != 0) {
self.focusIndex = index - 1;
} else self.focusIndex = curList.length - 1;
}
target = curList[self.focusIndex];
self.focusHighlight(target);
self.setHighlightSpan(self.getHighlightSpanByText(word.showWords), self.focusIndex, curList);
self.focusText = word.showWords;
});
self.marks[word.showWords].push(node);
navMarkParams.push([node, word, index, curList, scrollHeight]);
}
}
}
} else {
let blockValue = "";
if (node.nodeType == 1 && node.value && (node.offsetParent || node.offsetHeight) && !word.init && /^(button|select|input|textarea)$/i.test(node.nodeName) && !/^(hidden|file|password|radio|range|checkbox|image)$/i.test(node.type)) {
blockValue = node.value;
}
if (blockValue) {
checkChildren = false;
let wordMatch = false;
let lastIndex = 0;
let fakeTextarea = self.fakeTextareas.get(node);
if (insert && fakeTextarea) return 0;
let nodeStyle = getComputedStyle(node);
let baseLeft = node.offsetLeft;//textareaLoc.left - textareaParentLoc.left;
let baseTop = node.offsetTop//textareaLoc.top - textareaParentLoc.top;
let blockValueUp = blockValue.toUpperCase();
let normalizeArray = [];
for (let i = 0; i < blockValueUp.length; i++) {
const normalized = blockValueUp[i].normalize("NFD").replace(/[\u0300-\u036f]/g, "");
normalizeArray.push(normalized);
}
let wordUp = word.content.toUpperCase();
while (true) {
if (word.isRe) {
wordMatch = blockValue.match(new RegExp(word.content, word.reCase));
if (wordMatch) {
pos = wordMatch.index;
wordMatch = wordMatch[0];
}
} else {
let result = self.findPosInStr(blockValue, word.content, blockValueUp, wordUp, normalizeArray);
len = result.len;
pos = result.pos;
if ((word.init || inWordMode) && pos >= 0 && /^[a-z]+$/i.test(word.content)) {
if (pos !== 0 && /[a-z]/i.test(blockValue[pos - 1])) {
pos = -1;
}
if (pos + word.content.length !== blockValue.length && /[a-z]/i.test(blockValue[pos + len])) {
pos = -1;
}
}
wordMatch = (pos >= 0 ? blockValue.slice(pos, pos + len) : false);
}
if (wordMatch) {
findTextInBlock(wordMatch, lastIndex + pos);
lastIndex += (pos + wordMatch.length);
blockValue = blockValue.slice(pos + wordMatch.length);
blockValueUp = blockValueUp.slice(pos + wordMatch.length);
normalizeArray = normalizeArray.slice(pos + wordMatch.length);
} else break;
}
function findTextInBlock(curWord, pos) {
if (curWord) {
if (!fakeTextarea) {
fakeTextarea = document.createElement("pre");
fakeTextarea.className = "searchJumper";
let textNode = document.createTextNode(blockValue);
fakeTextarea.appendChild(textNode);
let name, rstyle =/^(number|string)$/;
let cssText = [], sStyle = node.style;
for (name in sStyle) {
if (!/^(content|outline|outlineWidth)$/.test(name)) {
let val = nodeStyle[name];
if (val !=='' && rstyle.test(typeof val)) {
name = name.replace(/([A-Z])/g, "-$1").toLowerCase();
cssText.push(name);
cssText.push(':');
cssText.push(val);
cssText.push(';');
};
};
};
cssText = cssText.join('');
fakeTextarea.style.cssText = cssText;
fakeTextarea.style.position = "fixed";
fakeTextarea.style.left = "0px";
fakeTextarea.style.top = "0px";
fakeTextarea.style.margin = "0";
if (node.nodeName && node.nodeName.toLowerCase && node.nodeName.toLowerCase() !== "textarea") {
fakeTextarea.style.display = "inline-grid";
fakeTextarea.style.lineHeight = fakeTextarea.style.height;
if (fakeTextarea.style.boxSizing == "border-box") fakeTextarea.style.paddingTop = 0;
}
self.fakeTextareas.set(node, fakeTextarea);
}
document.body.appendChild(fakeTextarea);
let range = document.createRange();
range.setStart(fakeTextarea.firstChild, Math.min(fakeTextarea.firstChild.length, pos));
range.setEnd(fakeTextarea.firstChild, Math.min(fakeTextarea.firstChild.length, pos + 1));
let rect = range.getBoundingClientRect();
document.body.removeChild(fakeTextarea);
if (typeof word.hideParent !== 'undefined') {
let parentDepth = word.hideParent;
let parent = node.parentElement;
while(parentDepth-- > 0 && parent) {
parent = parent.parentElement;
}
if (parent) {
parent.innerHTML = createHTML("");
parent.dataset.content = word.showWords;
parent.classList.add("searchJumper-hide");
return 0;
}
} else {
let curList = self.marks[word.showWords];
let index = curList.length;
let spannode = document.createElement("mark");
spannode.className = "searchJumper";
spannode.dataset.block = true;
if (word.title) spannode.title = JSON.parse('"' + word.title + '"');
spannode.style.cssText = word.style;
spannode.dataset.content = word.showWords;
spannode.innerText = curWord;
spannode.style.padding = "0";
spannode.style.position = "absolute";
spannode.style.fontSize = fakeTextarea.style.fontSize;
spannode.style.fontFamily = fakeTextarea.style.fontFamily;
spannode.style.lineHeight = "1";
spannode.style.pointerEvents = "none";
node.parentNode.appendChild(spannode);
let _baseLeft = rect.left + baseLeft;
let _baseTop = rect.top + baseTop;
spannode.style.left = _baseLeft + "px";
spannode.style.top = _baseTop + "px";
self.marks[word.showWords].push(spannode);
navMarkParams.push([spannode, word, index, curList, scrollHeight]);
if (node.nodeName && node.nodeName.toLowerCase && node.nodeName.toLowerCase() == "textarea") {
let nodeScrollHandler = e => {
if (!spannode.parentNode) {
spannode.parentNode.removeChild(spannode);
node.removeEventListener("scroll", nodeScrollHandler);
} else {
spannode.style.left = _baseLeft - node.scrollLeft + "px";
spannode.style.top = _baseTop - node.scrollTop + "px";
}
}
node.addEventListener("scroll", nodeScrollHandler);
}
}
}
}
}
}
if (checkChildren &&
(!root ||
node === ele
) &&
(node.nodeType == 1 ||
node.nodeType == 11
) &&
node.childNodes &&
!/^(SCRIPT|STYLE|MARK|SVG|TEXTAREA)$/i.test(node.nodeName) &&
(!word.init ||
(node.ariaHidden != 'true' &&
node.role != "search" &&
(!node.hasAttribute ||
node.hasAttribute('jsname') == false
)
)
)
) {
if (!searchingPre && /^(PRE|CODE)$/i.test(node.nodeName)) {
preEles.push(node);
} else {
for (var child = 0; child < node.childNodes.length; ++child) {
child = child + searchWithinNode(node.childNodes[child], word);
}
try {
if (node.shadowRoot) {
child = child + searchWithinNode(node.shadowRoot, word, true);
}
} catch(e) {
debug(e);
}
}
}
return skip;
}
words.forEach(w => {
if (!self.marks[w.showWords]) {
self.marks[w.showWords] = [];
}
if (w.inRange) {
let searchEle = ele;
if (ele.parentNode) searchEle = ele.parentNode;
[].forEach.call(searchEle.querySelectorAll(w.inRange), e => {
if (e == ele || ele.contains(e)) {
searchWithinNode(e, w, true);
}
})
} else searchWithinNode(ele, w, true);
});
navMarkParams.forEach(param => {
self.createNavMark(...param);
});
this.navMarks.style.display = "";
setTimeout(() => {
self.navMarks.style.display = "none";
navMarkParams = [];
searchingPre = true;
words.forEach(w => {
if (!self.marks[w.showWords]) {
self.marks[w.showWords] = [];
}
preEles.forEach(e => {
searchWithinNode(e, w, true);
});
});
navMarkParams.forEach(param => {
self.createNavMark(...param);
});
self.navMarks.style.display = "";
}, 1000);
if (this.navMarks.innerHTML != "") {
this.searchJumperNavBar.classList.add("sjNavShow");
if (navEnable) {
this.appendBar();
this.con.style.display = "";
this.setNav(true, true);
}
}
}
refreshPageWords(newWords) {
this.lockWords = "";
this.searchJumperInPageInput.value = "";
this.searchInPageLockWords.innerHTML = createHTML();
this.searchJumperInPageInput.style.paddingLeft = "";
this.submitInPageWords();
let words = newWords || globalInPageWords;
if (words) {
this.searchJumperInPageInput.value = words;
this.submitInPageWords(words == this.lastSearchEngineWords);
this.appendBar();
}
}
refreshNav() {
this.setNav(navEnable);
}
refreshNavMarks() {
if (this.refreshNavMarksTimer) clearTimeout(this.refreshNavMarksTimer);
this.refreshNavMarksTimer = setTimeout(() => {
let scrollHeight = Math.max(document.documentElement.scrollHeight, getBody(document).scrollHeight);
this.navPointer.style.display = "none";
this.navMarks.style.display = "none";
[].forEach.call(this.navMarks.children, m => {
m.style.top = m.dataset.top / scrollHeight * 100 + "%";
});
this.navMarks.style.display = "";
}, 1000);
}
checkCharacterData(target) {
setTimeout(() => {
this.highlight("insert", target, true);
}, 0);
}
removeMark(removedNode) {
let content = removedNode.dataset.content;
let markList = this.marks[content];
if (!markList) return;
var index = markList.indexOf(removedNode);
if (index === -1) return;
markList.splice(index, 1);
this.marks[content] = markList;
let navMark = this.navMarks.querySelectorAll(`span[data-content="${content}"]`)[index];
if (navMark) this.navMarks.removeChild(navMark);
}
submitIgnoreSpace(value) {
if (!value) return;
if (!this.lockWords && value.indexOf("$c") !== 0 && value.indexOf("$o") !== 0 && value.indexOf(" ") !== -1) {
this.splitSep = "◎";
}
this.searchJumperInPageInput.value = value;
this.submitInPageWords();
}
siteBtnReturnHome(btn) {
if (btn.parentNode) btn.parentNode.removeChild(btn);
/*for (let i = 0; i < searchTypes.length; i++) {
let typeBtn = searchTypes[i];
if (typeBtn.dataset.type == btn.dataset.type) {
if (btn.dataset.id) {
let curIndex = parseInt(btn.dataset.id);
for (let j = 1; j < typeBtn.children.length; j++) {
let targetIndex = parseInt(typeBtn.children[j].dataset.id);
if (isNaN(targetIndex) || curIndex < targetIndex) {
typeBtn.insertBefore(btn, typeBtn.children[j]);
break;
} else if (j == typeBtn.children.length - 1) {
typeBtn.appendChild(btn);
break;
}
}
//typeBtn.insertBefore(btn, typeBtn.children[parseInt(btn.dataset.id) - parseInt(typeBtn.dataset.id) + 1]);
} else typeBtn.insertBefore(btn, typeBtn.children[1]);
break;
}
}*/
}
closeShowAll() {
if (!this.con.classList.contains("search-jumper-showall") || isAllPage) return;
this.clearInputHide();
clearInterval(this.showAllTimeTimer);
document.removeEventListener("mousedown", self.showAllMouseHandler);
document.removeEventListener("keydown", self.showAllKeydownHandler);
this.con.classList.remove("search-jumper-showall");
document.documentElement.style.scrollbarWidth = this.preScrollbarWidth;
this.searchJumperInputKeyWords.value = "";
this.historylist.innerHTML = createHTML();
/*this.historySiteBtns.slice(0, 10).forEach(btn => {
this.siteBtnReturnHome(btn);
});*/
this.touched = false;
this.initPos();
if (this.funcKeyCall) {
this.setFuncKeyCall(false);
}
if (!searchData.prefConfig.disableAutoOpen && !searchData.prefConfig.disableTypeOpen) {
let firstType = this.bar.querySelector('.search-jumper-type:nth-child(1)>span');
if (firstType && !firstType.classList.contains("search-jumper-open")) {
if (firstType.onmousedown) {
firstType.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
firstType.dispatchEvent(mouseEvent);
}
}
}
this.bar.style.display = '';
}
toggleShowAll() {
this.appendBar();
if (!this.con || !this.con.parentNode) return;
if (this.con.classList.contains("search-jumper-showall")) {
this.closeShowAll();
} else {
this.showAllSites();
}
}
showAllSites() {
if (!this.con || !this.con.parentNode || this.con.classList.contains("search-jumper-showall")) return;
this.con.style.display = "";
this.clearInputHide();
this.alllist.appendChild(this.filterSites);
this.filterGlob.innerHTML = createHTML();
let self = this;
this.setFuncKeyCall(false);
this.hideSearchInput();
this.con.classList.add("search-jumper-showall");
this.preScrollbarWidth = document.documentElement.style.scrollbarWidth || "";
document.documentElement.style.scrollbarWidth = "none";
clearInterval(this.showAllTimeTimer);
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
if (window.innerWidth < 1000) {
self.timeInAll.style.fontSize = "15px";
self.dayInAll.style.fontSize = "15px";
} else {
self.timeInAll.style.fontSize = "";
self.dayInAll.style.fontSize = "";
}
let now = new Date();
let year = now.getFullYear(), month = now.getMonth(), date = now.getDate();
let dayLabelStr = i18n(days[now.getDay()]) + "<br/>" + year + '-' + (++month < 10 ? '0' + month : month) + '-' + (date < 10 ? '0' + date : date);
if (lang.indexOf("zh") == 0) {
let lunar = sloarToLunar(year, month, date);
if (lunar) {
let lunarStr = `${lunar.lunarYear}年${lunar.lunarMonth}月${lunar.lunarDay}`;
dayLabelStr = dayLabelStr + "<br/>" + lunarStr;
}
}
self.dayInAll.innerHTML = createHTML(dayLabelStr);
let setTimeLabel = () => {
let now = new Date();
let hour = now.getHours(), minute = now.getMinutes(), seconds = now.getSeconds();
self.timeInAll.innerText = (hour < 10 ? '0' + hour : hour) + ':' + (minute < 10 ? '0' + minute : minute) + ':' + (seconds < 10 ? '0' + seconds : seconds);
};
this.showAllTimeTimer = setInterval(setTimeLabel, 1000);
setTimeLabel();
searchTypes.forEach(type => {
if (type.style.display != 'none') {
let sitelist = type.querySelector('.sitelist');
if (sitelist) {
self.sitelistBox.appendChild(sitelist);
self.initList(sitelist);
}
}
});
this.historySiteBtns.slice(0, 20).forEach(btn => {
let siteImg = btn.querySelector('img');
if (siteImg && siteImg.dataset.src) {
siteImg.src = siteImg.dataset.src;
delete siteImg.dataset.src;
}
self.historylist.appendChild(btn);
});
let targetKw = "";
if (targetElement &&
(targetElement.nodeName.toUpperCase() == 'A' ||
(targetElement.parentNode && targetElement.parentNode.nodeName.toUpperCase() == 'A'))) {
targetKw = targetElement.textContent.trim();
}
let kw = getKeywords() || targetKw || cacheKeywords;
this.searchJumperInputKeyWords.value = kw;
setTimeout(() => {
if (!self.showAllMouseHandler) {
self.showAllMouseHandler = e => {
if (e.isTrusted == false || e.target.className === 'sitelistBox' || e.target.className === 'search-jumper-showallBg') {
self.closeShowAll();
}
};
}
self.con.addEventListener("mousedown", self.showAllMouseHandler);
if (!self.showAllKeydownHandler) {
self.showAllKeydownHandler = e => {
if (e.keyCode == 27) {
self.closeShowAll();
}
};
}
document.addEventListener("keydown", self.showAllKeydownHandler, true);
if (this.searchJumperInputKeyWords.value) {
this.searchJumperInputKeyWords.focus();
this.searchJumperInputKeyWords.select();
}
}, 0);
}
switchSite(next) {
if (!currentSite || this.bar.style.display == "none") return;
let siteEle = this.con.querySelector(".search-jumper-btn.current");
if (next) {
siteEle = siteEle.nextElementSibling;
while(siteEle) {
if (!siteEle.classList.contains("notmatch") && siteEle.style.display != "none" && siteEle.dataset.current != "true" && siteEle.dataset.isPage == "true") {
break;
}
siteEle = siteEle.nextElementSibling;
}
} else {
siteEle = siteEle.previousElementSibling;
while(siteEle) {
if (!siteEle.classList.contains("notmatch") && siteEle.style.display != "none" && siteEle.dataset.current != "true" && siteEle.dataset.isPage == "true") {
break;
}
siteEle = siteEle.previousElementSibling;
}
}
if (siteEle) {
this.openSiteBtn(siteEle, "_self");
}
}
clearInputHide() {
searchTypes.forEach(type => {
type.classList.remove("input-hide");
});
this.allSiteBtns.forEach(btn => {
btn[0].classList.remove("input-hide");
});
this.allListBtns.forEach(listItem => {
listItem.classList.remove("input-hide");
});
this.allLists.forEach(listCon => {
listCon.classList.remove("input-hide");
});
}
showSearchInput() {
if (this.con && this.con.classList.contains("search-jumper-showall")) return;
this.recoveHistory();
this.con.classList.add("in-input");
this.searchInput.value = "";
this.contentContainer.appendChild(this.filterSites);
let selStr = getSelectStr();
if (selStr) {
this.searchJumperInputKeyWords.value = selStr;
}
if (this.filterSitesTab.checked) {
this.con.classList.remove("in-find");
if (searchData.prefConfig.defaultPicker) {
this.togglePicker();
}
if (!this.searchJumperInputKeyWords.value) {
this.searchJumperInputKeyWords.value = getKeywords() || cacheKeywords;
}
let firstType = this.bar.querySelector('.search-jumper-needInPage:not(.notmatch)>span');
if (firstType && !firstType.parentNode.classList.contains('search-jumper-open')) {
if (firstType.onmousedown) {
firstType.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
firstType.dispatchEvent(mouseEvent);
}
}
if (cacheFilter) {
this.searchInput.value = cacheFilter;
this.searchInput.dispatchEvent(new Event("input"));
}
this.searchJumperInputKeyWords.focus();
this.searchJumperInputKeyWords.select();
} else if (this.searchInPageTab.checked) {
this.con.classList.add("in-find");
this.searchJumperInPageInput.focus();
setTimeout(() => {
if (selStr && this.lockWords.indexOf(selStr) == -1) {
this.searchJumperInPageInput.value = "";
if (!this.navMarks.innerHTML) {
this.submitIgnoreSpace(selStr);
} else {
this.searchJumperInPageInput.value = selStr;
this.submitInPageWords();
}
} else if (this.searchJumperInPageInput.value) {
this.submitInPageWords();
} else if (!this.initShowSearchInput && cacheKeywords && this.lockWords !== cacheKeywords) {
this.searchJumperInPageInput.value = cacheKeywords;
this.initShowSearchInput = true;
this.searchJumperInPageInput.select();
}
}, 10);
}
this.inInput = true;
this.clearInputHide();
if (this.lockWords) this.searchJumperInPageInput.style.paddingLeft = this.searchInPageLockWords.clientWidth + 3 + "px";
else this.searchJumperInPageInput.style.paddingLeft = "";
if (searchData.prefConfig.altToHighlight) {
document.removeEventListener("mouseup", this.checkSelHandler);
document.addEventListener("mouseup", this.checkSelHandler);
}
}
togglePicker() {
this.pickerBtn.classList.toggle("checked");
this.con.classList.toggle("in-pick");
this.searchJumperInputKeyWords.disabled = !this.searchJumperInputKeyWords.disabled;
picker.toggle(true);
if (this.searchJumperInputKeyWords.disabled) {
this.searchJumperInputKeyWords.value = "";
}
}
hideSearchInput() {
this.inInput = false;
this.clearInputHide();
this.con.classList.remove("in-find");
this.con.classList.remove("in-input");
this.con.classList.remove("lock-input");
this.bar.classList.remove("initShow");
this.searchInput.value = "";
this.searchJumperInputKeyWords.value = "";
this.pickerBtn.classList.remove("checked");
this.searchJumperInputKeyWords.disabled = false;
picker.close();
document.removeEventListener("mouseup", this.checkSelHandler);
this.setFuncKeyCall(false);
this.closeOpenType();
}
removeBar() {
if (this.shadowContainer && this.shadowContainer.parentNode) {
this.shadowContainer.parentNode.removeChild(this.shadowContainer);
}
if (this.con.parentNode) {
this.con.parentNode.removeChild(this.con);
}
}
async testCSP() {
let self = this;
let cspHandler = e => {
if (!e.violatedDirective || e.violatedDirective.indexOf("style-src") == -1) return;
disabled = true;
};
window.addEventListener('securitypolicyviolation', cspHandler);
let testStyleEle = _GM_addStyle(`html {color: #000;}`);
this.addToShadow(testStyleEle);
await sleep(0);
window.removeEventListener('securitypolicyviolation', cspHandler);
testStyleEle.parentNode && testStyleEle.parentNode.removeChild(testStyleEle);
}
addToShadow(ele) {
if (!this.shadowContainer) {
this.shadowContainer = document.createElement("div");
}
if (!this.shadowContainer.parentNode) {
if (shareEngines) {
document.body.appendChild(this.shadowContainer);
} else {
document.documentElement.appendChild(this.shadowContainer);
}
}
let shadow;
if (disabled) {
if (/^style$/i.test(ele.nodeName)) return true;
shadow = this.shadowContainer;
} else {
if (this.shadowRoot) {
shadow = this.shadowRoot;
} else {
//this.shadowContainer.setAttribute('contenteditable', 'true');
this.shadowContainer.className = "search-jumper-shadow";
let style = _GM_addStyle(`
.search-jumper-shadow {
display: block !important;
width: 0px !important;
height: 0px !important;
margin: 0px !important;
padding: 0px !important;
border-width: initial !important;
border-style: none !important;
border-color: initial !important;
border-image: initial !important;
outline: none !important;
position: unset !important;
}
`);
this.shadowContainer.appendChild(style);
let shadowRoot = this.shadowContainer.attachShadow({ mode: "closed" });
shadow = document.createElement("div");
shadow.id = "search-jumper-root";
shadow.style.display = "none";
shadow.setAttribute('contenteditable', 'false');
let hideShadowStyle = document.createElement("style");
hideShadowStyle.innerHTML = createHTML("#search-jumper-root{display: block!important;}");
shadow.appendChild(hideShadowStyle);
shadowRoot.appendChild(shadow);
this.shadowRoot = shadow;
}
}
if (ele.parentNode != shadow) shadow.appendChild(ele);
return true;
}
contains(ele) {
return ele == this.shadowContainer || this.bar.contains(ele);
}
appendBar() {
if (!mainStyleEle || !mainStyleEle.parentNode) {
mainStyleEle = _GM_addStyle(cssText);
if (!disabled) this.addToShadow(mainStyleEle);
}
if (this.addToShadow(this.con)) {
let self = this;
let checkZIndex = () => {
setTimeout(() => {
if (self.shadowContainer && !self.shadowContainer.parentNode) {
if (shareEngines) {
document.body.appendChild(self.shadowContainer);
} else {
document.documentElement.appendChild(self.shadowContainer);
}
checkZIndex();
return;
}
if (!isAllPage && self.con.parentNode) {
if (getComputedStyle(self.con).zIndex != "2147483647") {
this.removeBar();
if (disabled) {
debug(i18n("cspDisabled"));
} else {
disabled = true;
mainStyleEle = _GM_addStyle(cssText);
self.shadowContainer.parentNode.removeChild(self.shadowContainer);
self.shadowContainer = document.createElement("div");
self.shadowContainer.setAttribute('contenteditable', 'false');
document.documentElement.appendChild(self.shadowContainer);
self.appendBar();
}
}
}
}, 100);
};
checkZIndex();
}
}
async searchBySiteName(siteName, e, selfTab) {
if (!e) e = {};
if (e && e.type === 'drop') {
this.closeShowAll();
}
for (let [siteBtn, siteData] of this.allSiteBtns) {
if (siteBtn.dataset.name == siteName) {
if (siteBtn.dataset.showTips) {
siteBtn.dispatchEvent(new CustomEvent('showTips'));
return;
}
await this.siteSetUrl(siteBtn, {button: e.button, altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, metaKey: e.metaKey});
let isPage = /^(https?|ftp):/.test(siteBtn.href);
if (isPage) {
siteBtn.setAttribute("target", selfTab ? "_self" : "_blank");
}
siteBtn.click();
if (isPage) {
siteBtn.setAttribute("target", siteBtn.dataset.target == 1 ? "_blank" : "_self");
}
return;
}
}
for (let i = searchTypes.length - 1; i >= 0; i--) {
let typeEle = searchTypes[i];
if (typeEle.dataset.type == siteName) {
typeEle.firstChild.onmousedown({button: 2});
return;
}
}
}
async searcAllhByTypeName(siteName) {
for (let i = searchTypes.length - 1; i >= 0; i--) {
let typeEle = searchTypes[i];
if (typeEle.dataset.type == siteName) {
typeEle.firstChild.onmousedown({button: 2});
return;
}
}
}
autoGetFirstType() {
if (!targetElement) targetElement = getBody(document);
let firstType;
switch (targetElement.nodeName.toUpperCase()) {
case 'IMG':
firstType = this.bar.querySelector('.search-jumper-targetImg:not(.notmatch)');
break;
case 'AUDIO':
firstType = this.bar.querySelector('.search-jumper-targetAudio:not(.notmatch)');
break;
case 'VIDEO':
firstType = this.bar.querySelector('.search-jumper-targetVideo:not(.notmatch)');
break;
case 'A':
if (getSelectStr()) {
firstType = this.bar.querySelector('.search-jumper-needInPage:not(.notmatch)');
} else {
firstType = this.bar.querySelector('.search-jumper-targetLink:not(.notmatch)');
}
break;
default:
if (getSelectStr()) {
firstType = this.bar.querySelector('.search-jumper-needInPage:not(.notmatch)');
} else if (targetElement.parentNode.nodeName.toUpperCase() === 'A') {
firstType = this.bar.querySelector('.search-jumper-targetLink:not(.notmatch)');
} else {
firstType = this.bar.querySelector('.search-jumper-targetPage:not(.notmatch)');
}
break;
}
if (!firstType) firstType = this.bar.querySelector('.search-jumper-targetAll:not(.notmatch)') || this.bar.querySelector('.search-jumper-type');
if (firstType) {
this.setFuncKeyCall(false);
let mouseEvent = new PointerEvent("mousedown");
if (firstType.classList.contains('search-jumper-open')) {
if (firstType.children[0].onmousedown) firstType.children[0].onmousedown();
else {
firstType.children[0].dispatchEvent(mouseEvent);
}
}
if (firstType.children[0].onmousedown) firstType.children[0].onmousedown();
else {
firstType.children[0].dispatchEvent(mouseEvent);
}
}
return firstType;
}
searchAuto(index, e) {
if (!index) index = 0;
let firstType = this.autoGetFirstType();
if (!firstType) return;
let targetSites = firstType.querySelectorAll('a.search-jumper-btn:not(.notmatch)');
if (index < targetSites.length) {
let targetSite = targetSites[index];
this.searchBySiteName(targetSite.dataset.name, e);
}
}
setNav(enable, noSave) {
if (!noSave && navEnable != enable) {
storage.setItem("navEnable", enable || "");
navEnable = enable;
}
if (enable) {
if (!noSave) this.locBtn.classList.add("checked");
this.searchJumperNavBar.style.display = "";
} else {
if (!noSave) this.locBtn.classList.remove("checked");
this.searchJumperNavBar.style.display = "none";
this.navPointer.style.display = "none";
}
}
lockSearchInput(lockWords) {
this.lockSiteKeywords = true;
this.searchLockInput.innerText = lockWords;
this.con.classList.add("lock-input");
this.searchInput.value = "";
this.searchInput.style.paddingLeft = `${15 + this.searchLockInput.scrollWidth}px`;
this.searchInput.placeholder = i18n("inputKeywords");
}
async initRun() {
let self = this;
this.siteIndex = 1;
this.customInput = false;
this.fontPool = [];
this.allSiteBtns = [];
this.allListBtns = [];
this.allLists = [];
this.dockerScaleBtns = [];
this.bar.style.visibility = "hidden";
let sitesNum = 0;
let bookmarkTypes = [];
this.checkSelHandler = e => {
if (!e.altKey) return;
if (this.searchInPageTab.checked && window.getSelection().toString()) {
this.showSearchInput();
}
};
//Search in page
this.splitSep = "◎";
this.lockWords = "";
this.marks = {};
this.initInPageWords = [];
this.highlightSpans = {};
this.curHighlightWords = [];
this.curWordIndex = 0;
let editFunc = () => {
this.searchJumperInPageInput.focus();
this.highlight("");
let words = this.lockWords.trim();
if (!words) {
this.submitInPageWords();
return;
}
if (this.searchJumperInPageInput.value) words += this.splitSep + this.searchJumperInPageInput.value;
this.lockWords = "";
this.searchJumperInPageInput.value = words;
this.searchInPageLockWords.innerHTML = createHTML();
this.searchJumperInPageInput.style.paddingLeft = "";
};
document.addEventListener("keydown", e => {
if (e.keyCode === 27) {
if (isAllPage) {
this.searchInput.value = "";
this.searchInput.dispatchEvent(new CustomEvent("input"));
} else if (this.inInput) {
this.hideSearchInput();
} else if (this.lockWords) {
this.highlight("");
this.searchJumperInPageInput.value = this.lockWords;
this.lockWords = "";
this.searchInPageLockWords.innerHTML = createHTML();
this.setNav(false, true);
} else if (this.funcKeyCall) {
this.removeBar();
}
}
}, true);
this.searchJumperInPageInput.addEventListener("focus", e => {
this.searchInputDiv.classList.add("active");
});
this.searchJumperInPageInput.addEventListener("blur", e => {
this.searchInputDiv.classList.remove("active");
});
this.searchJumperInPageInput.addEventListener("keydown", e => {
e.stopPropagation();
switch(e.keyCode) {
case 8://退格
if (!this.searchJumperInPageInput.value) {
let lastWordSpan = this.searchInPageLockWords.lastChild;
if (lastWordSpan) {
lastWordSpan.dispatchEvent(new CustomEvent("editword"));
e.preventDefault();
}
}
break;
case 9://tab
e.preventDefault();
this.filterSitesTab.checked = true;
this.con.classList.remove("in-find");
this.searchInput.focus();
break;
case 13://回车
{
//let spans = this.submitInPageWords();
let spans = this.searchJumperInPageInput.value ? this.submitInPageWords() : [];
if (spans && spans.length > 0) {
let lastSpan = spans.pop();
if (this.currentSearchInPageLockWords) {
this.currentSearchInPageLockWords.firstChild.style.transform = "";
}
this.currentSearchInPageLockWords = lastSpan;
let mouseEvent = new PointerEvent("mousedown", {button: e.shiftKey ? 2 : 0});
lastSpan.dispatchEvent(mouseEvent);
} else if (this.lockWords) {
if (!this.currentSearchInPageLockWords) {
this.currentSearchInPageLockWords = this.searchInPageLockWords.lastChild;
this.currentSearchInPageLockWords.firstChild.style.transform = "scale(1.1)";
}
let mouseEvent = new PointerEvent("mousedown", {button: e.shiftKey ? 2 : 0});
this.currentSearchInPageLockWords.dispatchEvent(mouseEvent);
}
}
break;
case 37://←
if (this.searchJumperInPageInput.value == "" && this.lockWords) {
if (!this.currentSearchInPageLockWords) {
this.currentSearchInPageLockWords = this.searchInPageLockWords.lastChild;
this.currentSearchInPageLockWords.firstChild.style.transform = "scale(1.1)";
} else if (this.currentSearchInPageLockWords.previousElementSibling){
this.currentSearchInPageLockWords.firstChild.style.transform = "";
this.currentSearchInPageLockWords = this.currentSearchInPageLockWords.previousElementSibling;
this.currentSearchInPageLockWords.firstChild.style.transform = "scale(1.1)";
}
}
break;
case 39://→
if (this.searchJumperInPageInput.value == "" && this.lockWords) {
if (!this.currentSearchInPageLockWords) {
this.currentSearchInPageLockWords = this.searchInPageLockWords.lastChild;
this.currentSearchInPageLockWords.firstChild.style.transform = "scale(1.1)";
} else if (this.currentSearchInPageLockWords.nextElementSibling){
this.currentSearchInPageLockWords.firstChild.style.transform = "";
this.currentSearchInPageLockWords = this.currentSearchInPageLockWords.nextElementSibling;
this.currentSearchInPageLockWords.firstChild.style.transform = "scale(1.1)";
}
}
break;
default:
break;
}
}, true);
this.editBtn.addEventListener("click", e => {
editFunc();
});
this.addWord.addEventListener("click", e => {
this.showModifyWindow();
});
this.searchInPageTab.addEventListener("change", e => {
this.initSetInPageWords();
this.searchJumperInPageInput.focus();
this.con.classList.add("in-find");
});
this.filterSitesTab.addEventListener("change", e => {
this.searchInput.focus();
this.con.classList.remove("in-find");
});
if (globalInPageWords) {
this.recoverBtn.addEventListener("click", e => {
this.lockWords = "";
this.searchJumperInPageInput.value = globalInPageWords;
this.searchInPageLockWords.innerHTML = createHTML();
this.highlight("");
this.submitInPageWords();
this.searchJumperInPageInput.focus();
});
this.pinBtn.classList.add("checked");
} else {
this.recoverBtn.style.display = "none";
}
this.pinBtn.addEventListener("click", e => {
this.submitInPageWords();
if (this.pinBtn.classList.contains("checked")) {
globalInPageWords = "";
this.pinBtn.classList.remove("checked");
} else if (this.lockWords) {
globalInPageWords = this.lockWords;
this.pinBtn.classList.add("checked");
}
storage.setItem("globalInPageWords", globalInPageWords);
});
this.wordModeBtn.addEventListener("click", e => {
let inWordMode = this.wordModeBtn.classList.contains("checked");
if (inWordMode) {
this.wordModeBtn.classList.remove("checked");
} else {
this.wordModeBtn.classList.add("checked");
}
if (this.lockWords) {
this.refreshPageWords(this.lockWords);
}
});
this.saveRuleBtn.addEventListener("click", e => {
if (!this.lockWords) return;
if (shareEngines) return;
dataChanged(() => {
let inPageRule = searchData.prefConfig.inPageRule || {};
inPageRule[this.inPageRuleKey || href.replace(/([&\?]_i=|#).*/, "")] = this.lockWords;
searchData.prefConfig.inPageRule = inPageRule;
searchData.lastModified = new Date().getTime();
lastModified = searchData.lastModified;
storage.setItem("searchData", searchData);
_GM_notification(i18n("save completed"));
});
});
this.emptyBtn.addEventListener("click", e => {
this.lockWords = "";
this.searchJumperInPageInput.value = "";
this.searchInPageLockWords.innerHTML = createHTML();
this.searchJumperInPageInput.style.paddingLeft = "";
this.submitInPageWords();
this.searchJumperInPageInput.focus();
});
this.copyInPageBtn.addEventListener("click", e => {
if (!this.lockWords) return;
_GM_setClipboard(this.lockWords.replace(/◎/g, "\n"));
_GM_notification('Copied successfully!');
});
this.setNav(navEnable);
this.locBtn.addEventListener("click", e => {
this.setNav(!this.locBtn.classList.contains("checked"));
});
this.closeNavBtn.addEventListener("click", e => {
if (this.lockWords) {
this.searchJumperInPageInput.value = this.lockWords || "";
this.lockWords = "";
this.searchInPageLockWords.innerHTML = createHTML();
this.searchJumperInPageInput.style.paddingLeft = "";
this.highlight("");
this.searchJumperInPageInput.focus();
this.setNav(false, true);
storage.setItem("disableHighlight", location.hostname);
if (this.bar.style.display === "none") {
this.removeBar();
}
} else {
this.setNav(false);
}
});
this.minNavBtn.addEventListener("click", e => {
if (this.searchJumperNavBar.classList.contains("minimize")) {
this.searchJumperNavBar.classList.remove("minimize");
if (this.lockWords.trim()) return;
this.submitInPageWords();
} else {
this.searchJumperNavBar.classList.add("minimize");
this.highlight("");
let words = this.lockWords.trim();
if (!words) return;
if (this.searchJumperInPageInput.value) words += this.splitSep + this.searchJumperInPageInput.value;
this.lockWords = "";
this.searchJumperInPageInput.value = words;
this.searchInPageLockWords.innerHTML = createHTML();
this.searchJumperInPageInput.style.paddingLeft = "";
}
});
this.maxNavBtn.addEventListener("click", e => {
self.showInPage();
self.showInPageSearch();
});
this.navMarks.addEventListener("click", e => {
let topPercent = e.offsetY / this.navMarks.clientHeight * 100;
let sortedMarks = [].slice.call(this.navMarks.querySelectorAll("span"));
sortedMarks.sort((a, b) => {
a = parseFloat(a.style.top);
b = parseFloat(b.style.top);
if (a > b) return 1;
if (a < b) return -1;
return 0;
});
let mark;
for (let i = 0; i < sortedMarks.length; i++) {
mark = sortedMarks[i];
let markTop = parseFloat(mark.style.top);
if (markTop > topPercent) {
if (i > 0) {
let preMark = sortedMarks[i - 1];
let preMarkTop = parseFloat(preMark.style.top);
if (markTop - topPercent > topPercent - preMarkTop) {
mark = preMark;
}
}
break;
}
}
if (mark) {
mark.click();
}
});
this.bar.addEventListener("mousedown", e => {
e && e.stopPropagation && e.stopPropagation();
e && e.preventDefault && e.preventDefault();
});
this.con.addEventListener('dblclick', e=>{
e.stopPropagation();
e.preventDefault();
});
//Search in page
let expandTypeHandler = e => {
e.stopPropagation();
e.preventDefault();
let typeEle = self.searchJumperExpand.parentNode;
if (!typeEle || !typeEle.classList.contains('not-expand')) return;
typeEle.classList.remove('not-expand');
typeEle.classList.remove('search-jumper-move');
let leftRight = self.con.classList.contains("search-jumper-left") ||
self.con.classList.contains("search-jumper-right");
typeEle.removeChild(self.searchJumperExpand);
let scrollSize = Math.max(typeEle.scrollWidth, typeEle.scrollHeight) + 5 + "px";
if (leftRight) {
typeEle.style.height = scrollSize;
typeEle.style.width = "";
} else {
typeEle.style.width = scrollSize;
typeEle.style.height = "";
}
setTimeout(() => {
self.checkScroll();
typeEle.classList.add('search-jumper-move');
}, 251);
}, showTimer;
this.searchJumperExpand.addEventListener("click", expandTypeHandler, true);
this.searchJumperExpand.addEventListener("contextmenu", expandTypeHandler, true);
this.searchJumperExpand.addEventListener('mouseenter', e => {
if (searchData.prefConfig.overOpen) {
clearTimeout(showTimer);
showTimer = setTimeout(() => {
expandTypeHandler(e);
}, 500);
}
let sitelistEvent = new CustomEvent("sitelist", {
detail: {
bind: e.currentTarget,
}
});
e.currentTarget.parentNode.dispatchEvent(sitelistEvent);
}, false);
if (searchData.prefConfig.overOpen) {
this.searchJumperExpand.addEventListener('mouseleave', e => {
clearTimeout(showTimer);
}, false);
}
this.pickerBtn.addEventListener("click", e => {
this.togglePicker();
});
this.maxEleBtn.addEventListener("click", e => {
picker.expand();
});
this.minEleBtn.addEventListener("click", e => {
picker.collapse();
});
this.copyEleBtn.addEventListener("click", e => {
picker.copy();
});
this.openLinkBtn.addEventListener("click", e => {
picker.openLinks();
});
let listArrow = document.createElement("div");
listArrow.className = "listArrow";
this.listArrow = listArrow;
this.con.appendChild(listArrow);
for (let siteConfig of searchData.sitesConfig) {
let isBookmark = siteConfig.bookmark || siteConfig.sites.length > 100 || (/^BM/.test(siteConfig.type) && siteConfig.icon === "bookmark");
if (isBookmark) {
bookmarkTypes.push(siteConfig);
continue;
}
await this.createType(siteConfig);
sitesNum += siteConfig.sites.length;
if (sitesNum > 100) {
await sleep(1);
sitesNum = 0;
}
}
this.initHistorySites();
this.initSort();
this.bar.style.visibility = "";
this.bar.style.display = "none";
this.searchInPageRule();
if (currentSite && wordParamReg.test(currentSite.url)) {
this.inSearchEngine();
} else if (searchData.prefConfig.alwaysShow && !inIframe && !isInConfigPage) {
this.bar.style.display = "";
this.initPos();
this.appendBar();
}
if (lastSign) {
targetElement = lastSign.target;
this.batchOpen(lastSign.sites, {button: 2});
}
lastSign = false;
if (inPagePostParams) {
this.submitAction(inPagePostParams);
setTimeout(() => {
storage.setListItem("inPagePostParams", location.hostname, "");
}, 10000);
}
let searchWithCurrentFilter = e => {
clearTimeout(inputTimer);
let siteEle, forceTarget = "";
if (currentSite && !self.searchInput.value) {
siteEle = self.con.querySelector(".search-jumper-btn.current");
forceTarget = "_self";
} else {
siteEle = self.con.querySelector(".search-jumper-type.search-jumper-open>a.search-jumper-btn:not(.input-hide)") || self.con.querySelector(".search-jumper-needInPage>a.search-jumper-btn:not(.input-hide)") || self.con.querySelector("a.search-jumper-btn:not(.input-hide)");
forceTarget = "_blank";
}
if (siteEle) {
self.openSiteBtn(siteEle, forceTarget, !e.ctrlKey);
}
};
let inputTimer;
this.inInput = false;
let saveCacheFilter = () => {
if (cacheFilter !== self.searchInput.value) {
cacheFilter = self.searchInput.value;
storage.setItem("cacheFilter", cacheFilter);
}
};
this.searchInput.addEventListener("input", e => {
clearTimeout(inputTimer);
inputTimer = setTimeout(() => {
self.searchSiteBtns(self.searchInput.value)
}, 500);
});
this.searchInput.addEventListener("click", e => {
self.searchInput.select();
});
this.searchInput.addEventListener("blur", e => {
saveCacheFilter();
});
this.searchInput.addEventListener("keydown", e => {
e.stopPropagation();
switch(e.keyCode) {
case 9:
if (e.shiftKey) {
e.preventDefault();
this.searchInPageTab.checked = true;
this.con.classList.add("in-find");
this.searchJumperInPageInput.focus();
this.initSetInPageWords();
}
break;
case 13://回车
if (this.searchJumperInputKeyWords.disabled) {
clearTimeout(inputTimer);
let siteEle, forceTarget = "";
if (currentSite && !self.searchInput.value) {
siteEle = self.con.querySelector(".search-jumper-btn.current");
forceTarget = "_self";
} else {
siteEle = self.con.querySelector(".search-jumper-type.search-jumper-open>a.search-jumper-btn:not(.input-hide)") || self.con.querySelector(".search-jumper-needInPage>a.search-jumper-btn:not(.input-hide)") || self.con.querySelector("a.search-jumper-btn:not(.input-hide)");
forceTarget = "_blank";
}
if (siteEle) {
self.openSiteBtn(siteEle, forceTarget, !e.ctrlKey);
}
} else {
if (this.searchJumperInputKeyWords.value) {
searchWithCurrentFilter(e);
} else {
this.searchJumperInputKeyWords.focus();
}
saveCacheFilter();
}
break;
case 8://退格
/*if (self.lockSiteKeywords && !self.searchInput.value) {
self.searchInput.value = self.searchLockInput.innerText;
self.searchLockInput.innerText = "";
self.lockSiteKeywords = false;
self.con.classList.remove("lock-input");
self.searchInput.style.paddingLeft = "";
self.searchInput.placeholder = i18n("inputPlaceholder");
}*/
break;
default:
break;
}
});
this.searchJumperInputKeyWords.addEventListener("input", e => {
clearTimeout(inputTimer);
inputTimer = setTimeout(() => {
self.getSuggest(self.searchJumperInputKeyWords.value)
}, 200);
});
this.searchJumperInputKeyWords.addEventListener("keydown", e => {
if (e.keyCode !== 27) e.stopPropagation();
switch(e.keyCode) {
case 9:
if (!this.inInput) {
e.preventDefault();
this.searchInput.focus();
} else if (!e.shiftKey) {
e.preventDefault();
this.searchInPageTab.checked = true;
this.con.classList.add("in-find");
this.searchJumperInPageInput.focus();
this.initSetInPageWords();
}
break;
case 13://回车
searchWithCurrentFilter(e);
break;
default:
break;
}
}, true);
this.closeBtn.addEventListener("mousedown", e => {
self.hideSearchInput();
if (searchData.prefConfig.emptyAfterCloseInput) {
self.highlight("");
self.searchJumperInPageInput.value = self.lockWords || "";
self.lockWords = "";
self.searchInPageLockWords.innerHTML = createHTML();
self.setNav(false, true);
}
});
let startLeft = window.innerWidth / 2;
let startBottom;
let currentGroup, startX, startY;
let clientX = e => {
if (e.type.indexOf('mouse') === 0) {
return e.clientX;
} else {
return e.changedTouches[0].clientX;
}
};
let clientY = e => {
if (e.type.indexOf('mouse') === 0) {
return e.clientY;
} else {
return e.changedTouches[0].clientY;
}
};
let grabMousemoveHandler = e => {
let halfContainerWidth = 0.25 * window.innerWidth;
let left = startLeft + clientX(e) - startX;
self.searchInputDiv.style.top = 'unset';
self.searchInputDiv.style.left = left + "px";
self.searchInputDiv.style.bottom = startBottom - (clientY(e) - startY) + "px";
if (left > window.innerWidth / 2) {
let maxWidth = window.innerWidth - left + halfContainerWidth - 50;
self.searchInputDiv.style.maxWidth = maxWidth + "px";
} else {
let maxWidth = left + halfContainerWidth;
if (left < halfContainerWidth) {
left += halfContainerWidth - left;
self.searchInputDiv.style.left = left + "px";
}
self.searchInputDiv.style.maxWidth = maxWidth + "px";
}
e.stopPropagation();
e.preventDefault();
};
let grabMouseupHandler = e => {
document.removeEventListener("mouseup", grabMouseupHandler);
document.removeEventListener("mousemove", grabMousemoveHandler);
document.removeEventListener("touchend", grabMouseupHandler);
document.removeEventListener("touchmove", grabMousemoveHandler);
currentGroup.style.cursor = "";
startLeft += clientX(e) - startX;
startBottom -= clientY(e) - startY;
};
let setStartBottom = () => {
if (!startBottom) startBottom = self.con.classList.contains('search-jumper-bottom') ? window.innerHeight * 0.95 - 60 : window.innerHeight * 0.03;
};
let touchStart = false;
this.searchInputDiv.addEventListener("touchstart", e => {
touchStart = true;
if (e.target.className === 'inputGroup' || e.target.nodeName.toUpperCase() === 'LABEL') {
setStartBottom();
currentGroup = e.target;
currentGroup.style.cursor = "grabbing";
startX = clientX(e);
startY = clientY(e);
document.addEventListener("touchend", grabMouseupHandler);
document.addEventListener("touchmove", grabMousemoveHandler);
}
}, { passive: true, capture: false });
this.searchInputDiv.addEventListener("mousedown", e => {
if (touchStart) {
touchStart = false;
return;
}
if (e.target.className === 'inputGroup' || e.target.nodeName.toUpperCase() === 'LABEL') {
setStartBottom();
currentGroup = e.target;
currentGroup.style.cursor = "grabbing";
startX = e.clientX;
startY = e.clientY;
document.addEventListener("mouseup", grabMouseupHandler);
document.addEventListener("mousemove", grabMousemoveHandler);
e.stopPropagation();
e.preventDefault();
}
});
let initWidth, initX;
let sizeChangeMouseMove = e => {
let width = e.clientX - initX + initWidth + 20;
this.searchInputDiv.style.width = width + "px";
};
let sizeChangeMouseUp = e => {
document.removeEventListener("mousemove", sizeChangeMouseMove);
document.removeEventListener("mouseup", sizeChangeMouseUp);
};
this.rightSizeChange.addEventListener("mousedown", e => {
initX = e.clientX;
initWidth = this.searchInput.clientWidth * 2 + 2;
document.addEventListener("mousemove", sizeChangeMouseMove);
document.addEventListener("mouseup", sizeChangeMouseUp);
e.stopPropagation();
e.preventDefault();
});
let dragSiteBtn;
let dragOpenDropHandler = e => {
if (!this.contains(e.target)){
let isPage = /^(https?|ftp):/.test(dragSiteBtn.href);
if (isPage) {
dragSiteBtn.setAttribute("target", "_blank");
}
if (!isPage) {
dragSiteBtn.click();
} else {
_GM_openInTab(dragSiteBtn.href, {active: false, insert: true});
}
if (isPage) {
dragSiteBtn.setAttribute("target", dragSiteBtn.dataset.target == 1 ? "_blank" : "_self");
}
}
getBody(document).removeEventListener('dragover', dragOpenOverHandler);
document.removeEventListener('drop', dragOpenDropHandler);
document.removeEventListener('dragover', dragOpenOverHandler);
};
let dragOpenOverHandler = e => {
e.preventDefault();
};
let dragOpenEndHandler = e => {
getBody(document).removeEventListener('dragover', dragOpenOverHandler);
document.removeEventListener('drop', dragOpenDropHandler);
document.removeEventListener('dragover', dragOpenOverHandler);
};
this.bar.addEventListener("dragstart", e => {
let target = e.target;
let parentNode = target.parentNode;
if (target.nodeName.toUpperCase() !== 'IMG' && target.nodeName.toUpperCase() !== 'A') return;
if (target.classList && target.classList.contains('search-jumper-btn')) {
dragSiteBtn = target;
getBody(document).addEventListener('dragover', dragOpenOverHandler);
document.addEventListener('drop', dragOpenDropHandler);
document.addEventListener('dragend', dragOpenEndHandler);
} else if (parentNode && parentNode.classList && parentNode.classList.contains('search-jumper-btn')) {
dragSiteBtn = parentNode;
getBody(document).addEventListener('dragover', dragOpenOverHandler);
document.addEventListener('drop', dragOpenDropHandler);
document.addEventListener('dragend', dragOpenEndHandler);
}
}, true);
sitesNum = 0;
let hasCurrent = currentSite !== false;
for (let siteConfig of bookmarkTypes) {
await this.createType(siteConfig);
sitesNum += siteConfig.sites.length;
if (sitesNum > 200) {
await sleep(1);
sitesNum = 0;
}
}
if (!this.findInpageAddons) {
this.findInpageAddons = _unsafeWindow.searchJumperAddons.filter(
data => data.type == "findInPage"
).sort((a, b) => (a.sort || 0) - (b.sort || 0));
let self = this, index = 0, addonDict = {};
this.findInpageAddons.forEach(addon => {
let name = addon.name || ("addon" + index++);
if (addonDict[addon.sort]) addon.disable = true;
else if (searchData.prefConfig.disableAddon[name] === true) {
addon.disable = true;
} else if (searchData.prefConfig.disableAddon[name] === false) {
addon.disable = false;
} else {
addon.disable = ext ? true : false;
}
addonDict[addon.sort] = true;
self.createAddonSpan(name, addon);
});
}
if (this.fontPool.length > 0 || isInConfigPage) {
let linkEle = document.createElement("link");
linkEle.rel="stylesheet";
linkEle.href = searchData.prefConfig.fontAwesomeCss || "https://lib.baomitu.com/font-awesome/6.1.2/css/all.css";
document.documentElement.insertBefore(linkEle, document.documentElement.children[0]);
this.addToShadow(linkEle.cloneNode());
waitForFontAwesome(() => {
let hasFont = false;
this.fontPool.forEach(font => {
font.innerText = '';
font.style.fontSize = '';
font.style.color = '';
hasFont = true;
cacheFontPool.unshift(font);
});
if (hasFont && (isInConfigPage || href === firstRunPage)) {
setTimeout(() => {cacheFontManager()}, 3000);
}
this.buildAllPageGroupTab();
});
} else {
this.buildAllPageGroupTab();
}
if (isAllPage) return;
if (disableHighlight && disableHighlight != location.hostname && window.top == window.self) {
storage.setItem("disableHighlight", "");
}
await this.testCSP();
let foundKeyword = currentSite && wordParamReg.test(currentSite.url);
if (!hasCurrent && foundKeyword) {
this.inSearchEngine();
} else if (!currentSite && window.top == window.self) {
this.checkSearchJump();
}
let hasHighlightWords = this.initInPageWords && this.initInPageWords.length;
if (inMinMode || (this.bar.style.display === "none" && (!navEnable || !hasHighlightWords))) {
this.removeBar();
}
}
buildAllPageGroupTab() {
let self = this;
this.groupTab.innerHTML = createHTML();
searchTypes.forEach(type => {
if (type.classList.contains("notmatch")) return;
let typeName = type.dataset.type;
let icon = type.firstElementChild.cloneNode(true);
let groupSpan = document.createElement("span");
groupSpan.appendChild(icon);
groupSpan.dataset.type = typeName;
groupSpan.addEventListener("click", e => {
let targetType = self.sitelistBox.querySelector(`[data-type="${typeName}"]`);
if (targetType) targetType.scrollIntoView({behavior: "smooth", block: "start", inline: "center"});
});
self.groupTab.appendChild(groupSpan);
});
}
async refreshEngines() {
if (!searchData) return;
if (this.refreshing) return;
this.refreshing = true;
setTimeout(() => {
this.refreshing = false;
}, 500);
lastModified = searchData.lastModified;
this.removeBar();
if (searchTypes && searchTypes.length) {
searchTypes.forEach(type => {
type.parentNode && type.parentNode.removeChild(type);
});
}
searchTypes = [];
this.allSiteBtns = [];
this.allListBtns = [];
this.allLists = [];
this.historyTypeEle = null;
for (let siteConfig of searchData.sitesConfig) {
await this.createType(siteConfig);
}
this.initHistorySites();
this.initSort();
this.buildAllPageGroupTab();
if (isAllPage) {
this.appendBar();
}
}
waitForHide(delay) {
let self = this;
if (this.bar.classList.contains("grabbing")) return;
this.touched = false;
var hideHandler = () => {
//self.bar.classList.remove("search-jumper-isInPage");
self.bar.classList.remove("search-jumper-isTargetImg");
self.bar.classList.remove("search-jumper-isTargetAudio");
self.bar.classList.remove("search-jumper-isTargetVideo");
self.bar.classList.remove("search-jumper-isTargetLink");
//self.bar.classList.remove("search-jumper-isTargetPage");
self.bar.classList.remove("initShow");
self.tips.style.opacity = 0;
self.tips.style.display = "none";
self.tips.innerHTML = createHTML("");
//self.recoveHistory();
if (self.funcKeyCall) {
self.setFuncKeyCall(false);
if ((currentSite && !currentSite.hideNotMatch && !searchData.prefConfig.hideOnSearchEngine) || self.con.classList.contains("resizePage")) {
self.initPos();
let firstType = self.bar.querySelector('.search-jumper-type:nth-child(1)>span');
if (firstType && !firstType.classList.contains("search-jumper-open")) {
if (firstType.onmousedown) {
firstType.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
firstType.dispatchEvent(mouseEvent);
}
}
} else {
self.bar.style.display = 'none';
}
}
if (searchData.prefConfig.autoClose) {
self.closeOpenType();
}
self.hideTimeout = null;
};
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
}
let delayTime = typeof delay === 'undefined' ? (this.funcKeyCall ? 500 : (searchData.prefConfig.autoDelay || 1000)) : delay;
if (delayTime) {
this.hideTimeout = setTimeout(hideHandler, delayTime);
} else hideHandler();
if (this.preList) {
this.preList.style.visibility = "hidden";
this.listArrow.style.cssText = "";
}
}
searchEngineWords(words) {
words = words.replace(/( |^)-\S+/g, "");
if (/".+"/.test(words)) {
words = words.replace(/"(.+)"/g, (match, p, offset, string) => {
return `◎${p}◎`;
}).replace(/^◎|◎$/g, "");
}
this.lastSearchEngineWords = words.replace(/['";]/g, ' ');
return this.lastSearchEngineWords;
}
setInPageWords(inPageWords, cb) {
this.initInPageWords.push(inPageWords);
//this.searchInPageTab.checked = true;
this.con.classList.add("in-find");
let beginHandler = () => {
setTimeout(async () => {
if (getBody(document).style.display === "none") getBody(document).style.display = "";
if (this.lockWords) {
this.initInPageWords = [];
} else {
while (document.hidden) {
await sleep(1000);
}
storage.setItem("lastHighlight", location.hostname);
let word = this.initInPageWords.shift();
while (word) {
this.searchJumperInPageInput.value = word;
this.submitInPageWords(true);
word = this.initInPageWords.shift();
}
}
if (cb) cb();
await sleep(100);
storage.setItem("lastHighlight", "");
}, 300);
};
if (document.readyState != "complete") {
let loadHandler = e => {
if (document.readyState == "complete") {
document.removeEventListener("readystatechange", loadHandler);
window.removeEventListener('load', loadHandler);
beginHandler();
}
};
document.addEventListener("readystatechange", loadHandler);
window.addEventListener('load', loadHandler);
} else {
beginHandler();
}
}
searchInPageRule() {
if (searchData.prefConfig.disableAutoHighlight) {
let sites = searchData.prefConfig.disableAutoHighlight.trim().split("\n");
for (let i = 0; i < sites.length; i++) {
let key = sites[i], isMatch = false;
if (key.indexOf("/") === 0) {
let keyMatch = key.match(/^\/(.*)\/([igm]*)$/);
if (keyMatch) {
isMatch = new RegExp(keyMatch[1], keyMatch[2]).test(href);
}
} else {
isMatch = this.globMatch(key, href);
}
if (isMatch) {
this.disableAutoHighlight = true;
return;
}
}
}
if (lastHighlight === location.hostname) {
this.disableAutoHighlight = true;
}
if (searchData.prefConfig.inPageRule) {
let keys = Object.keys(searchData.prefConfig.inPageRule);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
if (!key) continue;
let isMatch = false;
if (key.indexOf("/") === 0) {
let keyMatch = key.match(/^\/(.*)\/([igm]*)$/);
if (keyMatch) {
isMatch = new RegExp(keyMatch[1], keyMatch[2]).test(href);
}
} else {
isMatch = this.globMatch(key, href);
}
if (isMatch) {
let rule = searchData.prefConfig.inPageRule[key];
if (!rule) continue;
this.inPageRuleKey = key;
this.disableAutoHighlight = true;
this.setInPageWords(rule);
break;
}
}
}
}
checkSearchJump() {
if (this.inPageRuleKey || this.disableAutoHighlight) return;
let inPageWords;
if (searchData.prefConfig.showInSearchJumpPage && referrer && !disableHighlight) {
if (curRef.indexOf(referrer) != -1) {
if (cacheKeywords) {
this.wordModeBtn.classList.add("checked");
}
inPageWords = cacheKeywords;
try {
inPageWords = decodeURIComponent(inPageWords);
inPageWords = this.searchEngineWords(inPageWords);
} catch (e) {}
//storage.setItem("referrer", location.hostname);
} else {
//storage.setItem("referrer", "");
}
}
inPageWords = inPageWords || globalInPageWords;
if (inPageWords) {
this.appendBar();
let self = this;
this.setInPageWords(inPageWords, () => {
if (!self.navMarks.innerHTML && self.bar.style.display === "none") self.removeBar();
});
} else if (!this.searchJumperInPageInput.value && curRef.indexOf(referrer) != -1 && cacheKeywords) {
inPageWords = cacheKeywords;
this.wordModeBtn.classList.add("checked");
try {
inPageWords = decodeURIComponent(inPageWords);
} catch (e) {}
this.searchJumperInPageInput.value = inPageWords;
}
}
inSearchEngine() {
if (!this.currentType || !currentSite || inIframe || this.inPageRuleKey || this.disableAutoHighlight) return;
if (!/sidesearch=(1|true)$/i.test(location.search)) {
if (!/#p{/.test(currentSite.url) || currentSite.keywords) {
this.appendBar();
if (this.currentType.classList.contains("search-jumper-needInPage")) {
this.bar.classList.add("search-jumper-isTargetPage");
} else if (this.currentType.classList.contains("search-jumper-targetAll") ||
this.currentType.classList.contains("search-jumper-targetImg") ||
this.currentType.classList.contains("search-jumper-targetAudio") ||
this.currentType.classList.contains("search-jumper-targetVideo") ||
this.currentType.classList.contains("search-jumper-targetLink") ||
this.currentType.classList.contains("search-jumper-targetPage")) {
return;
}
if (!searchData.prefConfig.hideOnSearchEngine) {
this.bar.style.display = "";
this.initPos();
}
}
}
this.insertHistory(this.currentType, true);
this.wordModeBtn.classList.add("checked");
let inPageWords = searchData.prefConfig.showInSearchEngine ? this.searchEngineWords(localKeywords) : globalInPageWords;
if (inPageWords) {
this.setInPageWords(inPageWords);
}
}
getSuggest(searchWords) {
let suggestDatalist = this.suggestDatalist;
suggestDatalist.innerHTML = createHTML();
if (!searchWords) return;
let requestSuggest = (api, cb, charset) => {
_GM_xmlhttpRequest({
method: 'GET',
url: api,
responseType: charset ? 'blob' : '',
headers: {
referer: api,
origin: api
},
onload: function(d) {
let response = d.response;
if (d.status >= 400 || !response) return;
if (charset) {
let reader = new FileReader();
reader.onload = () => {
cb(reader.result);
}
reader.readAsText(response, charset);
} else {
cb(response);
}
},
onerror: function(e){
debug(e);
},
ontimeout: function(e){
debug(e);
}
});
};
if (ext) {
requestSuggest = (api, cb) => {
chrome.runtime.sendMessage({action: "getSuggest", detail: {suggestType: searchData.prefConfig.suggestType, searchWords: searchWords}}, function(r) {
cb(r);
});
}
}
switch (searchData.prefConfig.suggestType) {
case "google":
requestSuggest("https://suggestqueries.google.com/complete/search?client=youtube&q=%s&jsonp=window.google.ac.h".replace("%s", searchWords), res => {
res = res.match(/window.google.ac.h\((.*)\)$/, "$1");
if (res) {
res = JSON.parse(res[1])[1];
for (let i in res) {
let option = document.createElement('option');
option.value = res[i][0];
suggestDatalist.appendChild(option);
}
}
});
break;
case "baidu":
requestSuggest("https://suggestion.baidu.com/su?wd=%s&cb=".replace("%s", searchWords), res => {
res = res.match(/.*,s:(.*)}\);$/, "$1");
if (res) {
res = JSON.parse(res[1]);
for (let i in res) {
let option = document.createElement('option');
option.value = res[i];
suggestDatalist.appendChild(option);
}
}
}, "GBK");
break;
case "bing":
requestSuggest("https://api.bing.com/qsonhs.aspx?type=json&q=%s".replace("%s", searchWords), res => {
if (res) {
res = JSON.parse(res).AS.Results;
for (let i in res) {
let result = res[i].Suggests;
for (let j in result) {
let option = document.createElement('option');
option.value = result[j].Txt;
suggestDatalist.appendChild(option);
}
}
}
});
break;
default:
break;
}
}
searchSiteBtns(inputWords) {
let checkIndex = inputWords.indexOf('**'), checkType = "", accurate = false;
if (checkIndex > 0) {
checkType = inputWords.slice(0, checkIndex);
inputWords = inputWords.slice(checkIndex + 2);
}
if (inputWords.indexOf('^') === 0) {
accurate = true;
} else {
checkType = checkType.toLowerCase();
inputWords = inputWords.toLowerCase();
}
if (inputWords) {
this.con.classList.add("searching");
} else {
this.con.classList.remove("searching");
}
let canCheckHost = !/[^\w\.\/\:\*\?\^\$]/.test(inputWords);
this.allListBtns.forEach(listItem => {
listItem.classList.add("input-hide");
});
searchTypes.forEach(type => {
type.classList.add("input-hide");
});
let optionNum = 0;
this.filterGlob.innerHTML = createHTML();
this.allSiteBtns.forEach(arr => {
let btn = arr[0];
let data = arr[1];
let typeNode = btn.parentNode;
let targetType = btn.dataset.type;
let targetName = btn.dataset.name;
let targetTitle = btn.title;
if (!accurate) {
targetType = targetType.toLowerCase();
targetName = targetName.toLowerCase();
targetTitle = targetTitle.toLowerCase();
}
let globMatchName = "";
if (checkType) {
let typeMatch = this.globMatch(checkType, targetType);
if (!typeMatch) return;
globMatchName = btn.dataset.type + "**";
}
let canMatch = false;
if (!btn.dataset.clone) {
if (this.globMatch(inputWords, targetName)) {
canMatch = true;
globMatchName += '^' + btn.dataset.name + '$';
} else if (btn.title && this.globMatch(inputWords, targetTitle)) {
canMatch = true;
globMatchName += '^' + btn.title + '$';
}
}
if (!canMatch) {
if (canCheckHost) {
if (!btn.dataset.host) {
let hostReg = /^https?:\/\/([^\/]*)\/[\s\S]*$/;
let href = data.url;
btn.dataset.host = hostReg.test(href) ? href.replace(hostReg, "$1") : href;
if (btn.dataset.host) btn.dataset.host = btn.dataset.host.toLowerCase();
}
canMatch = this.globMatch(inputWords, btn.dataset.host);
}
if (!canMatch) {
btn.classList.add("input-hide");
} else {
globMatchName += '^' + btn.dataset.host + '$';
}
}
if (canMatch) {
btn.classList.remove("input-hide");
if (typeNode) typeNode.classList.remove("input-hide");
let listItem;
for (let i = 0; i < this.allListBtns.length; i++) {
if (this.allListBtns[i].id == "list" + btn.dataset.id) {
listItem = this.allListBtns[i];
break;
}
}
if (listItem) listItem.classList.remove("input-hide");
if (optionNum < 50 && inputWords && this.searchInput.value !== globMatchName) {
optionNum++;
let option = document.createElement('option');
option.value = globMatchName;
this.filterGlob.appendChild(option);
}
}
});
searchTypes.forEach(type => {
let targetList;
for (let i = 0; i < this.allLists.length; i++) {
if (this.allLists[i].dataset.type == type.dataset.type) {
targetList = this.allLists[i];
break;
}
}
if (!targetList) return;
if (type.classList.contains("input-hide")) {
targetList.classList.add("input-hide");
} else targetList.classList.remove("input-hide");
});
let showType = this.bar.querySelector(".search-jumper-type:not(.input-hide)");
if (showType) {
if (!showType.classList.contains("search-jumper-open")) {
let typeBtn = showType.querySelector("span.search-jumper-btn");
if (typeBtn.onmousedown) {
typeBtn.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
typeBtn.dispatchEvent(mouseEvent);
}
}
if (this.searchJumperExpand.parentNode == showType) {
let mouseEvent = new PointerEvent("click");
this.searchJumperExpand.dispatchEvent(mouseEvent);
}
}
}
globMatch(glob, target, inner) {
if (target.length > 500) return false;
try {
if (glob.length == 0 || glob === '*') {
return true;
}
if (glob.length === 1 && glob[0] === '$') {
return !target || target.length === 0;
}
if (glob.length > 1 && glob[0] === '*' &&
(!target || target.length === 0)) {
return false;
}
if (!inner) {
inner = true;
if (glob.length > 1 && glob[0] === '^' &&
target && target.length !== 0) {
glob = glob.substring(1);
if (glob[0] !== target[0]) {
return false;
}
} else if (glob[0] !== '*') {
glob = '*' + glob;
}
}
if ((glob.length > 1 && glob[0] === '?') ||
(glob.length != 0 && target && target.length !== 0 &&
glob[0] === target[0])) {
return this.globMatch(glob.substring(1),
target.substring(1), !!inner);
}
if (glob.length > 0 && glob[0] === '*') {
return this.globMatch(glob.substring(1), target, !!inner) ||
this.globMatch(glob, target && target.substring(1), !!inner);
}
} catch(e) {
debug(e);
}
return false;
}
setCurrentSite(data, siteEle) {
currentSite = data;
siteEle.classList.add('current');
localKeywords = "";
if (!/#p{|^(showTips|find)/.test(data.url) && wordParamReg.test(data.url)) {
this.updateCacheKeywords();
storage.setItem("referrer", location.hostname);
}
}
updateCacheKeywords() {
let keywords = getKeywords();
if (keywords && keywords != cacheKeywords) {
cacheKeywords = keywords;
storage.setItem("cacheKeywords", keywords);
}
}
refresh() {
if (this.refreshInPageTimer) {
clearTimeout(this.refreshInPageTimer);
}
this.refreshInPageTimer = setTimeout(() => {
let oldWords = this.curHighlightWords;
this.highlight("");
this.highlight(oldWords);
if (this.bar.style.display == "none") {
currentSite = null;
let typeData;
for (let i in searchData.sitesConfig) {
if (currentSite) break;
typeData = searchData.sitesConfig[i];
if (!typeData) {
continue;
}
let sites = typeData.sites;
for (let j in sites) {
if (currentSite) break;
let data = sites[j];
if (!data || !data.url) {
continue;
}
let currentData;
if (data.match === '0') {
} else if (data.match) {
if (new RegExp(data.match).test(href)) {
currentData = data;
}
} else if (data.url.indexOf(location.hostname) != -1) {
if (data.url.indexOf("site") != -1) {
let siteMatch = data.url.match(/site(%3A|:)([\s\S]+?)[\s%]/);
if (siteMatch && href.indexOf(siteMatch[2]) != -1 && data.url.replace(siteMatch[0], "").indexOf(location.hostname) != -1) {
currentData = data;
}
} else if (!currentSite && data.url.replace(/^https?:\/\//, "").replace(location.host, "").replace(/\/?[\?#][\s\S]*/, "") == location.pathname.replace(/\/$/, "")) {
let urlReg = data.url.match(/[^\/\?&]+(?=%[stb])/g);
if (urlReg) {
urlReg = urlReg.join('.*');
if (new RegExp(urlReg).test(href)) {
currentData = data;
}
}
}
}
if (currentData) {
let siteEle = this.getTargetSitesByName([currentData.name])[0];
this.currentType = siteEle.parentNode;
this.setCurrentSite(currentData, siteEle);
}
}
}
if (currentSite && wordParamReg.test(currentSite.url) && (!/#p{/.test(currentSite.url) || currentSite.keywords) && !searchData.prefConfig.hideOnSearchEngine) {
if (this.currentType.classList.contains("search-jumper-targetAll") ||
this.currentType.classList.contains("search-jumper-targetImg") ||
this.currentType.classList.contains("search-jumper-targetAudio") ||
this.currentType.classList.contains("search-jumper-targetVideo") ||
this.currentType.classList.contains("search-jumper-targetLink") ||
this.currentType.classList.contains("search-jumper-targetPage")) {
return;
}
this.appendBar();
this.bar.style.display = "";
this.initPos();
let typeBtn = this.bar.querySelector(`.search-jumper-type[data-type="${typeData.type}"]>span`);
if (typeBtn && !typeBtn.classList.contains("search-jumper-open")) {
this.bar.insertBefore(typeBtn.parentNode, this.bar.children[0]);
if (!searchData.prefConfig.disableAutoOpen && !searchData.prefConfig.disableTypeOpen) {
if (typeBtn.onmousedown) {
typeBtn.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
typeBtn.dispatchEvent(mouseEvent);
}
}
}
}
}
}, 500);
}
initSort() {
if (searchData.prefConfig.shiftLastUsedType && this.historyTypeEle) {
if (currentSite) {
this.bar.insertBefore(this.historyTypeEle, this.bar.children[1]);
} else {
this.bar.insertBefore(this.historyTypeEle, this.bar.children[0]);
}
}
if (searchData.prefConfig.sortType) {
let self = this;
searchTypes.sort((a, b) => {
let aTypeValue = sortTypeNames[a.dataset.type] || 0;
let bTypeValue = sortTypeNames[b.dataset.type] || 0;
return bTypeValue - aTypeValue;
});
let changed = false;
let allHide = !self.bar.children[0].classList.contains("search-jumper-open");
for (let i = searchTypes.length - 1; i >= 0; i--) {
let typeEle = searchTypes[i];
let curValue = sortTypeNames[typeEle.dataset.type] || 0;
if (i == searchTypes.length - 1) {
if (curValue > 0) {
changed = true;
sortTypeNames[typeEle.dataset.type] = 0;
}
} else {
let preValue = sortTypeNames[searchTypes[i + 1].dataset.type] || 0;
if (curValue - preValue > 10) {
changed = true;
sortTypeNames[typeEle.dataset.type] = preValue + 10;
}
}
self.bar.insertBefore(typeEle, self.bar.children[allHide ? 0 : 1]);
}
if (changed) storage.setItem("sortTypeNames", sortTypeNames);
}
}
initHistorySites() {
this.historySiteBtns = [];
this.txtHistorySiteBtns = [];
this.imgHistorySiteBtns = [];
this.linkHistorySiteBtns = [];
this.videoHistorySiteBtns = [];
this.audioHistorySiteBtns = [];
let self = this;
historySites.forEach(async n => {
for (let siteConfig of searchData.sitesConfig) {
let found = false;
let isBookmark = siteConfig.bookmark || siteConfig.sites.length > 100 || (/^BM/.test(siteConfig.type) && siteConfig.icon === "bookmark");
for (let i = 0; i < siteConfig.sites.length; i++) {
let site = siteConfig.sites[i];
if (site.name == n) {
let siteBtn = await self.createSiteBtn((searchData.prefConfig.noIcons ? "0" : site.icon), site, true, isBookmark, siteConfig, true);
siteBtn.classList.add("historySite");
self.historySiteBtns.push(siteBtn);
if (!siteConfig.selectImg && !siteConfig.selectLink && !siteConfig.selectPage && !siteConfig.selectVideo && !siteConfig.selectAudio) {
self.txtHistorySiteBtns.push(siteBtn);
}
if (siteConfig.selectImg) {
self.imgHistorySiteBtns.push(siteBtn);
}
if (siteConfig.selectLink || siteConfig.selectPage) {
self.linkHistorySiteBtns.push(siteBtn);
}
if (siteConfig.selectVideo) {
self.videoHistorySiteBtns.push(siteBtn);
}
if (siteConfig.selectAudio) {
self.audioHistorySiteBtns.push(siteBtn);
}
found = true;
break;
}
}
if (found) break;
}
});
}
insertHistory(typeEle, init) {
if (!searchData.prefConfig.historyLength) {
return;
}
typeEle.style.width = "auto";
typeEle.style.height = "auto";
let self = this;
this.historyInserted = true;
let num = 0;
let toFirst = !init && searchData.prefConfig.historyInsertFirst;
let insertBefore = false, maxSiteNum = 0;
if (!toFirst) {
insertBefore = this.searchJumperExpand.parentNode == typeEle && !searchData.prefConfig.expandType;
if (insertBefore) {
maxSiteNum = (searchData.prefConfig.numPerLine || 7) - 1;
maxSiteNum = searchData.prefConfig.historyLength < maxSiteNum ? (maxSiteNum + maxSiteNum - searchData.prefConfig.historyLength) : maxSiteNum;
if (searchData.prefConfig.hideTileType) {
maxSiteNum++;
}
}
}
let historySiteBtns = this.historySiteBtns;
if (typeEle.classList.contains("search-jumper-needInPage")) {
historySiteBtns = this.txtHistorySiteBtns;
} else if (typeEle.classList.contains("search-jumper-targetImg")) {
historySiteBtns = this.imgHistorySiteBtns;
} else if (typeEle.classList.contains("search-jumper-targetAudio")) {
historySiteBtns = this.audioHistorySiteBtns;
} else if (typeEle.classList.contains("search-jumper-targetVideo")) {
historySiteBtns = this.videoHistorySiteBtns;
} else if (typeEle.classList.contains("search-jumper-targetLink") || typeEle.classList.contains("search-jumper-targetPage")) {
historySiteBtns = this.linkHistorySiteBtns;
}
for (let i = 0; i < historySiteBtns.length; i++) {
let btn = historySiteBtns[i];
if (btn.style.display == "none") continue;
let siteImg = btn.querySelector('img');
if (siteImg && siteImg.dataset.src) {
siteImg.src = siteImg.dataset.src;
delete siteImg.dataset.src;
}
if (btn.parentNode != typeEle) {
let sites = typeEle.querySelectorAll("a.search-jumper-btn");
let findSame = false;
for (let j = 0; j < sites.length; j++) {
let site = sites[j];
if ((site.dataset.oriName || site.dataset.name) == (btn.dataset.oriName || btn.dataset.name)) {
findSame = true;
break;
}
}
if (findSame) continue;
if (toFirst) {
if (typeEle.children.length > 1) {
typeEle.insertBefore(btn, typeEle.children[1]);
} else typeEle.appendChild(btn);
} else {
if (insertBefore) {
let siteBtns = typeEle.querySelectorAll("a.search-jumper-btn");
if (siteBtns.length > maxSiteNum) {
typeEle.insertBefore(btn, siteBtns[maxSiteNum]);
} else typeEle.insertBefore(btn, self.searchJumperExpand);
} else typeEle.appendChild(btn);
}
if (++num >= searchData.prefConfig.historyLength) break;
} else if (toFirst) {
if (typeEle.children.length > 1) {
typeEle.insertBefore(btn, typeEle.children[1]);
} else typeEle.appendChild(btn);
}
}
typeEle.style.width = typeEle.scrollWidth + "px";
typeEle.style.height = typeEle.scrollHeight + "px";
}
recoveHistory() {
if (!searchData.prefConfig.historyLength) return;
if (!this.historyInserted) return;
this.historyInserted = false;
let self = this;
let curParent;
for (let i = 0; i < this.historySiteBtns.length; i++) {
let btn = this.historySiteBtns[i];
if (!btn.classList.contains("historySite")) continue;
curParent = btn.parentNode;
this.siteBtnReturnHome(btn);
}
if (curParent && curParent.classList.contains("search-jumper-open")) {
curParent.style.width = "auto";
curParent.style.height = "auto";
curParent.style.width = curParent.scrollWidth + "px";
curParent.style.height = curParent.scrollHeight + "px";
}
}
bindSite(a, siteEle) {
if (a.getAttribute("bind")) return;
a.setAttribute("bind", true);
let self = this;
if (siteEle.href) a.href = siteEle.href;
a.style.display = siteEle.style.display;
a.addEventListener('mousedown', async e => {
if (siteEle.dataset.showTips) {
if (self.con.classList.contains("search-jumper-showall")) {
targetElement = a.parentNode;
} else self.waitForHide(0);
siteEle.dispatchEvent(new CustomEvent('showTips'));
} else {
await self.siteSetUrl(siteEle, {button: e.button, altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, metaKey: e.metaKey});
if (siteEle.href) a.href = siteEle.href;
a.setAttribute("target", siteEle.target);
}
if (!a.onclick) {
a.onclick = e => {
if (!siteEle.dataset.showTips) siteEle.click();
e.stopPropagation();
e.preventDefault();
return false;
}
}
}, false);
a.addEventListener("dragover", e => {
e.preventDefault();
}, true);
a.addEventListener("dragenter", e => {
if (self.dragTarget) {
self.dragTarget.classList.remove("dragTarget");
}
self.dragTarget = a;
self.dragTarget.classList.add("dragTarget");
clearTimeout(self.dragTimer);
self.dragTimer = setTimeout(() => {
a.scrollIntoView({behavior: "smooth", block: "center", inline: "center"});
}, 1000);
}, true);
a.addEventListener("dragleave", e => {
a.classList.remove("dragTarget");
}, true);
a.addEventListener("drop", e => {
clearTimeout(self.dragTimer);
if (self.dragTarget) {
self.dragTarget.classList.remove("dragTarget");
}
self.searchBySiteName(siteEle.dataset.name, e);
}, true);
}
async createList(sites, type, batchSiteNames) {
let self = this;
let list = document.createElement("div");
list.className = "sitelist";
list.style.visibility = "hidden";
let con = document.createElement("div");
con.className = "sitelistCon";
list.appendChild(con);
list.addEventListener('mouseenter', e => {
self.listArrow.style.cssText = "";
});
let title = document.createElement("p");
title.innerText = type.dataset.title;
title.title = i18n('batchOpen');
title.addEventListener('click', e => {
self.batchOpen(batchSiteNames, {ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, altKey: e.altKey, metaKey: e.metaKey, button: (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) ? 0 : 2});
});
list.dataset.type = type.dataset.type;
con.appendChild(title);
function createItem(siteEle, index) {
let li = document.createElement("div");
li.id = "list" + index;
let icon = siteEle.querySelector("img");
let a = document.createElement("a");
a.setAttribute("ref", "noopener noreferrer");
self.bindSite(a, siteEle);
li.appendChild(a);
self.allListBtns.push(li);
if (icon && !searchData.prefConfig.noIcons) {
let iconSrc = icon.src || icon.dataset.src;
let img = document.createElement("img");
a.appendChild(img);
img.onload = e => {
img.style.width = "";
img.style.height = "";
img.style.display = "";
};
img.onerror = e => {
img.src = noImgBase64;
};
img.style.width = "1px";
img.style.height = "1px";
img.style.display = "none";
if (iconSrc) {
if (!/^data:/.test(iconSrc)) {
img.οnerrοr = e => {
img.src = noImgBase64;
img.onerror = null;
img.style.width = "";
img.style.height = "";
img.style.display = "";
};
img.dataset.src = iconSrc;
} else {
img.dataset.src = iconSrc;
}
} else {
img.dataset.src = noImgBase64;
}
}
let p = document.createElement("p");
p.innerText = siteEle.dataset.name;
li.title = siteEle.title;
li.dataset.name = siteEle.dataset.name;
a.appendChild(p);
con.appendChild(li);
}
try {
for (let [index, siteEle] of sites.entries()) {
createItem(siteEle, siteEle.dataset.id);
if (index%50 === 49) await sleep(1);
}
} catch(e) {
for (let index = 0; index < sites.length; index++) {
let siteEle = sites[index];
createItem(siteEle, siteEle.dataset.id);
}
}
this.allLists.push(list);
return list;
}
async initList(list) {
if (!list.dataset.inited) {
list.style.display = "none";
list.dataset.inited = true;
[].forEach.call(list.querySelectorAll("div>a>img"), img => {
if (img.dataset.src) {
img.src = img.dataset.src;
delete img.dataset.src;
}
});
await sleep(0);
}
}
async listPos(ele, list) {
//if (this.preList) {
//this.preList.style.visibility = "hidden";
//}
await this.initList(list);
list.style = "";
this.preList = list;
let ew = ele.clientWidth;
let eh = ele.clientHeight;
let clientX = ele.offsetLeft + ew / 2 - this.con.scrollLeft;
let clientY = ele.offsetTop + eh / 2 - this.con.scrollTop;
let current = ele.offsetParent;
while (current !== null){
clientX += current.offsetLeft;
clientY += current.offsetTop;
current = current.offsetParent;
}
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
let arrowStyle = this.listArrow.style;
arrowStyle.visibility = "visible";
arrowStyle.opacity = 1;
if (this.funcKeyCall) {
list.style.display = "block";
arrowStyle.opacity = 0;
const clientRect = ele.getBoundingClientRect();
clientX = clientRect.x + ew / 2 - this.con.scrollLeft;
clientY = clientRect.y + eh / 2 - this.con.scrollTop;
clientX -= list.clientWidth / 2;
let actualTop = ele.getBoundingClientRect().top;
if (actualTop > viewHeight / 2) {
if (actualTop < list.clientHeight + 10) {
list.style.height = actualTop - 20 + "px";
}
clientY -= (list.clientHeight + eh / 2 + 5);
} else {
clientY += (eh / 2 + 5);
if (actualTop + list.clientHeight + eh + 10 > viewHeight) {
list.style.height = viewHeight - actualTop - eh - 20 + "px";
}
}
if (clientX < 20) clientX = 20;
let maxLeft = viewWidth - list.clientWidth - 30;
if (clientX > maxLeft) {
clientX = maxLeft;
}
list.style.left = clientX + "px";
list.style.top = clientY + "px";
list.style.display = "";
} else if (this.bar.clientWidth > this.bar.clientHeight) {
//横
let arrowX = clientX;
if (clientX < 30) {
arrowX = 30;
} else if (clientX > viewWidth - 40) {
arrowX = viewWidth - 40;
}
arrowStyle.left = arrowX - 10 + "px";
if (clientY - eh / 2 < 100) {
list.style.top = this.bar.clientHeight + "px";
arrowStyle.top = this.bar.clientHeight - 10 + "px";
} else {
list.style.bottom = this.bar.clientHeight + "px";
arrowStyle.bottom = this.bar.clientHeight - 9 + "px";
}
clientX -= list.scrollWidth / 2;
if (clientX > viewWidth - list.scrollWidth - 10) clientX = viewWidth - list.scrollWidth - 10;
if (clientX < 0) clientX = 0;
list.style.left = clientX + "px";
} else {
//竖
let arrowY = clientY;
if (clientY < 30) {
arrowY = 30;
} else if (clientY > viewHeight - 30) {
arrowY = viewHeight - 30;
}
arrowStyle.top = arrowY - 10 + "px";
if (clientX - ew / 2 < 100) {
list.style.left = this.bar.clientWidth + "px";
arrowStyle.left = this.bar.clientWidth - 9 + "px";
} else {
list.style.right = this.bar.clientWidth + "px";
arrowStyle.right = this.bar.clientWidth - 9 + "px";
}
clientY -= list.scrollHeight / 2;
if (clientY > viewHeight - list.scrollHeight) clientY = viewHeight - list.scrollHeight;
if (clientY < 0) clientY = 0;
list.style.top = clientY + "px";
list.style.maxHeight = "100vh";
}
}
clingPos(clingEle, target, close) {
//if (this.preList) {
//this.preList.style.visibility = "hidden";
//}
let ew = clingEle.clientWidth || clingEle.offsetWidth;
let eh = clingEle.clientHeight || clingEle.offsetHeight;
/*let clientX = clingEle.offsetLeft + ew / 2 - this.con.scrollLeft;
let clientY = clingEle.offsetTop + eh / 2 - this.con.scrollTop - clingEle.parentNode.scrollTop;
let current = clingEle.offsetParent;*/
const clientRect = clingEle.getBoundingClientRect();
let clientX, clientY;
let showall = this.con && this.con.classList.contains("search-jumper-showall");
/*while (current !== null){
clientX += current.offsetLeft;
clientY += current.offsetTop;
current = current.offsetParent;
}*/
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
this.tips.style.position = "";
target.style.height = "";
if (!clingEle || /^(body|html)$/i.test(clingEle.nodeName)) {
this.tips.style.transition = "none";
this.tips.style.position = "fixed";
target.style.right = "";
target.style.bottom = "";
target.style.left = (viewWidth - target.clientWidth) / 2 + "px";
target.style.top = "min(11%,110px)";
} else if (showall) {
clientX = clientRect.x + ew / 2;
clientY = clientRect.y + eh / 2;
clientX -= target.clientWidth / 2 - this.con.scrollLeft;
clientY += this.con.scrollTop;
if (clientY > viewHeight / 2) clientY -= (target.clientHeight + eh / 2 + 10);
else clientY += (eh / 2 + 10);
target.style.right = "";
target.style.bottom = "";
target.style.left = clientX + "px";
target.style.top = clientY + "px";
} else if (this.funcKeyCall) {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || getBody(document).scrollTop;
let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || getBody(document).scrollLeft;
clientX = clientRect.x + ew / 2 - this.con.scrollLeft + scrollLeft;
clientY = clientRect.y + eh / 2 - this.con.scrollTop + scrollTop;
clientX -= target.clientWidth / 2;
let actualTop = clingEle.getBoundingClientRect().top;
if (actualTop > viewHeight / 2) {
if (actualTop < target.clientHeight + 10) {
target.style.height = actualTop - 20 + "px";
}
clientY -= (target.clientHeight + eh / 2 + 5);
} else {
clientY += (eh / 2 + 5);
if (actualTop + target.clientHeight + eh + 10 > viewHeight) {
target.style.height = viewHeight - actualTop - eh - 20 + "px";
}
}
if (clientX < 20) clientX = 20;
let maxLeft = viewWidth + scrollLeft - target.clientWidth - 30;
if (clientX > maxLeft) {
clientX = maxLeft;
}
target.style.right = "";
target.style.bottom = "";
target.style.left = clientX + "px";
target.style.top = clientY + "px";
} else {
clientX = clingEle.offsetLeft + ew / 2 - this.con.scrollLeft - clingEle.parentNode.scrollLeft;
clientY = clingEle.offsetTop + eh / 2 - this.con.scrollTop - clingEle.parentNode.scrollTop;
let current = clingEle.offsetParent;
while (current !== null){
clientX += current.offsetLeft;
clientY += current.offsetTop;
current = current.offsetParent;
}
if (clientY < eh) {
clientX -= target.clientWidth / 2;
clientY += target.clientHeight / 2;
if (clientX < 5) {
clientX = 5;
target.style.left = "5px";
target.style.right = "";
target.style.bottom = "";
} else if (clientX > viewWidth - target.clientWidth) {
target.style.left = "";
target.style.right = "5px";
target.style.bottom = "";
} else {
target.style.left = clientX + "px";
target.style.right = "";
target.style.bottom = "";
}
target.style.top = (close ? eh : eh + 20) + "px";
} else if (clientY > viewHeight - eh - 10) {
clientX -= target.clientWidth / 2;
if (clientX < 5) {
target.style.left = "5px";
target.style.right = "";
target.style.top = "";
} else if (clientX > viewWidth - target.clientWidth) {
target.style.left = "";
target.style.right = "5px";
target.style.top = "";
} else {
target.style.left = clientX + "px";
target.style.right = "";
target.style.top = "";
}
target.style.bottom = (close ? eh : eh + 20) + "px";
} else if (clientX > viewWidth - ew - 10) {
target.style.left = "";
target.style.bottom = "";
clientY -= target.clientHeight / 2;
if (clientY < 5) clientY = 5;
target.style.right = (close ? ew : ew + 20) + "px";
target.style.top = clientY + "px";
} else if (clientX < ew) {
target.style.right = "";
target.style.bottom = "";
clientY -= target.clientHeight / 2;
if (clientY < 5) clientY = 5;
target.style.left = (close ? ew : ew + 20) + "px";
target.style.top = clientY + "px";
} else {
target.style.right = "";
target.style.bottom = "";
target.style.left = clientX + "px";
target.style.top = clientY + "px";
}
}
}
tipsPos(ele, type) {
this.tips.innerHTML = createHTML(type);
this.tips.style.pointerEvents = "";
this.tips.style.display = "";
this.tips.style.opacity = 1;
this.clingPos(ele, this.tips);
clearTimeout(this.hideTips);
if (this.tips.style.transition) {
setTimeout(() => {
this.tips.style.transition = "";
}, 1);
}
let self = this;
[].forEach.call(this.tips.querySelectorAll('iframe'), iframe => {
let html = iframe.innerHTML;
if (html) {
iframe.innerHTML = createHTML();
if (iframe.src) {
iframe.addEventListener('load', e => {
try {
if (!iframe || !iframe.parentNode) return;
let doc = iframe.contentDocument || iframe.contentWindow.document;
let div = doc.createElement('div');
doc.body.appendChild(div);
div.outerHTML = createHTML(html);
} catch(e) {}
});
} else {
try {
let doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(html);
doc.close();
} catch(e) {}
}
}
});
[].forEach.call(this.tips.querySelectorAll('img,video'), media => {
media.addEventListener('load', e => {
self.clingPos(ele, self.tips);
});
});
if (window.markdownit) {
if (!self.md) {
self.md = window.markdownit();
}
[].forEach.call(this.tips.querySelectorAll('.markdown'), markdown => {
markdown.innerHTML = createHTML(self.md.render(markdown.innerHTML));
});
}
}
checkKwFilter(kwFilter, checkKw) {
if (checkKw.length > 600) {
checkKw = checkKw.slice(0, 500) + checkKw.slice(checkKw.length - 10);
}
let selectorMatch = kwFilter.match(/^@{(.*?)}/);
if (selectorMatch) {
if (!targetElement) return false;
let selector = selectorMatch[1];
let pass = [].some.call(getAllElements(selector, document), e => e === targetElement);
if (!pass) return false;
kwFilter = kwFilter.replace(selectorMatch[0], "");
}
let kwRe, fullMatch = kwFilter.match(/^\/(.*)\/(\w*)$/);
if (fullMatch) {
kwRe = new RegExp(fullMatch[1], fullMatch[2]);
} else {
kwRe = new RegExp(kwFilter, "i");
}
return (kwRe.test(checkKw || ""));
}
async createType(data) {
let self = this;
let type = data.type;
let icon = data.icon;
let inPage = data.selectTxt;
let selectImg = data.selectImg;
let selectAudio = data.selectAudio;
let selectVideo = data.selectVideo;
let selectLink = data.selectLink;
let selectPage = data.selectPage;
let sites = data.sites;
let match = false;
let openInNewTab = typeof data.openInNewTab === 'undefined' ? searchData.prefConfig.openInNewTab : data.openInNewTab;
let siteEles = [];
let ele = document.createElement("span");
ele.className = "search-jumper-type";
if (!searchData.prefConfig.expandType && sites.length > 10) ele.classList.add("not-expand");
if (data.match === '0') {
ele.style.display = 'none';
ele.classList.add("notmatch");
} else if (data.match) {
if (new RegExp(data.match).test(href) == false) {
ele.style.display = 'none';
ele.classList.add("notmatch");
} else {
match = true;
}
}
if (typeof data.description !== 'undefined') {
ele.dataset.title = type + " - " + data.description;
} else {
ele.dataset.title = type;
}
ele.dataset.type = type;
let typeBtn = document.createElement("span");
let img = document.createElement("img");
let iEle = document.createElement("b");
if (type.length >= 3) {
iEle.innerText = type.trim().substr(0, 4);
if (!/^[\w \-]+$/.test(iEle.innerText.substr(0, 3))) iEle.innerText = iEle.innerText.substr(0, 2);
} else iEle.innerText = type;
typeBtn.appendChild(iEle);
img.style.display = "none";
ele.appendChild(typeBtn);
typeBtn.classList.add("search-jumper-word");
typeBtn.classList.add("search-jumper-btn");
typeBtn.classList.add("noIcon");
let isBookmark = /^BM/.test(type) && data.icon === "bookmark";//書簽就不緩存了
if (icon) {
typeBtn.classList.remove("noIcon");
let isFontIcon = /^[a-z\- ]+$/.test(icon);
img.onload = e => {
img.style.display = "";
iEle.innerText = '';
iEle.style.display = 'none';
if (!isFontIcon) {
typeBtn.classList.remove("search-jumper-word");
}
};
if (isFontIcon) {
let cache = cacheIcon[icon.trim().replace(/ /g, '_')];
if (cache === 'fail' || !cache) {
iEle.className = icon.indexOf("fa") === 0 ? icon : "fa fa-" + icon;
this.fontPool.push(iEle);
} else {
img.src = cache;
img.style.width = '100%';
img.style.height = '100%';
typeBtn.appendChild(img);
}
} else {
let isBase64 = /^data:/.test(icon);
if (isBase64) {
img.src = icon;
} else {
let cache = searchData.prefConfig.cacheSwitch && cacheIcon[icon];
if (cache === 'fail') {
} else if (cache) {
img.src = cache;
} else {
img.src = icon;
if (!cacheIcon[icon] && !isBookmark) cachePool.push(img);
}
}
typeBtn.appendChild(img);
}
}
ele.addEventListener('mouseleave', e => {
self.listArrow.style.cssText = "";
self.dockerScaleBtns.forEach(btn => {
btn.style.setProperty("--scale", 1);
});
});
let batchSiteNames = [];
let batchOpenConfirm = (e) => {
switch (searchData.prefConfig.batchOpenConfirm) {
case 1:
if (window.confirm(i18n('batchOpenConfirm'))) {
self.batchOpen(batchSiteNames, e);
}
break;
case 2:
self.batchOpen(batchSiteNames, e);
break;
default:
if (ele.classList.contains("search-jumper-open") || (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) || window.confirm(i18n('batchOpenConfirm'))) {
self.batchOpen(batchSiteNames, e);
}
break;
}
};
if (searchData.prefConfig.shortcut && data.shortcut && !ele.classList.contains("notmatch")) {
let shortcurStr = data.shortcut.replace('Key', '').replace('Digit', '').toUpperCase();
if (shortcurStr.length == 1) ele.dataset.title += ` (${shortcurStr})`;
document.addEventListener('keydown', e => {
if (e.target.id === "searchJumperInput") return;
if ((!data.ctrl == e.ctrlKey) ||
(!data.alt == e.altKey) ||
(!data.shift == e.shiftKey) ||
(!data.meta == e.metaKey)) {
return;
}
if (!searchData.prefConfig.enableInInput && !data.ctrl && !data.alt && !data.shift && !data.meta) {
if (inputActive(document)) return;
}
var key = (e.key || String.fromCharCode(e.keyCode)).toLowerCase();
if (data.shortcut == e.code || data.shortcut == key) {
batchOpenConfirm(e);
e.stopPropagation();
}
});
}
let shownSitesNum = 0;
let baseSize = this.scale * 40;
let taggleHide = (se, show) => {
if (show) {
se.style.display = '';
if (ele.children.length > 2) ele.insertBefore(se, ele.children[2]);
} else {
se.style.display = 'none';
if (self.searchJumperExpand.parentNode == ele) {
ele.insertBefore(se, self.searchJumperExpand);
} else ele.appendChild(se);
}
}
let typeAction = e => {
if (e) {
if (e.button === 2) {
batchOpenConfirm(e);
return false;
} if (e.button === 0 && (e.shiftKey || e.altKey || e.ctrlKey)) {
return false;
}
}
if (self.funcKeyCall) {
self.showAllSites();
return false;
}
let leftRight = self.con.classList.contains("search-jumper-left") ||
self.con.classList.contains("search-jumper-right");
if (self.preList) {
self.preList.style.visibility = "hidden";
self.listArrow.style.cssText = "";
}
ele.classList.remove('search-jumper-move');
if (!ele.classList.contains("search-jumper-open")) {
self.recoveHistory();
ele.classList.add("search-jumper-open");
if (searchData.prefConfig.minSizeMode) {
self.bar.classList.remove("minSizeModeClose");
}
let targetInput = false;
if (targetElement) {
targetInput = isInput(targetElement);
}
let href = targetElement && (targetElement.href || targetElement.src);
let keyWords = getKeywords();
shownSitesNum = 0;
siteEles.forEach((se, i) => {
let data = sites[i];
let pass = true;
if (data.kwFilter) {
let checkKw;
if (se.dataset.link) {
checkKw = href || keyWords;
} else {
checkKw = se.dataset.txt ? (keyWords || (targetElement && targetElement.innerText) || "") : (href || keyWords || location.href);
}
pass = self.checkKwFilter(data.kwFilter, checkKw);
}
if (pass && se.dataset.paste) {
pass = targetInput;
taggleHide(se, pass);
} else if (data.kwFilter) {
taggleHide(se, pass);
}
let si = se.querySelector("img");
if (se.style.display != "none") {
shownSitesNum++;
}
if (si && !si.src && si.dataset.src) {
si.src = si.dataset.src;
delete si.dataset.src;
}
});
if (shownSitesNum > (searchData.prefConfig.expandTypeLength || 12) && !searchData.prefConfig.expandType) {
ele.classList.add("not-expand");
ele.appendChild(self.searchJumperExpand);
}
let scrollSize = Math.max(ele.scrollWidth, ele.scrollHeight) + 5 + "px";
if (searchData.prefConfig.disableTypeOpen) {
scrollSize = baseSize + "px";
if (e) self.listPos(ele.children[0], siteList);
}
if (leftRight) {
ele.style.height = scrollSize;
ele.style.width = "";
} else {
ele.style.width = scrollSize;
ele.style.height = "";
}
setTimeout(() => {
if (ele.classList.contains("search-jumper-open")) {
ele.style.flexWrap = "nowrap";
ele.classList.add('search-jumper-move');
}
}, searchData.prefConfig.typeOpenTime);
searchTypes.forEach(type => {
if (ele != type) {
type.classList.remove("search-jumper-open");
type.style.width = baseSize + "px";
type.style.height = baseSize + "px";
type.style.flexWrap = "";
}
});
} else {
if (searchData.prefConfig.minSizeMode) {
self.bar.classList.add("minSizeModeClose");
}
ele.classList.remove("search-jumper-open");
if (leftRight) {
ele.style.height = baseSize + "px";
ele.style.width = "";
} else {
ele.style.height = "";
ele.style.width = baseSize + "px";
}
ele.style.flexWrap = "";
if (searchData.prefConfig.disableTypeOpen) {
siteList.style.visibility = "hidden";
}
}
if (!searchData.prefConfig.disableTypeOpen) {
setTimeout(() => {
self.checkScroll();
}, searchData.prefConfig.typeOpenTime);
}
};
let draged = false, initMousePos, initTilePos;
let mouseUpHandler = e => {
document.removeEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mousemove', mouseMoveHandler);
if (!draged) {
typeAction(e);
}
draged = false;
}
let mouseMoveHandler = e => {
if (!draged) {
self.tips.style.opacity = 0;
draged = true;
initMousePos = {x: e.clientX, y: e.clientY};
initTilePos = {x: parseInt(self.bar.style.left), y: parseInt(self.bar.style.top)};
} else {
self.bar.style.left = initTilePos.x + e.clientX - initMousePos.x + "px";
self.bar.style.top = initTilePos.y + e.clientY - initMousePos.y + "px";
}
}
typeBtn.onmousedown = function (e) {
if (e && self.funcKeyCall && e.button === 0 && !(e.shiftKey || e.altKey || e.ctrlKey)) {
draged = false;
e.preventDefault && e.preventDefault();
document.addEventListener('mouseup', mouseUpHandler);
document.addEventListener('mousemove', mouseMoveHandler);
return;
}
typeAction(e);
};
typeBtn.oncontextmenu = function (e) {
e.preventDefault();
};
typeBtn.addEventListener('click', e => {
self.batchOpen(batchSiteNames, e);
return false;
}, false);
typeBtn.addEventListener('dblclick', e=>{
e.stopPropagation();
e.preventDefault();
}, true);
let showTimer, siteList;
let viewWidth = window.screen.availWidth || window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.screen.availHeight || window.innerHeight || document.documentElement.clientHeight;
let availableSize = !isMobile || (viewWidth > 600 && viewHeight > 600);
ele.addEventListener('sitelist', async e => {
ele.appendChild(siteList);
await self.listPos(e.detail.bind, siteList);
siteList.style.display = "block";
}, false);
typeBtn.addEventListener('mouseenter', e => {
if (draged) {
return;
}
if (!self.funcKeyCall && searchData.prefConfig.showSiteLists && (searchData.prefConfig.alwaysShowSiteLists || !ele.classList.contains("search-jumper-open"))) {
ele.appendChild(siteList);
self.listPos(ele.children[0], siteList);
} else if (availableSize) {
self.tipsPos(typeBtn, ele.dataset.title);
}
if (searchData.prefConfig.overOpen) {
if (ele.classList.contains("search-jumper-open")) return;
clearTimeout(showTimer);
showTimer = setTimeout(() => {
typeAction(e);
}, 500);
}
}, false);
typeBtn.addEventListener('mouseleave', e => {
self.tips.style.opacity = 0;
if (searchData.prefConfig.overOpen) {
clearTimeout(showTimer);
}
}, false);
let isCurrent = false;
let tooLoog = sites && sites.length > 200;
ele.dataset.id = self.siteIndex;
self.stopInput = false;
async function createItem(site, i) {
if (!site.name) return;
let siteEle = await self.createSiteBtn((tooLoog || searchData.prefConfig.noIcons ? "0" : site.icon), site, openInNewTab, isBookmark, data);
if (!siteEle) {
return;
}
if (!siteEle.classList.contains("notmatch")) {
shownSitesNum++;
}
siteEle.dataset.type = type;
siteEle.dataset.id = self.siteIndex;
self.siteIndex++;
self.allSiteBtns.push([siteEle, site]);
ele.appendChild(siteEle);
siteEles.push(siteEle);
if (!site.nobatch && site.match !== "0") batchSiteNames.push(site.name);
if (!isCurrent && !currentSite && (siteEle.dataset.current || match) && !ele.classList.contains("notmatch")) {
isCurrent = true;
if (siteEle.dataset.current) {
if (!searchData.prefConfig.showCurrent) {
siteEle.style.display = 'none';
}
self.setCurrentSite(site, siteEle);
}
self.currentType = ele;
}
}
try {
for (let [i, site] of sites.entries()) {
await createItem(site, i);
if (i % 100 === 99) await sleep(1);
}
} catch(e) {
for (let i = 0; i < sites.length; i++) {
createItem(sites[i], i);
}
await sleep(1);
}
if (searchData.prefConfig.sortSite && ele.children.length > 1) {
siteEles.sort((a, b) => {
let aSiteValue = sortSiteNames[a.dataset.name] || 0;
let bSiteValue = sortSiteNames[b.dataset.name] || 0;
return bSiteValue - aSiteValue;
});
let changed = false;
for (let i = siteEles.length - 1; i >= 0; i--) {
let siteEle = siteEles[i];
let curValue = sortSiteNames[siteEle.dataset.name] || 0;
if (i == siteEles.length - 1) {
if (curValue > 0) {
changed = true;
sortSiteNames[siteEle.dataset.name] = 0;
}
} else {
let preValue = sortSiteNames[siteEles[i + 1].dataset.name] || 0;
if (curValue - preValue > 10) {
changed = true;
sortSiteNames[siteEle.dataset.name] = preValue + 10;
}
}
ele.insertBefore(siteEle, ele.children[1]);
}
if (changed) storage.setItem("sortSiteNames", sortSiteNames);
}
siteEles.forEach(siteEle => {
if (siteEle.classList.contains("notmatch")) {
ele.appendChild(siteEle);
}
});
siteList = await self.createList(siteEles, ele, batchSiteNames);
if (isCurrent) {
if (searchData.prefConfig.currentTypeFirst) {
self.bar.insertBefore(ele, self.bar.children[0]);
} else {
self.bar.insertBefore(ele, self.bar.children[self.bar.children.length - 1]);
}
if (!searchData.prefConfig.disableAutoOpen && !searchData.prefConfig.disableTypeOpen) {
ele.classList.add("search-jumper-open");
ele.classList.add('search-jumper-move');
if (shownSitesNum > (searchData.prefConfig.expandTypeLength || 12) && !searchData.prefConfig.expandType) {
ele.classList.add("not-expand");
ele.appendChild(self.searchJumperExpand);
}
let shownIconNum = -1, waitIconList = [];
if (document.readyState !== 'complete') {
shownIconNum = 3;
let loadHandler = e => {
if (document.readyState === "complete") {
document.removeEventListener("readystatechange", loadHandler);
window.removeEventListener('load', loadHandler);
waitIconList.forEach(icon => {
if (icon && !icon.src && icon.dataset.src) {
icon.src = icon.dataset.src;
delete icon.dataset.src;
}
});
waitIconList = [];
}
};
document.addEventListener("readystatechange", loadHandler);
window.addEventListener('load', loadHandler);
}
siteEles.forEach((se, i) => {
let si = se.querySelector("img");
let data = sites[i];
if (data && localKeywords && data.kwFilter) {
let pass = self.checkKwFilter(data.kwFilter, localKeywords);
if (pass) {
se.style.display = '';
} else {
se.style.display = 'none';
if (self.searchJumperExpand.parentNode == ele) {
ele.insertBefore(se, self.searchJumperExpand);
} else ele.appendChild(se);
}
}
if (se.style.display != 'none' && si && !si.src && si.dataset.src) {
if (shownIconNum >= 0 && !/^data/.test(si.dataset.src)) {
if (shownIconNum !== 0) {
shownIconNum--;
} else {
waitIconList.push(si);
return;
}
}
si.src = si.dataset.src;
delete si.dataset.src;
}
});
}
} else {
if (!self.historyTypeEle) {
if (historyType == type) {
self.historyTypeEle = ele;
}
}
self.bar.insertBefore(ele, self.bar.children[self.bar.children.length - 1]);
}
ele.style.width = ele.scrollHeight + "px";
ele.style.height = ele.scrollHeight + "px";
siteList.style.display = "none";
ele.appendChild(siteList);
if (inPage && selectImg && selectAudio && selectVideo && selectLink && selectPage) {
ele.classList.add("search-jumper-targetAll");
} else {
if (inPage) {
ele.classList.add("search-jumper-needInPage");
}
if (selectImg) {
ele.classList.add("search-jumper-targetImg");
}
if (selectAudio) {
ele.classList.add("search-jumper-targetAudio");
}
if (selectVideo) {
ele.classList.add("search-jumper-targetVideo");
}
if (selectLink) {
ele.classList.add("search-jumper-targetLink");
}
if (selectPage) {
ele.classList.add("search-jumper-targetPage");
}
}
searchTypes.push(ele);
return ele;
}
async openSiteBtn(siteEle, forceTarget, active = false) {
await this.siteSetUrl(siteEle);
let isPage = siteEle.dataset.isPage;
if (!forceTarget) forceTarget = "_blank";
if (isPage) {
siteEle.setAttribute("target", forceTarget);
}
if (isPage && forceTarget == "_blank" && siteEle.href) {
_GM_openInTab(siteEle.href, {active: active, insert: true});
} else {
siteEle.click();
}
siteEle.setAttribute("target", siteEle.dataset.target == 1 ? "_blank" : "_self");
}
async batchOpen(siteNames, e, newTab) {
let self = this;
self.batchOpening = true;
self.customInput = false;
if (e.altKey && e.shiftKey) {
let targetSites = self.getTargetSitesByName(siteNames);
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let html = '<title>SearchJumper Multi</title><style>body{background: black; margin: 0;}iframe{box-sizing: border-box;padding: 5px}</style>';
let c = window.open("", "_blank"), i = 1;
for (let siteEle of targetSites) {
if (siteEle.dataset.isPage) {
await self.siteSetUrl(siteEle);
if (self.stopInput) return;
if (!siteEle.href) continue;
let iframe = document.createElement('iframe');
iframe.width = targetSites.length <= 2 || viewWidth <= 1280 ? '50%' : '33%';
iframe.height = '100%';
iframe.frameBorder = '0';
iframe.sandbox = "allow-same-origin allow-scripts allow-popups allow-forms";
iframe.id = "searchJumper" + i++;
iframe.style.display = "none";
html += iframe.outerHTML;
_GM_xmlhttpRequest({
method: 'GET',
url: siteEle.href,
headers: {
referer: siteEle.href,
origin: siteEle.href,
'User-Agent': navigator.userAgent
},
onload: function(d) {
let curIframe = c.document.querySelector('iframe#' + iframe.id);
let waitReady = () => {
let doc = curIframe.contentDocument || (curIframe.contentWindow && curIframe.contentWindow.document);
if (doc) {
try {
curIframe.style.display = "";
curIframe.src = siteEle.href;
let base = `<base href="${siteEle.href.replace(/[^\/]*$/, "")}" />`;
let docContent = d.response.indexOf("<head") !== -1 ? d.response.replace(/(\<head.*?\>)/, "$1" + base) : base + d.response;
doc.write(docContent);
} catch(e) {
}
} else {
setTimeout(() => {
waitReady();
}, 500);
}
};
if (curIframe) {
waitReady();
}
},
onerror: function(e){
debug(e);
},
ontimeout: function(e){
debug(e);
}
});
}
}
c.document.write(html);
c.document.close();
} else if ((e.ctrlKey || e.metaKey) && e.shiftKey) {
let targetSites = self.getTargetSitesByName(siteNames);
for (let siteEle of targetSites) {
await self.siteSetUrl(siteEle);
if (self.stopInput) return;
if (siteEle.dataset.isPage && siteEle.href) {
let target = {};
if (targetElement) {
target = {src: targetElement.src || targetElement.href || '', title: targetElement.title || targetElement.alt};
}
siteNames = siteNames.filter(n => n !== siteEle.dataset.name);
storage.setItem("lastSign", {target: target, sites: siteNames});
setTimeout(() => {
_GM_openInTab(siteEle.href, {incognito: true});
}, 300);
setTimeout(() => {
storage.setItem("lastSign", false);
}, 2000);
break;
}
}
} else if (e.altKey) {
let targetSites = self.getTargetSitesByName(siteNames);
let urls=[];
for (let siteEle of targetSites) {
if (siteEle.dataset.isPage) {
await self.siteSetUrl(siteEle);
if (self.stopInput) return;
if (!siteEle.href) continue;
urls.push(siteEle.href);
}
}
let viewWidth = window.screen.availWidth || window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.screen.availHeight || window.innerHeight || document.documentElement.clientHeight;
let numPerLine = parseInt(viewWidth / 800);
if (numPerLine > urls.length) numPerLine = urls.length;
let _width = parseInt(viewWidth / numPerLine);
let _height = viewHeight / (parseInt((urls.length - 1) / numPerLine) + 1) - 65;
for (let i = 0; i < urls.length; i++) {
let left = (i % numPerLine) * _width;
let top = parseInt(i / numPerLine) * (_height + 70);
window.open(urls[i] + "#searchJumperMin", "_blank", `width=${_width-10}, height=${_height}, location=0, resizable=1, status=0, toolbar=0, menubar=0, scrollbars=0, left=${left}, top=${top}`);
}
} else if (e.shiftKey) {
let targetSites = self.getTargetSitesByName(siteNames);
for (let siteEle of targetSites) {
await self.siteSetUrl(siteEle);
if (self.stopInput) return;
if (siteEle.dataset.isPage && siteEle.href) {
let target = {};
if (targetElement) {
target = {src: targetElement.src || targetElement.href || '', title: targetElement.title || targetElement.alt};
}
siteNames = siteNames.filter(n => n !== siteEle.dataset.name);
storage.setItem("lastSign", {target: target, sites: siteNames});
window.open(siteEle.href, '_blank');
setTimeout(() => {
storage.setItem("lastSign", false);
}, 2000);
break;
}
}
} else if (e.ctrlKey || e.metaKey) {
let targetSites = self.getTargetSitesByName(siteNames).reverse();
for (let siteEle of targetSites) {
await self.siteSetUrl(siteEle);
let isPage = siteEle.dataset.isPage;
if (isPage && siteEle.href) {
_GM_openInTab(siteEle.href, {active: false, insert: true});
continue;
}
if (self.stopInput) return;
siteEle.click();
}
} else if (e.button === 2) {
let targetSites = self.getTargetSitesByName(siteNames);
targetSites.reverse().forEach(siteEle => {
if (siteEle.dataset.current) return;
self.openSiteBtn(siteEle, "_blank", !!newTab);
});
}
self.batchOpening = false;
}
async siteSetUrl(siteEle, e) {
return new Promise((resolve) => {
let actionOverHandler = e => {
siteEle.removeEventListener('actionOver', actionOverHandler);
resolve(true);
}
siteEle.addEventListener('actionOver', actionOverHandler);
let mouseDownEvent = new PointerEvent("mousedown", e);
siteEle.dispatchEvent(mouseDownEvent);
});
}
getTargetSitesByName(siteNames, noPointer) {
let self = this;
let targetSites = [];
siteNames.forEach(n => {
for (let i = 0; i < self.allSiteBtns.length; i++) {
let siteBtn = self.allSiteBtns[i][0];
if (siteBtn.dataset.name == n) {
if (!noPointer && siteBtn.dataset.pointer) {
if (siteBtn.dataset.oriName) {
let oriBtn = self.getTargetSitesByName([siteBtn.dataset.oriName], true);
if (oriBtn.length) {
targetSites.push(...oriBtn);
break;
}
}
} else {
targetSites.push(siteBtn);
}
break;
}
}
});
return targetSites;
}
async submitAction(params) {
params = params.slice();
if (document.readyState !== 'complete' && document.readyState !== 'interactive') {
await sleep(300);
this.submitAction(params);
return;
}
let form, input, clicked = false, self = this, inLoop = false, loopTimes = 0, loopArr = [];
let opened = false, copyList = [];
let copyStore = await storage.getItem("copyStore");
if (copyStore) {
copyList = JSON.parse(copyStore);
}
let singleAction = async (param, eleIndex) => {
let result = true;
if (param[0] === "sleep" || param[0] === "@sleep") {
await sleep(param[1]);
debug(`sleep ${param[1]}`);
} else if (param[0] === "@click") {
clicked = true;
let _r = await emuClick(param[1], eleIndex);
if (!_r) result = false;
} else if (param[0] === "@dblclick") {
clicked = true;
let _r = await emuDblClick(param[1], eleIndex);
if (!_r) result = false;
} else if (param[0] === "@rclick") {
clicked = true;
let _r = await emuRClick(param[1], eleIndex);
if (!_r) result = false;
} else if (param[1] === 'click' && param[0].indexOf('@') === 0) {
clicked = true;
let _r = await emuClick(param[0].substr(1), eleIndex);
if (!_r) result = false;
} else if (param[0] === '@copy') {
let _r = await returnElement(param[1], eleIndex);
if (_r && _r !== true) {
copyList.push(_r.innerText);
if (!reachLast) {
result = false;
}
}
} else if (param[0] === '@call') {
let engine = self.getTargetSitesByName([param[1]])[0];
if (engine) {
extSelectionText = extSelectionText || getKeywords() || cacheKeywords;
await self.siteSetUrl(engine);
engine.click();
} else {
let func = window[param[1]] || new AsyncFunction('"use strict";' + param[1]);
if (func) await func();
}
} else if (param[0] === '@open') {
let btn = await waitForElement(param[1]);
if (opened) {
_GM_openInTab(btn.href);
} else {
opened = true;
setTimeout(() => {
location.href = btn.href;
}, 50);
}
} else if (param[0] === '@reload') {
} else if (param[0] === '@wait') {
if (param[1].indexOf("!") === 0) {
await waitForElementHide(param[1].slice(1));
} else {
await waitForElement(param[1]);
}
} else {
let inputStr = param[1];
if (!localKeywords) localKeywords = inputStr;
if (inputStr.indexOf('%input{') !== -1) {
let customInputStr = await self.showCustomInputWindow(inputStr);
if (customInputStr) {
inputStr = customInputStr;
} else {
storage.setListItem("inPagePostParams", location.hostname, "");
return true;
}
}
let _r = await emuInput(param[0], inputStr, eleIndex);
if (!_r) result = false;
if (param[0] !== "@") {
input = getElement(param[0]);
}
}
return result;
};
for (let param of params) {
if (param[0] === "@loopStart") {
inLoop = true;
loopArr = [];
loopTimes = parseInt(param[1]) || 1;
} else if (param[0] === "@loopEnd") {
inLoop = false;
while (loopTimes-- > 0) {
let allReady = false, eleIndex = 0;
while (!allReady) {
allReady = true;
for (let param of loopArr) {
let ready = await singleAction(param, eleIndex);
if (!ready) allReady = false;
}
eleIndex++;
}
}
} else if (inLoop) {
loopArr.push(param);
} else {
await singleAction(param);
}
if (inPagePostParams) {
inPagePostParams.shift();
if (inPagePostParams && inPagePostParams.length) {
storage.setListItem("inPagePostParams", location.hostname, inPagePostParams);
storage.setItem("copyStore", JSON.stringify(copyList));
} else {
_GM_setClipboard(copyList.join("\n"));
storage.setListItem("inPagePostParams", location.hostname, "");
storage.setItem("copyStore", "");
}
if (param[0] === '@reload') {
location.reload(!!param[1]);
return;
}
}
}
if (inLoop) {
inLoop = false;
while (loopTimes-- > 0) {
let allReady = false, eleIndex = 0;
while (!allReady) {
allReady = true;
for (let param of loopArr) {
let ready = await singleAction(param, eleIndex);
if (!ready) allReady = false;
}
eleIndex++;
}
}
}
if (!clicked && input) {
form = input.parentNode;
while (form.nodeName.toUpperCase() != 'FORM') {
form = form.parentNode;
if (!form) break;
}
if (form) {
let submitBtn = form.querySelector("[type=submit]");
if (submitBtn) submitBtn.click();
else form.submit();
} else {
emuPress();
}
}
}
getCloneData(siteName) {
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let typeConfig = searchData.sitesConfig[i];
for (let j = 0; j < typeConfig.sites.length; j++) {
let siteData = typeConfig.sites[j];
if (/^\[/.test(siteData.url)) continue;
if (siteData.name == siteName) {
return siteData;
}
}
}
return null;
}
async createSiteBtn(icon, data, openInNewTab, isBookmark, typeData, isHistoryBtn) {
let self = this;
let ele = document.createElement("a");
ele.setAttribute("ref", "noopener noreferrer");
ele.setAttribute("referrerPolicy", "no-referrer");
let name = data.name;
let urlMatch = data.match;
let showTips = false;
let tipsData;
let pointer = !isBookmark && /^\[/.test(data.url);
let description = data.description;
let shortcut = data.shortcut;
if (typeof data.openInNewTab !== 'undefined') {
openInNewTab = data.openInNewTab;
}
if (pointer) {
ele.dataset.pointer = true;
let siteNames = JSON.parse(data.url);
if (siteNames.length === 1) {
ele.dataset.clone = true;
let cloneSite = this.getCloneData(siteNames[0]);
if (cloneSite) {
ele.dataset.oriName = cloneSite.name;
data = cloneSite;
if (data.icon && icon !== "0") icon = data.icon;
if (data.description) description = data.description;
}
}
}
if (/^d:/.test(data.url)) {
ele.setAttribute('download', '');
data.url = data.url.replace(/^d:/, '');
} else if (/^showTips:/.test(data.url)) {
showTips = true;
ele.dataset.showTips = true;
}
if (/^paste:/.test(data.url)) {
ele.dataset.paste = true;
}
let isPage = /^(https?|ftp):/.test(data.url);
if (isPage) ele.dataset.isPage = isPage;
ele.className = "search-jumper-btn";
if (typeof description !== 'undefined') ele.title = description;
ele.dataset.name = name;
ele.classList.add("search-jumper-word");
ele.dataset.inPagePost = (data.url.indexOf("#p{") != -1) ? 't' : 'f';
let inPagePost = ele.dataset.inPagePost === 't';
if (urlMatch === '0') {
ele.style.display = 'none';
ele.classList.add("notmatch");
} else if (!isBookmark && (!currentSite || data.hideNotMatch) && window.top == window.self) {
if (urlMatch) {
let urlRe, fullMatch = urlMatch.match(/^\/(.*)\/(\w*)$/);
if (fullMatch) {
urlRe = new RegExp(fullMatch[1], fullMatch[2]);
} else {
urlRe = new RegExp(urlMatch, "i");
}
if (urlRe.test(href)) {
ele.dataset.current = true;
}
} else if (!pointer && location.hostname && data.url.indexOf(location.hostname) != -1) {
if (!this.inSiteMatch) this.inSiteMatch = /site(%3A|:)(.+?)[\s%]/;
let match = data.url.match(this.inSiteMatch);
if (match) {
if (href.indexOf(match[2]) != -1 && data.url.replace(match[0], "").indexOf(location.hostname) != -1) {
ele.dataset.current = true;
}
} else {
if (!this.pathMatch) this.pathMatch = new RegExp("^https?://" + location.host + location.pathname + "?([\\?#].*|[%:#]p{|$)");
if (this.pathMatch.test(data.url)) {
if (!this.postMatch) this.postMatch = /[#:%]p{/;
if (this.postMatch.test(data.url)) {
ele.dataset.current = true;
} else {
if (!this.paramMatch) this.paramMatch = /[^\/\?&]+(?=%[stb])/g;
let urlReg = data.url.match(this.paramMatch);
if (urlReg) {
urlReg = urlReg.join('.*');
if (new RegExp(urlReg).test(href)) {
ele.dataset.current = true;
}
} else {
ele.dataset.current = true;
}
}
} else if (data.url.indexOf("http") === 0 && data.url.indexOf("?") === -1) {
if (!this.keywordMatch) this.keywordMatch = /%[stb][a-z]?\b/g;
if (new RegExp(data.url.replace(/^https?/, "").replace(/[#%]\w+{.*/, "").replace(/\./g, "\\.").replace(this.keywordMatch, ".*")).test(href)) {
ele.dataset.current = true;
}
}
}
}
if (ele.dataset.current) {
} else if (data.hideNotMatch) {
ele.style.display = 'none';
ele.classList.add("notmatch");
}
}
let word = document.createElement("span");
if (!isBookmark && name.length >= 3) {
word.innerText = name.substr(0, 4);
if (!/^[\w \-]+$/.test(word.innerText.substr(0, 3))) word.innerText = word.innerText.substr(0, 2);
} else word.innerText = name;
ele.appendChild(word);
let img = document.createElement("img");
img.style.display = "none";
ele.appendChild(img);
if (!isHistoryBtn && searchData.prefConfig.shortcut && shortcut && !ele.dataset.clone && !ele.classList.contains("notmatch")) {
let shortcutCover = document.createElement("div");
let shortcurStr = shortcut.replace('Key', '').replace('Digit', '').toUpperCase();
if (shortcurStr.length == 1) {
shortcutCover.innerText = shortcurStr;
ele.appendChild(shortcutCover);
}
document.addEventListener('keydown', async e => {
if (e.target.id === "searchJumperInput") return;
if (!self.hideTimeout) {
if ((!data.ctrl == e.ctrlKey) ||
(!data.alt == e.altKey) ||
(!data.shift == e.shiftKey) ||
(!data.meta == e.metaKey)) {
return;
}
}
if (!self.bar.contains(ele)) return;
if (!searchData.prefConfig.enableInInput && !data.ctrl && !data.alt && !data.shift && !data.meta) {
if (inputActive(document)) return;
}
var key = (e.key || String.fromCharCode(e.keyCode)).toLowerCase();
if (shortcut == e.code || shortcut == key) {
e.stopPropagation();
if (hoverElement) {
targetElement = hoverElement;
}
if (showTips) {
ele.dispatchEvent(new CustomEvent('showTips'));
} else if (await action() !== false && !self.customInput) {
ele.click();
}
}
});
}
let imgSrc;
if (icon == "0") {
} else if (icon) {
imgSrc = icon;
} else if (!isBookmark && isPage) {
imgSrc = data.url.replace(/\?.*/, "").replace(/^(https?:\/\/[^\/]*\/)[\s\S]*$/, "$1favicon.ico");
} else if (/^showTips:https?:\/\//.test(data.url)) {
imgSrc = data.url.replace(/\?.*/, "").replace(/^showTips:(https?:\/\/[^\/]*\/)[\s\S]*$/, "$1favicon.ico");
}
if (imgSrc) {
img.onload = e => {
ele.classList.remove("search-jumper-word");
if (word.parentNode && !searchData.prefConfig.showEngineWords) {
word.parentNode.removeChild(word);
}
img.style.display = "";
};
let isBase64 = /^data:/.test(imgSrc);
if (isBase64) {
img.dataset.src = imgSrc;
} else {
let cache = searchData.prefConfig.cacheSwitch && cacheIcon[imgSrc];
if (cache === 'fail') {
if (ele.dataset.current && imgSrc.indexOf(location.host) != -1) {
img.dataset.src = imgSrc;
cacheIcon[imgSrc] = '';
if (!isBookmark) {
setTimeout(() => {
cacheAction(img);
}, 0);
}
}
} else if (cache) {
img.dataset.src = cache;
} else {
img.dataset.src = imgSrc;
if (!isBookmark && !cacheIcon[imgSrc]) cachePool.push(img);
}
}
}
if (isPage) {
if (openInNewTab) {
ele.setAttribute("target", "_blank");
ele.dataset.target = 1;
} else ele.setAttribute("target", "_self");
}
let dataUrl = data.url;
let hasWordParam = wordParamReg.test(dataUrl);
if (hasWordParam) ele.dataset.txt = true;
if (/%[tb]\b/i.test(dataUrl)) {
ele.dataset.link = true;
}
let inputString;
let getUrl = async (_keyWords) => {
self.customInput = false;
dataUrl = data.url;
inputString = "";
let keywords = _keyWords || self.searchJumperInputKeyWords.value || getSelectStr();
if (!keywords && !draging && !self.bar.classList.contains("search-jumper-isTargetLink")) {
keywords = getKeywords();
}
if (keywords && !_keyWords) {
if (keywords != cacheKeywords) {
self.keywordIndex = 0;
if (isPage) {
cacheKeywords = keywords;
storage.setItem("cacheKeywords", keywords);
}
}
inputString = keywords;
}
let postMatch;
if (inPagePost || /^c(opy)?:|^paste:/.test(dataUrl)) {
if (dataUrl.indexOf('%input{') !== -1) {
dataUrl = await new Promise(resolve => {
self.showCustomInputWindow(dataUrl, _url => {
resolve(_url);
});
});
ele.dataset.url = "";
}
postMatch = dataUrl.match(/#p{([\s\S]*[^\\])}/);
}
let host = location.host;
let href = location.href;
let customReplaceSingle = (str, key, value, after) => {
if (str.indexOf(key + "[") !== -1) {
let multiMatch = str.match(keyToReg(key, "", "\\[(.*?)(\\|(.+))?\\]")), valueArr;
if (multiMatch) {
if (multiMatch[3]) {
valueArr = value.split(multiMatch[3]);
} else {
valueArr = value.split(/[\n\r]/);
if (valueArr.length === 1) {
valueArr = value.split(" ");
}
}
if (!self.keywordIndex) self.keywordIndex = 0;
switch(multiMatch[1]) {
case "all":
inputString = valueArr.join('\n');
break;
case ""://next
value = valueArr[self.keywordIndex];
if (++self.keywordIndex >= valueArr.length) {
self.keywordIndex = 0;
}
break;
case "-1"://prev
if (--self.keywordIndex < 0) {
self.keywordIndex = valueArr.length - 1;
}
value = valueArr[self.keywordIndex];
break;
default://number
value = valueArr[parseInt(multiMatch[1]) || 0];
break;
}
str = str.replace(multiMatch[0], key);
}
}
return replaceSingle(str, key, value, after);
};
let needDecode = (!/^showTips:h/i.test(dataUrl) && /^c(opy)?:|[#:%]P{|^javascript:|^showTips:/i.test(dataUrl));
let keywordsU = "", keywordsL = "", keywordsR = "", keywordsSC = "", keywordsTC = "";
let customReplaceKeywords = str => {
let _str = str;
_str = customReplaceSingle(_str, "%su", keywordsU);
_str = customReplaceSingle(_str, "%sl", keywordsL);
_str = customReplaceSingle(_str, "%sr", keywordsR);
_str = customReplaceSingle(_str, "%S", cacheKeywords || keywordsR);
_str = customReplaceSingle(_str, "%ss", keywordsSC);
_str = customReplaceSingle(_str, "%st", keywordsTC);
_str = customReplaceSingle(_str, "%se", escape ? escape(keywordsR) : keywordsR);
_str = customReplaceSingle(_str, "%s", keywordsR, v => {
return (needDecode ? v : encodeURIComponent(v));
});
if (/%bd\b/.test(_str)) {
try {
let debase64 = atob(keywordsR);
_str = customReplaceSingle(_str, "%bd", debase64);
} catch(e) {
console.log(e);
}
}
if (/%be\b/.test(_str)) {
try {
let enbase64 = btoa(keywordsR);
_str = customReplaceSingle(_str, "%be", enbase64);
} catch(e) {
console.log(e);
}
}
return _str;
};
let customVariable = str => {
let customMatch = str.match(/%element{(.*?)}(\.prop\((.*?)\))?/);
let runTimes = 0;
while (customMatch) {
if (runTimes++ > 100) break;
let selector = customMatch[1];
let prop = customMatch[3];
let value = "";
if (!selector) {
try {
let selectEles = window.getSelection();
let container = document.createElement('div');
for (let i = 0, len = selectEles.rangeCount; i < len; ++i) {
container.appendChild(selectEles.getRangeAt(i).cloneContents());
}
[].forEach.call(container.querySelectorAll("style,script,svg,canvas"), ele => {
let textNode = document.createTextNode('');
ele.parentNode.replaceChild(textNode, ele);
});
document.body.appendChild(container);
if (prop) {
for (let i = 0; i < container.childNodes.length; i++) {
let childNode = container.childNodes[i];
if (childNode.nodeType == 3) {
value += childNode.nodeValue;
value += "\n";
} else if (childNode.nodeType == 1) {
value += childNode.getAttribute(prop) || childNode[prop] || "";
value += "\n";
}
}
} else {
[].forEach.call(container.querySelectorAll("img"), img => {
if (!img.src) return;
let textNode = document.createTextNode(` ![${(img.alt || "").replace(/[\n\r]/g, " ").trim()}](${img.src || ""}) `);
img.parentNode.replaceChild(textNode, img);
});
[].forEach.call(container.querySelectorAll("a"), a => {
if (!a.href) return;
let innerText = (a.innerText || "").replace(/[\n\r]+/g, "\n").trim();
if (!innerText) return;
innerText = ` [${innerText}](${a.href || ""}) `;
let newNode;
if (innerText.indexOf("\n") == -1) {
newNode = document.createTextNode(innerText);
} else {
newNode = document.createElement("pre");
newNode.innerHTML = createHTML(innerText);
}
a.parentNode.replaceChild(newNode, a);
});
value = container.innerText;
}
if (value) {
value = value.replace(/[\n\r]\s*/g, "\n");
}
document.body.removeChild(container);
} catch(e) {
console.error(e);
}
} else {
let ele = getElement(selector);
if (ele) {
if (prop) {
value = ele.getAttribute(prop) || ele[prop];
} else {
value = ele.innerText;
}
}
}
str = customReplaceSingle(str, customMatch[0], needDecode ? value : encodeURIComponent(value));
customMatch = str.match(/%element{(.*?)}(\.prop\((.*?)\))?/);
}
customMatch = str.match(/%date({(.*?)})?/);
runTimes = 0;
let curTime = new Date().getTime();
while (customMatch) {
if (runTimes++ > 100) break;
let timeEval = customMatch[2];
let value = curTime;
if (timeEval) {
timeEval = timeEval.replace(/\s/g, '');
let mathEval = timeEval.match(/(\D*)?(\d+)/);
while (mathEval) {
switch (mathEval[1]) {
case "-":
value -= parseInt(mathEval[2]);
break;
case "*":
value *= parseInt(mathEval[2]);
break;
case "/":
if (mathEval[2] && mathEval[2] != '0') {
value = parseInt(value / parseInt(mathEval[2]));
}
break;
default:
value += parseInt(mathEval[2]);
break;
}
timeEval = timeEval.replace(mathEval[0], "");
mathEval = timeEval.match(/(\D*)?(\d+)/);
}
} else {
value = curTime;
}
str = str.replace(customMatch[0], value);
customMatch = str.match(/%date({(.*?)})?/);
}
return str;
}
if (!ele.dataset.url) {
let tempUrl = dataUrl;
if (inPagePost) {
tempUrl = tempUrl.replace(postMatch[0], "");
}
ele.dataset.url = tempUrl.replace(/%e\b/g, document.characterSet).replace(/%c\b/g, (isMobile?"mobile":"pc"));
}
let targetUrl = '', targetLink = '';
let targetName = inputString || document.title;
let imgBase64 = '', resultUrl = customVariable(ele.dataset.url);
if (targetElement && targetElement.nodeName) {
targetUrl = targetElement.href || (targetElement.parentNode && targetElement.parentNode.href) || '';
targetLink = targetUrl || (targetElement.parentNode && targetElement.parentNode.parentNode && targetElement.parentNode.parentNode.href) || '';
if ((typeData.selectImg || typeData.selectAudio || typeData.selectVideo) && targetElement.src) {
targetUrl = targetElement.src;
}
if (targetElement.nodeName.toUpperCase() == "VIDEO" || targetElement.nodeName.toUpperCase() == "AUDIO") {
if (!targetUrl) {
let source = targetElement.querySelector("source");
if (source) targetUrl = source.src;
}
if (targetUrl) targetUrl = targetUrl.replace(/^blob:/, "");
}
targetName = targetElement.title || targetElement.alt || document.title;
if (targetElement.nodeName.toUpperCase() == 'IMG' && /%i\b/.test(dataUrl)) {
if (targetElement.src) {
if (/^data/.test(targetElement.src)) {
imgBase64 = targetElement.src;
} else {
self.tipsPos(ele, "<span class='loader'></span><font>Loading...</font>");
imgBase64 = await image2Base64(targetElement);
}
resultUrl = resultUrl.replace(/%i\b/g, imgBase64);
}
} else if ((targetElement.nodeName.toUpperCase() == 'A' || (targetElement.parentNode && targetElement.parentNode.nodeName.toUpperCase() == 'A')) && hasWordParam && !keywords) {
if (targetElement.textContent.trim()) keywords = targetElement.textContent.trim();
}
}
while (resultUrl.indexOf('%template{') !== -1) {
let inputMatch = resultUrl.match(/%template{(.*?[^\\])}/);
if (!inputMatch) return false;
let templateName = inputMatch[1];
if (!searchData.prefConfig.templateData) searchData.prefConfig.templateData = {};
let templateResult = searchData.prefConfig.templateData[templateName];
if (!templateResult) {
if (self.stopInput) return false;
templateResult = window.prompt(i18n("template", templateName)) || "";
if (templateResult) {
searchData.prefConfig.templateData[templateName] = templateResult;
storage.setItem("searchData", searchData);
} else return false;
}
resultUrl = resultUrl.replace(inputMatch[0], templateResult);
}
while (resultUrl.indexOf('%input{') !== -1) {
let inputMatch = resultUrl.match(/%input{(.*?[^\\])}/);
if (!inputMatch) return false;
self.customInput = true;
if (self.stopInput) return false;
if (self.batchOpening) {
let promptStr;
if (inputMatch[1].indexOf("\"") === 0 && inputMatch[1].indexOf("\",\"") !== -1) {
promptStr = inputMatch[1].substr(1, inputMatch[1].length - 2).split("\",\"");
} else {
promptStr = inputMatch[1].split(",");
}
if (promptStr.length === 2) {
promptStr = window.prompt(promptStr[0], promptStr[1]);
} else {
promptStr = window.prompt(inputMatch[1]);
}
if (promptStr === null) return false;
resultUrl = resultUrl.replace(inputMatch[0], promptStr);
} else break;
}
if (targetUrl) {
targetUrl = targetUrl.replace(/%(\w{2})/g, (match, letter) => `%${letter.toUpperCase()}`);
}
if (targetLink) {
targetLink = targetLink.replace(/%(\w{2})/g, (match, letter) => `%${letter.toUpperCase()}`);
}
let targetBaseUrl = targetUrl.replace(/^https?:\/\//i, "");
if (!keywords) keywords = (currentSite && cacheKeywords);
try {
if (typeof navigator.clipboard.readText !== "undefined") {
if (!keywords && hasWordParam) {
keywords = await navigator.clipboard.readText();
if (keywords && !_keyWords) {
inputString = keywords;
}
}
if (!imgBase64 && /%i\b/.test(dataUrl)) {
const permission = await navigator.permissions.query({
name: "clipboard-read",
});
if (permission.state !== "denied") {
const clipboardContents = await navigator.clipboard.read();
for (const item of clipboardContents) {
if (item.types.includes("image/png")) {
const blob = await item.getType("image/png");
imgBase64 = await new Promise(resolve => {
const reader = new FileReader();
reader.onload = function (e) {
resolve(e.target && e.target.result);
};
reader.readAsDataURL(blob);
});
if (imgBase64) resultUrl = resultUrl.replace(/%i\b/g, imgBase64);
}
}
}
if (!imgBase64) {
self.customInput = true;
let src = window.prompt(i18n("targetUrl"), "https://www.google.com/favicon.ico");
if (src) {
self.tipsPos(ele, "<span class='loader'></span><font>Loading...</font>");
imgBase64 = await imageSrc2Base64(src);
} else return false;
}
}
}
} catch(e) {
console.error(e.message);
}
if (!keywords && hasWordParam) {
self.customInput = true;
if (self.con.classList.contains("search-jumper-showall")) return false;
if (self.inInput || showTips) return false;
if (self.stopInput) return false;
let promptStr = window.prompt(i18n("keywords"));
if (promptStr === null) return false;
localKeywords = promptStr;
setTimeout(() => {localKeywords = ''}, 1);
keywords = promptStr;
keywordsR = keywords;
keywordsU = keywordsR.toUpperCase();
keywordsL = keywordsR.toLowerCase();
keywordsSC = _unsafeWindow.tc2sc ? _unsafeWindow.tc2sc(keywordsR) : keywordsR;
keywordsTC = _unsafeWindow.sc2tc ? _unsafeWindow.sc2tc(keywordsR) : keywordsR;
if (!needDecode) keywords = encodeURIComponent(keywords);
resultUrl = customReplaceKeywords(resultUrl);
} else if (keywords && (!keywordsU && !keywordsL && !keywordsR)) {
keywordsR = keywords;
keywordsU = keywordsR.toUpperCase();
keywordsL = keywordsR.toLowerCase();
keywordsSC = _unsafeWindow.tc2sc ? _unsafeWindow.tc2sc(keywordsR) : keywordsR;
keywordsTC = _unsafeWindow.sc2tc ? _unsafeWindow.sc2tc(keywordsR) : keywordsR;
if (!needDecode) keywords = encodeURIComponent(keywords);
}
if (targetUrl === '') {
let canBeUrl = getSelectStr() || self.searchJumperInputKeyWords.value;
if (!hasWordParam && canBeUrl && /^(http|ftp)/i.test(canBeUrl)) {
targetUrl = canBeUrl;
targetUrl = targetUrl.replace(/%(\w{2})/g, (match, letter) => `%${letter.toUpperCase()}`);
} else {
let promptStr = false;
let getTargetUrl = () => {
if (self.stopInput || showTips) return false;
if (promptStr === false) {
promptStr = window.prompt(i18n("targetUrl"), "https://www.google.com/favicon.ico");
if (promptStr) {
promptStr = promptStr.replace(/%(\w{2})/g, (match, letter) => `%${letter.toUpperCase()}`);
targetElement = {src: promptStr};
}
}
if (promptStr === null) return false;
return true;
};
if (/%t\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = customReplaceSingle(resultUrl, "%t", promptStr);
}
if (/%T\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = resultUrl.replace(/%T\b/g, encodeURIComponent(promptStr));
}
if (/%τ\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = resultUrl.replace(/%τ\b/g, encodeURIComponent(encodeURIComponent(promptStr)));
}
if (/%b\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = resultUrl.replace(/%b\b/g, promptStr.replace(/^https?:\/\//i, ""));
}
if (/%B\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = resultUrl.replace(/%B\b/g, encodeURIComponent(promptStr.replace(/^https?:\/\//i, "")));
}
if (/%β\b/.test(resultUrl)) {
self.customInput = true;
if (getTargetUrl() === false) return false;
resultUrl = resultUrl.replace(/%β\b/g, encodeURIComponent(encodeURIComponent(promptStr.replace(/^https?:\/\//i, ""))));
}
}
}
let _host = host;
if ((targetLink || targetUrl) && !ele.dataset.link) {
href = targetLink || targetUrl;
_host = href.replace(/^\w+:\/\/([^\/]+).*/, "$1");
}
if (inPagePost) {
let postParams = [], hasCall = false;
postMatch[1].replace(/([^\\])&/g, "$1SJ^PARAM").split("SJ^PARAM").forEach(pair => {//ios不支持零宽断言,哭唧唧
pair = pair.trim();
if (/^loopStart\(\d+\)$/.test(pair)) {
let loopStart = pair.match(/loopStart\((.*)\)/);
postParams.push(['@loopStart', loopStart[1]]);
} else if (pair == "loopEnd") {
postParams.push(['@loopEnd', '']);
} else if (pair.startsWith("click(") && pair.endsWith(')')) {
let click = pair.slice(6, pair.length - 1);
if (click) {
postParams.push(['@click', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("dblclick(") && pair.endsWith(')')) {
let click = pair.slice(9, pair.length - 1);
if (click) {
postParams.push(['@dblclick', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("rclick(") && pair.endsWith(')')) {
let click = pair.slice(7, pair.length - 1);
if (click) {
postParams.push(['@rclick', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("copy(") && pair.endsWith(')')) {
let copy = pair.slice(5, pair.length - 1);
if (copy) {
postParams.push(['@copy', copy.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("call(") && pair.endsWith(')')) {
let func = pair.slice(5, pair.length - 1);
if (func) {
postParams.push(['@call', func.replace(/\\([\=&])/g, "$1").trim()]);
hasCall = true;
}
} else if (pair.startsWith("reload(") && pair.endsWith(')')) {
let func = pair.slice(7, pair.length - 1);
postParams.push(['@reload', func.trim()]);
} else if (pair.startsWith("wait(") && pair.endsWith(')')) {
let wait = pair.slice(5, pair.length - 1);
postParams.push(['@wait', wait.replace(/\\([\=&])/g, "$1").trim()]);
} else if (pair.startsWith("open(") && pair.endsWith(')')) {
let open = pair.slice(5, pair.length - 1);
if (open) {
postParams.push(['@open', open.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (/^sleep\(\d+\)$/.test(pair)) {
let sleep = pair.match(/sleep\((.*)\)/);
if (sleep) {
postParams.push(['@sleep', sleep[1]]);
}
} else {
pair = pair.replace(/([^\\])\=/g, "$1SJ^PARAM").replace(/\\([\=&])/g, "$1");
let pairArr = pair.split("SJ^PARAM");
if (pairArr.length === 2) {
let k = pairArr[0];
let v = customReplaceKeywords(pairArr[1].replace(/\\([\=&])/g, "$1").replace(/%e\b/g, document.characterSet).replace(/%i\b/g, imgBase64).replace(/%c\b/g, (isMobile?"mobile":"pc")).replace(/%U\b/g, encodeURIComponent(href)).replace(/%υ\b/g, encodeURIComponent(encodeURIComponent(href))).replace(/%h\b/g, _host).replace(/%T\b/g, encodeURIComponent(targetUrl)).replace(/%τ\b/g, encodeURIComponent(encodeURIComponent(targetUrl))).replace(/%b\b/g, targetBaseUrl).replace(/%B\b/g, encodeURIComponent(targetBaseUrl)).replace(/%β\b/g, encodeURIComponent(encodeURIComponent(targetBaseUrl))).replace(/%n\b/g, targetName));
v = customReplaceSingle(v, "%t", targetUrl);
v = customReplaceSingle(v, "%u", href);
postParams.push([k, v]);
} else if (pair.endsWith('.click()') || pair.endsWith('.click')) {
postParams.push(['@' + pair.replace(/\.click(\(\))?$/, ''), 'click']);
}
}
});
if (hasCall) {
self.updateCacheKeywords();
}
if (resultUrl === "" || resultUrl === location.href) {
inPagePostParams = postParams;
this.submitAction(postParams);
return false;
} else {
storage.setListItem("inPagePostParams", resultUrl.replace(/^https?:\/\/([^\/:]+).*/, "$1"), postParams);
}
}
resultUrl = customReplaceSingle(resultUrl, "%h", _host);
resultUrl = customReplaceSingle(resultUrl, "%t", targetUrl);
resultUrl = customReplaceSingle(resultUrl, "%u", href);
resultUrl = customReplaceKeywords(resultUrl.replace(/%U\b/g, encodeURIComponent(href)).replace(/%υ\b/g, encodeURIComponent(encodeURIComponent(href))).replace(/%T\b/g, encodeURIComponent(targetUrl)).replace(/%τ\b/g, encodeURIComponent(encodeURIComponent(targetUrl))).replace(/%b\b/g, targetBaseUrl).replace(/%B\b/g, encodeURIComponent(targetBaseUrl)).replace(/%β\b/g, encodeURIComponent(encodeURIComponent(targetBaseUrl))).replace(/%n\b/g, targetName));
if (openInNewTab && /^(https?|ftp):/.test(resultUrl)) {
ele.setAttribute("target", "_blank");
ele.dataset.target = 1;
} else {
ele.dataset.target = 0;
}
return resultUrl;
};
let targetUrlData;
let clicked = false;
let alt, ctrl, meta, shift;
let action = async e => {
delete ele.href;
if (!e) e = {};
alt = e.altKey;
ctrl = e.ctrlKey;
meta = e.metaKey;
shift = e.shiftKey;
if (!alt && !ctrl && !meta && !shift) {
if (e.button == 1 || e.button == 2) {
alt = false;
ctrl = true;
meta = false;
shift = false;
} else if (openInNewTab === 2) {//隱身窗口
alt = false;
ctrl = true;
meta = false;
shift = true;
} else if (openInNewTab === 3) {//小窗口
alt = true;
ctrl = false;
meta = false;
shift = false;
} else if (openInNewTab === 4) {//后台标签页
alt = false;
ctrl = true;
meta = false;
shift = false;
}
}
if (showTips) {
ele.removeAttribute("target");
if (tipsData) {
if (/^(https?|ftp):/.test(tipsData)) {
targetUrlData = tipsData;
ele.href = targetUrlData;
if (openInNewTab) {
ele.setAttribute("target", "_blank");
} else {
ele.setAttribute("target", "_self");
}
} else {
if (/^copy:/.test(tipsData)) {
tipsData = tipsData.replace(/^copy:/, "");
}
_GM_setClipboard(tipsData);
}
}
ele.dispatchEvent(new Event("actionOver"));
return;
}
clicked = false;
targetUrlData = "";
targetUrlData = await getUrl();
if (/^(https?|ftp):/.test(targetUrlData)) {
e.stopPropagation && e.stopPropagation();
}
if (/^c(opy)?:|^paste:/.test(data.url) || /^javascript:/.test(data.url) || /^\[/.test(data.url) || /[:%]P{/.test(data.url) || (data.charset && data.charset != 'utf-8') || /[:%]p{/.test(data.url)) {
if (e.button == 1 || e.button == 2) {
clicked = true;
}
} else {
if (!targetUrlData) {
//wait for all input stoped
if (!self.stopInput) {
self.stopInput = true;
setTimeout(() => {
self.stopInput = false;
}, 1);
}
return;
}
ele.href = targetUrlData;
}
if (self.customInput && targetUrlData) {
clicked = true;
}
ele.dispatchEvent(new Event("actionOver"));
if (clicked) {
if (e.preventDefault) e.preventDefault();
ele.click();
}
};
let addHistory = () => {
let historyLength = Math.max(searchData.prefConfig.historyLength, 20);
let isCurrent = ele.dataset.current;
if (!data.hideNotMatch && !data.kwFilter && !ele.dataset.clone && !ele.dataset.paste && urlMatch !== '0' && historyLength && !isCurrent) {
storage.getItem("historySites", data => {
historySites = (data || []);
historySites = historySites.filter(site => {return site && site != name});
historySites.unshift(name);
if (historySites.length > historyLength) {
historySites = historySites.slice(0, historyLength);
}
storage.setItem("historySites", historySites);
//self.initHistorySites();
});
}
if (searchData.prefConfig.shiftLastUsedType && !isCurrent) {
let parent = ele.parentNode;
let dismissHistory = parent && (parent.classList.contains("search-jumper-targetAll") ||
parent.classList.contains("search-jumper-targetImg") ||
parent.classList.contains("search-jumper-targetAudio") ||
parent.classList.contains("search-jumper-targetVideo") ||
parent.classList.contains("search-jumper-targetLink") ||
parent.classList.contains("search-jumper-targetPage") ||
parent.classList.contains("search-jumper-needInPage"));
if (!dismissHistory && historyType != ele.dataset.type) {
historyType = ele.dataset.type;
storage.setItem("historyType", historyType);
}
}
if (searchData.prefConfig.sortType) {
storage.getItem("sortTypeNames", data => {
sortTypeNames = (data || {});
if (!sortTypeNames[ele.dataset.type]) {
sortTypeNames[ele.dataset.type] = 1;
} else {
sortTypeNames[ele.dataset.type] = sortTypeNames[ele.dataset.type] + 1;
}
storage.setItem("sortTypeNames", sortTypeNames);
});
}
if (searchData.prefConfig.sortSite) {
storage.getItem("sortSiteNames", data => {
sortSiteNames = (data || {});
if (!sortSiteNames[ele.dataset.name]) {
sortSiteNames[ele.dataset.name] = 1;
} else {
sortSiteNames[ele.dataset.name] = sortSiteNames[ele.dataset.name] + 1;
}
storage.setItem("sortSiteNames", sortSiteNames);
});
}
};
let copyHandler = (inner, str) => {
_GM_setClipboard(str);
let target = ele;
if (!inner) {
self.appendBar();
self.closeOpenType();
self.con.style.display = "";
self.setFuncKeyCall(true);
if (window.getSelection().toString()) {
target = targetElement || ele;
} else target = getBody(document);
}
self.tipsPos(target, i18n('copyOver'));
clearTimeout(self.hideTips);
self.hideTips = setTimeout(() => {
if (self.tips.style.opacity == "1") {
self.tips.style.opacity = 0;
}
}, 1500);
};
let clickHandler = e => {
e && e.stopPropagation && e.stopPropagation();
if (targetElement) {
targetElement.focus && targetElement.focus();
}
if (self.waitForShowTips) {
showTipsHandler(ele, 0);
e && e.preventDefault && e.preventDefault();
return false;
}
clicked = true;
if (!targetUrlData) {
e && e.preventDefault && e.preventDefault();
return false;
}
if (!e) e = {};
let isPage = /^(https?|ftp):/.test(targetUrlData);
if (!self.batchOpening && !isBookmark) {
addHistory();
}
if (searchData.prefConfig.multiline == 1 || searchData.prefConfig.multiline == 2) {
if (inputString &&
wordParamReg.test(ele.dataset.url) &&
inputString.indexOf("\n") !== -1 &&
!/^(c|show)/.test(ele.dataset.url)) {
if (searchData.prefConfig.multiline == 1 ||
confirm(i18n("multiline"))) {
let selStrArr = inputString.split("\n");
if (selStrArr.length > 10 && !confirm(i18n("multilineTooMuch"))) return;
let searchIndex = 0;
let defaultTarget = ele.target;
ele.target = "_blank";
let searchByLine = async () => {
targetUrlData = await getUrl(selStrArr[searchIndex++]);
ele.href = targetUrlData;
ele.click();
if (searchIndex < selStrArr.length) {
setTimeout(() => {
searchByLine();
}, searchData.prefConfig.multilineGap || 1000);
} else ele.target = defaultTarget;
};
searchByLine();
ele.href = "";
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return false;
}
}
}
if (targetUrlData.indexOf('%input{') !== -1) {
self.showCustomInputWindow(targetUrlData, _url => {
targetUrlData = _url;
ele.href = _url;
ele.click();
});
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return;
}
let findWordsMatch = targetUrlData.match(/^find(\.addto\((.*?)\))?:(.*)/);
if (findWordsMatch) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
let addToGroup = findWordsMatch[2];
let findWords = findWordsMatch[3];
if (!findWords) {
return false;
} else {
if (addToGroup && searchData.prefConfig.inPageRule) {
if (addToGroup.indexOf("@") !== 0) addToGroup = "@" + addToGroup;
}
if (findWords.indexOf('%input{') !== -1) {
self.showCustomInputWindow(findWords, _url => {
if (addToGroup) {
self.addToHighlightGroup(_url, addToGroup);
} else {
self.searchJumperInPageInput.value = _url;
self.submitInPageWords();
self.waitForHide(0);
}
});
} else {
if (addToGroup) {
self.addToHighlightGroup(findWords, addToGroup);
} else {
self.searchJumperInPageInput.value = findWords;
self.submitInPageWords();
self.waitForHide(0);
}
}
}
return false;
} else if (/^javascript:/.test(data.url)) {
if (ext) {
_unsafeWindow.targetElement = targetElement;
_unsafeWindow.keywords = getKeywords();
let func = (/^javascript:[_a-zA-Z0-9]+$/.test(targetUrlData) && _unsafeWindow[targetUrlData.replace("javascript:", "")]);
if (func) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
func();
return false;
}
ele.href = targetUrlData;
return;
}
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
_unsafeWindow.targetElement = targetElement;
_unsafeWindow.keywords = getKeywords();
targetUrlData = targetUrlData.replace(/^javascript:/, '');
try {
targetUrlData = decodeURIComponent(targetUrlData);
} catch(e) {}
let func = (/^[_a-zA-Z0-9]+$/.test(targetUrlData) && _unsafeWindow[targetUrlData]) || new AsyncFunction(targetUrlData);
if (func) func();
return false;
} else if (/^c(opy)?:/.test(data.url)) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
if (!targetUrlData) {
return false;
} else if (targetUrlData.indexOf('%input{') !== -1) {
self.showCustomInputWindow(targetUrlData, _url => {
copyHandler(true, _url.replace(/^c(opy)?:/, ""));
});
} else {
copyHandler(e.isTrusted, targetUrlData.replace(/^c(opy)?:/, ""));
}
return false;
} else if (/^paste:/.test(data.url)) {
let targetInput = false;
if (targetElement &&
(/INPUT|TEXTAREA/i.test(targetElement.nodeName) &&
targetElement.getAttribute("aria-readonly") != "true")
) {
targetInput = true;
} else {
let parent = targetElement;
while (parent) {
targetInput = parent.contentEditable == 'true';
if (targetInput || parent.nodeName.toUpperCase() == 'BODY') {
break;
}
parent = parent.parentNode;
}
}
if (targetInput) {
if (!targetUrlData) {
return false;
}
targetUrlData = targetUrlData.replace(/^paste:/, "");
if (targetUrlData.indexOf('%input{') !== -1) {
self.showCustomInputWindow(targetUrlData, _url => {
triggerPaste(targetElement, _url);
});
} else if (targetUrlData) {
triggerPaste(targetElement, targetUrlData);
} else if (typeof navigator.clipboard.readText !== "undefined") {
navigator.clipboard.readText().then((clipboardValue) => {
triggerPaste(targetElement, clipboardValue);
});
}
}
} else if (/^\[/.test(data.url)) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
let siteNames = JSON.parse(data.url);
self.batchOpen(siteNames, {button: 2, altKey: alt || e.altKey, ctrlKey: ctrl || e.ctrlKey, shiftKey: shift || e.shiftKey, metaKey: meta || e.metaKey}, openInNewTab === 1);
return false;
} else if (/[:%]P{/.test(data.url)) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
if (targetUrlData === false) return false;
let postHandler = _url => {
let postBody = _url.match(/[:%]P{(.*)}/), postParam = "";
if (postBody) {
_url = _url.replace(postBody[0], '');
postBody = postBody[1];
if (postBody.charAt(0) === '"' && postBody.charAt(postBody.length - 1) === '"') {
postParam = postBody.substring(1, postBody.length - 1);
} else {
postBody = new URLSearchParams(postBody);
let postDict = {};
postBody.forEach((v, k) => {
postDict[k] = v;
});
postParam = JSON.stringify(postDict);
}
}
_GM_xmlhttpRequest({
method: "POST", url: _url, data: postParam,
onload: (d) => {
debug(d);
//_GM_notification(i18n("postOver") + d.statusText);
},
onerror: (e) => {
_GM_notification(i18n("postError") + (e.statusText || e.error));
},
ontimeout: (e) => {
_GM_notification(i18n("postError") + (e.statusText || e.error));
}
});
}
if (targetUrlData.indexOf('%input{') !== -1) {
self.showCustomInputWindow(targetUrlData, _url => {
postHandler(_url);
});
} else {
postHandler(targetUrlData);
}
return false;
} else if ((data.charset && data.charset != 'utf-8') || /[:%]p{/.test(data.url)) {
if (targetUrlData === false) return false;
let jumpFrom = data.url.match(/#(j(umpFrom|f)?|from){(.*?)}/);
let processPostUrl = _url => {
if (jumpFrom) {
storage.setItem("postUrl", [_url, data.charset]);
jumpFrom = jumpFrom[3];
if (jumpFrom.indexOf("http") !== 0) {
jumpFrom = _url.replace(/(:\/\/.*?\/)[\s\S]*/, "$1" + jumpFrom);
}
_url = jumpFrom;
} else {
if (ext) {
storage.setItem("postUrl", [_url + "#from{" + jumpHtml + "}", data.charset]);
_url = jumpHtml;
} else {
storage.setItem("postUrl", [_url, data.charset]);
_url = _url.replace(/(:\/\/.*?)\/[\s\S]*/, "$1").replace(/[:%]p{[\s\S]*/, '');
}
}
return _url;
};
if (targetUrlData.indexOf('%input{') !== -1) {
self.showCustomInputWindow(targetUrlData, _url => {
_url = processPostUrl(_url);
if (!_url) return;
ele.href = _url;
if (ele.target === '_blank') {
_GM_openInTab(ele.href, {active: true, insert: true});
} else {
location.href = ele.href;
}
});
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return;
} else {
targetUrlData = processPostUrl(targetUrlData);
if (!targetUrlData) return;
ele.href = targetUrlData;
}
}
if (shift && !ctrl && !meta && !alt && e.isTrusted) return;
if (/^(chrome|edge|about|extension|moz-extension)/.test(targetUrlData)) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
if (ctrl) {
_GM_openInTab(targetUrlData, {active: false, insert: true});
} else {
_GM_openInTab(targetUrlData, {active: true, insert: true, close: true});
}
return false;
} else if ((alt || ctrl || meta || shift) && isPage) {
if ((ctrl || meta) && shift) {
_GM_openInTab(targetUrlData, {incognito: true});
} else if (ctrl || meta) {
_GM_openInTab(targetUrlData, {active: false, insert: true});
} else if (alt) {
if (data.match) {
let match = data.match.replace(/\\/g, "");
let mobileMatch = match.match(/\((www)\|([^\)\|]+)/);
while (mobileMatch) {
targetUrlData = targetUrlData.replace(mobileMatch[1], mobileMatch[2]);
match = match.replace(mobileMatch[0], "");
mobileMatch = match.match(/\(([^\)\|]+)\|([^\)\|]+)/);
}
}
let viewWidth = window.screen.availWidth || window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.screen.availHeight || window.innerHeight || document.documentElement.clientHeight;
let showWidth = searchData.prefConfig.popupWidth, showHeight = searchData.prefConfig.popupHeight, left = searchData.prefConfig.popupLeft, top = searchData.prefConfig.popupTop;
if (showHeight) {
showHeight = parseFloat(showHeight);
showHeight = viewHeight / 100 * showHeight;
} else {
showHeight = Math.max(viewHeight / 3 * 2, viewHeight - 250);
}
if (showWidth) {
showWidth = parseFloat(showWidth);
showWidth = viewWidth / 100 * showWidth;
} else {
showWidth = Math.min(viewWidth, 650);
}
if (left) {
left = parseFloat(left);
left = viewWidth / 100 * left - showWidth / 2;
} else {
left = viewWidth - showWidth - 30;
}
if (top) {
top = parseFloat(top);
top = viewHeight / 100 * top - showHeight / 2;
} else {
top = (viewHeight - showHeight) / 2;
}
self.closePopupWindow();
self.popupWindow = window.open(targetUrlData + "#searchJumperMin" + (/#p{/.test(data.url) ? 'Post' : ''), "_blank", `width=${showWidth}, height=${showHeight}, location=0, resizable=1, status=0, toolbar=0, menubar=0, scrollbars=0, left=${left}, top=${top}`);
} else if (shift) {
_GM_openInTab(targetUrlData, {active: true, insert: true});
}
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return false;
} else if (isPage && ele.getAttribute("target") === "_blank" && !(alt || ctrl || meta || shift) && e.button === 0) {
_GM_openInTab(targetUrlData, {active: true, insert: true});
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return false;
}
};
//ele.href = data.url;
ele.addEventListener('mousedown', action, true);
ele.addEventListener('mouseup', e => {
if (e.stopPropagation) e.stopPropagation();
}, true);
ele.addEventListener('click', clickHandler, true);
ele.addEventListener('auxclick', e => {
if (clicked && e.preventDefault) {
e.preventDefault();
return false;
}
}, true);
ele.addEventListener('contextmenu', e => {
if (clicked && e.preventDefault) {
e.preventDefault();
return false;
}
}, true);
let tipsStr = ele.dataset.name;
if (shortcut) {
tipsStr += ` (${data.ctrl ? "Ctrl + " : ""}${data.shift ? "Shift + " : ""}${data.alt ? "Alt + " : ""}${data.meta ? "Meta + " : ""}${shortcut.replace("Key", "")})`;
}
let anylizing = false, tipsShowing = false;
let setTips = async (target, url, again) => {
self.tipsPos(target, '<span class="loader"></span><font>Loading...</font>');
tipsShowing = false;
if (url) {
try {
url = url.replace(/^showTips:/, '');
anylizing = true;
let tipsResult = await self.anylizeShowTips(url, ele.dataset.name, target);
anylizing = false;
if (self.tips.style.opacity == 0 || self.tips.innerHTML.indexOf('<span class="loader">') !== 0) {
tipsShowing = true;
return;
}
if (Array && Array.isArray && Array.isArray(tipsResult)) {
tipsData = tipsResult[1];
tipsResult = tipsResult[0];
}
if (tipsResult) {
if (tipsResult != "null" && tipsResult != "No result") {
tipsResult = `<div>${tipsResult}</div>`;
tipsShowing = true;
}
//self.tips.style.transition = "none";
self.tipsPos(target, tipsResult);
addHistory();
setTimeout(() => {
self.tips.style.pointerEvents = "all";
}, 100);
}
} catch(e) {debug(e)}
}
};
let showTipsHandler = async (target, time = 1000) => {
if (!target || target.nodeType !== 1) return;
if (self.preList) {
self.preList.style.visibility = "hidden";
self.listArrow.style.cssText = "";
}
tipsData = null;
clearTimeout(self.requestShowTipsTimer);
self.waitForShowTips = false;
self.tipsPos(target, tipsStr);
if (showTips) {
self.stopInput = true;
let url = await getUrl();
self.stopInput = false;
if (url && self.lastUrl === url) {
if (anylizing) {
self.tipsPos(target, "<span class='loader'></span><font>Loading...</font>");
} else {
setTips(target, url);
}
} else {
self.waitForShowTips = true;
self.requestShowTipsTimer = setTimeout(async () => {
url = url || await getUrl();
if (!url) return;
if (url.indexOf('%input{') !== -1) {
self.showCustomInputWindow(url, _url => {
url = _url;
setTips(target, url);
});
return;
}
self.lastUrl = url;
setTips(target, url);
self.waitForShowTips = false;
}, time);
}
}
}
let touchend = false;
ele.addEventListener('touchend', e => {
if (e.stopPropagation) e.stopPropagation();
if (showTips) {
touchend = true;
self.waitForShowTips = true;
}
}, false);
let scaleMove = e => {
if (self.funcKeyCall || searchData.prefConfig.noAni) return;
let leftRight = self.con.classList.contains("search-jumper-left") ||
self.con.classList.contains("search-jumper-right");
let newDockerScaleBtns = [];
let curRect = ele.getBoundingClientRect();
let offset = leftRight ? Math.abs(e.clientY - curRect.top) / curRect.height : Math.abs(e.clientX - curRect.left) / curRect.width;
let scale1st = 0.1;
let scale2nd = 0.1;
ele.style.setProperty("--scale", 1 + scale1st + scale2nd);
newDockerScaleBtns.push(ele);
let pre = ele.previousElementSibling;
if (pre && /^A$/i.test(pre.nodeName)) {
pre.style.setProperty("--scale", 1 + scale2nd + scale1st * (1 - offset));
newDockerScaleBtns.push(pre);
let prepre = pre.previousElementSibling;
if (prepre && /^A$/i.test(prepre.nodeName)) {
prepre.style.setProperty("--scale", 1 + scale2nd * (1 - offset));
newDockerScaleBtns.push(prepre);
}
}
let next = ele.nextElementSibling;
if (next && /^A$/i.test(next.nodeName)) {
next.style.setProperty("--scale", 1 + scale2nd + scale1st * offset);
newDockerScaleBtns.push(next);
let nextnext = next.nextElementSibling;
if (nextnext && /^A$/i.test(nextnext.nodeName)) {
nextnext.style.setProperty("--scale", 1 + scale2nd * offset);
newDockerScaleBtns.push(nextnext);
}
}
self.dockerScaleBtns.forEach(btn => {
if (newDockerScaleBtns.indexOf(btn) === -1) {
btn.style.setProperty("--scale", 1);
}
});
self.dockerScaleBtns = newDockerScaleBtns;
};
ele.addEventListener('mouseenter', e => {
if (e.stopPropagation) e.stopPropagation();
if (tipsShowing && self.lastTips === ele && self.tips.style.opacity == 1) {
return;
}
self.lastTips = ele;
if (showTips) {
if (touchend) {
touchend = false;
return;
}
if (hasWordParam) {
let keywords = self.searchJumperInputKeyWords.value || getKeywords();
if (!keywords) {
self.waitForShowTips = true;
self.tipsPos(ele, tipsStr);
return;
}
}
}
showTipsHandler(ele);
}, true);
ele.addEventListener('mousemove', e => {
scaleMove(e);
self.clingPos(ele, self.tips);
}, false);
ele.addEventListener('showTips', e => {
self.appendBar();
self.closeOpenType();
self.con.style.display = "";
self.setFuncKeyCall(true);
showTipsHandler(targetElement, 0);
}, false);
ele.addEventListener('mouseleave', e => {
if (!tipsShowing) {
self.tips.style.opacity = 0;
clearTimeout(self.requestShowTipsTimer);
}
}, false);
ele.addEventListener('drop', e => {
self.searchBySiteName(name, e);
}, false);
ele.addEventListener('dragover', e => {
e.preventDefault();
}, false);
return ele;
}
closePopupWindow() {
if (!searchData.prefConfig.closePopupWhenClick) return;
if (this.popupWindow) {
this.popupWindow.close();
this.popupWindow = null;
}
}
closeOpenType() {
let openType = this.bar.querySelector('.search-jumper-type.search-jumper-open>span');
if (openType) {
this.funcKeyCall = false;
if (openType.onmousedown) {
openType.onmousedown();
} else {
let mouseEvent = new PointerEvent("mousedown");
openType.dispatchEvent(mouseEvent);
}
}
}
addToHighlightGroup(findWords, addToGroup) {
let group = searchData.prefConfig.inPageRule[addToGroup];
if (group) {
let groupMatch = group.match(/^\/(.*)\/([il]*)$/);
if (groupMatch) {
group = `/${groupMatch[1]}|${findWords}/${groupMatch[2] || ''}`;
} else group = `/${group}|${findWords}/`;
} else {
group = `/${findWords}/`;
}
searchData.prefConfig.inPageRule[addToGroup] = group;
storage.setItem("searchData", searchData);
this.refreshPageWords(this.lockWords);
}
streamUpdate(data) {
this.streamUpdateCallBack && this.streamUpdateCallBack(data);
}
async anylizeShowTips(data, name, target) {
let tipsResult, self = this;
try {
const calcReg = /([^\\]|^)([\+\-*/])([\d\.]+)$/;
const cacheReg = /\|cache\=(\d+)$/;
const postReg = /%p(\{+)/;
const headersReg = /#headers({.*?})/;
const streamReg = /#stream({(.*?)})?/;
const thenReg = /.then{(.*?)}/;
data = data.replace(/^showTips:/, '').replace(/{name}/g, name).trim();
if (/^https?:/.test(data)) {
let url = data.split("\n");
if (url.length == 1) url = data.split(" ");
url = url[0];
data = data.replace(url, "").trim().replace(/\\{/g, "showTipsLeftBrace").replace(/\\}/g, "showTipsRightBrace").replace(/{url}/g, '【SEARCHJUMPERURL】');
let cache = url.match(cacheReg);
if (cache) {
cache = parseInt(cache[1]);
url = url.replace(cacheReg, "");
} else cache = 7200;
let now = Date.now() / 1000;
let newTipsStorage = tipsStorage.filter(t => {
if (now < t.time) {
if (!tipsResult && t.url == url) {
tipsResult = t.data;
}
return true;
}
return false;
});
if (newTipsStorage.length != tipsStorage.length) {
tipsStorage = newTipsStorage;
storage.setItem("tipsStorage", tipsStorage);
}
let allValue = [];
let calcJson = (json, template) => {
let finalData = data, allFailed = true;
while (template) {
let templateArr = template[1].replace(/\\\|/g, "【searchJumperJsonSplit】").split("|");
let props = templateArr[0].replace(/【searchJumperJsonSplit】/g, "|").replace(/\[(\d+)\]/g, ".$1").replace(/\[all\]/g, ".all").split("."), value = json, arrayValue = null;
props.shift();
props.forEach(prop => {
if (arrayValue) {
let tempArray = [];
for (let i = 0; i < arrayValue.length; i++) {
let curValue = arrayValue[i];
if (curValue) {
if (Array.isArray(curValue)) {
curValue = curValue.at ? curValue.at(prop) : curValue[prop];
} else curValue = curValue[prop];
}
tempArray.push(curValue);
}
arrayValue = tempArray;
} else {
if (value) {
if (Array.isArray(value)) {
if (prop === 'all') {
arrayValue = value;
} else {
value = value.at ? value.at(prop) : value[prop];
}
} else value = value[prop];
}
if (!value) return null;
}
});
if (arrayValue) {
value = arrayValue.join("");
}
if (templateArr.length != 1) {
let calcStr = templateArr[1];
let needCalc = calcStr.match(calcReg);
if (needCalc) {
let calcArr = [];
while (needCalc) {
calcStr = calcStr.replace(calcReg, "$1");
calcArr.unshift([needCalc[2], needCalc[3]]);
needCalc = calcStr.match(calcReg);
}
calcArr.forEach(calc => {
let param = parseFloat(calc[1]);
switch (calc[0]) {
case "+":
value += param;
break;
case "-":
value -= param;
break;
case "*":
value *= param;
break;
case "/":
value /= param;
break;
}
});
value = value.toFixed(2);
} else {
let fullReg = calcStr.match(/^\/(.*)\/(\w?)$/);
let regGroup = fullReg ? new RegExp(fullReg[1], fullReg[2]) : new RegExp(calcStr);
let valueMatch = value.match(regGroup);
if (valueMatch) {
value = valueMatch[1];
}
}
}
if (!value) value = "";
else allFailed = false;
allValue.push(value);
finalData = finalData.replace(template[0], value);
template = finalData.match(/{(.*?)}/);
}
if (allFailed) {
console.log("Error:", json);
}
finalData = finalData.replace(/showTipsLeftBrace/g, "{").replace(/showTipsRightBrace/g, "}");
return finalData;
}
let template = data.match(/{(.*?)}/);
if (tipsResult) {
if (template && template[1].indexOf("json") === 0) {
data = data.replace(/【SEARCHJUMPERURL】/g, url);
tipsResult = calcJson(tipsResult, template);
tipsResult = [tipsResult, "\n" + allValue.join(",")];
}
} else {
let storeData;
let postMatch = url.match(postReg), fetchOption = {}, _url = url;
if (postMatch) {
let braceNum = postMatch[1].length;
postMatch = url.match(new RegExp(`%p\{+(.*?)\}{${braceNum}}`));
if (postMatch) {
let body = postMatch[1];
if (body.indexOf("%") === 0) {
try {
body = decodeURIComponent(body);
} catch(e) {}
}
fetchOption.body = body;
fetchOption.method = "POST";
_url = _url.replace(postMatch[0], "");
}
}
let headersMatch = url.match(headersReg);
if (headersMatch) {
let headers = headersMatch[1];
if (headers.indexOf("%") === 0 || headers.indexOf("%") === 1) {
try {
headers = decodeURIComponent(headers);
} catch(e) {}
}
fetchOption.headers = JSON.parse(headers);
_url = _url.replace(headersMatch[0], "");
}
let failed = false, fetchData;
let isJson = (template && template[1].indexOf("json") === 0);
let streamMatch = url.match(streamReg);
if (streamMatch) {
fetchOption.responseType = "stream";
fetchOption.streamMode = streamMatch[2] || "concat";
_url = _url.replace(streamMatch[0], "");
tipsResult = await new Promise(resolve => {
fetchOption.onstream = data => {
let result;
if (isJson) {
result = data.json();
if (!result) return;
result = calcJson(result, template);
} else result = data.text;
self.tipsPos(target, result);
self.tips.style.pointerEvents = "all";
resolve && resolve(result);
};
if (ext) {
self.streamUpdateCallBack = data => {
let result;
if (isJson) {
if (!data.json) return;
result = calcJson(data.json, template);
} else result = data.text;
self.tipsPos(target, result);
self.tips.style.pointerEvents = "all";
resolve && resolve(result);
};
fetchData = new Promise((resolve) => {
chrome.runtime.sendMessage({action: "showTips", detail: {from: url + `\n{${template[1]}}`}}, function(r) {
data = data.replace(/【SEARCHJUMPERURL】/g, (r && r.finalUrl) || "");
resolve(isJson ? r.json : r.text);
});
});
} else {
fetchData = GM_fetch(_url, fetchOption).then(r => {
data = data.replace(/【SEARCHJUMPERURL】/g, r.finalUrl);
return isJson ? r.json() : r.text;
});
}
fetchData.then(r => {
let finalData = isJson ? (r && calcJson(r, template)) : r;
if (!finalData) return;
self.tipsPos(target, finalData);
resolve && resolve(finalData);
});
});
if (!tipsResult) {
tipsResult = "No result";
failed = true;
}
} else if (isJson) {
let allValue = [];
if (ext) {
fetchData = new Promise((resolve) => {
chrome.runtime.sendMessage({action: "showTips", detail: {from: url + `\n{${template[1]}}`}}, function(r) {
data = data.replace(/【SEARCHJUMPERURL】/g, (r && r.finalUrl) || "");
resolve((r && r.data) || "");
});
});
} else {
fetchData = GM_fetch(_url, fetchOption).then(r => {
data = data.replace(/【SEARCHJUMPERURL】/g, r.finalUrl);
return r.json();
});
}
tipsResult = await fetchData.then(r => {
if (!r) return null;
storeData = r;
let finalData = calcJson(r, template);
return finalData;
});
if (!tipsResult) {
tipsResult = "No result";
failed = true;
}
tipsResult = [tipsResult, "\n" + allValue.join(",")];
} else {
let hasData = false;
let thenMatch = _url.match(thenReg), thenEleSelArr = [];
while (thenMatch) {
let thenEleSel = thenMatch[1];
thenEleSelArr.push(thenEleSel);
_url = _url.replace(thenMatch[0], "");
thenMatch = _url.match(thenReg);
}
if (ext) {
fetchData = new Promise((resolve) => {
chrome.runtime.sendMessage({action: "showTips", detail: {from: url + `\n `}}, function(r) {
if (data.indexOf('【SEARCHJUMPERURL】') != -1) {
data = data.replace(/【SEARCHJUMPERURL】/g, (r && r.finalUrl) || "");
hasData = true;
}
resolve((r && r.data) || "");
});
});
while (thenEleSelArr.length) {
let thenEleSel = thenEleSelArr.shift();
let thenUrl = await fetchData.then(r => {
let doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = createHTML(r);
let ele = getElement(thenEleSel, doc);
if (!ele) return null;
let basepath = doc.querySelector("base");
return canonicalUri(ele.getAttribute("href"), (basepath ? basepath.href : _url));
});
if (thenUrl) {
fetchData = new Promise((resolve) => {
chrome.runtime.sendMessage({action: "showTips", detail: {from: thenUrl + `\n `}}, function(r) {
resolve((r && r.data) || "");
});
});
} else return "No result";
}
} else {
fetchData = GM_fetch(_url, fetchOption).then(r => {
if (data.indexOf('【SEARCHJUMPERURL】') != -1) {
data = data.replace(/【SEARCHJUMPERURL】/g, r.finalUrl);
hasData = true;
}
return r.text();
});
while (thenEleSelArr.length) {
let thenEleSel = thenEleSelArr.shift();
let thenUrl = await fetchData.then(r => {
let doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = createHTML(r);
let ele = getElement(thenEleSel, doc);
if (!ele) return null;
let basepath = doc.querySelector("base");
return canonicalUri(ele.getAttribute("href"), (basepath ? basepath.href : _url));
});
if (thenUrl) {
fetchData = GM_fetch(thenUrl).then(r => {
return r.text();
});
} else return "No result";
}
}
let title;
tipsResult = await fetchData.then(r => {
if (!data) {
return r;
}
let doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = createHTML(r);
title = doc.title;
let finalData = data;
while (template) {
let value = "";
if (template[1] == "title") {
value = doc.title;
} else {
let selArr = template[1].split("|");
let eles = getAllElements(selArr[0], doc);
if (eles && eles.length) {
hasData = true;
if (selArr.length == 1) {
value = eles[0].innerText;
} else {
let key = selArr[1];
let forEachMatch = key.match(/\(.*?\)/g);
if (forEachMatch) {
[].forEach.call(eles, ele => {
let _v = selArr[1];
forEachMatch.forEach(p => {
if (p === "()") {
_v = _v.replace(p, ele.innerText);
} else {
key = p.match(/\((.*)\)/)[1];
_v = _v.replace(p, ele.getAttribute(key) || ele[key]);
}
});
value += _v;
});
} else {
value = eles[0].getAttribute(key) || eles[0][key];
}
}
}
}
finalData = finalData.replace(template[0], value);
template = finalData.match(/{(.*?)}/);
}
if (!hasData) return null;
finalData = finalData.replace(/showTipsLeftBrace/g, "{").replace(/showTipsRightBrace/g, "}");
return finalData;
});
if (!tipsResult) {
tipsResult = "No result";
failed = true;
} else {
this.insertHistoryUrl(url, title);
}
tipsResult = [tipsResult, url];
storeData = tipsResult;
}
if (!failed) {
tipsResult = this.calcResult(tipsResult);
tipsStorage.push({url: url, data: storeData, time: Date.now() / 1000 + cache});
if (tipsStorage.length > 50) tipsStorage.shift();
storage.setItem("tipsStorage", tipsStorage);
}
}
} else {
tipsResult = /\breturn\b/.test(data) ? await new AsyncFunction('fetch', 'storage', 'name', '"use strict";' + data)(GM_fetch, storage, name) : data;
tipsResult = this.calcResult(tipsResult);
if (targetElement && targetElement.href) {
let newTitle = targetElement.title || targetElement.alt || targetElement.innerText;
this.insertHistoryUrl(targetElement.href, newTitle);
}
}
} catch(e) {debug(e)}
return tipsResult;
}
calcResult(result) {
let isString = typeof result === 'string';
let str = isString ? result : result[0];
const calcRegFull = /{([\d\.]+)(([\+\-*/][\d\.]+)+)}/;
const calcRegOperate = /([\+\-*/])([\d\.]+)/;
let needCalc = str.match(calcRegFull);
if (needCalc) {
let calcArr = [];
let fullMatch = needCalc[0];
let value = parseFloat(needCalc[1]);
let calcStr = needCalc[2];
needCalc = calcStr.match(calcRegOperate);
while (needCalc) {
calcStr = calcStr.replace(needCalc[0], "");
calcArr.push([needCalc[1], needCalc[2]]);
needCalc = calcStr.match(calcRegOperate);
}
calcArr.forEach(calc => {
let param = parseFloat(calc[1]);
switch (calc[0]) {
case "+":
value += param;
break;
case "-":
value -= param;
break;
case "*":
value *= param;
break;
case "/":
value /= param;
break;
}
});
value = value.toFixed(2);
str = str.replace(fullMatch, value);
}
if (isString) {
result = str;
} else {
result[0] = str;
}
return result;
}
insertHistoryUrl(url, title) {
if (url.indexOf(location.host) === -1) return;
let curUrl = location.href;
let oldTitle = document.title;
_unsafeWindow.history.pushState('', title, url);
document.title = title;
_unsafeWindow.history.replaceState('', oldTitle, curUrl);
document.title = oldTitle;
}
checkScroll(noIntoView, noSmooth) {
if (this.funcKeyCall || this.bar.style.display == "none") return;
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
if (this.bar.scrollWidth > viewWidth || this.bar.scrollHeight > viewHeight) {
if (!this.con.classList.contains("search-jumper-scroll")) {
this.bar.style.cssText = "";
this.con.classList.add("search-jumper-scroll");
this.con.style.display = "";
}
} else {
if (this.con.classList.contains("search-jumper-scroll")) {
this.bar.style.cssText = "";
this.con.classList.remove("search-jumper-scroll");
}
}
if (noIntoView) return;
let firstType = this.bar.querySelector(".search-jumper-type.search-jumper-open");
if (firstType) {
if (firstType.style.width === "0px") {
firstType.style.width = "auto";
}
if (firstType.style.height === "0px") {
firstType.style.height = "auto";
}
if (firstType != this.bar.firstElementChild) {
setTimeout(() => {
firstType.scrollIntoView(noSmooth ? {} : {behavior: "smooth"});
}, 0);
}
}
}
reopenType(type) {
let mouseEvent = new PointerEvent("mousedown");
if (type.parentNode.classList.contains('search-jumper-open')) {
if (type.onmousedown) type.onmousedown();
else {
type.dispatchEvent(mouseEvent);
}
}
if (type.onmousedown) type.onmousedown();
else {
type.dispatchEvent(mouseEvent);
}
}
showInPage(_funcKeyCall, e) {
if (this.contains(targetElement) || (this.inInput && mainStyleEle) || (!_funcKeyCall && this.funcKeyCall)) {
return;
}
if (!mainStyleEle || !mainStyleEle.parentNode) {
mainStyleEle = _GM_addStyle(cssText);
if (!disabled) this.addToShadow(mainStyleEle);
}
let selectStr = getSelectStr();
if (_funcKeyCall && selectStr && selectStr.length < (searchData.prefConfig.limitPopupLen || 1)) return;
if (this.con && this.con.classList.contains("search-jumper-showall")) return;
if (searchData.prefConfig.hidePopup) _funcKeyCall = false;
if (!targetElement) targetElement = getBody(document);
else if (!selectStr && targetElement != getBody(document) && (targetElement.className != "searchJumper" || !/^MARK$/i.test(targetElement.nodeName))) {
let _targetElement = targetElement, children;
while (_targetElement && _targetElement.nodeName) {
if (/^(img|audio|video|a)$/i.test(_targetElement.nodeName)) break;
if (_targetElement.parentNode) {
if (/^(img|audio|video|a)$/i.test(_targetElement.parentNode.nodeName)) {
_targetElement = _targetElement.parentNode;
break;
}
children = _targetElement.parentNode.querySelectorAll("audio,video");
if (children && children.length !== 1) {
children = _targetElement.parentNode.querySelectorAll("img");
}
if (children && children.length !== 1) {
children = _targetElement.parentNode.querySelectorAll("a");
}
if (children && children.length === 1) {
if (children[0].scrollHeight && _targetElement.scrollHeight / children[0].scrollHeight < 2) {
_targetElement = children[0];
}
break;
}
}
_targetElement = _targetElement.parentNode;
}
if (_targetElement) targetElement = _targetElement;
}
this.appendBar();
let self = this;
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
}
var delay = searchData.prefConfig.autoDelay || 1000;
var hideHandler = () => {
self.bar.classList.remove("search-jumper-isInPage");
self.bar.classList.remove("search-jumper-isTargetImg");
self.bar.classList.remove("search-jumper-isTargetAudio");
self.bar.classList.remove("search-jumper-isTargetVideo");
self.bar.classList.remove("search-jumper-isTargetLink");
self.bar.classList.remove("search-jumper-isTargetPage");
self.bar.classList.remove("initShow");
self.hideTimeout = null;
};
if (searchData.prefConfig.autoHide) this.hideTimeout = setTimeout(hideHandler, delay);
this.bar.classList.remove("search-jumper-isInPage");
this.bar.classList.remove("search-jumper-isTargetImg");
this.bar.classList.remove("search-jumper-isTargetAudio");
this.bar.classList.remove("search-jumper-isTargetVideo");
this.bar.classList.remove("search-jumper-isTargetLink");
this.bar.classList.remove("search-jumper-isTargetPage");
this.bar.classList.remove("initShow");
this.tips.style.opacity = 0;
this.tips.style.display = "none";
this.tips.style.transition = "none";
this.tips.innerHTML = createHTML("");
setTimeout(() => {this.bar.classList.add("initShow");}, 10);
let typeSel = "", secondType = "";
if (selectStr) {
this.bar.classList.add("search-jumper-isInPage");
if (this.bar.style.display == "none" || _funcKeyCall) {
typeSel = "needInPage";
} else {
let openType = this.bar.querySelector(".search-jumper-type.search-jumper-open");
if (!openType || openType.classList.contains('notmatch') ||
openType.classList.contains('search-jumper-targetPage') ||
openType.classList.contains('search-jumper-targetImg') ||
openType.classList.contains('search-jumper-targetAudio') ||
openType.classList.contains('search-jumper-targetVideo') ||
openType.classList.contains('search-jumper-targetLink')) {
typeSel = "needInPage";
}
}
} else {
if (targetElement.children.length == 1 && targetElement.children[0].nodeName.toUpperCase() === 'A') {
targetElement = targetElement.children[0];
}
switch (targetElement.nodeName.toUpperCase()) {
case 'IMG':
this.bar.classList.add("search-jumper-isTargetImg");
typeSel = "targetImg";
break;
case 'AUDIO':
this.bar.classList.add("search-jumper-isTargetAudio");
typeSel = "targetAudio";
break;
case 'VIDEO':
this.bar.classList.add("search-jumper-isTargetVideo");
typeSel = "targetVideo";
break;
case 'A':
this.bar.classList.add("search-jumper-isTargetLink");
typeSel = "targetLink";
break;
default:
break;
}
let parentNode = targetElement.parentNode;
if (parentNode && parentNode.nodeName.toUpperCase() === 'A') {
this.bar.classList.add("search-jumper-isTargetLink");
if (!typeSel) {
typeSel = "targetLink";
} else secondType = "targetLink";
}
if (!typeSel) {
this.bar.classList.add("search-jumper-isTargetPage");
typeSel = "targetPage";
}
if (!typeSel) {
typeSel = "targetAll";
}
}
if (this.bar.style.display == "none") {
this.bar.style.display = "";
}
let firstType, targetSiteImgs;
if (typeSel) {
firstType = this.bar.querySelector(`.search-jumper-${typeSel}:not(.notmatch)>span`);
targetSiteImgs = this.bar.querySelectorAll(`.search-jumper-${typeSel}:not(.notmatch)>a>img`);
}
self.setFuncKeyCall(false);
if (firstType) {
if ((!searchData.prefConfig.disableAutoOpen && !searchData.prefConfig.disableTypeOpen) || _funcKeyCall) {
let targetTypes = this.bar.querySelectorAll(`.search-jumper-${typeSel}:not(.notmatch)>span:first-child`);
[].forEach.call(targetTypes, type => {
if (type !== firstType) {
self.reopenType(type);
}
});
self.reopenType(firstType);
self.insertHistory(firstType.parentNode);
if (secondType) {
targetTypes = this.bar.querySelectorAll(`.search-jumper-${secondType}:not(.notmatch)>span:first-child`);
[].forEach.call(targetTypes, type => {
if (type !== firstType) {
self.reopenType(type);
}
});
self.reopenType(firstType);
}
}
}
if (!_funcKeyCall && (searchData.prefConfig.disableAutoOpen || searchData.prefConfig.disableTypeOpen)) {
this.closeOpenType();
}
self.setFuncKeyCall(_funcKeyCall);
if (_funcKeyCall) {
if (targetSiteImgs) {
[].forEach.call(targetSiteImgs, siteImg => {
if (siteImg.parentNode.style.display != "none" && siteImg.dataset.src) {
siteImg.src = siteImg.dataset.src;
delete siteImg.dataset.src;
}
});
}
self.con.classList.remove("search-jumper-scroll");
self.bar.style.cssText = "";
self.con.style.cssText = "";
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
let tileOffset = searchData.prefConfig.tileOffset || 0;
let _clientX = pageX(e) - self.bar.clientWidth / 2 - (getComputedStyle(document.documentElement).position !== 'static' ? document.documentElement.offsetLeft : 0);
if (_clientX < 0) _clientX = 5;
else if (_clientX + self.bar.clientWidth > viewWidth + scrollLeft) _clientX = viewWidth + scrollLeft - self.bar.clientWidth - 20;
let _clientY = pageY(e);
if (clientY(e) > viewHeight / 5) _clientY -= (self.bar.clientHeight + 20 + tileOffset);
else _clientY += (20 + tileOffset);
if (clientX(e) < viewWidth / 2) {
self.bar.style.left = _clientX + scrollLeft + "px";
self.bar.style.transformOrigin = '0 0';
} else {
self.bar.style.right = viewWidth - _clientX - self.bar.clientWidth - 15 + "px";
self.bar.style.transformOrigin = '100% 0';
}
self.bar.style.top = _clientY + "px";
self.removeBar();
self.bar.style.opacity = 0;
setTimeout(() => {
self.appendBar();
setTimeout(() => {
self.bar.style.opacity = 1;
setTimeout(() => {
let saladict = document.querySelector('#saladict-saladbowl-root>.saladict-external');
if (saladict) {
let saladbowl = saladict.shadowRoot.querySelector('.saladbowl');
saladbowl.style.transform = saladbowl.style.transform.replace(/\d+px\)/, `${e.clientY - 15}px)`);
}
}, 100);
}, 1);
}, 1);
} else {
self.bar.style.display = "";
self.initPos();
}
}
setFuncKeyCall(value) {
this.funcKeyCall = value;
if (!this.con.classList.contains("search-jumper-showall")) {
if (value) {
this.con.classList.add("funcKeyCall");
} else {
this.con.classList.remove("funcKeyCall");
}
}
}
initPos(relX, relY, posX, posY) {
if (this.preList) {
this.preList.style.visibility = "hidden";
this.preList.style.opacity = 0;
this.listArrow.style.cssText = "";
}
if (typeof relX === 'undefined') {
relX = searchData.prefConfig.position.x;
}
if (typeof relY === 'undefined') {
relY = searchData.prefConfig.position.y;
}
if (typeof posX === 'undefined') {
posX = searchData.prefConfig.offset.x;
}
if (typeof posY === 'undefined') {
posY = searchData.prefConfig.offset.y;
}
let self = this;
let setClass = className => {
self.bar.style.cssText = "";
self.con.style.cssText = "";
self.con.className = "search-jumper-searchBarCon " + className;
if (searchData.prefConfig.resizePage) {
if (typeof self.initBodyStyle == 'undefined') self.initBodyStyle = getBody(document).style.cssText;
else getBody(document).style.cssText = self.initBodyStyle;
self.con.classList.add("resizePage");
getBody(document).style.position = "absolute";
switch (className) {
case "search-jumper-left":
getBody(document).style.width = `calc(100% - ${self.scale * 42}px)`;
getBody(document).style.right = "0px";
break;
case "search-jumper-right":
getBody(document).style.width = `calc(100% - ${self.scale * 42}px)`;
getBody(document).style.left = "0px";
break;
case "search-jumper-bottom":
getBody(document).style.width = "100%";
getBody(document).style.height = `calc(100% - ${self.scale * 42}px)`;
getBody(document).style.top = "0px";
getBody(document).style.overflow = "auto";
break;
default:
getBody(document).style.width = "100%";
getBody(document).style.height = `calc(100% - ${self.scale * 42}px)`;
getBody(document).style.bottom = "0px";
getBody(document).style.overflow = "auto";
break;
}
} else if (searchData.prefConfig.autoHideAll) {
self.con.classList.add("hideAll");
}
let baseSize = self.scale * 40;
setTimeout(() => {
let leftRight = self.con.classList.contains("search-jumper-left") ||
self.con.classList.contains("search-jumper-right");
searchTypes.forEach(ele => {
if (!ele.classList.contains("search-jumper-open")) {
if (leftRight) {
ele.style.width = "";
ele.style.height = baseSize + "px";
} else {
ele.style.width = baseSize + "px";
ele.style.height = "";
}
} else {
let scrollSize = Math.max(ele.scrollWidth, ele.scrollHeight);
if (scrollSize) {
scrollSize += "px";
if (leftRight) {
ele.style.width = "";
ele.style.height = scrollSize;
} else {
ele.style.width = scrollSize;
ele.style.height = "";
}
}
}
});
}, 1);
};
if (posX < 0) {
posX = 0;
}
if (posY < 0) {
posY = 0;
}
if (relX == "center" && relY == "top") {
//上中
setClass("");
self.bar.style.position = "relative";
} else if (relX == "left" && relY == "top") {
if (posX > posY) {
//上左
setClass("");
self.bar.style.position = "fixed";
self.bar.style.left = posX + "px";
} else {
//左上
setClass("search-jumper-left");
self.bar.style.position = "fixed";
self.bar.style.top = posY + "px";
}
} else if (relX == "right" && relY == "top") {
if (posX > posY) {
//上右
setClass("");
self.bar.style.position = "fixed";
self.bar.style.right = posX + "px";
} else {
//右上
setClass("search-jumper-right");
self.bar.style.position = "fixed";
self.bar.style.top = posY + "px";
}
} else if (relX == "center" && relY == "bottom") {
//下中
setClass("search-jumper-bottom");
self.bar.style.position = "relative";
} else if (relX == "left" && relY == "bottom") {
if (posX > posY) {
//下左
setClass("search-jumper-bottom");
self.bar.style.position = "fixed";
self.bar.style.left = posX + "px";
self.bar.style.bottom = "0px";
self.bar.style.top = "unset";
} else {
//左下
setClass("search-jumper-left");
self.bar.style.position = "fixed";
self.bar.style.bottom = posY + "px";
}
} else if (relX == "right" && relY == "bottom") {
if (posX > posY) {
//下右
setClass("search-jumper-bottom");
self.bar.style.position = "fixed";
self.bar.style.right = posX + "px";
self.bar.style.bottom = "0px";
self.bar.style.top = "unset";
} else {
//右下
setClass("search-jumper-right");
self.bar.style.position = "fixed";
self.bar.style.bottom = posY + "px";
}
} else if (relX == "left" && relY == "center") {
//左中
setClass("search-jumper-left");
self.bar.style.position = "relative";
self.bar.style.marginTop = posY + "px";
self.con.style.display = "flex";
self.con.style.justifyContent = "center";
} else if (relX == "right" && relY == "center") {
//右中
setClass("search-jumper-right");
self.bar.style.position = "absolute";
self.bar.style.marginTop = posY + "px";
self.con.style.display = "flex";
self.con.style.justifyContent = "center";
self.con.style.alignItems = "flex-end";
}
searchData.prefConfig.position.x = relX;
searchData.prefConfig.position.y = relY;
searchData.prefConfig.offset.x = posX;
searchData.prefConfig.offset.y = posY;
if (searchData.prefConfig.disableAutoOpen || searchData.prefConfig.disableTypeOpen) {
self.checkScroll(false, true);
} else {
setTimeout(() => {
let openType = self.bar.querySelector('.search-jumper-type.search-jumper-open');
if (openType) {
openType.style.transition = "none";
openType.style.width = "auto";
openType.style.height = "auto";
setTimeout(() => {
openType.style.width = openType.scrollWidth + "px";
openType.style.height = openType.scrollHeight + "px";
setTimeout(() => {
openType.style.transition = "";
}, 1);
self.checkScroll(false, true);
}, 0);
}
}, 251);
}
}
}
class Picker {
//static picker;
constructor() {
this.clickedIndex = 0;
this.signList = [];//所有标记
this.clickedEles = {};//点击的元素
this.exact = true;
this.accu = 0;
this.wheelScrolling = false;
}
/*static getInstance() {
if (!Picker.picker) {
Picker.picker = new Picker();
}
return Picker.picker;
}*/
getSelector(callback, exact = true) {
this.exact = exact;
this.close();
this.toggle();
this.callback = callback;
}
init() {
if (this.inited) return;
this.inited = true;
let self = this;
let cssText = `
body.searchJumper-picker,
body.searchJumper-picker *:hover,
body.searchJumper-picker a:hover {
cursor: crosshair !important;
}
.select-rect {
position: fixed;
z-index: 2147483647;
background: none;
border: 1px dashed rgba(120, 170, 210, 0.8);
}
.select-rect>.dot {
width: 10px;
height: 10px;
border: 2px solid #000;
border-radius: 50%;
background-color: white;
position: absolute;
}
.select-rect>.top-left {
top: -5px;
left: -5px;
}
.select-rect>.top-right {
top: -5px;
right: -5px;
}
.select-rect>.bottom-left {
bottom: -5px;
left: -5px;
}
.select-rect>.bottom-right {
bottom: -5px;
right: -5px;
}
.select-rect>.top {
top: -5px;
left: calc(50% - 5px);
}
.select-rect>.right {
top: calc(50% - 5px);
right: -5px;
}
.select-rect>.left {
top: calc(50% - 5px);
left: -5px;
}
.select-rect>.bottom {
bottom: -5px;
left: calc(50% - 5px);
}
`;
_GM_addStyle(cssText);
let clickTarget = target => {
if (!target) return;
if (self.callback) {
if (target) {
let sel = self.geneSelector(target, self.exact);
self.callback(sel);
self.close();
}
return;
}
let sign = self.createSignDiv();
self.clickedEles[self.clickedIndex] = target;
self.appendSign(sign, target, self.clickedIndex);
self.clickedIndex++;
searchBar.con.classList.add("selectedEle");
}
let cleanTimer;
this.initSelectRect();
this.mainSignDiv = this.createSignDiv();
this.setImportant(this.mainSignDiv, "pointer-events", "none");
this.setImportant(this.mainSignDiv, "background", "rgba(120, 170, 210, 0.3)");
this.moveHandler = e => {
if (e.target === document) return;
if (self.inPicker) {
e.preventDefault();
}
if (self.rectSelecting) {
if (self.mainSignDiv.parentNode) self.mainSignDiv.parentNode.removeChild(self.mainSignDiv);
if (!self.selectRect.parentNode) getBody(document).appendChild(self.selectRect);
self.createSelectRect({x: e.clientX, y: e.clientY});
} else if (self.creatingRect) {
return;
} else {
let target = self.getTarget(e.target);
if (self.mainSignDiv.parentNode !== target.parentNode) target.parentNode.appendChild(self.mainSignDiv);
self.adjustSignDiv(self.mainSignDiv, target);
if (e.ctrlKey || e.metaKey) {
clearTimeout(cleanTimer);
cleanTimer = setTimeout(() => {
let target = self.cleanTarget(e.target);
clickTarget(target);
}, 5);
}
}
};
this.leaveHandler = e => {
if (self.mainSignDiv.parentNode) self.mainSignDiv.parentNode.removeChild(self.mainSignDiv);
};
this.clickHandler = e => {
if (self.inPicker) {
e.stopPropagation();
e.preventDefault();
}
if (self.creatingRect) return;
if (self.rectSelecting) {
if (self.selectRect.parentNode) {
self.selectRect.parentNode.removeChild(self.selectRect);
}
self.rectSelecting = false;
searchBar.bar.classList.remove("rectSelecting");
return;
}
let target = self.getTarget(e.target);
clickTarget(target);
};
this.mouseDownHandler = e => {
self.rectSelecting = true;
searchBar.bar.classList.add("rectSelecting");
self.rectInitPos = {x: e.clientX, y: e.clientY};
e.stopPropagation();
e.preventDefault();
};
this.mouseUpHandler = e => {
self.rectSelecting = false;
searchBar.bar.classList.remove("rectSelecting");
if (self.creatingRect) return;
if (self.selectRect.parentNode) {
self.selectRect.parentNode.removeChild(self.selectRect);
self.finishSelectRect();
e && e.stopPropagation && e.stopPropagation();
e && e.preventDefault && e.preventDefault();
}
};
this.wheelHandler = e => {
e.preventDefault();
e.stopPropagation();
if (self.wheelScrolling) return;
self.wheelScrolling = true;
setTimeout(() => {
self.wheelScrolling = false;
}, 100);
let deltaY;
if(e.type !== 'wheel'){
let y = 0;
if (typeof e.axis == 'number') {
if (e.axis == 2) {
y = e.detail;
}
} else {
if (typeof e.wheelDeltaY == 'undefined' || e.wheelDeltaY != 0) {
y = -e.wheelDelta / 40;
}
};
deltaY = y;
} else {
deltaY = e.deltaY;
}
if (deltaY > 0) self.accu--;
else self.accu++;
if (self.accu < 0) self.accu = 0;
else if (self.accu > 8) self.accu = 8;
let target = self.getTarget(e.target);
if (self.mainSignDiv.parentNode !== target.parentNode) target.parentNode.appendChild(self.mainSignDiv);
self.adjustSignDiv(self.mainSignDiv, target);
};
}
initSelectRect() {
this.waitToRemoveSigns = [];
this.waitToAddSigns = [];
let selectRect = document.createElement("div");
selectRect.innerHTML = createHTML(`
<div class="dot top-left"></div>
<div class="dot top-right"></div>
<div class="dot bottom-left"></div>
<div class="dot bottom-right"></div>
<div class="dot top"></div>
<div class="dot right"></div>
<div class="dot left"></div>
<div class="dot bottom"></div>
`);
selectRect.className = "select-rect";
this.selectRect = selectRect;
}
createSelectRect(pos) {
this.rectToPos = pos;
if (this.creatingRect) return;
this.creatingRect = true;
setTimeout(() => {
this.creatingRect = false;
this.selectRect.style.left = Math.min(this.rectToPos.x, this.rectInitPos.x) + "px";
this.selectRect.style.top = Math.min(this.rectToPos.y, this.rectInitPos.y) + "px";
this.selectRect.style.width = Math.abs(this.rectToPos.x - this.rectInitPos.x) + "px";
this.selectRect.style.height = Math.abs(this.rectToPos.y - this.rectInitPos.y) + "px";
this.checkRectAndSign();
if (!this.rectSelecting) this.mouseUpHandler();
}, 100);
}
finishSelectRect() {
let self = this;
this.waitToRemoveSigns.forEach(sign => {
self.removeSign(sign);
});
this.waitToAddSigns.forEach(sign => {
delete sign.dataset.recttemp;
});
this.waitToRemoveSigns = [];
this.waitToAddSigns = [];
if (this.signList.length) {
searchBar.con.classList.add("selectedEle");
} else {
searchBar.con.classList.remove("selectedEle");
}
}
checkRectAndSign() {
if (!this.domInfo) return;
let self = this;
this.waitToRemoveSigns.forEach(sign => {
sign.style.opacity = "";
});
this.waitToRemoveSigns = [];
this.signList.forEach(signArr => {
let sign = signArr[0];
if (sign.dataset.recttemp) return;
let signRect = sign.getBoundingClientRect();
let curRect = self.selectRect.getBoundingClientRect();
if (self.compareRect(signRect, curRect)) {
sign.style.opacity = "0";
self.waitToRemoveSigns.push(sign);
} else {
sign.style.opacity = "";
}
});
this.waitToAddSigns.forEach(sign => {
self.removeSign(sign);
});
this.waitToAddSigns = [];
if (this.waitToRemoveSigns.length === 0) {
this.curRectInfo = {};
if (this.rectInitPos.x < this.rectToPos.x) {
this.curRectInfo.left = this.rectInitPos.x;
this.curRectInfo.right = this.rectToPos.x;
} else {
this.curRectInfo.left = this.rectToPos.x;
this.curRectInfo.right = this.rectInitPos.x;
}
if (this.rectInitPos.y < this.rectToPos.y) {
this.curRectInfo.top = this.rectInitPos.y;
this.curRectInfo.bottom = this.rectToPos.y;
} else {
this.curRectInfo.top = this.rectToPos.y;
this.curRectInfo.bottom = this.rectInitPos.y;
}
this.compareDomWithRect(this.domInfo);
this.signDomWithRect(this.domInfo);
}
}
compareDomWithRect(dom) {
if (dom.children && dom.children.length > 0) {
let matched = 0;
for (let i = 0; i < dom.children.length; i++) {
let child = dom.children[i];
if (this.compareDomWithRect(child)) {
matched++;
}
}
if (matched === dom.children.length) {
let rect = dom.target.getBoundingClientRect();
if (rect.width && rect.height) {
dom.sign = true;
return true;
}
}
} else {
if (this.compareRect(this.curRectInfo, dom.target.getBoundingClientRect())) {
dom.sign = true;
return true;
}
}
dom.sign = false;
return false;
}
signDomWithRect(dom) {
if (dom.sign) {
let sign = this.createSignDiv();
sign.dataset.recttemp = 1;
dom.target.parentNode.appendChild(sign);
this.adjustSignDiv(sign, dom.target);
this.signList.push([sign, dom.target]);
this.waitToAddSigns.push(sign);
} else if (dom.children && dom.children.length > 0) {
for (let i = 0; i < dom.children.length; i++) {
let child = dom.children[i];
this.signDomWithRect(child);
}
}
}
compareRect(rect1, rect2) {
return (
rect2.width &&
rect2.height &&
rect1.left <= rect2.right &&
rect1.right >= rect2.left &&
rect1.top <= rect2.bottom &&
rect1.bottom >= rect2.top
);
}
cleanTarget(target) {
if (!target || target.className == "searchJumperSign") return null;
target = this.getTarget(target);
if (!target) return null;
for (let i in this.clickedEles) {
let clickedEle = this.clickedEles[i];
try {
if (clickedEle == target || clickedEle.contains(target) || target.contains(clickedEle)) return null;
} catch (e) {
return null;
}
}
return target;
}
appendSign(sign, target, index) {
if (target.dataset) {
target.dataset.signNum = parseInt(target.dataset.signNum || 0) + 1;
}
sign.dataset.target = index;
target.parentNode.appendChild(sign);
this.adjustSignDiv(sign, target);
this.signList.push([sign, target]);
}
removeSign(sign) {
if (sign.parentNode) sign.parentNode.removeChild(sign);
for (let i = 0; i < this.signList.length; i++) {
let signArr = this.signList[i];
if (signArr[0] === sign) {
this.signList.splice(i, 1);
break;
}
}
let targetIndex = sign.dataset.target;
let target = this.clickedEles[targetIndex];
if (!target) return;
let signNum = parseInt(target.dataset.signNum || 0) - 1;
target.dataset.signNum = signNum;
if (signNum <= 0) {
delete this.clickedEles[targetIndex];
}
}
getTarget(ele) {
let accu = this.accu;
while (ele && accu) {
let parentNode = ele.parentNode;
if (!parentNode) break;
ele = parentNode;
accu--;
}
while (ele.parentNode && (ele.offsetWidth === 0 || ele.offsetHeight === 0)) {
ele = ele.parentNode;
}
return ele;
}
close() {
if (!this.mainSignDiv) return;
if (this.rectSelecting) {
if (this.selectRect.parentNode) {
this.selectRect.parentNode.removeChild(this.selectRect);
}
this.finishSelectRect();
this.rectSelecting = false;
}
this.callback = null;
this.domInfo = null;
this.clearSigns();
this.clickedEles = {};
if (this.mainSignDiv.parentNode) this.mainSignDiv.parentNode.removeChild(this.mainSignDiv);
getBody(document).classList.remove("searchJumper-picker");
searchBar.con.classList.remove("selectedEle");
searchBar.con.removeEventListener("mouseenter", this.leaveHandler, true);
getBody(document).removeEventListener("mousemove", this.moveHandler, true);
getBody(document).removeEventListener("click", this.clickHandler, true);
getBody(document).removeEventListener("mousedown", this.mouseDownHandler, true);
getBody(document).removeEventListener("mouseup", this.mouseUpHandler, true);
getBody(document).removeEventListener(getSupportWheelEventName(), this.wheelHandler, { passive: false, capture: true });
this.inPicker = false;
}
setImportant(ele, prop, value) {
ele.style.setProperty(prop, value, "important");
}
createSignDiv() {
let signDiv = document.createElement("div");
this.setImportant(signDiv, "position", "absolute");
this.setImportant(signDiv, "z-index", "2147483647");
this.setImportant(signDiv, "background", "rgba(120, 170, 210, 0.6)");
this.setImportant(signDiv, "transition", "all 0.15s ease-out");
this.setImportant(signDiv, "box-shadow", "rgb(0 0 0) 0px 0px 3px 0px");
this.setImportant(signDiv, "cursor", "pointer");
signDiv.className = "searchJumperSign";
signDiv.addEventListener("mouseenter", e => {
if (this.mainSignDiv.parentNode) this.mainSignDiv.parentNode.removeChild(this.mainSignDiv);
}, true);
signDiv.addEventListener("mousedown", e => {
e.stopPropagation();
e.preventDefault();
this.removeSign(signDiv);
}, true);
return signDiv;
}
adjustSignDiv(div, target) {
this.setImportant(div, "width", target.offsetWidth + "px");
this.setImportant(div, "height", target.offsetHeight + "px");
let left = target.offsetLeft;
let top = target.offsetTop;
if (target.offsetParent && div.offsetParent && target.offsetParent !== div.offsetParent) {
let rect1 = div.offsetParent.getBoundingClientRect();
let rect2 = target.offsetParent.getBoundingClientRect();
left += rect2.left - rect1.left;
top += rect2.top - rect1.top;
}
this.setImportant(div, "left", left + "px");
this.setImportant(div, "top", top + "px");
}
geneSelector(ele, id) {
let selector = ele.nodeName.toLowerCase();
if (selector !== "html" && selector !== "body") {
if (id && ele.id && /^[a-z\-_][\w\-_]+$/i.test(ele.id)) selector = '#' + ele.id;
else {
if (ele.className) {
let classLen = ele.classList.length;
selector += [].map.call(ele.classList, d => /^[a-z][\w]+$/i.test(d) || (classLen < 3 && /^[a-z\-_][\w\-_]+$/i.test(d)) ? ('.' + d) : "").join('');
}
let parent = ele.parentElement;
if (parent) {
selector = this.geneSelector(parent, !!id) + ' > ' + selector;
if (id && parent.children.length > 1 && !/^HTML$/i.test(parent.nodeName)) {
let i, nth = 0, all = 0;
for (i = 0; i < parent.children.length; i++) {
if (parent.children[i].nodeName == ele.nodeName) {
all++;
if (parent.children[i] == ele) {
nth = all;
}
if (nth > 0 && all > 1) break;
}
}
selector += (all == 1 ? "" : `:nth-of-type(${nth})`);
}
}
}
}
return selector;
}
copy() {
let self = this;
let html = "", text = "";
this.signList.forEach(sign => {
text += "\n" + sign[1].innerText;
html += sign[1].outerHTML;
});
text = text.trim();
const htmlData = new Blob([html], {type: 'text/html'})
const textData = new Blob([text], {type: 'text/plain'})
try {
const item = new ClipboardItem({'text/html': htmlData, 'text/plain': textData});
navigator.clipboard.write([item]).then(
() => {
_GM_notification('Copied successfully!');
},
(e) => {
_GM_setClipboard(text);
console.log(e);
}
);
} catch(e) {
_GM_setClipboard(text);
}
}
openLinks() {
if (!window.confirm(i18n('batchOpenConfirm'))) return;
let links = [];
this.signList.forEach(sign => {
let ele = sign[1];
if (ele.href) {
if (/^(http|ftp)/i.test(ele.href) && links.indexOf(ele.href) === -1) {
links.push(ele.href);
}
} else if (ele.parentNode && ele.parentNode.href) {
if (/^(http|ftp)/i.test(ele.parentNode.href) && links.indexOf(ele.parentNode.href) === -1) {
links.push(ele.parentNode.href);
}
} else if (ele.querySelectorAll) {
[].forEach.call(ele.querySelectorAll('a[href]'), a => {
if (/^(http|ftp)/i.test(a.href) && links.indexOf(a.href) === -1) {
links.push(a.href);
}
});
}
});
links.forEach(link => {
_GM_openInTab(link, {active: false, insert: true});
});
}
getPickerStr() {
if (!this.inPicker) return "";
let resultStr = "";
this.signList.forEach(sign => {
resultStr += "\n" + sign[1].innerText;
});
return resultStr.trim();
}
expand() {
let self = this;
this.clearSigns();
Object.keys(this.clickedEles).forEach(index => {
let target = self.clickedEles[index];
let sel = self.geneSelector(target);
target.dataset.signNum = 0;
[].forEach.call(document.querySelectorAll(sel), ele => {
let sign = self.createSignDiv();
getBody(document).appendChild(sign);
self.appendSign(sign, ele, index);
});
});
}
collapse() {
let self = this;
this.clearSigns();
Object.keys(this.clickedEles).forEach(index => {
let target = self.clickedEles[index];
target.dataset.signNum = 0;
let sign = self.createSignDiv();
getBody(document).appendChild(sign);
self.appendSign(sign, target, index);
});
}
clearSigns() {
this.signList.forEach(sign => {
sign = sign[0];
if (sign.parentNode) sign.parentNode.removeChild(sign);
});
this.signList = [];
}
processNode(node, parent) {
const nodeInfo = {};
nodeInfo.target = node;
nodeInfo.children = [];
if (node.nodeType === Node.ELEMENT_NODE) {
const style = window.getComputedStyle(node);
if (style.display === 'none' && style.visibility === 'hidden') return null;
if (node.innerHTML.trim() === "") return null;
} else if (node.nodeType !== Node.TEXT_NODE || node.textContent.trim() === "") {
return null;
}
const childNodes = node.childNodes;
if (childNodes.length > 0) {
nodeInfo.target = node;
parent.children.push(nodeInfo);
for (const childNode of childNodes) {
if (childNode.nodeType === Node.ELEMENT_NODE || childNode.nodeType === Node.TEXT_NODE) {
this.processNode(childNode, nodeInfo);
}
}
} else {
if (node.nodeType === Node.TEXT_NODE) {
const lines = node.textContent.split("\n");
const range = document.createRange();
range.selectNodeContents(node);
let offset = 0;
let parentNode = node.parentNode;
let paRect = parentNode.getBoundingClientRect();
for (const line of lines) {
if (line.trim() === '') {
offset += (line.length + 1);
continue;
}
range.setStart(node, offset);
offset += line.length;
range.setEnd(node, offset);
offset++;
const lineRect = range.getBoundingClientRect();
let offsetLeft = lineRect.left - paRect.left;
let offsetTop = lineRect.top - paRect.top;
let offsetWidth = lineRect.width;
let offsetHeight = lineRect.height;
let textNodeInfo = {
target: {innerText: line,
outerHTML: line,
parentNode: parentNode,
offsetLeft: offsetLeft + parentNode.offsetLeft,
offsetTop: offsetTop + parentNode.offsetTop,
offsetWidth: offsetWidth,
offsetHeight: offsetHeight,
getBoundingClientRect: () => {
let paRect = parentNode.getBoundingClientRect();
return {
left: paRect.left + offsetLeft,
top: paRect.top + offsetTop,
right: paRect.left + offsetLeft + offsetWidth,
bottom: paRect.top + offsetTop + offsetHeight,
width: offsetWidth,
height: offsetHeight,
};
}}
};
parent.children.push(textNodeInfo);
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
nodeInfo.target = node;
parent.children.push(nodeInfo);
}
}
return nodeInfo;
}
toggle(rectSel) {
this.init();
if (this.inPicker) {
this.close();
return;
}
this.rectSel = !!rectSel;
if (rectSel) {
this.domInfo = this.processNode(getBody(document), {children: []});
getBody(document).addEventListener("mousedown", this.mouseDownHandler, true);
getBody(document).addEventListener("mouseup", this.mouseUpHandler, true);
} else {
getBody(document).addEventListener(getSupportWheelEventName(), this.wheelHandler, { passive: false, capture: true });
}
this.accu = 0;
this.inPicker = true;
getBody(document).classList.add("searchJumper-picker");
searchBar.con.addEventListener("mouseenter", this.leaveHandler, true);
getBody(document).addEventListener("mousemove", this.moveHandler, true);
getBody(document).addEventListener("click", this.clickHandler, true);
}
}
const picker = new Picker();
function emuPress(v) {
if (!targetElement) return;
let eventParam = v || { key: "Enter", keyCode: 13, bubbles: true };
let event = new KeyboardEvent('keydown', eventParam);
targetElement.dispatchEvent(event);
event = new KeyboardEvent('keyup', eventParam);
targetElement.dispatchEvent(event);
event = new KeyboardEvent('keypress', eventParam);
targetElement.dispatchEvent(event);
debug(targetElement, `press ${v || 'Enter'}`);
}
async function waitForElement(sel) {
return new Promise((resolve) => {
let checkInv = setInterval(() => {
let result = null;
if (!sel) {
result = document.readyState === "complete";
} else if (sel === "@") {
result = targetElement;
} else result = getElement(sel);
if (result === false) return null;
if (result) {
clearInterval(checkInv);
resolve(result);
}
}, 100);
});
}
async function waitForElementHide(sel) {
if (!sel) return null;
return new Promise((resolve) => {
let checkInv = setInterval(() => {
let result = getElement(sel);
if (!result) {
clearInterval(checkInv);
resolve(null);
}
}, 100);
});
}
let reachLast = false;
async function startInput(input, v) {
if (!input) return true;
targetElement = input;
let event = new FocusEvent('focusin', { bubbles: true });
input.dispatchEvent(event);
event = new Event('focus', { bubbles: true });
input.dispatchEvent(event);
const selection = window.getSelection();
const range = selection.rangeCount ? selection.getRangeAt(0) : new Range();
range.selectNode(input);
selection.removeAllRanges();
selection.addRange(range);
await sleep(1);
input.type !== 'file' && input.click && input.click();
let lastValue = input.value;
if (input.type == 'file') {
let file = v;
if (file.indexOf('data:') == 0) {
file = dataURLtoFile(file);
} else {
let blob = new Blob([file], {
type: 'text/plain'
});
file = new File([blob], 'noname.txt', { type: blob.type })
}
let dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
input.files = dataTransfer.files;
v = "c:/fakepath/fakefile";
} else if (/INPUT/i.test(input.nodeName)) {
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, v);
} else if (/SELECT/i.test(input.nodeName)) {
var nativeSelectValueSetter = Object.getOwnPropertyDescriptor(window.HTMLSelectElement.prototype, "value").set;
nativeSelectValueSetter.call(input, v);
} else if (input.nodeName.toUpperCase() == "TEXTAREA") {
var nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
nativeTextareaValueSetter.call(input, v);
} else {
let contentEditableParent = input;
while (contentEditableParent && contentEditableParent.contentEditable !== 'true') {
contentEditableParent = contentEditableParent.parentNode;
}
if (contentEditableParent) {
contentEditableParent.dispatchEvent(new InputEvent('beforeinput', {inputType: "insertText", data: v}));
await sleep(1);
if (input.innerText !== v) {
input.innerHTML = createHTML(v);
}
} else {
let file = v;
if (file.indexOf('data:') == 0) {
file = dataURLtoFile(file);
} else {
let blob = new Blob([file], {
type: 'text/plain'
});
file = new File([blob], 'noname.txt', { type: blob.type })
}
var pasteEvent = new ClipboardEvent('paste', {
target: document.body,
clipboardData: new DataTransfer()
});
pasteEvent.clipboardData.items.add(file);
input.dispatchEvent(pasteEvent);
}
}
event = new Event('input', { bubbles: true });
let tracker = input._valueTracker;
if (tracker) {
tracker.setValue(lastValue);
}
input.dispatchEvent(event);
event = new Event('change', { bubbles: true });
input.dispatchEvent(event);
debug(input, `input`);
}
async function returnElement(sel, eleIndex = -1) {
reachLast = false;
let ele;
if (eleIndex >= 0) {
if (eleIndex === 0) await waitForElement(sel);
let eles = getAllElements(sel);
if (eles.length === 0) {
return true;
}
if (eles.length === 1) {
ele = eles[0];
reachLast = true;
} else if (eles.length <= eleIndex) {
return true;
} else {
ele = eles[eleIndex];
if (eles.length === eleIndex + 1) {
reachLast = true;
}
}
} else {
ele = await waitForElement(sel);
if (!ele) return true;
}
return ele;
}
async function emuInput(sel, v, eleIndex = -1) {
let input = await returnElement(sel, eleIndex);
if (input === true) return true;
await startInput(input, v);
return reachLast;
}
async function emuClick(sel, eleIndex = -1) {
let btn = await returnElement(sel, eleIndex);
if (btn === true) return true;
targetElement = btn;
if(!PointerEvent) return btn.click();
let eventParam = {
isTrusted: true,
altKey: false,
azimuthAngle: 0,
bubbles: true,
button: 0,
buttons: 0,
clientX: 1,
clientY: 1,
cancelBubble: false,
cancelable: true,
composed: true,
ctrlKey: false,
defaultPrevented: false,
detail: 1,
eventPhase: 2,
fromElement: null,
height: 1,
isPrimary: false,
metaKey: false,
pointerId: 1,
pointerType: "mouse",
pressure: 0,
relatedTarget: null,
returnValue: true,
shiftKey: false,
toElement: null,
twist: 0,
which: 1
};
btn.focus();
var mouseEvent = new PointerEvent("mouseover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mousedown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerdown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mouseup",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerup",eventParam);
btn.dispatchEvent(mouseEvent);
let dispatchTouchEvent = (ele, type) => {
let touchEvent;
try {
touchEvent = document.createEvent('TouchEvent')
touchEvent.initTouchEvent(type, true, true)
} catch (err) {
try {
touchEvent = document.createEvent('UIEvent')
touchEvent.initUIEvent(type, true, true)
} catch (err) {
touchEvent = document.createEvent('Event')
touchEvent.initEvent(type, true, true)
}
}
try {
touchEvent.targetTouches = [{
pageX: 1,
pageY: 1,
clientX: 1,
clientY: 1,
target: btn
}];
touchEvent.touches = [{
pageX: 1,
pageY: 1,
clientX: 1,
clientY: 1,
target: btn
}];
touchEvent.changedTouches = [{
pageX: 1,
pageY: 1,
clientX: 1,
clientY: 1,
target: btn
}];
} catch (err) {}
ele.dispatchEvent(touchEvent);
}
dispatchTouchEvent(btn, "touchstart");
dispatchTouchEvent(btn, "touchend");
btn.click();
debug(btn, `click ${sel}`);
return reachLast;
}
async function emuDblClick(sel, eleIndex = -1) {
let btn = await returnElement(sel, eleIndex);
if (btn === true) return true;
targetElement = btn;
let eventParam = {
isTrusted: true,
altKey: false,
azimuthAngle: 0,
bubbles: true,
button: 0,
buttons: 0,
clientX: 1,
clientY: 1,
cancelBubble: false,
cancelable: true,
composed: true,
ctrlKey: false,
defaultPrevented: false,
detail: 2,
eventPhase: 2,
fromElement: null,
height: 1,
isPrimary: false,
metaKey: false,
pointerId: 1,
pointerType: "mouse",
pressure: 0,
relatedTarget: null,
returnValue: true,
shiftKey: false,
toElement: null,
twist: 0,
which: 1
};
btn.focus();
var mouseEvent = new PointerEvent("mouseover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mousedown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerdown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mouseup",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerup",eventParam);
btn.dispatchEvent(mouseEvent);
btn.click();
btn.click();
mouseEvent = new MouseEvent("dblclick", {
...eventParam,
view: _unsafeWindow
});
btn.dispatchEvent(mouseEvent);
debug(btn, `dblclick ${sel}`);
return reachLast;
}
async function emuRClick(sel, eleIndex = -1) {
let btn = await returnElement(sel, eleIndex);
if (btn === true) return true;
targetElement = btn;
let eventParam = {
isTrusted: true,
altKey: false,
azimuthAngle: 0,
bubbles: true,
button: 2,
buttons: 0,
clientX: 1,
clientY: 1,
cancelBubble: false,
cancelable: true,
composed: true,
ctrlKey: false,
defaultPrevented: false,
detail: 0,
eventPhase: 2,
fromElement: null,
height: 1,
isPrimary: false,
metaKey: false,
pointerId: 1,
pointerType: "mouse",
pressure: 0,
relatedTarget: null,
returnValue: true,
shiftKey: false,
toElement: null,
twist: 0,
which: 3
};
btn.focus();
var mouseEvent = new PointerEvent("mouseover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerover",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mousedown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerdown",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("mouseup",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("pointerup",eventParam);
btn.dispatchEvent(mouseEvent);
mouseEvent = new PointerEvent("contextmenu",eventParam);
btn.dispatchEvent(mouseEvent);
debug(btn, `rclick ${sel}`);
return reachLast;
}
async function triggerPaste(element, value) {
if (!targetElement) return;
targetElement.focus();
if (typeof element.value !== "undefined") {
const startPos = element.selectionStart;
const endPos = element.selectionEnd;
let newValue = element.value.substring(0, startPos) + value + element.value.substring(endPos, element.value.length);
await startInput(element, newValue);
element.selectionStart = startPos + value.length;
element.selectionEnd = startPos + value.length;
} else {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
if (!selection.toString()) {
range.selectNode(element.childNodes.length === 1 ? element.firstChild : element);
}
range.deleteContents();
range.insertNode(document.createTextNode(value));
selection.removeAllRanges();
selection.addRange(range);
}
}
function submitByForm(charset, url, target) {
url = url.replace(/#(j(umpFrom|f)?|from){(.*?)}/, "");
currentFormParams = {charset: charset, url: url, target: target};
if (url.indexOf("#submitBySearchJumper") !== -1) {
currentFormParams = {charset: charset, url: url.replace("#submitBySearchJumper", ""), target: target};
jumpBySearchJumper();
return;
}
const formId ="searchJumper_form";
var form = document.getElementById(formId);
if (!form) {
form = document.createElement("form");
form.id = formId;
form.style.display = "none";
document.documentElement.appendChild(form);
}
var params;
let postBody = url.match(/[:%]p{(.*?)}/);
let targetUrl = url;
if (postBody) {
targetUrl = url.replace(postBody[0], '');
postBody = postBody[1];
form.method = 'post';
params = new URLSearchParams(postBody);
} else {
form.method = 'get';
params = new URLSearchParams(new URL(targetUrl).search);
}
if (charset) {
form.acceptCharset = charset;
}
form.innerHTML = createHTML();
form.target = target;
form.action = targetUrl;
params.forEach((v, k) => {
let input = document.createElement("input");
input.name = k;
input.value = v;
form.appendChild(input);
});
return form.submit();
}
function dataURLtoFile(dataurl) {
try {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--) {
u8arr[n] = bstr.charCodeAt(n);
}
} catch(e) { debug(e); }
let ext = mime.split("/");
ext = ext.length > 1 ? ext[1] : ext[0];
return new File([u8arr], "image." + ext, {type: mime});
}
async function image2Base64(img) {
if (!img) return null;
if (img.dataset.src) {
img.src = img.dataset.src;
}
if (!img.src) return null;
let urlSplit = img.src.split("/");
if (urlSplit[2] == document.domain) {
let imgStyle = getComputedStyle(img);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (img.complete) {
canvas.width = img.naturalWidth || img.width || parseInt(imgStyle.width);
canvas.height = img.naturalHeight || img.height || parseInt(imgStyle.height);
ctx.drawImage(img, 0, 0);
try {
return (canvas.toDataURL("image/png"));
} catch (e) {
return await imageSrc2Base64(img.src);
}
} else {
return await new Promise((resolve) => {
img.addEventListener("load", async e => {
canvas.width = img.naturalWidth || img.width || parseInt(imgStyle.width);
canvas.height = img.naturalHeight || img.height || parseInt(imgStyle.height);
ctx.drawImage(img, 0, 0);
try {
resolve(canvas.toDataURL("image/png"));
} catch (e) {
resolve(await imageSrc2Base64(img.src));
}
});
});
}
} else {
return await imageSrc2Base64(img.src);
}
}
async function imageSrc2Base64(src) {
let urlSplit = src.split("/");
return new Promise((resolve) => {
if (ext) {
chrome.runtime.sendMessage({action: "getImgBase64", detail: {img: src}}, function(r) {
resolve(r);
});
} else {
_GM_xmlhttpRequest({
method: 'GET',
url: src,
responseType:'blob',
headers: {
origin: urlSplit[0] + "//" + urlSplit[2],
referer: src,
accept: "*/*"
},
onload: function(d) {
try {
var blob = d.response;
var fr = new FileReader();
fr.readAsDataURL(blob);
fr.onload = function (e) {
resolve(e.target.result);
};
} catch(e) {
resolve(null);
}
},
onerror: function(){
resolve(null);
},
ontimeout: function(){
resolve(null);
}
});
}
});
}
function icon2Base64(icon) {
let iconStyle = getComputedStyle(icon);
let content = getComputedStyle(icon,':before').content.replace(/"/g, '');
if (!content) return false;
var canvas = document.createElement("canvas");
canvas.width = icon.clientWidth || parseInt(iconStyle.lineHeight);
canvas.height = icon.clientHeight || parseInt(iconStyle.lineHeight);
var ctx = canvas.getContext("2d");
ctx.font = iconStyle.font;
ctx.strokeStyle = iconStyle.color || "black";
ctx.fillStyle = iconStyle.color || "black";
ctx.textBaseline = "top";
let metrics = ctx.measureText(content);
ctx.fillText(content, (canvas.width - metrics.width) / 2, (canvas.height - parseInt(iconStyle.fontSize)) / 2);
return canvas.toDataURL("image/png");
}
function cacheFontIcon(icon) {
let iconName = icon.className.trim().replace('fa fa-', '').replace(/ /g, '_');
if (cacheIcon[iconName]) return;
let cache = icon2Base64(icon);
if (cache == 'data:,' || !cache) return;
cacheIcon[iconName] = cache;
storage.setItem("cacheIcon", cacheIcon);
}
async function cacheAction(target) {
if (target.nodeName.toUpperCase() == 'IMG') {
let src = target.src || target.dataset.src;
if (src) {
if (cacheIcon[src]) return;
let cache = await image2Base64(target);
if (cache == 'data:,' || !cache) cache = 'fail';
cacheIcon[src] = cache;
storage.setItem("cacheIcon", cacheIcon);
debug(src + " cached, left " + cachePool.length + " icons");
}
} else {
cacheFontIcon(target);
}
await new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 1);
});
}
async function cachePoolAction() {
while (cachePool.length > 0) {
await cacheAction(cachePool.shift());
}
}
async function cacheImgManager(noti) {
if (searchData.prefConfig.cacheSwitch) {
let needCache = cachePool.length > 0;
await Promise.all([cachePoolAction(), cachePoolAction(), cachePoolAction(), cachePoolAction(), cachePoolAction()]);
if (needCache) {
if (noti) _GM_notification(i18n("cacheOver"));
debug(i18n("cacheOver"));
}
}
}
async function cacheFontManager(noti) {
if (!isAllPage) {
searchBar.con.classList.add("in-input");
searchBar.con.style.visibility = "hidden";
searchBar.con.style.display = "";
searchBar.appendBar();
let needCache = cacheFontPool.length > 0;
while (cacheFontPool.length > 0) {
await cacheAction(cacheFontPool.shift());
}
if (needCache) {
let str = 'All font icons cached!';
debug(str);
}
}
}
function getSelectStr() {
let selStr = extSelectionText || picker.getPickerStr() || window.getSelection().toString();
extSelectionText = "";
if (!selStr) {
let tar = getActiveElement(document);
if (tar && /^(TEXTAREA|INPUT)$/i.test(tar.nodeName)) {
let start = tar.selectionStart;
let finish = tar.selectionEnd;
if (start || finish) selStr = tar.value.substring(start, finish);
}
}
if (selStr) {
selStr = selStr.trim();
if (selStr) {
return selStr;
}
} else {
if (targetElement && targetElement.className === "searchJumper" && /^MARK$/i.test(targetElement.nodeName)) {
return targetElement.dataset.matched || targetElement.innerText;
}
}
return "";
}
function keyToReg(key, sign, more) {
if (!more) {
if (/\w$/.test(key)) {
more = '(\\b|$)';
} else more = '';
}
return new RegExp(key.replace(/([\*\.\?\+\$\^\[\]\(\)\{\}\|\\\/])/g, "\\$1") + more, sign);
}
function replaceSingle(str, key, value, after) {
if (str.indexOf(key + ".replace(/") !== -1) {
let replaceMatch = str.match(keyToReg(key, "", "\\.replace\\(/(.*?[^\\\\])/([gimsuyx]*),\\s*[\"'](.*?[^\\\\])??[\"']\\)"));
if (!replaceMatch) return str.replace(keyToReg(key, "g"), (after ? after(value) : value));
value = value.replace(new RegExp(replaceMatch[1], replaceMatch[2]), replaceMatch[3] || '');
str = str.replace(replaceMatch[0], key);
return replaceSingle(str, key, value, after);
} else {
return str.replace(keyToReg(key, "g"), (after ? after(value.replace(/\$/g, "$$$$")) : value.replace(/\$/g, "$$$$")));
}
}
function getKeywords() {
let selStr = getSelectStr();
if (selStr) {
return selStr;
}
if (!currentSite) return localKeywords || '';
//if (localKeywords === '' && cacheKeywords) return cacheKeywords;
let keywordsMatch, keywords = '', isUtf8 = !currentSite.charset || currentSite.charset == 'UTF-8';
try {
if (currentSite.keywords) {
let rules = currentSite.keywords.split("\n");
for (let i = 0; i < rules.length; i++) {
let rule = rules[i];
if (!rule || !rule.trim()) continue;
let ruleMatch = rules[i].match(/^(.*?)\.replace\(\//);
if (ruleMatch) rule = ruleMatch[1];
if (isUtf8) {
if (/^\w[\w\|]*$/.test(rule)) {
let keywordsList = rule.split("|");
let urlParams = new URLSearchParams(location.search);
for (let i = 0; i < keywordsList.length; i++) {
keywords = urlParams.get(keywordsList[i]);
if (keywords) break;
}
} else if (/\(.+\)/.test(rule) && rule.indexOf("@") !== 0) {
try {
keywordsMatch = href.match(new RegExp(rule));
if (keywordsMatch) {
keywords = keywordsMatch[1];
}
if (keywords) {
keywords = decodeURIComponent(keywords);
}
} catch (e) {
keywords = '';
}
}
}
if (!keywords && getBody(document)) {
try {
let targetEle = getElement(rule);
if (targetEle) {
keywords = targetEle.value || targetEle.innerText;
}
} catch (e) {
keywords = '';
}
}
if (keywords && ruleMatch) {
keywords = replaceSingle(rules[i], rule, keywords);
}
if (keywords) break;
}
} else if (isUtf8 && wordParamReg.test(currentSite.url) && !/[#:%]p{/.test(currentSite.url)) {
if (href.indexOf("?") != -1) {
keywordsMatch = currentSite.url.match(new RegExp(`[\\?&]([^&]*?)=${wordParam}.*`));
if (keywordsMatch) {
keywords = new URLSearchParams(location.search).get(keywordsMatch[1]);
}
}
if (!keywords) {
keywordsMatch = currentSite.url.match(new RegExp(`https?://[^/]*/(.*)${wordParam}`));
if (keywordsMatch) {
keywordsMatch = href.match(new RegExp((keywordsMatch[1].replace(/\?/g, "\\?") || (location.host.replace(/\./g, "\\.") + "/")) + "(.*?)(\/|$)"));
if (keywordsMatch) {
keywords = keywordsMatch[1];
}
if (keywords) {
try {
keywords = decodeURIComponent(keywords);
} catch (e) {
keywords = '';
}
}
}
}
}
if (keywords == '' && getBody(document)) {
let firstInput = getBody(document).querySelector('input[type=text]:not([readonly]),input:not([type])');
if (firstInput) keywords = firstInput.value;
}
if (keywords) localKeywords = keywords;
} catch(e) {
debug(e);
}
return localKeywords || "";//!localKeywords ? cacheKeywords : localKeywords;
}
function eventSupported(eventName, elem) {
elem = elem || document.createElement("div");
eventName = "on" + eventName;
var isSupported = (eventName in elem);
if (!isSupported) {
if (!elem.setAttribute) {
elem = document.createElement("div");
};
var setAttr;
if (!elem.hasAttribute(eventName)) {
setAttr = true;
elem.setAttribute(eventName, "return;");
};
isSupported = typeof elem[eventName] == "function";
if (setAttr) elem.removeAttribute(eventName);
}
return isSupported;
}
function getSupportWheelEventName() {
var ret = 'DOMMouseScroll';
if (eventSupported('wheel')) {
ret = 'wheel';
} else if (eventSupported('mousewheel')) {
ret = 'mousewheel';
}
return ret;
}
let draging = false;
let extSelectionText = "";
function initListener() {
_GM_registerMenuCommand(i18n('settings'), () => {
_GM_openInTab(configPage, {active: true, insert: true});
});
_GM_registerMenuCommand(i18n('searchInPage'), () => {
searchBar.showInPage();
searchBar.showInPageSearch();
});
_GM_registerMenuCommand(i18n('search'), () => {
searchBar.searchAuto(0, {});
});
_GM_registerMenuCommand(i18n('addSearchEngine'), () => {
let openSearch = document.head.querySelector('[rel="search"]');
if (openSearch) {
showSiteAddFromOpenSearch(openSearch.href, (type, e) => {
if (type != 'load') {
if (e) debug(e.statusText || e.error || e.response || e);
let firstInput = getBody(document).querySelector('input[type=text]:not([readonly]),input[type=search]:not([readonly]),input:not([type])') ||
getBody(document).querySelector('textarea');
quickAddByInput(firstInput);
}
});
} else {
let firstInput = getBody(document).querySelector('input[type=text]:not([readonly]),input[type=search]:not([readonly]),input:not([type])') ||
getBody(document).querySelector('textarea');
quickAddByInput(firstInput);
}
});
if (ext) {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.selectionText) extSelectionText = request.selectionText;
let validCommand = false;
switch (request.command) {
case "settings":
validCommand = true;
_GM_openInTab(configPage, {active: true, insert: true});
break;
case "searchInPage":
validCommand = true;
searchBar.showInPage();
searchBar.showInPageSearch();
break;
case "filterSearch":
validCommand = true;
searchBar.showInPage();
searchBar.showFilterSearch();
break;
case "search":
validCommand = true;
if (request.name) {
searchBar.searchBySiteName(request.name, request.key || {});
} else {
searchBar.searchAuto(request.index || 0, request.key || {});
}
break;
case "searchAll":
validCommand = true;
if (request.name) {
searchBar.searcAllhByTypeName(request.name);
}
break;
case "toggle":
validCommand = true;
location.reload();
break;
case "streamUpdate":
validCommand = true;
searchBar.streamUpdate(request.detail);
break;
case "showAll":
validCommand = true;
searchBar.toggleShowAll();
break;
case "addSearchEngine":
{
validCommand = true;
if (shareEngines) return;
let openSearch = document.head.querySelector('[rel="search"]');
if (openSearch) {
showSiteAddFromOpenSearch(openSearch.href, (type, e) => {
if (type != 'load') {
if (e) debug(e.statusText || e.error || e.response || e);
let firstInput = getBody(document).querySelector('input[type=text]:not([readonly]),input[type=search]:not([readonly]),input:not([type])') ||
getBody(document).querySelector('textarea');
quickAddByInput(firstInput);
}
});
} else {
let firstInput = getBody(document).querySelector('input[type=text]:not([readonly]),input[type=search]:not([readonly]),input:not([type])') ||
getBody(document).querySelector('textarea');
quickAddByInput(firstInput);
}
}
break;
default:
break;
}
if (validCommand) {
sendResponse({ msg: "ok" });
}
});
}
document.addEventListener('searchJumper', e => {
switch (e.detail.action) {
case "search":
if (e.detail.name) {
searchBar.searchBySiteName(e.detail.name, e.detail.key || {});
} else {
searchBar.searchAuto(e.detail.index, e.detail.key || {});
}
break;
case "show":
searchBar.setFuncKeyCall(false);
searchBar.showInPage();
if (!searchData.prefConfig.disableInputOnWords || searchBar.inInput || !getSelectStr()) {
searchBar.showSearchInput();
}
break;
case "showAll":
searchBar.appendBar();
searchBar.showAllSites();
break;
}
});
targetElement = getBody(document);
let logoSvg = logoBtn.children[0];
let grabState = 0;//0 未按下 1 已按下 2 已拖动
let hideTimer;
let touchStart = false;
let mouseUpHandler = e => {
clearTimeout(hideTimer);
searchBar.bar.classList.remove("grabbing");
document.removeEventListener('mouseup', mouseUpHandler, false);
document.removeEventListener('mousemove', mouseMoveHandler, false);
document.removeEventListener('touchend', mouseUpHandler, false);
document.removeEventListener('touchmove', mouseMoveHandler, false);
searchBar.bar.style.marginLeft = "";
searchBar.bar.style.marginTop = "";
searchBar.bar.style.transform = "";
if (grabState === 1) {
grabState = 0;
searchBar.showAllSites();
//_GM_openInTab(configPage, {active: true});
return;
}
grabState = 0;
let viewWidth = window.innerWidth || document.documentElement.clientWidth;
let viewHeight = window.innerHeight || document.documentElement.clientHeight;
let baseWidth = viewWidth / 3;
let baseHeight = viewHeight / 3;
let relX, relY, posX, posY;
let curX = clientX(e);
let curY = clientY(e);
if (curX < baseWidth) {
relX = "left";
posX = parseInt(searchBar.bar.style.left) > 0 ? parseInt(searchBar.bar.style.left) : 0;
} else if (curX < baseWidth * 2) {
relX = "center";
posX = parseInt(searchBar.bar.style.left) - viewWidth / 2;
} else {
relX = "right";
posX = viewWidth - parseInt(searchBar.bar.style.left) - searchBar.bar.scrollWidth;
}
if (curY < viewHeight / 2) {
relY = "top";
posY = parseInt(searchBar.bar.style.top);
} else {
relY = "bottom";
posY = viewHeight - parseInt(searchBar.bar.style.top) - searchBar.bar.scrollHeight;
if (posY < 0) {
posY = 0;
}
}
logoSvg.style.cursor = "";
searchBar.closeOpenType();
searchBar.initPos(relX, relY, posX, posY);
storage.setItem("searchData", searchData);
};
let startPos = {x: 0, y: 0};
let mouseMoveHandler = e => {
let curX = clientX(e);
let curY = clientY(e);
if (Math.abs(startPos.x - curX) + Math.abs(startPos.y - curY) < 50) return;
if (grabState === 1) {
clearTimeout(hideTimer);
logoSvg.style.cursor = "grabbing";
searchBar.bar.style.position = "fixed";
searchBar.bar.style.marginLeft = "0";
searchBar.bar.style.marginTop = "0";
searchBar.bar.style.right = "";
searchBar.bar.style.bottom = "";
searchBar.bar.style.transform = "unset";
searchBar.con.classList.remove("search-jumper-scroll");
searchBar.bar.className = "search-jumper-searchBar grabbing";
}
grabState = 2;
searchBar.bar.style.left = curX - searchBar.bar.scrollWidth + 20 + "px";
searchBar.bar.style.top = curY - searchBar.bar.scrollHeight + 20 + "px";
};
logoBtn.oncontextmenu = function (event) {
searchBar.bar.style.display = 'none';
event.preventDefault();
};
logoBtn.addEventListener('mousedown', e => {
if (touchStart) {
touchStart = false;
return;
}
if (e.button === 2) {
if (searchData.prefConfig.resizePage) {
if (typeof searchBar.initBodyStyle != "undefined") getBody(document).style.cssText = searchBar.initBodyStyle;
searchBar.con.classList.remove("resizePage");
}
document.removeEventListener('mouseup', mouseUpHandler, false);
document.removeEventListener('mousemove', mouseMoveHandler, false);
document.removeEventListener('touchend', mouseUpHandler, false);
document.removeEventListener('touchmove', mouseMoveHandler, false);
return;
}
e.preventDefault();
e.stopPropagation();
if (searchBar.inInput || e.button === 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
_GM_openInTab(configPage, {active: true, insert: true});
return;
}
grabState = 1;
startPos = {x: clientX(e), y: clientY(e)};
document.addEventListener('mouseup', mouseUpHandler, false);
setTimeout(() => {
if (grabState === 1) {
document.addEventListener('mousemove', mouseMoveHandler, false);
}
}, 100);
hideTimer = setTimeout(() => {
searchBar.bar.style.display = 'none';
document.removeEventListener('mouseup', mouseUpHandler, false);
document.removeEventListener('mousemove', mouseMoveHandler, false);
}, 2000);
}, false);
logoBtn.addEventListener('touchstart', e => {
e.preventDefault();
e.stopPropagation();
touchStart = true;
grabState = 1;
startPos = {x: clientX(e), y: clientY(e)};
document.addEventListener('touchend', mouseUpHandler, false);
setTimeout(() => {
if (grabState === 1) {
document.addEventListener('touchmove', mouseMoveHandler, false);
}
}, 100);
hideTimer = setTimeout(() => {
searchBar.bar.style.display = 'none';
if (searchData.prefConfig.resizePage) {
if (typeof searchBar.initBodyStyle != "undefined") getBody(document).style.cssText = searchBar.initBodyStyle;
searchBar.con.classList.remove("resizePage");
}
document.removeEventListener('touchend', mouseUpHandler, false);
document.removeEventListener('touchmove', mouseMoveHandler, false);
}, 1500);
}, { passive: false, capture: false });
searchBar.bar.addEventListener(getSupportWheelEventName(), e => {
if (e.target.parentNode && (e.target.parentNode.className == "sitelistCon" ||
(e.target.parentNode.parentNode && e.target.parentNode.parentNode.className == "sitelistCon"))) return;
let targetClassList = searchBar.con.classList;
if (!targetClassList.contains('search-jumper-scroll')) return;
if (targetClassList.contains('search-jumper-left') ||
targetClassList.contains('search-jumper-right')) return;
var deltaX, deltaY;
if(e.type !== 'wheel'){
var x = 0, y = 0;
if (typeof e.axis == 'number') {
if (e.axis == 2) {
y = e.detail;
} else {
x = e.detail;
}
} else {
if (typeof e.wheelDeltaY == 'undefined' || e.wheelDeltaY != 0) {
y = -e.wheelDelta / 40;
} else {
x = -e.wheelDelta / 40;
};
};
deltaY = y;
deltaX = x;
} else {
deltaX = e.deltaX;
deltaY = e.deltaY;
}
e.preventDefault();
e.stopPropagation();
searchBar.con.scrollLeft += deltaY;
}, { passive: false, capture: false });
if (searchData.prefConfig.shortcut &&
(searchData.prefConfig.switchSitesPreKey ||
searchData.prefConfig.switchSitesNextKey ||
searchData.prefConfig.shortcutKey ||
searchData.prefConfig.showAllShortcutKey)) {
let inputing = -1, key = false;
let checkShortcutEnable = (e, _alt, _ctrl, _shift, _meta, _key) => {
if ((_alt && !e.altKey) ||
(_ctrl && !e.ctrlKey) ||
(_shift && !e.shiftKey) ||
(_meta && !e.metaKey)) {
return false;
}
if (!key) key = (e.key || String.fromCharCode(e.keyCode)).toLowerCase();
if (_key != key && _key != e.code) {
return false;
}
if (!searchData.prefConfig.enableInInput && inputing == -1) {
inputing = 1;
if (!_ctrl && !_alt && !_shift && !_meta && inputActive(document)) return false;
}
inputing = 0;
e.preventDefault();
e.stopPropagation();
return true;
};
document.addEventListener('mouseenter', e => {
if (e.target && !searchBar.contains(e.target)) {
hoverElement = e.target;
}
}, true);
document.addEventListener('keydown', e => {
if (e.target.id === "searchJumperInput") return;
inputing = -1;
key = false;
if (searchData.prefConfig.shortcutKey) {
if (checkShortcutEnable(e, searchData.prefConfig.callBarAlt, searchData.prefConfig.callBarCtrl, searchData.prefConfig.callBarShift, searchData.prefConfig.callBarMeta, searchData.prefConfig.shortcutKey)) {
searchBar.setFuncKeyCall(false);
searchBar.showInPage();
if (!searchData.prefConfig.disableInputOnWords || searchBar.inInput || !getSelectStr()) {
searchBar.showSearchInput();
}
}
}
if (inputing == 1) return;
if (searchData.prefConfig.showAllShortcutKey) {
if (checkShortcutEnable(e, searchData.prefConfig.showAllAlt, searchData.prefConfig.showAllCtrl, searchData.prefConfig.showAllShift, searchData.prefConfig.showAllMeta, searchData.prefConfig.showAllShortcutKey)) {
searchBar.appendBar();
searchBar.showAllSites();
}
}
if (currentSite && searchBar.bar.style.display !== "none") {
if (searchData.prefConfig.switchSitesPreKey) {
if (checkShortcutEnable(e, searchData.prefConfig.switchSitesAlt, searchData.prefConfig.switchSitesCtrl, searchData.prefConfig.switchSitesShift, searchData.prefConfig.switchSitesMeta, searchData.prefConfig.switchSitesPreKey)) {
searchBar.switchSite();
return;
}
}
if (searchData.prefConfig.switchSitesNextKey) {
if (checkShortcutEnable(e, searchData.prefConfig.switchSitesAlt, searchData.prefConfig.switchSitesCtrl, searchData.prefConfig.switchSitesShift, searchData.prefConfig.switchSitesMeta, searchData.prefConfig.switchSitesNextKey)) {
searchBar.switchSite(true);
}
}
}
}, true);
}
let clickHandler;
if (searchData.prefConfig.enableInPage) {
let shown = false;
let showToolbarTimer;
let clientRect;
document.addEventListener('selectionchange', (e) => {
if (searchData.prefConfig.leftMouse || searchData.prefConfig.middleMouse) {
if (window.getSelection().toString()) {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
clientRect = range.getBoundingClientRect();
} else {
clientRect = null;
}
}
});
let waitForMouse = false;
clickHandler = e => {
if (shown) {
e.preventDefault();
}
shown = false;
document.removeEventListener('click', clickHandler, true);
};
function isTargetInput(target) {
let targetInput = false;
if (inputActive(document)) {
targetInput = true;
} else {
let contentEditable = false;
let parent = target;
while (parent) {
contentEditable = parent.contentEditable == 'true';
if (contentEditable || parent.nodeName.toUpperCase() == 'BODY') {
break;
}
parent = parent.parentNode;
}
if (contentEditable) {
targetInput = true;
}
}
return targetInput;
}
let mouseDownHandler = e => {
if ((waitForMouse && e.type === 'mousedown' && e.button === 0) ||
(e.target.classList && e.target.classList.contains('search-jumper-btn')) ||
searchBar.contains(e.target)) {
return;
}
if (searchBar.bar.classList.contains("grabbing")) return;
let targetInput = isTargetInput(e.target);
let inputSign = !searchData.prefConfig.enableInInput && targetInput;
if (inputSign && e.type === 'dblclick') return;
if (searchData.prefConfig.minPopup == 2) {
if (targetInput) {
searchBar.con.classList.add("targetInput");
} else searchBar.con.classList.remove("targetInput");
}
if (e.type === "touchstart") {
if (searchData.prefConfig.selectToShow) {
setTimeout(() => {
if (getSelectStr()) {
searchBar.showInPage(true, e);
} else searchBar.waitForHide(0);
}, 0);
}
return;
}
waitForMouse = true;
setTimeout(() => {
waitForMouse = false;
}, 500);
shown = false;
targetElement = e.target;
searchBar.closePopupWindow();
let matchKey = false;
if ((searchData.prefConfig.altKey ||
searchData.prefConfig.ctrlKey ||
searchData.prefConfig.shiftKey ||
searchData.prefConfig.metaKey) &&
!((searchData.prefConfig.altKey && !e.altKey) ||
(searchData.prefConfig.ctrlKey && !e.ctrlKey) ||
(searchData.prefConfig.shiftKey && !e.shiftKey) ||
(searchData.prefConfig.metaKey && !e.metaKey))) {
matchKey = true;
}
if (!searchData.prefConfig.selectToShow) {
if ((e.button === 0 && !searchData.prefConfig.leftMouse) || (e.button === 1 && !searchData.prefConfig.middleMouse)) {
searchBar.waitForHide(0);
return;
}
}
let startX = e.clientX;
let startY = e.clientY;
let moved = false;
let inpageMouseMoveHandler = e => {
if (Math.abs(startX - e.clientX) + Math.abs(startY - e.clientY) > 2) {
clearTimeout(showToolbarTimer);
document.removeEventListener('mousemove', inpageMouseMoveHandler, true);
e.target.removeEventListener('scroll', scrollHandler);
moved = true;
}
};
let scrollHandler = e => {
clearTimeout(showToolbarTimer);
document.removeEventListener('mousemove', inpageMouseMoveHandler, true);
e.target.removeEventListener('scroll', scrollHandler);
};
let inpageMouseUpHandler = e => {
draging = false;
if (searchBar.contains(e.target) || shown) {
e.preventDefault();
} else {
setTimeout(() => {
if (shown) return;
targetInput = isTargetInput(e.target);
inputSign = !searchData.prefConfig.enableInInput && targetInput;
if (!inputSign && (
(matchKey && e.button === 2) ||
(moved && e.button === 0 && searchData.prefConfig.selectToShow && getSelectStr())
)) {
searchBar.showInPage(true, e);
} else {
waitForMouse = false;
searchBar.waitForHide(0);
}
}, 0);
}
clearTimeout(showToolbarTimer);
document.removeEventListener('mouseup', inpageMouseUpHandler, true);
document.removeEventListener('mousemove', inpageMouseMoveHandler, true);
e.target.removeEventListener('scroll', scrollHandler);
};
if (e.type === 'dblclick') {
if (getSelectStr() !== '') {
shown = true;
draging = false;
document.removeEventListener('mouseup', inpageMouseUpHandler, true);
document.removeEventListener('mousemove', inpageMouseMoveHandler, true);
e.target.removeEventListener('scroll', scrollHandler);
clearTimeout(showToolbarTimer);
setTimeout(() => {//wait for triple click
searchBar.showInPage(true, e);
}, 200);
}
return;
}
if (showToolbarTimer) clearTimeout(showToolbarTimer);
showToolbarTimer = setTimeout(() => {
if (draging) return;
if (targetElement != e.target) return;
if (e.button === 1 && !searchData.prefConfig.middleMouse) return;
if (e.button === 2 && !searchData.prefConfig.rightMouse) return;
if (e.button === 0 && !searchData.prefConfig.leftMouse) return;
//if (e.button === 0 && getSelectStr() !== '') return;
if (searchData.prefConfig.longPressTile) {
searchBar.showInPage(true, e);
} else {
searchBar.setFuncKeyCall(false);
searchBar.showInPage();
}
shown = true;
}, parseInt(searchData.prefConfig.longPressTime));
let canShow = false;
if (e.button === 2) {
if (matchKey) {
canShow = true;
}
} else {
if (e.button === 0) {
if (searchData.prefConfig.leftMouse) {
canShow = true;
}
} else if (e.button === 1) {
if (searchData.prefConfig.middleMouse) {
canShow = true;
}
}
if (canShow) {
if (inputSign) {
canShow = false;
} else if (!clientRect) {
canShow = false;
} else if (e.clientX < clientRect.left) {
canShow = false;
} else if (e.clientX > clientRect.left + clientRect.width) {
canShow = false;
} else if (e.clientY < clientRect.top) {
canShow = false;
} else if (e.clientY > clientRect.top + clientRect.height) {
canShow = false;
}
}
}
if (canShow) {
setTimeout(() => {
if (!draging) {
searchBar.showInPage(true, e);
}
document.removeEventListener('mousemove', inpageMouseMoveHandler, true);
e.target.removeEventListener('scroll', scrollHandler);
}, 200);
shown = true;
document.addEventListener('mouseup', inpageMouseUpHandler, true);
document.addEventListener('click', clickHandler, true);
return false;
}
document.addEventListener('mousemove', inpageMouseMoveHandler, true);
document.addEventListener('mouseup', inpageMouseUpHandler, true);
e.target.addEventListener('scroll', scrollHandler);
};
document.addEventListener('mousedown', mouseDownHandler);
document.addEventListener('dblclick', mouseDownHandler);
if (searchData.prefConfig.selectToShow) {
let touchTimer, touchstartEvent;
let selectionchange = e => {
clearTimeout(touchTimer);
touchTimer = setTimeout(() => {
if (window.getSelection().toString()) {
mouseDownHandler(touchstartEvent);
document.removeEventListener('selectionchange', selectionchange);
}
}, 300);
};
document.addEventListener('touchstart', e => {
if (e.isTrusted === false) return;
touchstartEvent = e;
document.addEventListener('selectionchange', selectionchange);
});
}
document.addEventListener('contextmenu', e => {
if (shown) e.preventDefault();
shown = false;
});
}
if (searchData.prefConfig.dragToSearch && !isInConfigPage) {
getBody(document).addEventListener('dragstart', e => {
if (!e.isTrusted ||
(searchData.prefConfig.dragAlt && !e.altKey) ||
(searchData.prefConfig.dragCtrl && !e.ctrlKey) ||
(searchData.prefConfig.dragShift && !e.shiftKey) ||
(searchData.prefConfig.dragMeta && !e.metaKey)) {
return;
}
if (!searchData.prefConfig.enableInInput && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey && inputActive(document)) {
return;
}
targetElement = e.target;
if (targetElement.nodeType !== 1) targetElement = targetElement.parentNode;
if (targetElement.shadowRoot) {
targetElement = targetElement.shadowRoot.activeElement || targetElement;
}
if (targetElement.getAttribute && targetElement.getAttribute("draggable") == "true") return;
if (targetElement.parentNode && targetElement.parentNode.getAttribute && targetElement.parentNode.getAttribute("draggable") == "true") return;
searchBar.waitForHide(0);
setTimeout(() => {
showDragSearch(e.clientX, e.clientY);
}, 2);
if (clickHandler) document.removeEventListener('click', clickHandler, true);
draging = true;
});
}
if (searchData.prefConfig.quickAddRule) {
document.addEventListener('click', e => {
if (!(((e.ctrlKey || e.metaKey) && e.shiftKey) || ((e.ctrlKey || e.metaKey) && e.altKey) || (e.altKey && e.shiftKey))) return;
if (!/^(INPUT|TEXTAREA)$/i.test(e.target.nodeName)) return;
if (/^INPUT$/i.test(e.target.nodeName) && e.target.type && e.target.type != 'text' && e.target.type != 'search') return;
quickAddByInput(e.target);
}, true);
}
let changeHandler = e => {
setTimeout(() => {
searchBar.refresh();
}, 100);
}
document.addEventListener("fullscreenchange", e => {
if (document.fullscreenElement) {
searchBar.bar.style.display = 'none';
}
});
let waitForClick = false;
let clickAHandler = e => {
if (waitForClick) return;
waitForClick = true;
setTimeout(() => {
waitForClick = false;
}, 300);
let _t = e.target;
if (currentSite && _t) {
if (_t.nodeName && _t.nodeName.toLowerCase && _t.nodeName.toLowerCase() == 'a') {
searchBar.updateCacheKeywords();
} else {
let _tp = _t.parentNode;
if (_tp && _tp.nodeName && _tp.nodeName.toLowerCase && _tp.nodeName.toLowerCase() == 'a') {
searchBar.updateCacheKeywords();
}
}
}
};
getBody(document).addEventListener("auxclick", clickAHandler, true);
getBody(document).addEventListener("click", clickAHandler, true);
let _wr = function(type) {
var orig = history[type];
return function() {
var rv = orig.apply(this, arguments);
let _href = location.href.slice(0, 500);
if (href != _href) {
href = _href;
var e = new Event('sj_' + type);
e.arguments = arguments;
window.dispatchEvent(e);
}
return rv;
};
};
history.pushState = _wr('pushState');
history.replaceState = _wr('replaceState');
window.addEventListener('sj_pushState', changeHandler);
window.addEventListener('sj_replaceState', changeHandler);
window.addEventListener('yt-navigate-finish', changeHandler);
window.addEventListener("securitypolicyviolation", (e) => {
if (e.violatedDirective === 'form-action') {
jumpBySearchJumper();
}
});
/*let headObserverOptions = {
childList: true
};
let checkCssEle = ele => {
if (ele === mainStyleEle) {
mainStyleEle = _GM_addStyle(cssText);
}
};
let headObserver = new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.removedNodes.length) {
[].forEach.call(mutation.removedNodes, removedNode => {
checkCssEle(removedNode);
});
}
}
});
headObserver.observe(document.head, headObserverOptions);*/
let removeMark = node => searchBar.removeMark(node);
let highlight = (words, node) => searchBar.highlight(words, node);
let appendBar = () => searchBar.appendBar();
let bodyObserverOptions = {
childList: true,
characterData: true,
subtree: true
};
let highlightTimes = 0;
let bodyObserver = new MutationObserver((mutationsList, observer) => {
let lockWords = searchBar.lockWords;
if (lockWords) {
if (searchBar.initHighlight && highlightTimes > 100) return;
for (let mutation of mutationsList) {
if (mutation.type === "characterData") {
let parentNode = mutation.target.parentNode;
if (!parentNode ||
(mutation.target.previousElementSibling && mutation.target.previousElementSibling.className === "searchJumper") ||
(mutation.target.nextElementSibling && mutation.target.nextElementSibling.className === "searchJumper")) {
return;
}
searchBar.checkCharacterData(parentNode);
searchBar.initHighlight && highlightTimes++;
}
if (mutation.removedNodes.length) {
[].forEach.call(mutation.removedNodes, removedNode => {
if (removedNode.nodeType !== 1) return;
if (removedNode.classList && removedNode.classList.contains("searchJumper")) {
removeMark(removedNode);
} else if (removedNode.children.length) {
[].forEach.call(removedNode.querySelectorAll("mark.searchJumper,a.searchJumper,input.searchJumper,textarea.searchJumper"), node => {
removeMark(node);
});
}
});
}
if (mutation.addedNodes.length) {
for (let i = 0; i < mutation.addedNodes.length; i++) {
let addedNode = mutation.addedNodes[i], target;
if (addedNode.nodeType === 1) {
if (/^searchJumper$/.test(addedNode.className)) {
continue;
}
target = addedNode;
} else {
if (addedNode.previousElementSibling && /^searchJumper$/.test(addedNode.previousElementSibling.className)) {
continue;
} else if (addedNode.nextElementSibling && /^searchJumper$/.test(addedNode.nextElementSibling.className)) {
continue;
}
target = addedNode.parentNode;
}
if (target) {
setTimeout(() => {
highlight("insert", target);
}, 0);
searchBar.initHighlight && highlightTimes++;
}
}
}
}
appendBar();
}
});
bodyObserver.observe(getBody(document), bodyObserverOptions);
}
function canonicalUri(src, href) {
if (!src) {
return "";
}
let origin, basePath;
if (!href) {
if (src.charAt(0) == "#") return location.href + src;
if (src.charAt(0) == "?") return location.href.replace(/^([^\?#]+).*/, "$1" + src);
origin = location.protocol + '//' + location.host;
let base = document.querySelector("base");
basePath = base ? base.href : location.href;
} else {
origin = href.replace(/(^https?:\/\/.+)\/[^\/]*$/, "$1");
basePath = href;
}
let url = basePath || origin;
url = url.replace(/(\?|#).*/, "");
if (/https?:\/\/[^\/]+$/.test(url)) url = url + '/';
if (url.indexOf("http") !== 0) url = origin + url;
var root_page = /^[^\?#]*\//.exec(url)[0],
root_domain = /^\w+\:\/\/\/?[^\/]+/.exec(root_page)[0],
absolute_regex = /^\w+\:\/\//;
while (src.indexOf("../") === 0) {
src = src.substr(3);
root_page = root_page.replace(/\/[^\/]+\/$/, "/");
}
src = src.replace(/\.\//, "");
if (/^\/\/\/?/.test(src)) {
src = location.protocol + src;
}
return (absolute_regex.test(src) ? src : ((src.charAt(0) == "/" ? root_domain : root_page) + src));
}
function quickAddByInput(input) {
if (shareEngines) return;
let parentForm, url = location.href;
if (input && input.name) {
parentForm = input.parentNode;
while (parentForm) {
if (parentForm.nodeName.toUpperCase() === "FORM") {
let target = parentForm.target;
if (target && typeof target == "string" && target != '_blank' && target != '_self' && target != '_parent' && target != '_top') {
let targetIframe = getBody(document).querySelector(target);
if (!targetIframe) {
parentForm = null;
break;
}
}
break;
}
parentForm = parentForm.parentNode;
}
}
let fail = () => {
if (window.confirm(i18n("noValidItemAsk"))) {
return false;
}
return true;
}
if (parentForm) {
url = canonicalUri(parentForm.getAttribute("action") || url);
let params = [];
let formData = new FormData(parentForm);
for (let [key, value] of formData) {
if (input.name === key) {
value = "%s";
} else value = encodeURIComponent(value);
params.push(key + "=" + value);
}
if (parentForm.method.toLowerCase() == "post") {
url += "%p{" + params.join("&") + "}";
if (parentForm.action.indexOf(location.origin) == 0 && location.pathname && location.pathname !== "/") url += `#from{${location.pathname.slice(1)}}`;
} else {
let existParams = url.match(/\?(.*)/);
if (existParams) {
url = url.replace(existParams[0], "");
existParams[1].split("&").forEach(existParam => {
let existSplit = existParam.split("=");
let key = existSplit[0];
if (params.findIndex(p => p.indexOf(key + "=") === 0) !== -1) return;
let value = existSplit[1];
if (value == input.value) value = "%s";
params.push(key + "=" + value);
});
}
url += "?" + params.join("&");
}
} else if (input && input.value) {
if (location.href.indexOf(input.value) !== -1) {
url = location.href.replace(input.value, "%s");
} else {
let encodeValue = encodeURIComponent(input.value);
if (location.pathname.indexOf(encodeValue) !== -1 || location.search.indexOf(encodeValue) !== -1) {
url = location.origin + location.pathname.replace(encodeValue, "%s") + location.search.replace(encodeValue, "%s");
} else {
encodeValue = escape && escape(input.value);
if (encodeValue && location.pathname.indexOf(encodeValue) !== -1 || location.search.indexOf(encodeValue) !== -1) {
url = location.origin + location.pathname.replace(encodeValue, "%se") + location.search.replace(encodeValue, "%se");
} else {
if (fail()) return;
}
}
}
} else {
if (fail()) return;
}
let icons = [];
[].forEach.call(document.querySelectorAll("link[rel='shortcut icon'],link[rel='icon'],link[rel='fluid-icon'],link[rel='apple-touch-icon']"), link => {
if (icons.indexOf && icons.indexOf(link.href) !== -1) return;
icons.push(link.href);
});
showSiteAdd(document.title.replace(input ? input.value : "", "").replace(/^\s*[-_]\s*/, ""), "", url, icons, document.characterSet);
}
const jumpHtml = ext ? chrome.runtime.getURL('config/jump.html') : "https://hoothin.github.io/SearchJumper/jump.html";
function jumpBySearchJumper() {
let jumpTo = `${jumpHtml}#jump{url=${encodeURIComponent(currentFormParams.url)}&charset=${currentFormParams.charset}}`;
if (currentFormParams.target == '_self') {
if (ext) {
_GM_openInTab(jumpTo, {active: true, insert: true, close: true});
} else {
location.href = jumpTo;
}
} else {
_GM_openInTab(jumpTo, {active: true, insert: true});
}
}
function preAction() {
if (href.indexOf(jumpHtml) != -1) {
let submitParams = href.match(/#jump{url=(.*)&charset=(.*)}/);
if (submitParams) {
submitByForm(submitParams[2], decodeURIComponent(submitParams[1]), '_self');
}
}
}
var shareEngines;
async function checkConfigPage() {
if (href.indexOf(configPage) === 0 || ((document.title === "SearchJumper" || document.querySelector('[name="from"][content="SearchJumper"]')) && document.querySelector('[name="author"][content="Hoothin"]'))) {
shareEngines = document.querySelector('[name="engines"]');
let spotlight = document.getElementById("spotlight");
if (shareEngines) {
try {
shareEngines = shareEngines.getAttribute("content");
if (shareEngines.indexOf("http") === 0) {
if (spotlight) {
const loadingCollection = i18n("loadingCollection");
spotlight.innerText = loadingCollection;
spotlight.setAttribute("spotlight", loadingCollection);
}
let config = await new Promise((resolve) => {
if (ext) {
chrome.runtime.sendMessage({action: "getShareEngines", detail: {engineUrl: shareEngines}}, function(r) {
resolve(r);
});
} else {
_GM_xmlhttpRequest({
method: 'GET',
url: shareEngines,
onload: function(result) {
var jsonData = null;
try {
jsonData = JSON.parse(result.responseText);
resolve(jsonData);
} catch (e) {
console.log(e);
resolve(false);
}
},
onerror: function(e) {
console.log(e);
resolve(false);
},
ontimeout: function(e) {
console.log(e);
resolve(false);
}
});
}
});
if (config) {
searchData.sitesConfig = config;
shareEngines = true;
} else {
shareEngines = false;
}
} else {
searchData.sitesConfig = JSON.parse(decodeURI(shareEngines));
shareEngines = true;
}
} catch (e) {
shareEngines = false;
}
}
let trustSite = href.indexOf(configPage.replace(/\/config.*/, "")) === 0 || href.indexOf(homePage) === 0 || href.indexOf(githubPage) === 0 || location.hostname === "localhost";
if (trustSite) {
isAllPage = !!shareEngines || /all(\.html)?$/.test(location.pathname);
}
if (spotlight) {
spotlight.style.display = "none";
} else {
setTimeout(() => {
spotlight = document.getElementById("spotlight");
if (spotlight) {
spotlight.style.display = "none";
}
}, 500);
}
return trustSite;
}
return false;
}
async function initConfig() {
isInConfigPage = await checkConfigPage();
if (!isInConfigPage && searchData.webdavConfig) {
webDAV = new WebDAV(searchData.webdavConfig.host + "/SearchJumper" + (searchData.webdavConfig.path || "").replace(/^\/*/, "/").replace(/\/*$/, "/"), searchData.webdavConfig.username, searchData.webdavConfig.password);
}
if (isInConfigPage && !isAllPage) {
let sendMessageTimer, received = false;
let loadConfig = () => {
sendMessageTimer = setTimeout(() => {
if (!received) {
loadConfig();
}
}, 50);
window.postMessage({
searchData: searchData,
cacheIcon: cacheIcon,
version: _GM_info.script.version || 0,
command: 'loadConfig'
}, '*');
}
let delayTimeout = setTimeout(() => {
if (received) return;
location.reload();
}, 3000);
document.addEventListener('received', e => {
received = true;
clearTimeout(sendMessageTimer);
clearTimeout(delayTimeout);
if (cachePool.length > 0 && searchData.prefConfig.cacheSwitch) {
debug(`Start cache ${cachePool.length} icons!`);
cacheImgManager();
}
});
document.addEventListener('downloadCache', e => {
downloadCache();
});
document.addEventListener('importCache', e => {
let cacheData = e.detail ? e.detail.cacheData : e.cacheData;
importCache(cacheData);
_GM_notification('Cache imported successfully!');
});
document.addEventListener('showSiteAdd', e => {
let siteData = e.detail ? e.detail.site : e.site;
if (!siteData) return;
if (siteData.url) {
showSiteAdd(siteData.name, siteData.description, siteData.url, (siteData.icon ? [siteData.icon] : []), siteData.charset, siteData.kwFilter, siteData.match, siteData.hideNotMatch);
} else {
importFilter.open(siteData);
}
});
loadConfig();
document.addEventListener('dataChanged', e => {
loadConfig();
});
let sendVerifyResult = (url, name, status, finalUrl) => {
window.postMessage({
url: url,
name: name,
status: status,
finalUrl: finalUrl,
command: 'verifyResult'
}, '*');
};
document.addEventListener('verifyUrl', e => {
let targetUrl = (e.detail ? e.detail.url : e.url);
let name = (e.detail ? e.detail.name : e.name);
_GM_xmlhttpRequest({
method: 'GET',
url: targetUrl,
headers: {
referer: targetUrl,
'User-Agent': navigator.userAgent
},
onload: function(e) {
sendVerifyResult(targetUrl, name, e && e.status, e && e.finalUrl);
},
onerror: function(e){
sendVerifyResult(targetUrl, name, 'error', '');
},
ontimeout: function(e){
sendVerifyResult(targetUrl, name, 'timeout', '');
}
});
});
let preSwitch = searchData.prefConfig.cacheSwitch;
document.addEventListener('saveConfig', e => {
searchData = (e.detail ? e.detail.searchData : e.searchData) || _unsafeWindow.searchData;
storage.setItem("searchData", searchData);
let newCache = {}, oldCacheLength = cacheIcon ? Object.keys(cacheIcon).length : 0;
if (preSwitch == searchData.prefConfig.cacheSwitch) {
searchData.sitesConfig.forEach(type => {
if (/^[a-z\- ]+$/.test(type.icon || "") || /^http/.test(type.icon)) {
let icon = type.icon.trim().replace(/ /g, '_');
let typeCache = cacheIcon[icon];
if (typeCache) {
newCache[icon] = typeCache;
}
}
type.sites.forEach(site => {
let icon = site.icon;
if (!icon) icon = site.url.replace(/^showTips:/, "").replace(/\?.*/, "").replace(/^(https?:\/\/[^\/]*\/)[\s\S]*$/, "$1favicon.ico");
if (/^http/.test(icon)) {
let siteCache = cacheIcon[icon];
if (siteCache) {
newCache[icon] = siteCache;
}
}
});
});
if (oldCacheLength !== Object.keys(newCache).length) {
cacheIcon = newCache;
storage.setItem("cacheIcon", newCache);
}
} else {
searchData.sitesConfig.forEach(type => {
if (/^http/.test(type.icon)) {
let typeCache = cacheIcon[type.icon];
if (typeCache) {
if (typeCache === 'fail') {
let img = document.createElement("img");
img.src = type.icon;
cachePool.push(img);
} else {
newCache[type.icon] = typeCache;
}
}
}
type.sites.forEach(site => {
let icon = site.icon;
if (!icon) icon = site.url.replace(/^showTips:/, "").replace(/\?.*/, "").replace(/^(https?:\/\/[^\/]*\/)[\s\S]*$/, "$1favicon.ico");
if (/^http/.test(icon)) {
let siteCache = cacheIcon[icon];
if (siteCache) {
if (siteCache === 'fail') {
let img = document.createElement("img");
img.src = icon;
cachePool.push(img);
} else {
newCache[icon] = siteCache;
}
}
}
});
});
storage.setItem("cacheIcon", newCache);
if (searchData.prefConfig.cacheSwitch) {
if (cachePool.length > 0) {
_GM_notification(i18n('startCache'));
cacheImgManager(true);
}
cacheFontManager();
}
}
preSwitch = searchData.prefConfig.cacheSwitch;
if (e.notification || (e.detail && e.detail.notification)) {
_GM_notification('Configuration imported successfully!');
}
});
document.addEventListener('copyConfig', e => {
let copyTarget = searchData.sitesConfig.filter(type => {return type && !(/^BM/.test(type.type) && type.icon === "bookmark")});
_GM_setClipboard(JSON.stringify(copyTarget, null, 2));
_GM_notification('Configuration copied successfully!');
});
} else if (importPageReg.test(href)) {
let importCss = _GM_addStyle(`
#import-btns-con {
position: absolute;
display: block;
font-size: 20px;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
#import-btns-con.hide {
pointer-events: none;
}
#import-btns-con>button {
opacity: 0.5;
}
#import-btns-con>button:hover {
opacity: 0.9;
}
#import-btn {
position: absolute;
display: block;
font-size: 20px;
right: 45px;
top: 45px;
pointer-events: all;
}
#filter-btn {
position: absolute;
display: none;
font-size: 20px;
left: 45px;
top: 45px;
pointer-events: all;
}
.filter>#filter-btn {
display: block;
}
#import-btns-con>h3 {
float: left;
margin-left: 20px;
}
#import-btns-con.hide>h3 {
display: none;
}
`);
let targetPre, ruleType = 0;
let importBtn = document.createElement("button");
importBtn.id = "import-btn";
importBtn.className = "btn Button--secondary Button";
let filterBtn = document.createElement("button");
filterBtn.id = "filter-btn";
filterBtn.className = "btn Button--secondary Button";
let ruleTitle = document.createElement("h3");
let btnsCon = document.createElement("div");
btnsCon.id = "import-btns-con";
btnsCon.appendChild(importCss);
btnsCon.appendChild(importBtn);
btnsCon.appendChild(filterBtn);
btnsCon.appendChild(ruleTitle);
btnsCon.addEventListener("click", e => {
if (targetPre) targetPre.style.filter = "";
btnsCon.classList.add("hide");
});
importBtn.innerText = i18n("import");
importBtn.addEventListener("click", e => {
if (shareEngines) return;
if (!targetPre) return;
let configTxt = targetPre.innerText.trim(), configData;
if (!configTxt) return;
try {
configData = JSON.parse(configTxt);
} catch (e) {
_GM_notification(e.toString());
return;
}
switch (ruleType) {
case 0:
if (window.confirm(i18n("importOrNot"))) {
if (btnsCon.parentNode) {
btnsCon.parentNode.removeChild(btnsCon);
}
dataChanged(() => {
searchData.sitesConfig = configData;
searchData.lastModified = new Date().getTime();
storage.setItem("searchData", searchData);
_GM_notification(i18n("siteAddOver"));
searchBar.refreshEngines();
}, true);
}
break;
case 1:
showSiteAdd(configData.name, "", configData.url, (configData.icon ? [configData.icon] : []), configData.charset, configData.kwFilter, configData.match, configData.hideNotMatch);
break;
case 2:
if (!searchData.prefConfig.inPageRule) searchData.prefConfig.inPageRule = {};
Object.keys(configData).forEach(key => {
let value = configData[key];
if (!value) return;
if (key.indexOf("@") === 0) {
searchData.prefConfig.inPageRule[key] = value;
return;
}
if (!value.words || value.words.length === 0) return;
let pre = "", sep = value.sep || "";
if (sep) {
pre = "$c" + sep;
} else {
sep = " ";
if (value.words.length === 1) {
let onlyWord = value.words[0];
if (onlyWord.indexOf(" ") !== -1) {
sep = "";
pre = "$o";
}
}
}
searchData.prefConfig.inPageRule[key] = pre + value.words.join(sep);
});
storage.setItem("searchData", searchData);
_GM_notification('Over!');
break;
}
});
filterBtn.innerText = i18n("filter");
filterBtn.addEventListener("click", e => {
if (targetPre) {
if (btnsCon.parentNode) {
btnsCon.parentNode.removeChild(btnsCon);
}
let configTxt = targetPre.innerText.trim(), configData;
if (!configTxt || configTxt.indexOf('[') !== 0) return;
try {
configData = JSON.parse(configTxt);
importFilter.open(configData);
} catch (e) {
_GM_notification(e.toString());
}
}
});
let bindPre = target => {
if (target == targetPre && btnsCon.parentNode) return;
let top = target.offsetTop + 'px';
let innerText = target.innerText.trim();
if (!innerText) return;
ruleTitle.innerText = "";
if (/^\[/.test(innerText)) {
ruleType = 0;
btnsCon.style.top = top;
btnsCon.classList.add("filter");
} else if (/^\{\s*"name"/.test(innerText)) {
ruleType = 1;
btnsCon.style.top = top;
btnsCon.classList.remove("filter");
ruleTitle.innerText = innerText.match(/"name":\s*"(.*)"/)[1];
} else if (/^\{/.test(innerText)) {
ruleType = 2;
btnsCon.style.top = top;
btnsCon.classList.remove("filter");
} else return;
if (targetPre) targetPre.style.filter = "";
target.parentNode.appendChild(btnsCon);
target.style.filter = "blur(5px)";
targetPre = target;
btnsCon.classList.remove("hide");
};
window.addEventListener("load", e => {
if (!targetPre) {
let _targetPre = document.querySelector('.highlight>pre');
if (_targetPre) {
bindPre(_targetPre);
}
}
});
document.addEventListener("mouseover", e => {
if (importPageReg.test(href)) {
if (e.target.nodeName === "PRE") {
bindPre(e.target);
} else {
let target = e.target.children[0];
if (target && target.nodeName === "PRE") {
bindPre(target);
}
}
}
});
}
}
class ImportFilter {
//static importFilter;
constructor() {
this.inited = false;
}
/*static getInstance() {
if (!ImportFilter.importFilter) {
ImportFilter.importFilter = new ImportFilter();
}
return ImportFilter.importFilter;
}*/
init() {
if (this.inited) return;
this.inited = true;
let self = this;
this.openList = [];
this.filterCss = `
#searchJumperFilter {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 100000;
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(5px);
transform: translateZ(0);
}
.searchJumperFrame-body {
width: 350px;
text-align: left;
background-color: #ffffff;
border: 1px solid #afb3b6;
border-radius: 10px;
opacity: 0.95;
filter: alpha(opacity=95);
box-shadow: 5px 5px 20px 0px #000;
color: #6e7070;
transition: all 0.25s ease;
border: 0;
font-size: initial;
}
.searchJumperFrame-title {
background: #458bd1!important;
display: flex!important;
align-items: center!important;
justify-content: center!important;
color: white!important;
font-weight: bold;
font-size: 18px!important;
border-radius: 10px 10px 0 0!important;
}
.searchJumperFrame-title>img {
margin: 5px;
height: 32px;
width: 32px;
}
.searchJumperFrame-buttons {
text-align: center;
margin: 5px;
display: flex;
justify-content: space-evenly;
}
.searchJumperFrame-buttons>button {
width: 32%;
font-size: 16px;
cursor: pointer;
border: 1px solid #1976d2;
border-radius: 4px;
transition: all .3s;
color: #fff;
background-color: #458bd1;
line-height: 25px;
padding: 3px;
}
.searchJumperFrame-buttons>button:hover {
color: #e3f2fd;
}
.searchJumperFrame-body>.sitesCon {
max-height: 70vh;
overflow: auto;
width: 100%;
border-top: 1px solid rgba(0, 0, 0, 0.23);
border-bottom: 1px solid rgba(0, 0, 0, 0.23);
padding: 5px;
user-select: none;
white-space: nowrap;
}
.searchJumperFrame-body>.sitesCon>details>summary>span,
.searchJumperFrame-body>.sitesCon>details>div>span {
line-height: 25px;
overflow: hidden;
text-overflow: ellipsis;
max-width: 180px;
display: inline-block;
vertical-align: middle;
}
.searchJumperFrame-body>.sitesCon>details>summary>button {
display: none;
position: absolute;
}
.searchJumperFrame-body>.sitesCon>details>summary:hover>button {
display: inline-block;
}
.searchJumperFrame-body>.sitesCon input {
margin: 2px 5px;
width: 20px;
height: 20px;
vertical-align: sub;
}
.searchJumperFrame-body>.sitesCon div {
margin-left: 32px;
}
.searchJumperFrame-body>.sitesCon div.exist {
text-decoration:line-through;
}
@media (prefers-color-scheme: dark) {
.searchJumperFrame-body,
.searchJumperFrame-input-title,
.searchJumperFrame-inputs>input,
.searchJumperFrame-inputs>textarea,
.searchJumperFrame-inputs>select,
.searchJumperFrame-body select {
background-color: black;
color: #d5d5d5;
}
.searchJumperFrame-title,
.searchJumperFrame-buttons>button {
background: #245d8f!important;
}
}
`;
this.filterCssEle = _GM_addStyle(this.filterCss);
this.filterFrame = document.createElement("div");
this.filterFrame.id = "searchJumperFilter";
this.filterFrame.innerHTML = createHTML(`
<div class="searchJumperFrame-body">
<a href="${configPage}" class="searchJumperFrame-title" target="_blank">
<img onerror="this.style.display='none'" width="32px" height="32px" src="${logoBase64}" />${i18n("addSearchEngine")}
</a>
<div class="searchJumperFrame-buttons">
<button id="expandAll" type="button">${i18n("expandAll")}</button>
<button id="collapseAll" type="button">${i18n("collapseAll")}</button>
</div>
<div class="sitesCon"></div>
<div class="searchJumperFrame-buttons">
<button id="cancel" type="button">${i18n("siteCancel")}</button>
<button id="selectAll" type="button">${i18n("selectAll")}</button>
<button id="add" type="button">${i18n("import")}</button>
</div>
</div>
`);
this.sitesCon = this.filterFrame.querySelector(".sitesCon");
let add = this.filterFrame.querySelector("#add");
let selectAll = this.filterFrame.querySelector("#selectAll");
let expandAll = this.filterFrame.querySelector("#expandAll");
let collapseAll = this.filterFrame.querySelector("#collapseAll");
let checkMark = false;
expandAll.addEventListener("click", e => {
[].forEach.call(this.filterFrame.querySelectorAll("details"), details => {
details.setAttribute("open", "open");
});
});
collapseAll.addEventListener("click", e => {
[].forEach.call(this.filterFrame.querySelectorAll("details"), details => {
details.removeAttribute("open");
});
});
selectAll.addEventListener("click", e => {
checkMark = !checkMark;
[].forEach.call(this.filterFrame.querySelectorAll("input[type=checkbox]"), checkbox => {
checkbox.checked = checkMark;
});
});
add.addEventListener("click", e => {
if (shareEngines) return;
dataChanged(() => {
let canImport = false;
[].forEach.call(this.filterFrame.querySelectorAll("details"), details => {
let typeName = details.children[0].children[0];
let typeData = self.typeDict[typeName.title];
typeData.type = typeName.innerText.trim();
typeData.sites = [];
[].forEach.call(details.querySelectorAll('div>[type="checkbox"]'), checkSite => {
if (checkSite.checked) {
canImport = true;
let curData = self.siteDict[checkSite.parentNode.title];
let otherType = checkSite.nextElementSibling;
if (!curData || !otherType) return;
if (otherType.value === "0") {
typeData.sites.push(curData);
} else {
let typeIndex = self.searchType(otherType.value);
searchData.sitesConfig[typeIndex].sites.push(curData);
}
}
});
if (typeData.sites.length) {
let typeIndex = self.searchType(typeData.type);
if (typeIndex === false) {
searchData.sitesConfig.push(typeData);
} else {
searchData.sitesConfig[typeIndex].sites = searchData.sitesConfig[typeIndex].sites.concat(typeData.sites);
}
}
});
if (canImport) {
searchData.lastModified = new Date().getTime();
storage.setItem("searchData", searchData);
_GM_notification(i18n("siteAddOver"));
searchBar.refreshEngines();
this.close();
}
});
});
this.filterFrame.addEventListener("click", e => {
if (e.target.id == "searchJumperFilter" || e.target.id == "cancel") {
this.close();
}
});
}
searchType(type) {
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let typeData = searchData.sitesConfig[i];
if (typeData.type == type) return i;
}
return false;
}
searchUrl(url) {
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let sites = searchData.sitesConfig[i].sites;
for (let j = 0; j < sites.length; j++) {
if (sites[j].url.replace(/^https?/, "") == url.replace(/^https?/, "")) return true;
}
}
return false;
}
searchName(name) {
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let sites = searchData.sitesConfig[i].sites;
for (let j = 0; j < sites.length; j++) {
if (sites[j].name == name) {
let newName = name + "_1";
return this.searchName(newName);
}
}
}
return name;
}
anylizeType(typeData) {
let self = this;
let details = document.createElement("details");
let summary = document.createElement("summary");
let typeName = document.createElement("span");
typeName.title = typeData.type;
typeName.innerText = typeData.type;
summary.appendChild(typeName);
let checkType = document.createElement("input");
checkType.type = 'checkbox';
summary.appendChild(checkType);
let renameBtn = document.createElement("button");
renameBtn.innerText = i18n("rename");
renameBtn.addEventListener("click", e => {
let newName = window.prompt(i18n('rename'), typeName.innerText);
if (newName) typeName.innerText = newName;
});
summary.appendChild(renameBtn);
details.appendChild(summary);
for (let i = 0; i < this.openList.length; i++) {
if (this.openList[i] == typeData.type) {
details.setAttribute("open", "open");
break;
}
}
let sites = [];
this.typeDict[typeData.type] = typeData;
if (typeData.sites) {
typeData.sites.forEach(siteData => {
let siteCon = document.createElement("div");
let siteName = document.createElement("span");
siteName.innerText = siteData.name;
siteData.name = self.searchName(siteData.name);
siteCon.appendChild(siteName);
siteCon.title = siteData.url;
details.appendChild(siteCon);
if (self.searchUrl(siteData.url)) {
siteCon.classList.add("exist");
return;
}
let checkSite = document.createElement("input");
checkSite.type = 'checkbox';
checkSite.onclick = e => {
if (!checkSite.checked) {
checkType.checked = false;
} else {
let allchecked = true;
for (let i = 0; i < sites.length; i++) {
if (!sites[i].checked) {
allchecked = false;
break;
}
}
if (allchecked) checkType.checked = true;
}
};
siteCon.appendChild(checkSite);
siteCon.addEventListener("click", e => {
if (e.target.nodeName.toUpperCase() == 'SPAN') {
checkSite.click();
}
});
let typeSelect = document.createElement("select");
let option = document.createElement("option");
option.value = 0;
option.innerText = i18n("currentType");
typeSelect.appendChild(option);
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let _type = searchData.sitesConfig[i];
if (_type.type != typeData.type) {
let option = document.createElement("option");
option.value = _type.type;
option.innerText = _type.type;
typeSelect.appendChild(option);
}
}
siteCon.appendChild(typeSelect);
self.siteDict[siteData.url] = siteData;
sites.push(checkSite);
});
}
if (sites.length == 0) {
checkType.style.display = "none";
renameBtn.style.display = "none";
}
checkType.addEventListener("click", e => {
sites.forEach(checkSite => {
checkSite.checked = checkType.checked;
});
});
this.sitesCon.appendChild(details);
}
close() {
this.openList = [];
[].forEach.call(this.sitesCon.querySelectorAll("details"), details => {
if (details.hasAttribute("open")) {
this.openList.push(details.querySelector("summary").innerText);
}
});
if (this.filterFrame.parentNode) {
this.filterFrame.parentNode.removeChild(this.filterFrame);
}
}
open(configData) {
this.init();
let self = this;
this.siteDict = {};
this.typeDict = {};
if (!this.filterCssEle || !this.filterCssEle.parentNode) this.filterCssEle = _GM_addStyle(this.filterCss);
document.documentElement.appendChild(this.filterFrame);
this.sitesCon.innerHTML = createHTML('');
configData.forEach(type => {
self.anylizeType(type);
});
//storage.setItem("searchData", searchData);
//_GM_notification('Over!');
}
}
const importFilter = new ImportFilter();
var dragRoundFrame, dragCon, dragSiteCurSpans, dragSiteHistorySpans, dragEndHandler, dragenterHandler, openAllTimer, dragScaleWidth, dragScaleHeight, zoomDrag;
function showDragSearch(left, top) {
if (!searchBar || !searchBar.bar) return;
let preOpenType = searchBar.bar.querySelector('.search-jumper-type.search-jumper-open');
let removeFrame = () => {
document.removeEventListener('dragend', dragEndHandler, true);
document.removeEventListener('dragenter', dragenterHandler, true);
if (dragCon.parentNode) {
dragCon.parentNode.removeChild(dragCon);
dragRoundFrame.style.opacity = "";
dragRoundFrame.style.transform = '';
}
draging = false;
clearTimeout(openAllTimer);
if ((currentSite && !currentSite.hideNotMatch && !searchData.prefConfig.hideOnSearchEngine) || searchBar.con.classList.contains("resizePage")) {
if (preOpenType && !preOpenType.classList.contains('search-jumper-open')) {
if (preOpenType.children[0].onmousedown) preOpenType.children[0].onmousedown();
else {
let mouseEvent = new PointerEvent("mousedown");
preOpenType.children[0].dispatchEvent(mouseEvent);
}
}
} else {
searchBar.bar.style.display = 'none';
}
};
if (!dragScaleWidth && !dragScaleHeight) {
zoomDrag = (searchData.prefConfig.zoomDrag || 100) / 100;
dragScaleWidth = zoomDrag * 190;
dragScaleHeight = zoomDrag * 190;
}
if (!dragRoundFrame) {
let dragCssText = `
#dragCon {
position: fixed;
top: 0;
left: 0;
transform: scale(${zoomDrag});
z-index: 2147483647;
-moz-transition:left 0.3s ease, top 0.3s;
-webkit-transition:left 0.3s ease, top 0.3s;
transition:left 0.3s ease, top 0.3s;
}
#searchJumperWrapper * {
margin: 0;
padding: 0;
border: none;
outline: none;
user-select: none;
box-sizing: content-box;
font-size: 12px;
line-height: normal;
overflow: visible;
background-image: initial;
float: initial;
}
#searchJumperWrapper {
position: fixed;
height: 300px;
width: 300px;
padding: 20px;
margin: 20px;
background-color: #000000${searchData.prefConfig.hideDragHistory ? "10" : "9e"};
box-shadow: #000000 0px 0px 10px;
border-radius: 50%;
z-index: 2147483647;
box-sizing: content-box;
opacity: 0;
transform: scale(.5);
-moz-transition:opacity 0.3s ease, transform 0.15s;
-webkit-transition:opacity 0.3s ease, transform 0.15s;
transition:opacity 0.3s ease, transform 0.15s;
}
#searchJumperWrapper>.panel {
position: relative;
}
#searchJumperWrapper .sector:nth-child(2n+1) .sector-inner {
background: #454545;
color: white;
}
#searchJumperWrapper .sector:nth-child(2n) .sector-inner {
background: #ffffff;
color: black;
}
#searchJumperWrapper .sector.out:nth-child(2n+1) .sector-inner {
background: #353535;
}
#searchJumperWrapper .sector.out:nth-child(2n) .sector-inner {
background: #eeeeee;
}
#searchJumperWrapper .sector {
position: absolute;
left: 150px;
top: 50px;
width: 100px;
height: 200px;
font-size: 14px;
border-radius: 0px 100px 100px 0;
overflow: hidden;
transform-origin: left center;
z-index: 1;
-moz-transition:transform 0.3s ease;
-webkit-transition:transform 0.3s ease;
transition:transform 0.3s ease;
pointer-events: none;
}
#searchJumperWrapper .sector.out {
left: 150px;
top: 0px;
width: 150px;
height: 300px;
font-size: 14px;
border-radius: 0px 150px 150px 0;
overflow: hidden;
transform-origin: left center;
z-index: 0;
${searchData.prefConfig.hideDragHistory ? "display: none;" : ""}
}
#searchJumperWrapper .sector-inner {
text-align: center;
display: block;
width: 40px;
padding: 5px 3px 0 57px;
height: 195px;
transform: translateX(-100px) rotate(60deg);
transform-origin: right center;
border-radius: 100px 0 0 100px;
}
#searchJumperWrapper .sector.out>.sector-inner {
text-align: center;
display: block;
width: 90px;
height: 295px;
transform: translateX(-150px) rotate(36deg);
transform-origin: right center;
border-radius: 150px 0 0 150px;
}
#searchJumperWrapper .sector-inner span {
transform-origin: center;
padding: 20px 0;
pointer-events: all;
opacity: 0.8;
word-break: break-word;
height: 55px;
font-size: 12px;
font-weight: bold;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
#searchJumperWrapper .sector-inner span {
width: 70px;
margin-left: -15px;
}
#searchJumperWrapper .sector-inner span>p {
max-width: 58px;
}
#searchJumperWrapper .sector.out>.sector-inner span {
width: unset;
margin-left: unset;
}
#searchJumperWrapper .over>.sector-inner span {
opacity: 1;
}
#searchJumperWrapper .sector-inner span>img {
width: 25px;
height: 25px;
}
#searchJumperWrapper .sector-inner span:hover {
opacity: 1;
}
#searchJumperWrapper .dragLogo {
position: absolute;
left: 150px;
top: 150px;
border-radius: 50%;
box-shadow: #000000 0px 0px 10px;
z-index: 10;
font-size: 0;
-moz-transition:transform 0.3s ease;
-webkit-transition:transform 0.3s ease;
transition:transform 0.3s ease;
}
.dragLogo>svg {
width: 40px;
height: 40px;
pointer-events: none;
}
`;
let dragCssEle = _GM_addStyle(dragCssText);
dragSiteCurSpans = [];
dragSiteHistorySpans = [];
dragRoundFrame = document.createElement("div");
dragRoundFrame.id = "searchJumperWrapper";
dragRoundFrame.innerHTML = createHTML(`
<div class="panel"></div>
<div class="dragLogo">${logoBtnSvg}</div>
`);
if (!disabled) dragRoundFrame.appendChild(dragCssEle);
const sector1Num = 6;
const sector2Num = 10;
let sectorCon = dragRoundFrame.querySelector(".panel");
let sector1Gap = 360 / sector1Num;
let sector2Gap = 360 / sector2Num;
let sector1Start = -sector1Gap / 2;
let sector2Start = -sector2Gap / 2;
let dragSector;
let dragLogo = dragRoundFrame.querySelector(".dragLogo");
let removeTimer;
dragLogo.addEventListener("dragover", e => {
e.preventDefault();
}, true);
dragLogo.addEventListener("dragenter", e => {
clearTimeout(removeTimer);
if (dragSector) {
dragSector.style.transform = `rotate(${dragSector.dataset.deg}deg) ${searchData.prefConfig.hideDragHistory ? 'scale(1.2)' : ''}`;
dragSector.classList.remove("over");
}
dragSector = null;
dragLogo.style.transform = `scale(1.35)`;
e.preventDefault();
clearTimeout(openAllTimer);
openAllTimer = setTimeout(() => {
removeFrame();
searchBar.appendBar();
searchBar.showAllSites();
}, 1000);
}, true);
let geneSector = (className, deg, spanTransform) => {
let sector = document.createElement("div");
sector.className = className;
let sectorInner = document.createElement("div");
sectorInner.className = "sector-inner";
let sectorSpan = document.createElement("span");
sectorInner.appendChild(sectorSpan);
sector.appendChild(sectorInner);
let transform = `rotate(${deg}deg)`;
sectorSpan.style.transform = spanTransform;
sector.style.transform = transform + (searchData.prefConfig.hideDragHistory ? 'scale(1.2)' : '');
sector.dataset.deg = deg;
sectorCon.appendChild(sector);
sectorSpan.addEventListener("dragover", e => {
if (e.clientX < 50) {
dragCon.style.left = "0px";
} else if (e.clientX > document.documentElement.clientWidth - 50) {
dragCon.style.left = document.documentElement.clientWidth - (dragScaleWidth<<1) + "px";
}
if (e.clientY < 50) {
dragCon.style.top = "0px";
} else if (e.clientY > document.documentElement.clientHeight - 50) {
dragCon.style.top = document.documentElement.clientHeight - (dragScaleHeight<<1) + "px";
}
e.preventDefault();
}, true);
sectorSpan.addEventListener("dragenter", e => {
clearTimeout(removeTimer);
if (!sectorSpan.innerText) return;
if (dragSector) {
dragSector.style.transform = `rotate(${dragSector.dataset.deg}deg) ${searchData.prefConfig.hideDragHistory ? 'scale(1.2)' : ''}`;
dragSector.classList.remove("over");
}
dragLogo.style.transform = "";
sector.style.transform = `scale(${searchData.prefConfig.hideDragHistory ? '1.6' : '1.25'}) ${transform}`;
sector.classList.add("over");
dragSector = sector;
clearTimeout(openAllTimer);
}, true);
return sectorSpan;
};
for (let i = 0; i < sector1Num; i++) {
let sectorSpan = geneSector("sector", sector1Start + sector1Gap * i, `translateX(-10px) translateY(-10px) rotate(${sector1Start - sector1Gap * i}deg)`);
dragSiteCurSpans.push(sectorSpan);
}
for (let i = 0; i < sector2Num; i++) {
let sectorSpan = geneSector("sector out", sector2Start + sector2Gap * i, `translateX(12px) translateY(-15px) rotate(${sector2Start - sector2Gap * i}deg)`);
dragSiteHistorySpans.push(sectorSpan);
}
dragEndHandler = e => {
removeFrame();
}
dragRoundFrame.addEventListener('click', e => {
removeFrame();
});
dragRoundFrame.addEventListener('drop', e => {
if (e.target === dragLogo) {
searchBar.setFuncKeyCall(false);
searchBar.showInPage();
} else if (dragSector) {
removeFrame();
searchBar.searchBySiteName(dragSector.children[0].dataset.name, e);
dragSector.style.transform = `rotate(${dragSector.dataset.deg}deg)`;
dragSector.classList.remove("over");
dragSector = null;
}
e.preventDefault();
});
let minClientX, maxClientX, minClientY, maxClientY;
dragenterHandler = e => {
clearTimeout(removeTimer);
if (!dragRoundFrame.contains(e.target)) {
removeTimer = setTimeout(() => {
removeFrame();
}, 300);
}
};
dragCon = document.createElement("div");
dragCon.id = "dragCon";
dragCon.appendChild(dragRoundFrame);
}
searchBar.recoveHistory();
let firstType = searchBar.autoGetFirstType();
let siteBtns = firstType.querySelectorAll("a.search-jumper-btn:not(.notmatch)");
let targetIndex = 0;
let getTargetSiteBtn = () => {
let result = null;
for (let i = targetIndex; i < siteBtns.length; i++) {
let btn = siteBtns[i];
if (btn.style.display !== 'none') {
result = btn;
targetIndex = i + 1;
break;
}
}
return result;
};
const filldragSpan = (span, targetSite) => {
span.parentNode.dataset.name = targetSite.dataset.name;
let word = document.createElement("p");
word.innerText = targetSite.dataset.name.substr(0, 10).trim();
if (!/^\w+$/.test(word.innerText)) {
let text = "", len = 0;
for (let char of word.innerText) {
text += char;
if (/^\w+$/.test(char)) {
len++;
} else len += 2;
if (len > 10) {
text += "...";
break;
}
}
word.innerText = text;
}
let img = document.createElement("img");
img.style.display = "none";
span.appendChild(img);
span.appendChild(word);
img.onload = e => {
img.style.display = "";
};
let targetIcon = targetSite.querySelector("img");
if (targetIcon) {
let src = targetIcon.src || targetIcon.dataset.src;
if (src) img.src = src;
}
};
dragSiteCurSpans.forEach((span, i) => {
span.innerHTML = createHTML();
let targetSite = getTargetSiteBtn();
if (!targetSite) {
span.parentNode.parentNode.style.filter = 'contrast(0.5)';
return;
}
span.parentNode.parentNode.style.filter = '';
filldragSpan(span, targetSite);
});
let findIndex = 0;
let historySiteBtns;
if (firstType.classList.contains("search-jumper-needInPage")) {
historySiteBtns = searchBar.txtHistorySiteBtns;
} else if (firstType.classList.contains("search-jumper-targetImg")) {
historySiteBtns = searchBar.imgHistorySiteBtns;
} else if (firstType.classList.contains("search-jumper-targetAudio")) {
historySiteBtns = searchBar.audioHistorySiteBtns;
} else if (firstType.classList.contains("search-jumper-targetVideo")) {
historySiteBtns = searchBar.videoHistorySiteBtns;
} else if (firstType.classList.contains("search-jumper-targetLink") || firstType.classList.contains("search-jumper-targetPage")) {
historySiteBtns = searchBar.linkHistorySiteBtns;
}
if (historySiteBtns) {
historySiteBtns = historySiteBtns.concat(searchBar.historySiteBtns);
historySiteBtns = historySiteBtns.filter((value, index, self) => self.indexOf(value) === index);
} else {
historySiteBtns = searchBar.historySiteBtns;
}
let getHistorySiteBtn = () => {
if (searchData.prefConfig.reuseDragHistory) {
return getTargetSiteBtn();
} else if (searchData.prefConfig.hideDragHistory) {
return false;
}
let result = null;
for (let i = findIndex; i < historySiteBtns.length; i++) {
let btn = historySiteBtns[i];
if (btn.style.display !== 'none') {
result = btn;
findIndex = i + 1;
break;
}
}
return result;
};
dragSiteHistorySpans.forEach((span, i) => {
let dragleaveEvent = new DragEvent("dragleave");
span.dispatchEvent(dragleaveEvent);
span.innerHTML = createHTML();
span.parentNode.parentNode.style.opacity = 0.6;
let targetSite = getHistorySiteBtn();
if (!targetSite) return;
let siteImg = targetSite.querySelector('img');
if (siteImg && siteImg.dataset.src) {
siteImg.src = siteImg.dataset.src;
delete siteImg.dataset.src;
}
span.parentNode.parentNode.style.opacity = 1;
filldragSpan(span, targetSite);
});
dragCon.style.left = left - dragScaleWidth + "px";
dragCon.style.top = top - dragScaleHeight + "px";
dragRoundFrame.style.opacity = "";
dragRoundFrame.style.transform = '';
setTimeout(() => {
document.addEventListener('dragend', dragEndHandler, true);
searchBar.addToShadow(dragCon);
setTimeout(() => {
dragRoundFrame.style.opacity = 1;
dragRoundFrame.style.transform = 'scale(1)';
}, 10);
setTimeout(() => {
if (getComputedStyle(dragRoundFrame).zIndex != "2147483647") {
removeFrame();
} else {
document.addEventListener('dragenter', dragenterHandler, true);
}
}, 100);
}, 0);
}
var addFrame, nameInput, descInput, urlInput, iconInput, iconShow, iconsCon, typeSelect, testBtn, cancelBtn, addBtn, siteKeywords, siteMatch, openSelect, crawlBtn;
function showSiteAdd(name, description, url, icons, charset, kwFilter, match, hideNotMatch) {
self.kwFilter = kwFilter;
self.charset = charset;
self.hideNotMatch = hideNotMatch;
self.match = match;
if (!addFrame) {
let addFrameCssText = `
.searchJumperFrame-body,
.searchJumperFrame-crawlBody {
width: 300px;
min-height: 300px;
position: fixed;
text-align: left;
left: 50%;
top: 45%;
margin-top: -250px;
margin-left: -150px;
z-index: 100000;
background-color: #ffffff;
border: 1px solid #afb3b6;
border-radius: 10px;
opacity: 0.95;
filter: alpha(opacity=95);
box-shadow: 5px 5px 20px 0px #000;
color: #6e7070;
transition: all 0.25s ease;
border: 0;
font-size: initial;
}
.searchJumperFrame-title {
background: #458bd1!important;
display: flex!important;
align-items: center!important;
justify-content: center!important;
color: white!important;
font-weight: bold;
font-size: 18px!important;
border-radius: 10px 10px 0 0!important;
}
.draging .searchJumperFrame-body,
.draging .searchJumperFrame-crawlBody {
transition: none;
pointer-events: none;
}
.searchJumperFrame-title>img {
margin: 5px;
height: 32px;
width: 32px;
}
.searchJumperFrame-input-title {
font-size: 9pt;
font-family: Arial, sans-serif;
display: inline-block;
background-color: white;
position: relative;
left: 20px;
padding: 0px 4px;
text-align: left;
color: #646464;
}
.searchJumperFrame-inputs>input,
.searchJumperFrame-inputs>textarea,
.searchJumperFrame-inputs>select,
.searchJumperFrame-body select {
resize: both;
font-size: 11pt;
font-weight: normal;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.23);
margin: 4px;
font-family: inherit;
background-color: #FFF;
width: calc(100% - 8px);
min-width: calc(100% - 8px);
max-width: calc(100% - 8px);
color: #4A4A4A;
margin-top: -8px;
padding: 4px;
padding-top: 8px;
box-sizing: border-box;
height: 36px;
word-break: break-all;
}
.searchJumperFrame-inputs>input:focus,
.searchJumperFrame-inputs>textarea:focus,
.searchJumperFrame-inputs>select:focus,
.searchJumperFrame-body select:focus {
background-color: #FFF;
}
.searchJumperFrame-buttons {
text-align: center;
margin-bottom: 5px;
display: flex;
justify-content: space-evenly;
}
.searchJumperFrame-buttons>button {
width: 32%;
font-size: 16px;
cursor: pointer;
border: 1px solid #1976d2;
border-radius: 4px;
transition: all .3s;
color: #fff;
background-color: #458bd1;
line-height: 25px;
padding: 3px;
}
.searchJumperFrame-buttons>button:hover {
color: #e3f2fd;
}
.searchJumperFrame-inputs>.sideIcon {
float: right;
margin-top: -38px;
position: relative;
right: 20px;
opacity: 0.8;
background: rgb(0 0 0 / 50%);
border-radius: 5px;
pointer-events: none;
width: 27px;
height: 27px;
}
.searchJumperFrame-inputs>svg.sideIcon {
fill: white;
pointer-events: all;
cursor: pointer;
transition: transform 0.25s ease;
}
.searchJumperFrame-inputs>svg.sideIcon:hover {
transform: scale(1.2);
opacity: 1;
background: rgb(0 0 0);
}
.searchJumperFrame-body>.iconsCon {
max-height: 150px;
overflow: auto;
width: 100%;
border-top: 1px solid rgba(0, 0, 0, 0.23);
border-bottom: 1px solid rgba(0, 0, 0, 0.23);
}
.searchJumperFrame-body>.iconsCon>img {
margin: 5px;
cursor: pointer;
max-width: 120px;
border: 2px solid #ffffff;
box-sizing: border-box;
background: #80808030;
transition: background 0.25s ease;
}
.searchJumperFrame-body>.iconsCon>img:hover {
border: 2px solid #4e91d3;
background: gray;
}
.maxContent .searchJumperFrame-inputs {
width: 50%;
float: left;
}
.searchJumperFrame-body>.moreItem {
display: none;
}
.maxContent>.searchJumperFrame-body>.moreItem {
display: block;
}
.maxContent>.searchJumperFrame-body {
width: 600px;
margin-left: -300px;
}
.searchJumperFrame-maxBtn,
.searchJumperFrame-closeBtn {
position: absolute;
right: 5px;
top: 5px;
color: white;
width: 25px;
cursor: pointer;
transition:transform 0.25s ease;
}
.searchJumperFrame-maxBtn:hover,
.searchJumperFrame-closeBtn:hover {
transform: scale(1.2);
}
.searchJumperFrame-maxBtn>#maxBtn {
display: block;
}
.searchJumperFrame-maxBtn>#minBtn {
display: none;
}
.maxContent .searchJumperFrame-maxBtn>#maxBtn {
display: none;
}
.maxContent .searchJumperFrame-maxBtn>#minBtn {
display: block;
}
.crawling>.searchJumperFrame-body {
display: none;
}
.searchJumperFrame-crawlBody {
display: none;
}
.crawling>.searchJumperFrame-crawlBody {
display: block;
}
.searchJumperFrame-buttons>button#submitCrawl,
.searchJumperFrame-buttons>button#record,
.searchJumperFrame-buttons>button#copy,
.searchJumperFrame-buttons>button#loop {
width: 100%;
margin: 0 3px;
}
.searchJumperFrame-crawlBody>.actionCon {
height: 200px;
background: gray;
border-radius: 10px;
margin: 10px;
padding: 0 10px 10px 10px;
resize: auto;
box-sizing: border-box;
overflow: auto;
}
.searchJumperFrame-crawlBody>.actionCon>div {
width: 100%;
font-size: 16px;
background: #000000cc;
border-radius: 8px;
color: white;
margin: 3px 0;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
white-space: nowrap;
}
.searchJumperFrame-crawlBody>.actionCon>div>span {
background: #275f90;
border-radius: 5px;
max-width: 40px;
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
margin: 0 3px;
white-space: nowrap;
}
@media (prefers-color-scheme: dark) {
.searchJumperFrame-body,
.searchJumperFrame-crawlBody,
.searchJumperFrame-input-title,
.searchJumperFrame-inputs>input,
.searchJumperFrame-inputs>textarea,
.searchJumperFrame-inputs>select,
.searchJumperFrame-body select {
background-color: black!important;
color: #d5d5d5!important;
}
.searchJumperFrame-inputs>input:focus,
.searchJumperFrame-inputs>textarea:focus,
.searchJumperFrame-inputs>select:focus,
.searchJumperFrame-body select:focus {
background-color: #1e1e1e!important;
}
.searchJumperFrame-inputs>input,
.searchJumperFrame-inputs>textarea,
.searchJumperFrame-inputs>select,
.searchJumperFrame-body select {
border: 1px solid rgb(255 255 255 / 36%);
}
.searchJumperFrame-title,
.searchJumperFrame-buttons>button {
background: #245d8f!important;
}
.searchJumperFrame-body>.iconsCon>img {
border: 2px solid #000000;
}
}
@media screen and (max-height: 600px) {
.searchJumperFrame-body,
.searchJumperFrame-crawlBody {
top: 10px;
margin-top: 0px;
}
}
`;
let addFrameCssEle = _GM_addStyle(addFrameCssText);
addFrame = document.createElement("div");
addFrame.innerHTML = createHTML(`
<div class="searchJumperFrame-body">
<a href="${configPage}" class="searchJumperFrame-title" target="_blank" draggable="false">
<img width="32px" height="32px" src="${logoBase64}" />${i18n("addSearchEngine")}
</a>
<div class="searchJumperFrame-maxBtn">
<svg id="maxBtn" fill="white" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("maxAddSiteBtn")}</title><path d="M192 832h160a32 32 0 0 1 0 64H160a32 32 0 0 1-32-32V672a32 32 0 0 1 64 0zM182.72 886.72a32 32 0 0 1-45.44-45.44l224-224a32 32 0 0 1 45.44 45.44zM832 832V672a32 32 0 0 1 64 0v192a32 32 0 0 1-32 32H672a32 32 0 0 1 0-64zM886.72 841.28a32 32 0 0 1-45.44 45.44l-224-224a32 32 0 0 1 45.44-45.44zM192 192v160a32 32 0 0 1-64 0V160a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64zM137.28 182.72a32 32 0 0 1 45.44-45.44l224 224a32 32 0 0 1-45.44 45.44zM832 192H672a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0zM841.28 137.28a32 32 0 1 1 45.44 45.44l-224 224a32 32 0 0 1-45.44-45.44z"></path></svg>
<svg id="minBtn" fill="white" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("minAddSiteBtn")}</title><path d="M672 352h160a32 32 0 0 1 0 64H640a32 32 0 0 1-32-32V192a32 32 0 0 1 64 0zM662.72 406.72a32 32 0 0 1-45.44-45.44l224-224a32 32 0 1 1 45.44 45.44zM352 352V192a32 32 0 0 1 64 0v192a32 32 0 0 1-32 32H192a32 32 0 0 1 0-64zM406.72 361.28a32 32 0 0 1-45.44 45.44l-224-224a32 32 0 0 1 45.44-45.44zM672 672v160a32 32 0 0 1-64 0V640a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64zM617.28 662.72a32 32 0 0 1 45.44-45.44l224 224a32 32 0 0 1-45.44 45.44zM192 672a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V672zM361.28 617.28a32 32 0 0 1 45.44 45.44l-224 224a32 32 0 0 1-45.44-45.44z"></path></svg>
</div>
<div class="searchJumperFrame-inputs">
<div class="searchJumperFrame-input-title">${i18n("siteName")}</div>
<input name="siteName" type="text" />
<div class="searchJumperFrame-input-title">${i18n("siteUrl")}</div>
<textarea name="url" type="text"></textarea>
<svg id="crawlBtn" class="sideIcon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>${i18n("crawlInfo")}</title><path d="M385 926.3c-11 0-21.4-4.3-29.2-12l-0.6-0.6c-0.7-0.7-65.6-70.4-108.4-112.7-42.8-42.3-118.6-111.4-119.3-112.1l-0.6-0.5c-15.9-15.7-24.6-36.6-24.5-58.8s9-43.1 25-58.6c28.6-27.7 72.2-31 104.6-8.2l90.5 44-83.1-290.1c-4.9-17.1-4.2-34.9 2.1-51.6 6.3-16.6 17.5-30.5 32.5-40.1 22-14.1 47.7-17.7 70.3-10 22.6 7.7 40.7 26.3 49.5 50.9L431 369.8V176.9c0-43.4 35.3-78.7 78.7-78.7 20.7 0 40.2 7.9 55 22.4 14.8 14.4 23.2 33.8 23.7 54.4v0.2l2.4 165.5L625 229.1l0.1-0.4c8.2-23.2 26.2-41.1 49.4-49.3 23.2-8.2 48.5-5.5 69.4 7.3 15.6 9.6 27.7 24.3 33.9 41.6s6.4 36.3 0.6 53.7L736 409.5l42.9-48.6 0.3-0.3c15.7-16.2 34.4-25.7 54.1-27.3 19.8-1.6 39.1 4.7 56 18.1 33 26.4 40.8 60.1 22.7 97.5l-0.5 1.1-0.6 1c-41.8 65.2-107.1 171.9-115.8 199-12.4 38.6-41 140.7-41.3 141.7l-0.2 0.7-34.5 107.2-0.6 1.2c-6.8 14.3-21.5 23.7-37.4 23.8l-295.9 1.6c0 0.1-0.1 0.1-0.2 0.1z"></path></svg>
<div class="searchJumperFrame-input-title">${i18n("siteDesc")}</div>
<textarea name="description" type="text"></textarea>
<div class="searchJumperFrame-input-title">${i18n("siteIcon")}</div>
<textarea name="icon" type="text"></textarea>
<img class="sideIcon" width="27px" height="27px" />
</div>
<div class="searchJumperFrame-inputs moreItem">
<div class="searchJumperFrame-input-title">${i18n("siteKeywords")}</div>
<input name="siteKeywords" placeholder="kw|key" type="text" />
<div class="searchJumperFrame-input-title">${i18n("siteMatch")}</div>
<input name="siteMatch" placeholder="(www|m)\\.google\\.com" type="text" />
<div class="searchJumperFrame-input-title">${i18n("openSelect")}</div>
<select name="openSelect">
<option value="-1">${i18n("openInDefault")}</option>
<option value="true">${i18n("openInNewTab")}</option>
<option value="false">${i18n("openInCurrent")}</option>
</select>
</div>
<div class="iconsCon"></div>
<div class="searchJumperFrame-input-title">${i18n("siteType")}</div>
<select name="typeSelect">
</select>
<div class="searchJumperFrame-buttons">
<button id="test" type="button">${i18n("siteTest")}</button>
<button id="cancel" type="button">${i18n("siteCancel")}</button>
<button id="add" type="button">${i18n("siteAdd")}</button>
</div>
</div>
<div class="searchJumperFrame-crawlBody searchJumperFrame-hide">
<a href="${configPage}" class="searchJumperFrame-title" target="_blank">
<img width="32px" height="32px" src="${logoBase64}" />${i18n("addAction")}
</a>
<svg class="searchJumperFrame-closeBtn" fill="white" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>Close crawl</title>${closePath}</svg>
<div class="actionCon"></div>
<div class="searchJumperFrame-buttons">
<button id="input" type="button" title="${i18n("emuInputTips")}">${i18n("inputAction")}</button>
<button id="click" type="button" title="${i18n("emuClickTips")}">${i18n("clickAction")}</button>
<button id="sleep" type="button" title="${i18n("emuWaitTips")}">${i18n("sleepAction")}</button>
</div>
<div class="searchJumperFrame-buttons">
<button id="copy" type="button" title="${i18n("emuCopyTips")}">${i18n("copyAction")}</button>
</div>
<div class="searchJumperFrame-buttons">
<button id="record" type="button" title="${i18n("emuRecordTips")}">${i18n("recordAction")}</button>
</div>
<div class="searchJumperFrame-buttons">
<button id="loop" type="button" title="${i18n("emuLoopTips")}">${i18n("loopAction")}</button>
</div>
<div class="searchJumperFrame-buttons">
<button id="submitCrawl" type="button" title="${i18n("emuStopTips")}">${i18n("submitCrawl")}</button>
</div>
</div>
`);
if (!disabled) addFrame.appendChild(addFrameCssEle);
let addBody = addFrame.children[0];
nameInput = addFrame.querySelector("[name='siteName']");
descInput = addFrame.querySelector("[name='description']");
urlInput = addFrame.querySelector("[name='url']");
iconInput = addFrame.querySelector("[name='icon']");
iconShow = addFrame.querySelector(".searchJumperFrame-inputs>img");
iconsCon = addFrame.querySelector(".iconsCon");
testBtn = addFrame.querySelector("#test");
cancelBtn = addFrame.querySelector("#cancel");
addBtn = addFrame.querySelector("#add");
typeSelect = addFrame.querySelector("select[name='typeSelect']");
siteKeywords = addFrame.querySelector("[name='siteKeywords']");
siteMatch = addFrame.querySelector("[name='siteMatch']");
openSelect = addFrame.querySelector("select[name='openSelect']");
let title = addFrame.querySelector(".searchJumperFrame-title");
let initMousePos, initFramePos, moving = false;
let dragTitleMove = e => {
if (!moving) {
addFrame.classList.add("draging");
moving = true;
}
let x = e.clientX - initMousePos.x + initFramePos.x;
let y = e.clientY - initMousePos.y + initFramePos.y;
addBody.style.marginLeft = x + "px";
addBody.style.marginTop = y + "px";
};
let dragTitleUp = e => {
e.preventDefault();
e.stopPropagation();
addFrame.classList.remove("draging");
document.removeEventListener("mousemove", dragTitleMove);
document.removeEventListener("mouseup", dragTitleUp);
};
title.addEventListener("mousedown", e => {
e.preventDefault();
e.stopPropagation();
moving = false;
initMousePos = {x: e.clientX, y: e.clientY};
let addBodyStyle = getComputedStyle(addBody);
initFramePos = {x: parseInt(addBodyStyle.marginLeft || 0), y: parseInt(addBodyStyle.marginTop || 0)};
document.addEventListener("mousemove", dragTitleMove);
document.addEventListener("mouseup", dragTitleUp);
});
iconShow.onload = e => {
iconShow.style.display = "";
}
let maxBtn = addFrame.querySelector("#maxBtn");
maxBtn.addEventListener("click", e => {
addFrame.classList.add("maxContent");
});
let minBtn = addFrame.querySelector("#minBtn");
minBtn.addEventListener("click", e => {
addFrame.classList.remove("maxContent");
});
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let typeConfig = searchData.sitesConfig[i];
let option = document.createElement("option");
option.value = i;
if (lastAddType !== "" && lastAddType == i) {
option.selected = "selected";
}
option.innerText = typeConfig.type;
typeSelect.appendChild(option);
}
testBtn.addEventListener("click", e => {
if (/#p{/.test(urlInput.value)) {
let actionParams = urlInput.value.match(/#p{(.*)}/);
if (!actionParams) return;
let postParams = [];
actionParams[1].replace(/([^\\])&/g, "$1SJ^PARAM").split("SJ^PARAM").forEach(pair => {//ios不支持零宽断言,哭唧唧
pair = pair.trim();
if (/^loopStart\(\d+\)$/.test(pair)) {
let loopStart = pair.match(/loopStart\((.*)\)/);
postParams.push(['@loopStart', loopStart[1]]);
} else if (pair == "loopEnd") {
postParams.push(['@loopEnd', '']);
} else if (pair.startsWith("click(") && pair.endsWith(')')) {
let click = pair.slice(6, pair.length - 1);
if (click) {
postParams.push(['@click', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("dblclick(") && pair.endsWith(')')) {
let click = pair.slice(9, pair.length - 1);
if (click) {
postParams.push(['@dblclick', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("rclick(") && pair.endsWith(')')) {
let click = pair.slice(7, pair.length - 1);
if (click) {
postParams.push(['@rclick', click.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("copy(") && pair.endsWith(')')) {
let copy = pair.slice(5, pair.length - 1);
if (copy) {
postParams.push(['@copy', copy.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("call(") && pair.endsWith(')')) {
let func = pair.slice(5, pair.length - 1);
if (func) {
postParams.push(['@call', func.replace(/\\([\=&])/g, "$1").trim()]);
}
} else if (pair.startsWith("wait(") && pair.endsWith(')')) {
let wait = pair.slice(5, pair.length - 1);
postParams.push(['@wait', wait.replace(/\\([\=&])/g, "$1").trim()]);
} else if (/^sleep\(\d+\)$/.test(pair)) {
let sleep = pair.match(/sleep\((.*)\)/);
if (sleep) {
postParams.push(['@sleep', sleep[1]]);
}
} else if (/^reload\(\d?\)$/.test(pair)) {
let reload = pair.match(/reload\((.*)\)/);
postParams.push(['@reload', reload[1]]);
} else {
pair = pair.replace(/([^\\])\=/g, "$1SJ^PARAM").replace(/\\([\=&])/g, "$1");
let pairArr = pair.split("SJ^PARAM");
if (pairArr.length === 2) {
let k = pairArr[0];
let v = pairArr[1].replace(/\\([\=&])/g, "$1");
postParams.push([k, v]);
} else if (pair.endsWith('.click()') || pair.endsWith('.click')) {
postParams.push(['@' + pair.replace(/\.click(\(\))?$/, ''), 'click']);
}
}
});
inPagePostParams = postParams;
searchBar.submitAction(postParams);
} else if (/[:%]p{/.test(urlInput.value) || (charset && charset.toLowerCase() != 'utf-8')) {
submitByForm(charset, urlInput.value.replace(/%se?\b/g, "searchJumper"), "_blank");
} else {
_GM_openInTab(urlInput.value.replace(/%se?\b/g, "searchJumper"), {active: true, insert: true});
}
});
cancelBtn.addEventListener("click", e => {
if (addFrame.parentNode) {
addFrame.parentNode.removeChild(addFrame);
}
});
addBtn.addEventListener("click", e => {
if (shareEngines) return;
dataChanged(() => {
let siteObj = null;
for (let i = 0; i < searchData.sitesConfig.length; i++) {
let typeConfig = searchData.sitesConfig[i];
for (let j = 0; j < typeConfig.sites.length; j++) {
let curSite = typeConfig.sites[j];
if (curSite.url == urlInput.value) {
if (i == parseInt(typeSelect.value)) {
alert('Already added!');
return;
}
if (window.confirm(i18n("siteExist"))) {
siteObj = {
name: curSite.name + " - " + typeConfig.type,
url: `["${curSite.name}"]`
};
} else return;
}
}
}
if (siteObj == null) {
siteObj = {
name: nameInput.value,
url: urlInput.value
};
if (iconInput.value && iconInput.value != urlInput.value.replace(/\?.*/, "").replace(/^(https?:\/\/[^\/]*\/)[\s\S]*$/, "$1favicon.ico")) {
siteObj.icon = iconInput.value;
}
if (descInput.value && descInput.value != nameInput.value) {
siteObj.description = descInput.value;
}
if (siteKeywords.value) {
siteObj.keywords = siteKeywords.value;
}
if (siteMatch.value) {
siteObj.match = siteMatch.value;
}
if (openSelect.value && openSelect.value != '-1') {
siteObj.openInNewTab = openSelect.value === 'true';
}
if (self.charset && charset.toLowerCase() != 'utf-8') {
siteObj.charset = self.charset;
}
if (self.kwFilter) {
siteObj.kwFilter = self.kwFilter;
}
if (self.match) {
siteObj.match = self.match;
}
if (self.hideNotMatch) {
siteObj.hideNotMatch = self.hideNotMatch;
}
}
searchData.sitesConfig[typeSelect.value].sites.push(siteObj);
searchData.lastModified = new Date().getTime();
storage.setItem("lastAddType", typeSelect.value);
storage.setItem("searchData", searchData);
_GM_notification(i18n("siteAddOver"));
if (addFrame.parentNode) {
addFrame.parentNode.removeChild(addFrame);
}
window.postMessage({
searchData: searchData,
version: _GM_info.script.version || 0,
command: 'loadConfig'
}, '*');
searchBar.refreshEngines();
});
});
crawlBtn = addFrame.querySelector("#crawlBtn");
let closeCrawlBtn = addFrame.querySelector(".searchJumperFrame-closeBtn");
let actionCon = addFrame.querySelector(".actionCon");
let inputAction = addFrame.querySelector("#input");
let clickAction = addFrame.querySelector("#click");
let sleepAction = addFrame.querySelector("#sleep");
let copyAction = addFrame.querySelector("#copy");
let submitCrawl = addFrame.querySelector("#submitCrawl");
let recordBtn = addFrame.querySelector("#record");
let loopBtn = addFrame.querySelector("#loop");
let dragDiv;
let addAction = (type, sel = '', val = '') => {
let div = document.createElement("div");
let words = type;
switch(type) {
case "input":
words = i18n('inputOutput', [sel, val]);
break;
case "click":
words = i18n('clickOutput', sel);
break;
case "dblclick":
words = i18n('dblclickOutput', sel);
break;
case "rclick":
words = i18n('rclickOutput', sel);
break;
case "copy":
words = i18n('copyOutput', sel);
break;
case "loopStart":
words = i18n('loopStart', val);
break;
case "loopEnd":
words = i18n('loopEnd');
break;
case "sleep":
words = i18n('sleepOutput', val);
break;
default:
break;
}
if (words) {
div.innerHTML = createHTML(words);
div.dataset.type = type;
div.dataset.sel = sel;
div.dataset.val = val;
div.draggable = "true";
div.ondragover = e => {
e.preventDefault();
};
div.ondragstart = e => {
dragDiv = div;
}
div.ondrop = e => {
actionCon.insertBefore(dragDiv, div);
}
div.onclick = e => {
let target = e.target;
if (target.nodeName.toUpperCase() == 'SPAN') {
if (target.className == 'element') {
picker.getSelector(selector => {
target.innerText = selector;
target.title = selector;
addFrame.style.display = '';
div.dataset.sel = selector;
});
addFrame.style.display = 'none';
} else {
let newValue = prompt(i18n('inputNewValue'), target.innerText);
if (newValue) {
target.innerText = newValue;
target.title = newValue;
div.dataset.val = newValue;
}
}
} else if (confirm(i18n('deleteConfirm'))) {
actionCon.removeChild(div);
}
}
div.oncontextmenu = e => {
let target = e.target;
if (target.nodeName.toUpperCase() == 'SPAN') {
e.preventDefault();
if (target.className == 'element') {
let newValue = prompt('Selector', target.innerText);
if (newValue) {
target.innerText = newValue;
target.title = newValue;
div.dataset.sel = newValue;
}
} else {
let newValue = prompt(i18n('inputNewValue'), target.innerText);
if (newValue) {
target.innerText = newValue;
target.title = newValue;
div.dataset.val = newValue;
}
}
}
}
actionCon.appendChild(div);
}
};
let anylizeEmuUrl = () => {
actionCon.innerHTML = createHTML();
let actionParams = urlInput.value.match(/#p{(.*)}/);
if (!actionParams) return;
actionParams[1].replace(/([^\\])&/g, "$1SJ^PARAM").split("SJ^PARAM").forEach(pair => {
pair = pair.trim();
if (/^loopStart\(\d+\)$/.test(pair)) {
let loopStart = pair.match(/loopStart\((.*)\)/);
addAction('loopStart', '', loopStart[1]);
} else if (pair == "loopEnd") {
addAction('loopEnd');
} else if (pair.startsWith("click(") && pair.endsWith(')')) {
let click = pair.slice(6, pair.length - 1);
if (click) {
addAction('click', click.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("dblclick(") && pair.endsWith(')')) {
let click = pair.slice(9, pair.length - 1);
if (click) {
addAction('dblclick', click.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("rclick(") && pair.endsWith(')')) {
let click = pair.slice(7, pair.length - 1);
if (click) {
addAction('rclick', click.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("copy(") && pair.endsWith(')')) {
let copy = pair.slice(5, pair.length - 1);
if (copy) {
addAction('copy', copy.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("call(") && pair.endsWith(')')) {
let func = pair.slice(5, pair.length - 1);
if (func) {
addAction('call', '', func.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("wait(") && pair.endsWith(')')) {
let func = pair.slice(5, pair.length - 1);
if (func) {
addAction('wait', '', func.replace(/\\([\=&])/g, "$1").trim());
}
} else if (pair.startsWith("open(") && pair.endsWith(')')) {
let func = pair.slice(5, pair.length - 1);
if (func) {
addAction('open', '', func.replace(/\\([\=&])/g, "$1").trim());
}
} else if (/^sleep\(\d+\)$/.test(pair)) {
let sleep = pair.match(/sleep\((.*)\)/);
if (sleep) {
addAction('sleep', '', sleep[1]);
}
} else if (/^reload\(\d?\)$/.test(pair)) {
let reload = pair.match(/reload\((.*)\)/);
addAction('reload', '', reload[1]);
} else {
pair = pair.replace(/([^\\])\=/g, "$1SJ^PARAM").replace(/\\([\=&])/g, "$1");
let pairArr = pair.split("SJ^PARAM");
if (pairArr.length === 2) {
addAction('input', pairArr[0], pairArr[1].replace(/\\([\=&])/g, "$1"));
} else if (pair.endsWith('.click()') || pair.endsWith('.click')) {
addAction('click', pair.replace(/\.click(\(\))?$/, ''));
}
}
});
};
let geneUrl = () => {
let actions = [];
[].forEach.call(actionCon.children, action => {
if (!action) return;
let sel = action.dataset.sel;
let val = action.dataset.val || '';
switch(action.dataset.type) {
case "click":
actions.push(`click(${sel.replace(/([=&])/g, '\\$1')})`);
break;
case "dblclick":
actions.push(`dblclick(${sel.replace(/([=&])/g, '\\$1')})`);
break;
case "rclick":
actions.push(`rclick(${sel.replace(/([=&])/g, '\\$1')})`);
break;
case "copy":
actions.push(`copy(${sel.replace(/([=&])/g, '\\$1')})`);
break;
case "input":
actions.push(`${sel.replace(/([=&])/g, '\\$1')}=${val}`);
break;
case "sleep":
actions.push(`sleep(${val})`);
break;
case "loopEnd":
actions.push('loopEnd');
break;
default:
actions.push(`${action.dataset.type}(${val.replace(/([=&])/g, '\\$1')})`);
break;
}
});
return actions.join('&');
};
crawlBtn.addEventListener("click", e => {
anylizeEmuUrl();
addFrame.classList.add("crawling");
});
closeCrawlBtn.addEventListener("click", e => {
addFrame.classList.remove("crawling");
});
let targetInput;
let clickTimer;
let clickSthHandler = e => {
if (addFrame.style.display === '') return;
if (/INPUT|TEXTAREA|SELECT|OPTION/i.test(e.target.nodeName)) {
return;
}
clearTimeout(clickTimer);
clickTimer = setTimeout(() => {
addAction('click', picker.geneSelector(e.target, true));
}, 300);
};
let dblclickSthHandler = e => {
if (addFrame.style.display === '') return;
if (/INPUT|TEXTAREA|SELECT|OPTION/i.test(e.target.nodeName)) {
return;
}
clearTimeout(clickTimer);
addAction('dblclick', picker.geneSelector(e.target, true));
};
let rclickSthHandler = e => {
if (addFrame.style.display === '') return;
if (/INPUT|TEXTAREA|SELECT|OPTION/i.test(e.target.nodeName)) {
return;
}
e.preventDefault();
clearTimeout(clickTimer);
addAction('rclick', picker.geneSelector(e.target, true));
};
let changeHandler = e => {
if (addFrame.style.display === '') return;
addAction('input', picker.geneSelector(e.target, true), e.target.value);
};
let keydownHandler = e => {
if (addFrame.style.display === '') return;
let quit = false;
if (e.keyCode == 27) {
quit = true;
} else if (e.keyCode == 13) {
//enter
e.preventDefault();
e.stopPropagation();
e.target && e.target.blur && e.target.blur();
quit = true;
}
if (quit) {
addFrame.style.display = '';
document.removeEventListener('keydown', keydownHandler, true);
document.removeEventListener('click', clickSthHandler);
document.removeEventListener('dblclick', dblclickSthHandler);
document.removeEventListener('contextmenu', rclickSthHandler);
document.removeEventListener('change', changeHandler);
}
};
recordBtn.addEventListener("click", e => {
alert(i18n("startRecord"));
addFrame.style.display = 'none';
setTimeout(() => {
document.addEventListener('keydown', keydownHandler, true);
document.addEventListener('click', clickSthHandler);
document.addEventListener('dblclick', dblclickSthHandler);
document.addEventListener('contextmenu', rclickSthHandler);
document.addEventListener('change', changeHandler);
}, 100);
});
let inLoop = false;
loopBtn.addEventListener("click", e => {
if (inLoop) {
addAction('loopEnd');
loopBtn.innerText = i18n("loopAction");
} else {
let loopTimes = prompt(i18n('loopTimes'), 1);
if (!loopTimes) return;
addAction('loopStart', '', loopTimes || '1');
loopBtn.innerText = i18n("loopActionEnd");
}
inLoop = !inLoop;
});
inputAction.addEventListener("click", e => {
picker.getSelector(selector => {
addAction('input', selector, '%s');
addFrame.style.display = '';
}, !inLoop);
addFrame.style.display = 'none';
});
copyAction.addEventListener("click", e => {
picker.getSelector(selector => {
addAction('copy', selector, '%s');
addFrame.style.display = '';
}, !inLoop);
addFrame.style.display = 'none';
});
clickAction.addEventListener("dblclick", e => {
clearTimeout(clickTimer);
e.preventDefault();
e.stopPropagation();
picker.getSelector(selector => {
addAction('dblclick', selector);
addFrame.style.display = '';
}, !inLoop);
addFrame.style.display = 'none';
});
clickAction.addEventListener("contextmenu", e => {
clearTimeout(clickTimer);
e.preventDefault();
e.stopPropagation();
picker.getSelector(selector => {
addAction('rclick', selector);
addFrame.style.display = '';
}, !inLoop);
addFrame.style.display = 'none';
});
clickAction.addEventListener("click", e => {
clearTimeout(clickTimer);
clickTimer = setTimeout(() => {
picker.getSelector(selector => {
addAction('click', selector);
addFrame.style.display = '';
}, !inLoop);
addFrame.style.display = 'none';
}, 250);
});
sleepAction.addEventListener("click", e => {
let sleepTime = prompt(i18n('sleepPrompt'), 1000);
sleepTime = sleepTime && parseInt(sleepTime);
if (sleepTime) addAction('sleep', '', sleepTime);
});
submitCrawl.addEventListener("click", e => {
let actionUrl = geneUrl();
if (actionUrl) {
urlInput.value = location.href + '#p{' + actionUrl + '}';
}
addFrame.classList.remove("crawling");
});
}
searchBar.addToShadow(addFrame);
siteKeywords.value = "";
siteMatch.value = "";
nameInput.value = name || "";
descInput.value = description || "";
urlInput.value = url || "";
if (icons && icons[0]) {
iconShow.style.display = "";
if (url.indexOf(location.origin) === 0) {
iconShow.onerror = e => {
iconShow.onerror = null;
iconInput.value = icons[0];
iconShow.src = icons[0];
}
iconShow.src = location.origin + "/favicon.ico";
} else {
iconInput.value = icons[0];
iconShow.src = icons[0];
}
} else {
iconShow.style.display = "none";
iconShow.src = (/^(showTips:)?https?:/.test(url) ? url.split('\n')[0].replace(/\?.*/, "").replace(/^(showTips:)?(https?:\/\/[^\/]+).*/, '$2') : location.origin) + "/favicon.ico";
}
iconsCon.innerHTML = createHTML();
if (icons && icons.length > 1) {
iconsCon.style.opacity = "";
icons.forEach(iconSrc => {
let curIcon = document.createElement("img");
curIcon.src = iconSrc;
curIcon.addEventListener("click", e => {
iconInput.value = iconSrc;
iconShow.src = iconSrc;
});
curIcon.onload = e => {
curIcon.title = curIcon.naturalWidth + " x " + curIcon.naturalHeight + "\n" + iconSrc.replace(/.*\/([^\/]+)/, "$1");
};
iconsCon.appendChild(curIcon);
});
} else {
iconsCon.style.opacity = 0;
}
}
function downloadCache() {
let downloadEle = document.createElement('a');
downloadEle.download = "searchJumperCache.json";
downloadEle.target = "_blank";
let blobStr = [JSON.stringify({sortTypeNames: sortTypeNames, cacheIcon: cacheIcon, sortSiteNames: sortSiteNames}, null , 4)];
let myBlob = new Blob(blobStr, { type: "application/json" });
downloadEle.href = window.URL.createObjectURL(myBlob);
downloadEle.click();
}
function importCache(cacheData) {
if (cacheData.cacheIcon) {
cacheIcon = cacheData.cacheIcon;
storage.setItem("cacheIcon", cacheIcon);
cachePool = [];
searchData.prefConfig.cacheSwitch = true;
storage.setItem("searchData", searchData);
}
if (cacheData.sortTypeNames) {
sortTypeNames = cacheData.sortTypeNames;
storage.setItem("sortTypeNames", sortTypeNames);
}
if (cacheData.sortSiteNames) {
sortSiteNames = cacheData.sortSiteNames;
storage.setItem("sortSiteNames", sortSiteNames);
}
}
function showSiteAddFromOpenSearch(url, callback) {
_GM_xmlhttpRequest({
method: "GET",
url: url,
headers: {
referer: url,
origin: url
},
onload: (d) => {
let urlparam = d && d.responseXML && d.responseXML.querySelector('Url[type="text/html"]');
if (!urlparam) {
callback('error', d);
return;
}
let shortName = d.responseXML.querySelector("ShortName");
let description = d.responseXML.querySelector("Description");
let image = d.responseXML.querySelector("Image");
let inputEncoding = d.responseXML.querySelector("InputEncoding");
let postParams = urlparam.querySelectorAll("Param");
let name = shortName && shortName.textContent;
let desc = description && description.textContent;
let url = urlparam.getAttribute("template");
let ico = image && image.textContent;
let charset = inputEncoding && inputEncoding.textContent;
if (postParams.length > 0) {
let params = [];
[].forEach.call(postParams, postParam => {
params.push(`${postParam.getAttribute("name")}=${postParam.getAttribute("value")}`);
});
url += `%p{${params.join("&")}}`;
}
showSiteAdd(name, desc, url.replace(/{searchTerms\??}/g, "%s").replace(/{startPage\??}/g, '1').replace(/{count\??}/g, '10').replace(/{startIndex\??}/g, '1').replace(/{startPage\??}/g, '1').replace(/{language\??}/g, '*').replace(/{inputEncoding\??}/g, 'UTF-8').replace(/{outputEncoding\??}/g, 'UTF-8'), [ico], charset);
callback('load', d);
},
onerror: (e) => {
callback('error', e);
},
ontimeout: (e) => {
callback('error', e);
}
});
}
function initMycroft() {
if (location.hostname !== "mycroftproject.com") return;
_GM_addStyle(`
.searchJumper-loading {
animation-name: changeScale;
animation-duration: 2.5s;
animation-iteration-count: infinite;
}
@keyframes changeScale {
0% {
-webkit-transform:rotate(0deg) scale(1);
-moz-transform:rotate(0deg) scale(1);
transform:rotate(0deg) scale(1);
}
50% {
-webkit-transform:rotate(180deg) scale(1.5);
-moz-transform:rotate(180deg) scale(1.5);
transform:rotate(180deg) scale(1.5);
}
100% {
-webkit-transform:rotate(360deg) scale(1);
-moz-transform:rotate(360deg) scale(1);
transform:rotate(360deg) scale(1);
}
}
`);
let checkLinks = () => {
let installLinks = document.querySelectorAll("img.icon~a[href^='/install']");
if (installLinks.length <= 0) return;
let isLoading = false;
[].forEach.call(installLinks, installLink => {
if (installLink.previousElementSibling && installLink.previousElementSibling.classList.contains("searchJumperIcon")) return;
if (installLink.previousElementSibling && installLink.previousElementSibling.previousElementSibling && installLink.previousElementSibling.previousElementSibling.classList.contains("searchJumperIcon")) return;
let urlMatch = installLink.href.match(/\?id=(\d+)&basename=(.+?)&/);
if (urlMatch === null) {
return;
}
let icon = document.createElement("img");
icon.className = "icon searchJumperIcon";
icon.style.cssText = "border: 1px solid #4c4c4c; border-radius: 9px; box-sizing: border-box; margin-right: 4px; cursor: pointer;";
icon.title = "Add to SearchJumper";
icon.src = logoBase64;
installLink.parentNode.insertBefore(icon, installLink);
icon.onclick = e => {
if (isLoading) return;
isLoading = true;
icon.classList.add("searchJumper-loading");
showSiteAddFromOpenSearch(`https://mycroftproject.com/installos.php/${urlMatch[1]}/${urlMatch[2]}.xml`, (type, e) => {
isLoading = false;
icon.classList.remove("searchJumper-loading");
if (type != 'load') {
_GM_notification(e.statusText || e.error);
}
});
};
});
};
checkLinks();
let checkInterval = setInterval(() => {
checkLinks();
}, 1000);
window.addEventListener("load", e => {
clearInterval(checkInterval);
checkLinks();
});
}
function initView() {
searchBar = new SearchBar();
}
function initAllPage() {
if (!isAllPage) return;
searchBar.appendBar();
searchBar.showAllSites();
setTimeout(() => {
searchBar.con.style.zIndex = 0;
}, 5);
if (location.hash) {
let hash = location.hash.slice(1);
try {
hash = decodeURIComponent(hash);
} catch (e) {}
searchBar.searchJumperInputKeyWords.value = hash;
} else if (location.search) {
let search = location.search.slice(1).split("&");
let _keyWords, _engine, _self;
search.forEach(s => {
let sArr = s.split("=");
let k = sArr[0], v = sArr[1];
try {
v = decodeURIComponent(v);
} catch (e) {}
switch(k) {
case "kw":
_keyWords = v;
break;
case "engine":
_engine = v;
break;
case "self":
_self = v;
break;
}
});
if (_keyWords) {
searchBar.searchJumperInputKeyWords.value = _keyWords || "";
}
if (_engine) {
searchBar.searchBySiteName(_engine, {}, !!_self);
}
}
getBody(document).style.cssText = `
zoom: 1;
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
background-position: center 0;
background-repeat: no-repeat;
background-size: cover;
-webkit-background-size: cover;
-o-background-size: cover;
overflow: hidden;
`;
if (searchData.prefConfig.bgUrl) {
allPageBgUrl = searchData.prefConfig.bgUrl;
if (allPageBgUrl.length) {
getBody(document).style.backgroundImage = `url("${allPageBgUrl}")`;
return;
}
}
storage.getItem("allPageBg", allPageBg => {
if (allPageBg) {
allPageBgUrl = allPageBg.url;
getBody(document).style.backgroundImage = `url("${allPageBg.base64 || allPageBgUrl}")`;
} else allPageBg = {url: ""};
if (ext) {
chrome.runtime.sendMessage({action: "getBingBG", detail: {curBgUrl: allPageBg.url}}, function(r) {
if (r) {
allPageBg = r;
storage.setItem("allPageBg", allPageBg);
allPageBgUrl = allPageBg.url;
getBody(document).style.backgroundImage = `url("${allPageBg.base64 || allPageBgUrl}")`;
}
});
return;
}
_GM_xmlhttpRequest({
method: 'GET',
url: "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&pid=hp&video=1&n=1",
onload: function(result) {
var jsonData = null;
try {
jsonData = JSON.parse(result.responseText);
var bgUrl = jsonData.images[0].url;
if (!/^https?:\/\//.test(bgUrl)) {
bgUrl = "https://global.bing.com" + bgUrl;
}
allPageBgUrl = bgUrl;
if (bgUrl == allPageBg.url) return;
_GM_xmlhttpRequest({
method: 'GET',
url: bgUrl,
responseType: "blob",
onload: function(r) {
var blob = r.response;
var fr = new FileReader();
fr.readAsDataURL(blob);
fr.onload = function (e) {
var base64ImgData = e.target.result;
allPageBg = {url: bgUrl, base64: base64ImgData};
storage.setItem("allPageBg", allPageBg);
};
}
});
if (!allPageBg.base64) getBody(document).style.backgroundImage = `url("${bgUrl}")`;
} catch (e) {
console.log(e);
}
}
});
});
}
async function initRun() {
await searchBar.initRun();
initListener();
initAllPage();
}
async function sleep(time) {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
})
}
async function initData() {
let _searchData = await new Promise((resolve) => {
storage.getItem("searchData", data => {
resolve(data);
});
});
cacheKeywords = await new Promise((resolve) => {
storage.getItem("cacheKeywords", data => {
resolve(data || '');
});
});
cacheFilter = await new Promise((resolve) => {
storage.getItem("cacheFilter", data => {
resolve(data || '');
});
});
disableState = await new Promise((resolve) => {
storage.getItem("disableState", data => {
resolve(data || false);
});
});
tipsStorage = await new Promise((resolve) => {
storage.getItem("tipsStorage", data => {
resolve(data || []);
});
});
lastSign = await new Promise((resolve) => {
storage.getItem("lastSign", data => {
resolve(data || false);
});
});
storage.setItem("lastSign", false);
inPagePostParams = await storage.getListItem("inPagePostParams", location.hostname);
cacheIcon = await new Promise((resolve) => {
storage.getItem("cacheIcon", data => {
resolve(data || {});
});
});
historySites = await new Promise((resolve) => {
storage.getItem("historySites", data => {
resolve(data || []);
});
});
historyType = await new Promise((resolve) => {
storage.getItem("historyType", data => {
resolve(data || '');
});
});
sortTypeNames = await new Promise((resolve) => {
storage.getItem("sortTypeNames", data => {
resolve(data || {});
});
});
sortSiteNames = await new Promise((resolve) => {
storage.getItem("sortSiteNames", data => {
resolve(data || {});
});
});
globalInPageWords = await new Promise((resolve) => {
storage.getItem("globalInPageWords", data => {
resolve(data || '');
});
});
navEnable = await new Promise((resolve) => {
storage.getItem("navEnable", data => {
resolve(typeof data === "undefined" ? true : data);
});
});
referrer = await new Promise((resolve) => {
storage.getItem("referrer", data => {
resolve(data || "");
});
});
disableHighlight = await new Promise((resolve) => {
storage.getItem("disableHighlight", data => {
resolve(data || "");
});
});
lastHighlight = await new Promise((resolve) => {
storage.getItem("lastHighlight", data => {
resolve(data || "");
});
});
allPageNewMode = await new Promise((resolve) => {
storage.getItem("allPageNewMode", data => {
resolve(data || false);
});
});
lastAddType = await new Promise((resolve) => {
storage.getItem("lastAddType", data => {
resolve(data || "");
});
});
if (_searchData) {
searchData = _searchData;
lastModified = searchData.lastModified;
}
if (!searchData.lastModified) {
searchData.sitesConfig = sitesConfig;
}
if (searchData.prefConfig.lang && searchData.prefConfig.lang != '0') {
lang = searchData.prefConfig.lang;
}
setLang();
if (searchData.prefConfig.firstRun && (ext || storage.supportCrossSave())) {
searchData.prefConfig.firstRun = false;
storage.setItem("searchData", searchData);
setTimeout(() => {
storage.getItem("searchData", data => {
if (data.prefConfig.firstRun === false) {
_GM_openInTab(firstRunPage, {active: true, insert: true});
}
});
}, 100);
}
//旧版兼容
if (typeof searchData.prefConfig.customSize === "undefined") {
searchData.prefConfig.customSize = 100;
}
if (typeof searchData.prefConfig.tilesZoom === "undefined") {
searchData.prefConfig.tilesZoom = 100;
}
if (typeof searchData.prefConfig.tipsZoom === "undefined") {
searchData.prefConfig.tipsZoom = 100;
}
if (typeof searchData.prefConfig.typeOpenTime === "undefined") {
searchData.prefConfig.typeOpenTime = 250;
}
if (typeof searchData.prefConfig.longPressTime === "undefined") {
searchData.prefConfig.longPressTime = 500;
}
if (typeof searchData.prefConfig.cacheSwitch === "undefined") {
searchData.prefConfig.cacheSwitch = false;
}
if (typeof searchData.prefConfig.noIcons === "undefined") {
searchData.prefConfig.noIcons = false;
}
if (typeof searchData.prefConfig.noAni === "undefined") {
searchData.prefConfig.noAni = false;
}
if (typeof searchData.prefConfig.quickAddRule === "undefined") {
searchData.prefConfig.quickAddRule = true;
}
if (typeof searchData.prefConfig.multiline === "undefined") {
searchData.prefConfig.multiline = 2;
}
if (typeof searchData.prefConfig.multilineGap === "undefined") {
searchData.prefConfig.multilineGap = 1000;
}
if (typeof searchData.prefConfig.historyLength === "undefined") {
searchData.prefConfig.historyLength = 0;
}
if (typeof searchData.prefConfig.dragToSearch === "undefined") {
searchData.prefConfig.dragToSearch = true;
}
if (typeof searchData.prefConfig.firstFiveWordsColor === "undefined") {
searchData.prefConfig.firstFiveWordsColor = [];
}
if (typeof searchData.prefConfig.inPageWordsStyles === "undefined") {
searchData.prefConfig.inPageWordsStyles = [];
}
if (typeof searchData.prefConfig.rightMouse === "undefined") {
searchData.prefConfig.rightMouse = true;
}
if (typeof searchData.prefConfig.mouseLeaveToHide === "undefined") {
searchData.prefConfig.mouseLeaveToHide = true;
}
if (typeof searchData.prefConfig.currentTypeFirst === "undefined") {
searchData.prefConfig.currentTypeFirst = true;
}
if (typeof searchData.prefConfig.disableAddon === "undefined") {
searchData.prefConfig.disableAddon = {};
}
if (typeof searchData.prefConfig.suggestType === "undefined") {
if (lang === "zh-CN") {
searchData.prefConfig.suggestType = "baidu";
} else searchData.prefConfig.suggestType = "google";
}
if (typeof searchData.prefConfig.syncBuild === "undefined") {
searchData.prefConfig.syncBuild = true;
}
if (searchData.prefConfig.minSizeMode) {
searchData.prefConfig.disableAutoOpen = false;
searchData.prefConfig.disableTypeOpen = false;
}
if (ext) {
configPage = chrome.runtime.getURL('config/index.html');
if (!searchData.prefConfig.configPage) {
searchData.prefConfig.configPage = configPage;
}
} else if (searchData.prefConfig.configPage) {
configPage = searchData.prefConfig.configPage;
} else {
searchData.prefConfig.configPage = configPage;
}
}
function globMatch(first, second) {
if (first === '*') {
return true;
}
if (first.length == 0 && second.length == 0){
return true;
}
if (first.length > 1 && first[0] == '*' &&
second.length == 0){
return false;
}
if ((first.length > 1 && first[0] == '?') ||
(first.length != 0 && second.length != 0 &&
first[0] == second[0])){
return globMatch(first.substring(1),
second.substring(1));
}
if (first.length > 0 && first[0] == '*'){
return globMatch(first.substring(1), second) ||
globMatch(first, second.substring(1));
}
return false;
}
if (href.indexOf("#searchJumperMin") != -1) {
inMinMode = true;
if (href.indexOf("#searchJumperMinPost") != -1) {
window.history.replaceState(null, '', href.replace(/#searchJumperMin(Post)?/, ""));
} else {
if (href.indexOf("#searchJumperMinMobile") != -1) {
Object.defineProperty(Object.getPrototypeOf(navigator), 'userAgent', { get:function() { return mobileUa }});
_GM_xmlhttpRequest({
method: 'GET',
url: location.href,
headers: {
referer: location.href,
"User-Agent": mobileUa
},
onload: function(d) {
document.open();
document.write(d.response);
document.close();
},
onerror: function(){
},
ontimeout: function(){
}
});
return;
}
window.history.replaceState(null, '', location.href.replace(/#searchJumperMin(Mobile)?/, ""));
}
}
if (document.title == 'SearchJumper Multi') return;
var inited = false;
var checkGlobalIntv, flashTitleIntv, defaultTitle;
async function init(cb) {
if (inited) {
if (cb) cb();
return;
}
inited = true;
preAction();
await initData();
if (disableState) return;
if (searchData.prefConfig.blacklist && searchData.prefConfig.blacklist.length > 0) {
let commentStart = false;
for (let i = 0; i < searchData.prefConfig.blacklist.length; i++) {
let curGlob = searchData.prefConfig.blacklist[i];
if (!curGlob) continue;
if (curGlob.indexOf("//") == 0) continue;
if (commentStart) {
if (/\*\/$/.test(curGlob)) {
commentStart = false;
}
continue;
}
if (curGlob.indexOf("/*") == 0) {
commentStart = true;
continue;
}
if (curGlob.indexOf("/") == 0) {
let regMatch = curGlob.match(/^\/(.*)\/(\w*)$/);
if (regMatch && new RegExp(regMatch[1], regMatch[2]).test(href)) {
return;
}
} else if (globMatch(curGlob, href)) {
return;
}
}
}
initView();
await initConfig();
initMycroft();
initRun();
if (cb) cb();
defaultTitle = document.title;
}
function checkVisibility() {
if (document.hidden) {
if (searchBar) searchBar.closeShowAll();
else return;
if (!searchData.prefConfig.globalSearchNow) return;
checkGlobalIntv = setInterval(async () => {
let oldGlobalInPageWords = globalInPageWords;
globalInPageWords = await storage.getItem("globalInPageWords");
if ((oldGlobalInPageWords || '') == (globalInPageWords || '')) return;
searchBar.refreshPageWords();
if (searchBar.navMarks.innerHTML) {
clearInterval(checkGlobalIntv);
clearInterval(flashTitleIntv);
defaultTitle = document.title;
flashTitleIntv = setInterval(() => {
document.title = document.title == defaultTitle ? '🚩' : defaultTitle;
}, 500);
}
}, parseInt(500 + Math.random() * 500));
return;
}
init(async () => {
if (isInConfigPage || searchData.prefConfig.syncBuild) {
searchData = await storage.getItem("searchData");
if (searchBar && searchData.lastModified && lastModified != searchData.lastModified) {
searchBar.refreshEngines();
document.dispatchEvent(new Event('dataChanged'));
}
}
let oldGlobalInPageWords = globalInPageWords || '';
storage.getItem("globalInPageWords", data => {
globalInPageWords = (data || '');
if (oldGlobalInPageWords != globalInPageWords) {
if (searchBar) searchBar.refreshPageWords();
}
});
let oldNavEnable = navEnable || false;
storage.getItem("navEnable", data => {
navEnable = (typeof data === "undefined" ? true : data);
if (oldNavEnable != navEnable) {
if (searchBar) searchBar.refreshNav();
}
});
});
}
var waiting = false;
function visibilitychangeHandler() {
if (!document.head || !getBody(document) || inIframe || disableState) return;
if (searchData.prefConfig.globalSearchNow) {
clearInterval(checkGlobalIntv);
clearInterval(flashTitleIntv);
if (document.hidden) {
defaultTitle = document.title;
} else if (defaultTitle) document.title = defaultTitle;
}
if (waiting) return;
waiting = true;
setTimeout(() => {
checkVisibility();
waiting = false;
}, 500);
}
storage.getItem("postUrl", postUrl => {
if (postUrl && postUrl[0].indexOf(location.hostname.replace(/.*\.(\w+\.\w+)/, "$1")) != -1) {
storage.setItem("postUrl", '');
submitByForm(postUrl[1], postUrl[0], '_self');
} else {
if (document.head && getBody(document)) {
init();
} else {
let checkReady = () => {
if (document.head && getBody(document)) {
init();
} else {
setTimeout(() => {
checkReady();
}, 10);
}
};
checkReady();
}
document.addEventListener('visibilitychange', visibilitychangeHandler);
}
});
}
if (document && document.documentElement) {
run();
} else {
let checkReady = () => {
if (document && document.documentElement) {
run();
} else {
setTimeout(() => {
checkReady();
}, 10);
}
};
checkReady();
}
})();