Enhanced word highlight

Enhanced keywords highlight for Search Engines and All !

目前为 2017-10-13 提交的版本。查看 最新版本

// ==UserScript==
// @name           Enhanced word highlight
// @namespace      http://userscripts.org/users/86496
// @description    Enhanced keywords highlight for Search Engines and All !
// @include        http://*
// @include        https://*
// @exclude        http://maps.google.com/*
// @exclude        https://maps.google.com/*
// @grant          GM_log
// @grant          GM_xmlhttpRequest
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_openInTab
// @grant          GM_registerMenuCommand
// @version        1.6.0
// ==/UserScript==

// great credit for original script wright os0x [http://userscripts.org/scripts/show/43419]
// hzhbest modded  | detail in http://userscripts.org/scripts/show/64877

//console.time("highlight");
//var l = function(){var len = arguments.length; var tx=''; for(i=0;i<len;i++){tx += (arguments[i] + '; ');} GM_log(tx.toString())};//+'['+len+']'
function l(message) {if (typeof console == 'object') {console.log(message)} else {GM_log(message)}}
(function word_hightlight(loaded){
	
	//if (window.top != window.self) return; //don't run on frames or iframes
    
	// check browser
	if (!loaded && window.opera && document.readyState == 'interactive') {
		document.addEventListener('DOMContentLoaded', function(){
			loaded = true;
			word_hightlight(true);
		}, false);
		window.addEventListener('load', function(){
			if (!loaded)
				word_hightlight(true);
		}, false);
		return;
	}
	if (document.contentType && !/html/i.test(document.contentType))
		return;
	// check api
	if (typeof GM_getValue == "function") {
		var getv = GM_getValue;
		var setv = GM_setValue;
	} else { // workaround functions, creadit to ww_start_t
		var setv = function(cookieName, cookieValue, lifeTime){
			if (!cookieName) {return;}
			if (lifeTime == "delete") {lifeTime = -10;} else {lifeTime = 31536000;}
			document.cookie = escape(cookieName)+ "=" + escape(getRecoverableString(cookieValue))+
				";expires=" + (new Date((new Date()).getTime() + (1000 * lifeTime))).toGMTString() + ";path=/";
		};
		var getv = function(cookieName, oDefault){
			var cookieJar = document.cookie.split("; ");
			for (var x = 0; x < cookieJar.length; x++ ) {
				var oneCookie = cookieJar[x].split("=");
				if (oneCookie[0] == escape(cookieName)) {
					try {
						eval('var footm = '+unescape(oneCookie[1]));
					} catch (e) {return oDefault;}
					return footm;
				}
			}
			return oDefault;
		};
	}
		
//{	values >
	var isOpera = !!this.opera,
		isFirefox = !!this.Components,
		isChromium = !!this.chromium,
		isSafari = this.getMatchedCSSRules && !isChromium;
		
	var STYLE_COLOR = ['#FFFF80','#99ccff','#ff99cc','#66cc66','#cc99ff','#ffcc66','#66aaaa','#dd9966','#aaaaaa','#dd6699'];
	var BORDER_COLOR = ['#aaaa20','#4477aa','#aa4477','#117711','#7744aa','#aa7711','#115555','#884411','#555555','#881144'];
	var STYLE_COLOR_2 = ['#FFFFa0','#bbeeff','#ffbbcc','#88ee88','#ccbbff','#ffee88','#88cccc','#ffbb88','#cccccc','#ffaabb'];
	var BORDER_COLOR_2 = ['#aaaa40','#6699aa','#aa6699','#339933','#9966aa','#aa9933','#337777','#aa6633','#777777','#aa3366'];
	var but_c = '#99cc99', but_ca = '#FFD000', but_cd = '#999999', but_cb = '#669966'; // button normal/active/disable background color/border color.
	
	// Initialize value
	var PRE = 'wordhighlight', ID_PRE = PRE + '_id', ST_PRE = PRE + '_store', PO_PRE = PRE + '_position', CO_PRE = PRE + '_config';
	var STYLE_CLASS = '0123456789'.split('').map(function(a,i){return PRE + '_word'+i;});
	var setuped = false;
	var highlight_off = false;
	var addKeyword = true;
	var keyword = '', words = [], word_lists = [], word_inputs_list, layers, positions = [];
	var words_off = [];
	var xp_all = new $XE('descendant::span[starts-with(@name,"' + PRE + '_word")]', document.body);
	var keyCodeStr = {
		8:  'BAC',
		9:  'TAB',
		10: 'RET',
		13: 'RET',
		27: 'ESC',
		33: 'PageUp',
		34: 'PageDown',
		35: 'End',
		36: 'Home',
		37: 'Left',
		38: 'Up',
		39: 'Right',
		40: 'Down',
		45: 'Insert',
		46: 'Delete',
		112: 'F1',
		113: 'F2',
		114: 'F3',
		115: 'F4',
		116: 'F5',
		117: 'F6',
		118: 'F7',
		119: 'F8',
		120: 'F9',
		121: 'F10',
		122: 'F11',
		123: 'F12'
	};
	var whichStr = {
		32: 'SPC'
	};
	var htmlDoc = isChromium ? document.implementation.createHTMLDocument('hogehoge') : document;
	var highlight_reset = function(){};
	var canvas, cw, c2context, nav;
	var root = /BackCompat/i.test(document.compatMode) ? document.body : document.documentElement;
	var CanvasWidth = 150;
	var ratio = 1;
	var aside, section, td0, lock, edit, off, text_input, posi_tip, posi_tip_timer, inputBOX;  // panel elements
	var sheet, main_sheet, move_sheet, inst_sheet;  // style sheets
	
	//language detection
	if ((navigator.userAgent.toLowerCase().indexOf('zh-') == -1) || ((navigator.userAgent.toLowerCase().indexOf('firefox') != -1) && (navigator.language.indexOf('zh-') == -1))) {
		_L = 0;
	} else _L = 1;
	//var _L = (!!(navigator.userAgent.toLowerCase().indexOf('zh-') == -1))? 0:1;
	//if(navigator.userAgent.toLowerCase().indexOf('firefox') != -1) 
	//{_L = (!!(navigator.language.indexOf('zh-') == -1))? 0:1;} // Thanks to SoIN(http://userscripts.org/users/302257)
	var _ti = { // en/zh locale string for tooltip.
		edit: ['Edit current keywords','编辑现有关键词'],
		edit_a: ['Confirm editing keywords','确认编辑关键词'],
		off:  ['Toggle all keywords\' highlight','切换全部关键词的高亮'],
		td0:  ['Double-click to minimize the panel','双击最小化面板'],
		td0_a:  ['Double-click to restore EWH panel','双击恢复 EWH 面板'],
		lock: ['Lock current set of keywords','锁定当前的关键词组'],
		lock_a: ['Current locked keyword(s):','当前锁定的关键词组:'],
		lock_u: ['Function not supported by this browser','此浏览器不支持该功能'],
		close: ['Close Enhanced word highlight','关闭关键词高亮'],
		kwL:  ['Left click to the next; Right click to the previous','左击跳到下一个;右击跳到上一个'],
		check: [['Toggle highlight of "','"'],['切换“','”的高亮']],
		mapl:['Toggle highlight map locking status','切换高亮分布图的锁定状态'],
		ad_nw: ['Toggle add/new keywords for highlight','切换添加/取代关键词的高亮'],
		subm: ['Submit keywords','提交关键词'],
		clos: ['Close input box','关闭输入框']
	};
	var _di = { // en/zh locale string for dialog.
		update: [['There is an update available for the Greasemonkey script "','."\nWould you like to go to the install page now?','No update is available for "','."','An error occurred while checking for updates:\n',' - Manual Update Check'],
				['发现 GM 脚本“','”有更新,\n是否现在打开脚本发布页?','没找到“','”脚本的更新。','检查更新时出现了一个错误:\n',' - 手动检查更新']],
		confT:  ['Enhanced word highlight Advanced Config','Enhanced word highlight 高级设置'],
		conf:   [['What auto-pager tool do you mostly use?',
				'Turn off highlight of short keywords by default?',
				'Disable auto-highlight (auto-capture keywords for highlight) ?',
				'Sort keyword for more accurate highlight (Recommended, except for regular expression users)',
				'Save panel position',
				'Show indicator bar when navigating'],
				['你主要用那种自动翻页工具?',
				'是否默认停用短关键词的高亮?',
				'是否禁用自动高亮(自动抓取关键词来高亮)?',
				'排列关键词以更准确高亮(推荐;需要高亮正则表达式的用户除外)',
				'保存面板位置',
				'查找关键词时显示指示条']],
		confR:  [[['Autopagerize GM script','Autopager extension','Other (can handle all auto-pager tools but works slow)'],
				['Don\'t turn off','One-letter/digit word','One- and two-letter/digit word'],
				['Enable','Completely disable','Disable on pages opened from supported search results','Disable on supported search result pages']],
				[['Autopagerize GM 脚本','Autopager 扩展','其他(能应付任何自动翻页工具但运作较慢)'],
				['否','是;针对单个字母/数字','是,针对单/两个字母/数字'],
				['不禁用','完全禁用','仅在从支持的搜索结果中打开的页面上禁用','仅在支持的搜索结果页面上禁用']]]
	};
//}
		
	var urlArr = [], queryArr = [];

//{	Config I >
// #### Config I #### --------------------------{{
	
	// List of url patterns; Array('NAME', 'KEYWORD_PREFIX', 'URL_PATTERN')
	urlArr[0] = ['Google',	 'q=',	 'www.google.'];
	urlArr[1] = ['Yahoo',	 'p=',	 'search.yahoo.c'];
	urlArr[2] = ['Baidu',	 'wd=',	 'www.baidu.com'];
	urlArr[3] = ['Baidu',	 'word=', '.baidu.com'];
	urlArr[4] = ['Ask',		 'q=',	 'www.ask.com'];
	urlArr[5] = ['Bing',	 'q=',	 '.bing.com'];
	urlArr[6] = ['Youdao',	 'q=',	 'www.youdao.com'];
	
	// List of IDs of query input boxes; Array('#SEARCHBOX_ID#', 'SEARCHPAGE SPEC_URL')
	queryArr[0] = ['query', '/search'];		// most common
	queryArr[1] = ['search', ''];				// most common
	queryArr[2] = ['script_q', 'userscripts.org/scripts/search'];			// userscripts.org
	queryArr[3] = ['top-search-input', 'www.verycd.com/search/folders'];	// verycd.com
	queryArr[4] = ['search-q', '/search'];		// addons.mozilla.org
		
	// keybinds
	var KEY_NEXT = 'n';		// "n"			Next occurrence
	var KEY_PREV = 'N';		// "Shift-n"	Previous occurrence
	var KEY_SEARCH = 'M-/';	// "Alt-/"		Add keywords
	var KEY_OFF = 'M-,';	// "Alt-,"		Suspend highlight
	var KEY_CLOSE = 'C-M-/';	// "Ctrl-Alt-/"		Disable highlight
	var KEY_EDIT = 'M-.';	// "Alt-."		Edit highlight
	var KEY_REFRESH = 'r';	// "r"			Refresh highlight

	// delay of highlighting (ms)
	var delay = 500;
	
	// instant highlight selected keywords
	var instant = true;

	// restore focus and scroll position after closing keyword input box with shortcut key?
	// mainly useful for keyboard navigation, not recommend for mouse navigation.
	var refocus = false;
	
	// minimize the panel initially?
	var panel_hide = false;

// #### Config I #### --------------------------}}
//}
	if (window.top != window.self) panel_hide = true; //hide panel in iframes

//{	Config II >
// #### Config II #### --------------------------{{
	// What's your main auto-pager tool?
	// 0 - Autopagerize (GM script)
	// 1 - AuroPager (Firefox Extension)
	// 2 - Other (Other auto-pager scripts, site-specific scripts, bookmarklets, etc.)
	//<!> From top option to botom one, the compatibility of the script
	//	will be strengthened while the performance of highlight will be lower.
	var ap_option = 0;
	
	// turn off short keywords (one or two letters or number) by default?
	//	0-no, 1-one letter, 2-one or two letters
	var off_short_words = 1;

	// Stop auto-highlight on supported pages?
	// 0-no, 1-yes, 2-only those from search results, 3-only search results
	var no_auto_hili = 0;
	
	// sort keywords? 0-no, 1-yes 
	//<!> Setting this to "yes" will produce better highlight result,
	//	while "no" will perform faster and support ReExp input better.
	var sort_keywords = 1;
	
	// save panel position?
	var save_panel_pos = false;
	
	// show indicator bar when navigating?
	var show_indc_bar = false;
// #### Config II #### --------------------------}}
//}

	// var config = {
		// key: {next:'n', prev:'N', srch:'C-/', off:'M-.', clos:'C-M-/', edit:'M-/', rfsh:'r'},
		// delay:500,
		// instant:true,
		// refocus:false,
		
		// ap_comp: {
			// name: '',
			// val: getv('ap_comp', 0),
			// dom: {label:'LABLE', type:'radio', set:['set1','set2','set3']}
		// },
		// short_w: {
			// name: '',
			// val: getv('short_w', 1),
			// dom: {label:'LABLE', type:'radio', set:['set1','set2','set3']}
		// },
		// sort_kw: {
			// name: '',
			// val: getv('sort_kw', true),
			// dom: {label:'LABLE', type:'checkbox', set:['set1']}
		// }
	// }

	
	// GM APIs available?
	if (typeof GM_getValue == "function") var gm_ok = true;
	// Configs
	if (!gm_ok) {


		//
		var Ewh_configs = [ap_option, off_short_words, no_auto_hili, sort_keywords, save_panel_pos, show_indc_bar];
	} else {
		var Ewh_configs = GM_getValue(CO_PRE, '0|1|0|1|0|0').split('|');
	}
	for (i in Ewh_configs) {Ewh_configs[i] = Number(Ewh_configs[i]);}
	// Locked keywords
	if (gm_ok) var keyword_store = GM_getValue(ST_PRE);
	// Saved position
	var panel_pos_arr = ['right:-1px;','bottom:-1px;'];
	if (Ewh_configs[4] && gm_ok) panel_pos_arr = GM_getValue(PO_PRE, panel_pos_arr.join('|')).split('|');
	// Configs menu
	if (gm_ok) window.addEventListener('load', function(){GM_registerMenuCommand(_di.confT[_L], config_box);}, false);
	
	if (gm_ok) {
		unsafeWindow.EWH_iSearch = function() {instant_search(false, null);};
		unsafeWindow.EWH_cClose = function() {command_close();};
	}

	// main process
	init_keyboard();
	if (load_keyword() !== false || init_keyword() !== false) {
		//window.addEventListener('load', go, false);
		setTimeout(go, delay);
	}
	
	// var oldurl = window.location.href;
	// window.addEventListener('DOMNodeInserted', function(e){ l(window.location.href);
		// if (window.location.href !== oldurl) {
			// if (load_keyword() !== false || init_keyword() !== false) {
				
				// setTimeout(go, delay*2);
			// }
		// }
	// }, false);
	
	function go(){
	setup();
	
/*	// CHECK FOR UPDATE //
	if (gm_ok) {var SUC_script_num = 64877;
	try{function updateCheck(forced){if ((forced) || (parseInt(GM_getValue('SUC_last_update', '0')) + 86400000 <= (new Date().getTime()))){try{GM_xmlhttpRequest({method: 'GET',url: 'http://userscripts.org/scripts/source/'+SUC_script_num+'.meta.js?'+new Date().getTime(),headers: {'Cache-Control': 'no-cache'},onload: function(resp){var local_version, remote_version, rt, script_name;rt=resp.responseText;GM_setValue('SUC_last_update', new Date().getTime()+'');remote_version=parseInt(/@uso:version\s*(.*?)\s*$/m.exec(rt)[1]);local_version=parseInt(GM_getValue('SUC_current_version', '-1'));if(local_version!=-1){script_name = (/@name\s*(.*?)\s*$/m.exec(rt))[1];GM_setValue('SUC_target_script_name', script_name);if (remote_version > local_version){if(confirm(_di.update[_L][0]+script_name+_di.update[_L][1])){GM_openInTab('http://userscripts.org/scripts/show/'+SUC_script_num);GM_setValue('SUC_current_version', remote_version);}}else if (forced)alert(_di.update[_L][2]+script_name+_di.update[_L][3]);}else GM_setValue('SUC_current_version', remote_version+'');}});}catch (err){if (forced)alert(_di.update[_L][4]+err);}}}GM_registerMenuCommand(GM_getValue('SUC_target_script_name', 'BPT') + _di.update[_L][5], function(){updateCheck(true);});updateCheck(false);}catch(err){}
	}*/
	
	}

	
// Functions
	
	function highlight(doc, ext_word) {
		var _words = words.filter(function(w,i){return !words_off[i];});
		if (_words.length <= 0)
			return;
		var _index;
		if (ext_word && ext_word.words) {
			_words = ext_word.words;
			_index = ext_word.index;
		}
		var exd_words, xw;
		if (_words.length === 1 && _words[0].exp) {
			exd_words = _words.map(function(e){return e.exp;});
			xw = '';
		} else {
			exd_words = _words.map(function(w){return w.test ? w : new RegExp('(' + w.replace(/\W/g,'\\$&') + ')(?!##)', 'ig');});
			xw = ' and (' + _words.map(function(w){return ' contains(translate(self::text(),"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ"),'+escapeXPathExpr(w.toUpperCase())+') ';}).join(' or ') + ') ';
		}
		$X('descendant::text()[string-length(normalize-space(self::text())) > 0 ' + xw +' and not(ancestor::textarea or ancestor::script or ancestor::style or ancestor::aside)]', doc).forEach(function(text_node) {
			var df, text = text_node.nodeValue, id_index = 0,
			parent = text_node.parentNode, range = document.createRange(), replace_strings = [],
			new_text = reduce(exd_words, function(text,ew,i) {
				var _i = _index || i;
				return text.replace(ew,function($0,$1) {
					replace_strings[id_index] = '<span id="' + ID_PRE + id_index + '" class="' + STYLE_CLASS[_i%10] + '" name="'+PRE+'_word'+_i+'">' + $1 + '</span>';
					return '##'+(id_index++)+'##';
				});
			}, text).
				replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').
				replace(/##(\d+)##/g, function($0,$1) {
				return replace_strings[$1] || '';
			});
			if (replace_strings.length) {
				try {
					if (isChromium) {
						range.selectNodeContents(htmlDoc.documentElement);
					} else {
						range.selectNode(text_node);
					}
					df = range.createContextualFragment(new_text);
					if (df.firstChild) parent.replaceChild(df, text_node);
					range.detach();
				} catch (e) {
					error(e);
				}
			}
		});
	}

	function addsheet() {
		if (!main_sheet) {
		var hilistyles = STYLE_COLOR.map(function(rgb,i){
			return 'span.' + PRE + '_word'+i+',.' + PRE + '_item'+i+'{background:'+rgb+'!important;}';
			});
		var borderstyles = BORDER_COLOR.map(function(rgb,i){
			return 'li.' + PRE + '_item'+i+'{outline:1px solid '+rgb+'!important;}';
			});
		sheet = addCSS([
			//Additional Style
			'span[class^="' + PRE + '_word"]{color:black!important;font:inherit!important;display:inline!important;margin:0!important;padding:0!important;text-align:inherit!important;float:none!important;position:static!important;}', //vertical-align:inherit !important;
			'#' + PRE + '_words, #' + PRE + '_words *{font-family: Arial ;}',
			'#' + PRE + '_words{line-height:1;position:fixed;z-index:60000;opacity:0.8;list-style-type:none;margin:0;padding:0;width:auto;max-width:100%;' + panel_pos_arr[0] + panel_pos_arr[1] +'}',
			'#' + PRE + '_words > section{clear:right;line-height:1;border:1px solid #666;/*border-left-width:10px;*/background:#fff;display:block;position:relative;}',
			'#' + PRE + '_words * {margin:0;padding:0;width:auto;height:auto;}',
			'#' + PRE + '_words:hover{opacity:1;}',
			'#' + PRE + '_words:hover > section{opacity:1;border-color:#333;}',
			'#' + PRE + '_words #_ewh_handle{background:#666;width:10px;cursor:move;}',
			'#' + PRE + '_words:hover #_ewh_handle{background:#333;}',
			'#' + PRE + '_words.ewh_hide #_ewh_handle{cursor:pointer;}',
//			'#' + PRE + '_words.ewh_hide:hover #_ewh_handle{width:10px;}',
//			'#' + PRE + '_words.ewh_hide > section form.' + PRE + '_ctrl > input.c_b{display:none;}',
			'#' + PRE + '_words > nav{display:none;width:100%;padding:3px;position:relative;}',
			'#' + PRE + '_words > nav > canvas.backport{background:rgba(0,0,0,0.5);cursor:pointer;position:absolute;right:6px;z-index:3;}',
			'#' + PRE + '_words > nav > canvas.viewport{background:rgba(79,168,255,0.7);cursor:default;position:absolute;bottom:0px;right:6px;}',//outline:6px solid rgba(79,168,255,0.7);
//			'#' + PRE + '_words > nav:hover > canvas.backport{background:rgba(0,0,0,0.5);}',
			'#' + PRE + '_words:hover > nav{display:block;}',
			'#' + PRE + '_words > nav._locked{display:block;}',
			'#' + PRE + '_words:hover > nav > canvas.backport{bottom:0px;}',
			'#' + PRE + '_words > nav._locked > canvas.backport{bottom:0px;}',
			'#' + PRE + '_words.ewh_edit{opacity:1;}',
			'#' + PRE + '_words.ewh_edit #' + PRE + '_word_inputs_list{display:none;}',
			'#' + PRE + '_words form.' + PRE + '_editor{display:none;}',
			'#' + PRE + '_words.ewh_edit form.' + PRE + '_editor{display:inline-block;}',
			'#' + PRE + '_words.ewh_edit form.' + PRE + '_editor input{min-width:80px;}',
			'#' + PRE + '_words li{display:inline-block;margin:0.1em 0.2em;line-height:1.3em;font-size:medium;}',
			'#' + PRE + '_words > section > * {vertical-align:middle;}',
			'#' + PRE + '_words > section td {border:none;}',
			'#' + PRE + '_words > section > h3.' + PRE + '_title{display:inline-block;background:#333;color:#fff;padding:0.1em 0.3em;border:none;margin:0 0.2em;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl{display:inline-block;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input{display:inline;width:1.3em;margin:0.1em 0.1em;background:'+ but_c +';border:1px solid '+ but_cb +';cursor:pointer;font-size:10pt;color:black;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input._active{background:'+ but_ca +';}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input._disable{background:'+ but_cd +' !important;cursor:default;}',
			'#' + PRE + '_words > section  form.' + PRE + '_ctrl > input:hover{outline:1px solid '+ but_cb +'!important;}',
			'#' + PRE + '_word_inputs_list {padding:0!important;margin:0.2em!important;display:inline-block;border:none!important;}',
			'#' + PRE + '_word_inputs_list > li{position:relative;padding:0 4px;}',
			'#' + PRE + '_word_inputs_list > li.ewh_disable{background:white!important;outline:1px solid #999!important;}',
			'#' + PRE + '_word_inputs_list > li > label{cursor:pointer;color:black!important;}',
			'#' + PRE + '_word_inputs_list > li > input{cursor:pointer;}',
//			'#' + PRE + '_word_inputs_list > li > label > input[type=image]{vertical-align:top;padding:0;height:12px;}',
			'#' + PRE + '_word_inputs_list > li > input[type=checkbox]{display:none;position:absolute;right:0px;top:0px;opacity:0.7;}',
			'#' + PRE + '_word_inputs_list > li:hover{outline-width:2px!important;}',
			'#' + PRE + '_word_inputs_list > li:hover > input[type=checkbox]{display:block;}',
			'#' + PRE + '_word_inputs_list > li > input[type=checkbox]:hover{opacity:1;}',
			'#' + PRE + '_words > section td+td+td > input {display:inline;width:1.3em;margin:0.1em 0.1em;background:#FAFAFA;border:1px solid #aaaaaa;cursor:pointer;font-size:10pt;color:black;}',
		].concat(hilistyles, borderstyles).join('\n'));
		main_sheet = true;
		}
		if (!move_sheet) addmovesheet()
	}
	
	function addmovesheet() {
		addCSS('.wordhighlight_em{outline:4px solid #FF7B00;-webkit-outline:4px solid #FF7B00;text-decoration:blink;}');
		move_sheet = true;
	}
	
	function setup(init) {
		setuped = true;
		addsheet();

	// build ui
		aside = creaElemIn('aside', document.body);
			aside.id = PRE + '_words';
		section = creaElemIn('section', aside);
		var table_COL = creaElemIn('table', section);
			table_COL.setAttribute('style', 'border:0;margin:0;padding:0;border-spacing:2px;border-collapse:separate!important;');
			table_COL.setAttribute('cellspacing', '0');
			table_COL.setAttribute('cellpadding', '0');
		var tbdy_COL = creaElemIn('tbody', table_COL);
		var tr_COL = creaElemIn('tr', tbdy_COL);
		td0 = creaElemIn('td', tr_COL);
			td0.id = '_ewh_handle';
			td0.title = _ti.td0[_L];
		var td1 = creaElemIn('td', tr_COL);
			td1.setAttribute('style', 'border-right: 1px solid black; padding:0.2em 0.3em 0 0;vertical-align:top;');//width:7.2em;
		var td2 = creaElemIn('td', tr_COL);
		var td3 = creaElemIn('td', tr_COL);
		var editor = creaElemIn('form', td2);
			editor.className = PRE + '_editor';
		text_input = creaElemIn('input', editor);
			text_input.type = 'text';
		var ctrl = creaElemIn('form', td1);
			ctrl.className = PRE + '_ctrl';
		var close_button = creaElemIn('input', ctrl);
			close_button.type = 'button';
			close_button.className = 'c_b';
			close_button.value = 'X';
			close_button.title = _ti.close[_L];
		off = creaElemIn('input', ctrl);
			off.type = 'button';
			off.value = 'O';
			off.title = _ti.off[_L];
		lock = creaElemIn('input', ctrl);
			lock.type = 'button';
			lock.value = 'L';
		edit = creaElemIn('input', ctrl);
			edit.type = 'button';
			edit.value = 'E';
			edit.title = _ti.edit[_L];
		word_inputs_list = creaElemIn('ul', td2);
			word_inputs_list.id = PRE + '_word_inputs_list';
			word_inputs_list.className = PRE + '_inputs';
		var maplock = creaElemIn('input', td3);
			maplock.type = 'button';
			maplock.value = '<';
			maplock.title = _ti.mapl[_L];

	// add interactivity
		edit.addEventListener('click',command_edit,false);
		off.addEventListener('click',command_off,false);
		close_button.addEventListener('click',command_close,false);
		editor.addEventListener('submit',function(e){
				command_edit();
				e.preventDefault();
			},false);
		if (gm_ok) {
			lock.title = _ti.lock[_L];
			lock.className = (keyword_store)? '_active' : '';
			lock.addEventListener('click',function(){
				if (aside.className == 'ewh_edit') return;
				if (keyword_store) {
					lock.className = '';
					lock.title = _ti.lock[_L];
					GM_setValue(ST_PRE, '');
					keyword_store = '';
	//				lock.value = 'Lock: Off';
				} else {
					lock.className = '_active';
					lock.title = _ti.lock_a[_L] + ' ' + keyword;
					GM_setValue(ST_PRE, keyword);
					keyword_store = keyword;
	//				lock.value = 'Lock: On';
				}
			},false);
		} else {
			lock.title = _ti.lock_u[_L];
			lock.className = '_disable';
		}
		td0.addEventListener('dblclick',function(evt){//l(panel_hide,window.innerWidth - aside.offsetLeft,1);
				if (panel_hide)	{//l('O');
					aside.style.right = '0px';
					aside.className = '';
					panel_hide = false;
					this.title = _ti.td0[_L];
				}else{//l(panel_hide);
					aside.style.right = (14 - aside.offsetWidth) +'px';
					aside.className = 'ewh_hide';
					panel_hide = true;//l(panel_hide,3);
					this.title = _ti.td0_a[_L];
				}
			}, false);
		maplock.addEventListener('click',function(){
				if(!nav.className) {nav.className = '_locked'; this.value = '>';}
				else {nav.className = ''; this.value = '<';}
			},false);
		
	// enable drag
		var drag = endrag(aside,{x:'right',y:'bottom'});
		drag.hook('__drag_begin', function(e){
			if (this.element && ((this.element.className === 'ewh_edit') || (this.element.className === 'ewh_hide'))) // || /^canvas$/i.test(e.target.localName) || /^lable$/i.test(e.target.localName))
				return false;
		});

	// build map
		nav = document.createElement('nav');
		aside.insertBefore(nav,aside.firstChild);
		canvas = creaElemIn('canvas', nav);
			canvas.className='backport';
		cw = creaElemIn('canvas', nav);
			cw.className='viewport';
		var c2 = c2context = canvas.getContext('2d');

	// /+drag codes by grea
		// scrolling per events
		this.perf = 2, this.perfic = 0;
		this.moveTo = function(evt){
			if (perfic++ % perf || !window.drgg) return;
			var x = (evt.offsetX || evt.layerX)/ratio - root.clientWidth/2;
			var y = (evt.offsetY || evt.layerY)/ratio - root.clientHeight/2;
			window.scrollTo(x, y);
		}
		with(canvas){
			addEventListener('mousedown', function(e){ window.drgg = true; moveTo(e); },false);
			addEventListener('mousemove', function(e){ moveTo(e); },false);
			addEventListener('mouseup', function(e){ window.drgg = false; moveTo(e); },false);
			addEventListener('mouseout', function(e){ window.drgg = false; moveTo(e); },false);
		}
	// +/codes end
		
	// add AutoPager page change detector
		if (Ewh_configs[0]) {
			this.pagef = 5, this.pagefic = 0;
			var docHeight = document.body.scrollHeight, pageChanged;
			this.checkpage = function(){
				if ((pagefic++ % pagef == 0) && (document.body.scrollHeight > docHeight)) {
					switch (Ewh_configs[0]) {
					case 1:
						after_load();
						break;
					case 2:
						resetup();
						break;
					}
					docHeight = document.body.scrollHeight;
				}
			}
		}

	// sync with map & check page
		window.addEventListener('scroll',function(){
			var x = window.pageXOffset * ratio;
			var y = window.pageYOffset * ratio;
			cw.style.bottom = (canvas.height - cw.height - y) + 'px';
			cw.style.right = (-x + 6) + 'px';
			if (Ewh_configs[0]) checkpage();
		},false);
		
	// go to highlight
		highlight(document.body);
		word_lists = create_inputlist(words);
		layers = xp_all.get();
		draw_wordmap();
		if (!Ewh_configs[0]) init_autopager();
		if (panel_hide && !init){
			aside.style.right = (14 - aside.offsetWidth) +'px';
			aside.className = 'ewh_hide';
			td0.title = _ti.td0_a[_L];
		}
	}

	function restore_words(words) {
		(words||xp_all.get()).forEach(function(layer,i){
			var parent = layer.parentNode;
			while (layer.firstChild){
				parent.insertBefore(layer.firstChild, layer);
			}
			parent.removeChild(layer);
		});
	}

	function draw_wordmap() {
		var c2 = c2context;

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址