// ==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 // @downloadURL none // ==/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 // #### 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] = '' + $1 + ''; return '##'+(id_index++)+'##'; }); }, text). replace(/&/g, '&').replace(//g, '>'). 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;