// ==UserScript== // @name Ultimate Search Highlighter // @version 1.30 // @description Highlights search terms on page, with summaries of results, and search engine integration. // @include * // ==/UserScript== /* USAGE * As a button (to be used in conjuction with an existing field): * 1) Enter the following lines into the address bar * opera:/button/Search,"javascript:opera.USH.run(opera.USH.check='%s','newSearch');",,"Highlight" + Show hidden popup menu & Search,"javascript:opera.USH.run(opera.USH.check='USHRegExp %s','newSearch');",,"Highlight" * 2) Drag the tab onto a toolbar and answer yes when asked if you want to add the button * * As a search field: * 1) Enter the following lines into the address bar * opera:/Edit/Search,"javascript:opera.USH.run(opera.USH.check='%s','newSearch');",,"Highlight" * 2) Drag the tab onto a toolbar and answer yes when asked if you want to add the field * * From the context menu (see http://operawiki.info/EditingINIFiles for details on how to edit the menu file) * 1) Add the following line to the [Hotclick Popup Menu] section * Item, "Highlight"=Go to page,"javascript:opera.USH.run(window.getSelection().toString(),'new');",1,,"Blank" * * As a keyboard shortcut (least trouble free method) * 1) Add the following as an action * Go to page,"javascript:opera.USH.run(null,'newBlank');",1 * * Visit the following thread if you have any questions/feedback * http://my.opera.com/community/forums/findpost.pl?id=1648805 */ (opera.USH = new function() { var preferences = { runOnLoad: true, // Run script on page load based on search engine referrer highlightOnLoad: true, // Highlight page automatically or just show toolbar toolbarHiddenOnLoad: false, // Toolbar is initially hidden toolbarAtBottom: false, // Show the toolbar at the bottom of the screen darkSkin: false, // Set to true if you are using a dark coloured Opera skin and you cant see the button text stripPluses: false, // Strip pluses from search string. For use when using Opera's search field useStopwords: false, // Highlight words ignored by search engines. Only used for search engine highlights useCookies: true, // Use cookies to store searches searchHiddenText: true, // Searches within text that is not visible to the user embedStyle: true, // Embed CSS via javascript. False if using external CSS keyShortcuts: ['0)', // The key for the 'Options' button '-_', // The key for the 'New' button '=+', // The key for the 'Toggle' button '\\|', // The key for the 'Close' button '9(', // The key that toggles the visibility of the toolbar '`'], // The toggle key. Enables or disables the other shortcuts. Search terms are 1-8 usePunctuation: false, // Allow matching of search terms regardless of punctuation wholeWordsOnly: true, // Only highlight whole words matchCase: false // Highlights are case sensitive }, colours = ['#ffff66','#A0FFFF','#99ff99','#ff9999','#ff66ff','#FF7F50','#00FF00','#7FFF00','#00BFFF','#FF00FF','#FFD700','#CD5C5C','#C0C0C0','#B0C4DE','#808000','#FFA500','#ADD8E6'], searchEngines = [ null, [1,,,'##(.+)$'], [2,'\\w+\\.+google\\.(?:[^\\.]+|[^\\.]{2,3}\\.[^\\.]{2})',,'[&?]q=([^&]+)'], [2,'search\\.msn\\.com',,'q=([^&]+)'], [2,'search\\.yahoo\\.com',,'p=([^&]+)'], [2,'(?:\\w+\\.)?a9\\.com',,'(?:\\w+\\.)?a9\\.com/([^&]+)'], [2,'en\\.wikipedia\\.org/wiki/Special:Search','','search=([^&]+)'], [2,'http://my\\.opera\\.com/community/forums/search\\.dml.*?',true,'term=([^&]+)'], [4,,,'UserJS-USH=(.*?)(?:;|(%3B)|$)'] ], strings = { _prompt: 'Highlight keywords:', _opts: 'Options', _new: 'New Highlight', _hide: 'Toggle Highlights', _close: 'Close', _goto: 'Goto next instance of', _nfound: 'not found', _error: 'Ultimate Search Highlighter:\nFailed to create RegExp. Check syntax\n', _usePunctuation: 'Match punctuation', _wholeWordsOnly: 'Match whole words only', _matchCase: 'Match case' }, enabled = false, query = '', regExp = null, frameIndex = 0, frames = [null], highlighter = { add: function() { if( !regExp ) { return; } var excElems = ['UserJS-USH-toolbar','head','applet','object','embed','param','script','style','frameset','frame','iframe','textarea','input','option','select','img','map'], textNodes = document.selectNodes('//*[not(ancestor-or-self::*[local-name()="'+excElems.join('" or local-name()="')+'"])]/text()'); if( !(toolbar.progress.max = textNodes.length) ) { return false; } var hFind, hElem = document.createElementNS(resolver.xhtmlNS,'UserJS-USH-highlight'); hElem.className = 'UserJS-USH-highlight'; toolbar.tBar.className = (preferences.darkSkin?'UserJS-USH-darkSkin ':'')+'UserJS-USH-'+(preferences.toolbarAtBottom?'bottom':'top')+' UserJS-USH-progress'; for( var i = 0, k, textNode, term; textNode = textNodes[i]; i++) { if( textNode.nodeType != 3 || (!preferences.searchHiddenText && (!textNode.parentNode || !textNode.parentNode.offsetHeight)) ) { continue; } toolbar.progress.value = i; while(hFind = regExp.exec(textNode.data)) { if( !hFind[0] ) { break; } for( k = 1; !hFind[k++]; ); term = results.terms[k-=2]; (hElem = hElem.cloneNode(false)).style.background = hElem.oldBGrnd = term[0].colour+' !important'; textNode = textNode.splitText(hFind.index+hFind[0].length-hFind[k+1].length); textNode.deleteData(0,(hElem.text=hFind[k+1]).length); textNode.parentNode.insertBefore(hElem,textNode); hElem.setAttribute('term',k); hElem.setAttribute('count',term[1]); term[1] = ++term[0].total; } } }, remove: function(toggle,idx) { var hNodes = document.selectNodes('//xhtml:UserJS-USH-highlight'+(idx!==undefined?'[@term="'+idx+'"]':''),resolver); for (var i = 0, hNode, hText; hNode = hNodes[i]; i++) { if(toggle) { hNode.className = hNode.className?'':'UserJS-USH-highlight'; hNode.style.background = hNode.style.background?'':hNode.oldBGrnd; } else { hText = hNode.firstChild; hNode.parentNode.replaceChild(hText,hNode); hText.parentNode.normalize(); } } }, run: function() { if( query ) { query = query.replace(/(^\s*)|(\s*$)/g,''); if( searchEngines[0]&2 || preferences.stripPluses ) { query = query.replace(/[+]/g,' '); } } if( enabled ) { this.remove(); } toolbar.create(); if( !searchEngines[0]||preferences.highlightOnLoad ) { results.createRegExp(); this.add(); } toolbar.update(); searchEngines[0] = !(enabled = true); } }, resolver = { xhtmlNS: 'http://www.w3.org/1999/xhtml', lookupNamespaceURI: function() { return this.xhtmlNS; } }, results = { terms: [], timer: null, createRegExp: function () { if( !(regExp = query) ) { return; } saveVal('query',query); var terms = [], termsArray = [], term, quote, tsplit, doRegExp = false, sText; if( (term = query.indexOf('USHRegExp ')) == 0 ) { doRegExp = true; terms[0] = [query.substring(10),1]; } if( !doRegExp ) { sText = query.split(/([\s+\-\|]*)"([^"]*)"/); for( var i = 0, k, j; (term = sText[i]) != null; i++ ) { k = i%3; if( !k && term ) { tsplit = ((searchEngines[0]&2 && !preferences.useStopwords)? term.replace(/(?:^|\s)(?:I|a|about|an|are|as|at|be|by|com|for|from|how|in|is|it|of|on|or|that|the|this|to|was|what|when|where|who|will|with|and|the|www|(??:filetype|inurl|site|related)(?::.*?)))(?:$|\s)/gi,' '): term).split(/([^\s+\-\|]+)/); tsplit.pop(); for( j = 0; (term = tsplit[j]) != null; j++ ) { if( !(j%2) ) { if( !term || !(/\s+.*-+$/).test(term) ) { terms[terms.length] = [tsplit[j+1],0]; } } else if( (/^-+$/).test(term) ) { terms[terms.length] = [terms[terms.length][0]+'-'+tsplit[j+1],0]; } } } else if( k==1 ) { if( !term || term[term.length-1] != '-' ) { terms[terms.length] = [sText[i+1],1]; } } } } var wb = (preferences.wholeWordsOnly&&/[^\x00-\xFF]/.test(query))?/[^\u0030-\u0039\u0041-\u005a\u005f\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u021f\u0222-\u0233\u0250-\u02ad\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03d7\u03da-\u03f3\u0400-\u0481\u048c-\u04c4\u04c7\u04c8\u04cb\u04cc\u04d0-\u04f5\u04f8\u04f9\u0531-\u0556\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u063a\u0641-\u064a\u0660-\u0669\u0671-\u06d3\u06d5\u06f0-\u06fc\u0710\u0712-\u072c\u0780-\u07a5\u0905-\u0939\u093d\u0950\u0958-\u0961\u0966-\u096f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09dc\u09dd\u09df-\u09e1\u09e6-\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a85-\u0a8b\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae6-\u0aef\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b36-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b66-\u0b6f\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb5\u0bb7-\u0bb9\u0be7-\u0bef\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60\u0c61\u0c66-\u0c6f\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cde\u0ce0\u0ce1\u0ce6-\u0cef\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60\u0d61\u0d66-\u0d6f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e45\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ed0-\u0ed9\u0edc\u0edd\u0f00\u0f20-\u0f29\u0f40-\u0f47\u0f49-\u0f6a\u0f88-\u0f8b\u1000-\u1021\u1023-\u1027\u1029\u102a\u1040-\u1049\u1050-\u1055\u10a0-\u10c5\u10d0-\u10f6\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1206\u1208-\u1246\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1286\u1288\u128a-\u128d\u1290-\u12ae\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12ce\u12d0-\u12d6\u12d8-\u12ee\u12f0-\u130e\u1310\u1312-\u1315\u1318-\u131e\u1320-\u1346\u1348-\u135a\u1369-\u1371\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1780-\u17b3\u17e0-\u17e9\u1810-\u1819\u1820-\u1842\u1844-\u1877\u1880-\u18a8\u1e00-\u1e9b\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u203f\u2040\u207f\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2131\u2133-\u2139\u3006\u3041-\u3094\u30a1-\u30fb\u3105-\u312c\u3131-\u318e\u31a0-\u31b7\u3400-\u4db5\u4e00-\u9fa5\ua000-\ua48c\uac00-\ud7a3\uf900-\ufa2d\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe72\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff65-\uff6f\uff71-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/.source:'\\b', b1 = '(?:^|'+wb+')(?', b2 = '))(?='+wb+'|$)', punc = /[`~!@#$%^&*()\_=\\[\]{}:;'<>.,/?]/g; this.terms = []; for( i = 0; term = terms[i]; i++ ) { quote = term[1]; term = term[0]; terms[i] = doRegExp?term:term.replace(punc,(quote||preferences.usePunctuation||term.length<2)?'\\s*\\$&\\s*':punc.source+'?'); if( terms[' '+term] ) { terms.splice(i,1); i--; continue; } terms[' '+term] = true; this.terms[i] = [{ text: term, colour: colours[i%colours.length], total: 0 }, 0, 0]; } term = (!doRegExp && preferences.wholeWordsOnly?b1+terms.join(')|(')+b2:'('+terms.join(')|(')+')'); try { regExp = new RegExp(term,preferences.matchCase?'':'i'); } catch(e) { alert(strings['_error']+term); } }, handleEvent: function(e) { var el = e.target, text = el.nextSibling, idx = el.count, term = this.terms[idx]; if( !term[0].total || this.timer === true ) { this.timer = null; return; } if( e.type == 'mousedown' ) { this.timer = setTimeout(function(){highlighter.remove(true,idx); results.timer=true;},1000); return; } this.timer = clearTimeout(this.timer); if( e.ctrlKey ) { if( --term[2] < 0 ) { term[2] = term[1]-1; } } else if( text.data.indexOf('/') != -1 ) { if( ++term[2] >= term[1] ) { term[2] = 0; } } text.data = '('+(term[2]+1)+'/'+term[0].total+')'; var w = self, elem = document.selectSingleNode('//xhtml:UserJS-USH-highlight[@term="'+idx+'"][@count="'+term[2]+'"]',resolver); if( !elem || !elem.offsetHeight ) { return; } elem.scrollIntoView(); w.scrollBy(0,-40); if( e.shiftKey ) { var s = w.getSelection(), r = w.document.createRange(); s.removeAllRanges(); r.selectNodeContents(elem); s.addRange(r); } if( !toolbar.isFocused ) { toolbar.isFocused = true; setTimeout(function(){toolbar.isFocused = false;},0); } } }, searchData = { hash: location.hash, referrer: document.referrer, cookie: document.cookie, assign: function(data) { if( data && (data = data.split('|')) ) { for( var i = 0, key, keys = ['hash','referrer','cookie']; key = keys[i]; i++ ) { this[key] = unescape(data[i])||this[key]; } } for( var i = 1, sE, data, rE = new RegExp(); sE = searchEngines[i]; i++ ) { if( sE[1] && rE.compile('^'+sE[1]+'$').test(sE[2]?location:location.hostname) ) { this.referrer = this.cookie = ''; break; } switch( searchEngines[0] = sE[0] ) { case 1: data = this.hash; break; case 2: if( !preferences.runOnLoad || !(data = this.referrer) || !(rE.compile('^'+(sE[2]?'':'https?:\\/\\/')+sE[1]).test(data)) ) { continue; } break; case 4: data = this.cookie; } rE.compile(sE[3]); if( data && (data = rE.exec(data)) ) { query = unescape(decodeURIComponent(data[1])); break; } } }, toString: function() { return 'USH|searchData|'+escape(this.hash)+'|'+escape(this.referrer)+'|'+escape(this.cookie)+'|'; } }, toolbar = { mOver: null, tBar: null, styles: null, buttons: [], progress: null, optsBttn: null, optsMenu: null, input: null, newBttn: null, hideBttn: null, closeBttn: null, isFocused: false, handleEvent: function(e,state) { var tBar = toolbar.tBar; if(!tBar || toolbar.isFocused) { return; } var vis = tBar.style.visibility, type = e&&e.type; if(state === undefined) { state = (type=='mouseover')||((!type||type=='mouseup')&&vis!='visible'); } tBar.style.visibility = (state?'visible':'hidden'); return state; }, close: function() { highlighter.remove(); saveVal('query',query=''); results.terms = []; this.update(); if( this.styles ) { this.styles.removeNode(true); } this.tBar.removeNode(true); this.mOver.removeNode(true); enabled = false; }, contains: function(el) { return this.tBar&&this.tBar.contains(el); }, create: function() { var divEl = this.tBar, d = document; if( !divEl ) { var xhtmlNS = resolver.xhtmlNS, i, term, terms, menuEl = d.createElementNS(xhtmlNS,'UserJS-USH-menu'); this.tBar = divEl = d.createElementNS(xhtmlNS,'UserJS-USH-toolbar'); function createButton(id,fn) { var el = d.createElementNS(xhtmlNS,'button'); el.id = 'UserJS-USH-'+id+'Bttn'; el.title = strings['_'+id]; el.setAttribute('form',''); el.onmouseup = fn||function(e){ opera.USH.run(e,this.id); } return toolbar[id+'Bttn'] = el; } (this.progress = menuEl.appendChild(d.createElementNS(xhtmlNS,'label'))).id = 'UserJS-USH-progress'; this.progress.text = 'Searching: '; this.progress = this.progress.appendChild(d.createElementNS(xhtmlNS,'input')); this.progress.type = 'range'; var ul = d.createElementNS(xhtmlNS,'ul'), li = d.createElementNS(xhtmlNS,'li'), lbl, chkbx; (this.optsMenu = ul).id = 'UserJS-USH-optsMenu'; li.appendChild(d.createElementNS(xhtmlNS,'label')); li.appendChild(d.createElementNS(xhtmlNS,'input')).type = 'checkbox'; for( i = 0, terms = ['usePunctuation','wholeWordsOnly','matchCase']; term = terms[i++]; ) { li = ul.appendChild(li.cloneNode(true)); lbl = li.firstChild; chkbx = li.lastChild; lbl.text = strings['_'+term]; chkbx.prefIdx = term; chkbx.checked = preferences[term]; chkbx.onchange = function() { saveVal(this.prefIdx,this.checked); } lbl.htmlFor = chkbx.id = 'UserJS-USH-'+term+'Bttn'; } menuEl.appendChild(createButton('opts',function(e) { toolbar.isFocused = e.ctrlKey?toolbar.handleEvent(null,!toolbar.isFocused):!toolbar.optsMenu.className; if( e.ctrlKey ) { return; } toolbar.optsMenu.className = toolbar.isFocused?'UserJS-USH-selected':''; })); menuEl.appendChild(ul); this.input = i = menuEl.appendChild(d.createElementNS(xhtmlNS,'input')); i.setAttribute('form',''); i.id = 'UserJS-USH-input'; i.onfocus = i.onblur = function(e) { var func = arguments.callee; clearTimeout(func.hTimer); if( !(toolbar.isFocused = (e.type == 'focus' || !!toolbar.optsMenu.className)) ) { func.hTimer = setTimeout(toolbar.handleEvent,2000,e,false); } } for( i = 0, terms = ['new','hide','close']; term = terms[i++]; ) { menuEl.appendChild(createButton(term)); } divEl.appendChild(menuEl); divEl.onmouseout = divEl.onmouseover = (this.mOver=divEl=d.createElementNS(xhtmlNS,'UserJS-USH-mouseover')).onmouseover = divEl.onmouseup = this; if( preferences.embedStyle ) { (this.styles = d.createElementNS(xhtmlNS,"style")).text = '\ UserJS-USH-toolbar, UserJS-USH-mouseover { position: fixed !important; right: 0 !important; left: 0 !important; min-width: 100% !important; font: 12px/18px normal Arial, sans-serif !important; }\ UserJS-USH-toolbar { height: auto !important; color: #000 !important; background: -o-skin("Browser Window Skin") #f2f2ee !important; border: solid #000 !important; border-width: 0 0 1px 0 !important; z-index: 9999 !important; }\ .UserJS-USH-darkSkin { color: #FFF !important; }\ UserJS-USH-mouseover { height: 10px !important; z-index: 9998 !important; }\ .UserJS-USH-top, .UserJS-USH-top + UserJS-USH-mouseover { top: 0 !important; }\ .UserJS-USH-bottom, .UserJS-USH-bottom + UserJS-USH-mouseover { bottom: 0 !important; border-width: 1px 0 0 0 !important; }\ .UserJS-USH-empty, .UserJS-USH-empty + UserJS-USH-mouseover { right: auto !important; border-right-width: 1px !important; min-width: 100% !important; }\ UserJS-USH-toolbar, UserJS-USH-toolbar *, UserJS-USH-highlight { display: inline-block !important; text-align: left !important; text-indent: 0 !important; margin: 0 !important; padding: 0 !important; height: auto !important; width: auto !important; float: none !important; clear: none !important; }\ UserJS-USH-toolbar *, UserJS-USH-highlight { font: inherit !important; color: inherit !important; }\ UserJS-USH-highlight { display: inline !important; }\ .UserJS-USH-highlight { color: #000 !important; font-weight: bold !important; }\ UserJS-USH-toolbar input { background: inherit !important; }\ UserJS-USH-toolbar button:hover { cursor: hand !important; }\ UserJS-USH-result { margin: 2px 0 2px 3px !important; vertical-align: middle !important; }\ UserJS-USH-result>button { color: #000 !important; font-weight: bold !important; padding: 0 5px !important; margin-right: 2px !important; border: 1px #666 solid !important; }\ UserJS-USH-result>button[disabled] { color: inherit !important; background: none !important; }\ UserJS-USH-menu { position: relative !important; float: right !important; margin: 2px 0 2px 3px !important; }\ UserJS-USH-menu>* { vertical-align: middle !important; margin-right: 3px !important; }\ .UserJS-USH-progress UserJS-USH-menu { float: none !important; }\ .UserJS-USH-progress #UserJS-USH-progress { display: block !important; }\ .UserJS-USH-progress UserJS-USH-result, .UserJS-USH-progress UserJS-USH-menu>*, #UserJS-USH-progress { display: none !important; }\ UserJS-USH-menu>button { height: 16px !important; width: 16px !important; border: none !important; }\ #UserJS-USH-optsBttn { background: -o-skin("Edit Properties") !important; }\ #UserJS-USH-newBttn { background: -o-skin("Search") !important; }\ #UserJS-USH-hideBttn { background: -o-skin("Caption Restore") !important; }\ #UserJS-USH-closeBttn { background: -o-skin("Caption Close") !important; }\ #UserJS-USH-input { background: #FFF !important; color: #000 !important; border: 1px solid #000; padding: 1px 2px 2px !important; min-width: 11em !important; }\ UserJS-USH-toolbar ul { display: none !important; position: absolute !important; background: #f2f2ee !important; border: 1px solid #000 !important; padding: 2px 2px 2px 4px !important; list-style: none !important; }\ .UserJS-USH-top ul { top: 1.5em !important; margin-top: 4px !important; border-top-width: 0 !important; }\ .UserJS-USH-bottom ul { bottom: 1.5em !important; margin-bottom: 4px !important; border-bottom-width: 0 !important; }\ UserJS-USH-toolbar ul.UserJS-USH-selected, UserJS-USH-toolbar ul>li { display: block !important; }\ UserJS-USH-toolbar ul>li>* { display: inline !important; }\ UserJS-USH-toolbar ul label { padding-right: 2em !important; }\ UserJS-USH-toolbar ul input { border: none !important; height: 1.5em !important; position: absolute !important; right: 0 !important; margin: 0 2px !important; }'; } } this.isFocused = false; if( query ) { this.input.value = query; } if( this.styles ) { d.documentElement.appendChild(this.styles); } d.documentElement.appendChild(this.tBar); d.documentElement.appendChild(this.mOver); this.handleEvent(null,!searchEngines[0]||!preferences.toolbarHiddenOnLoad); }, update: function() { var divEl = this.tBar; divEl.className = (preferences.darkSkin?'UserJS-USH-darkSkin ':'')+'UserJS-USH-'+(preferences.toolbarAtBottom?'bottom':'top')+(results.terms.length?'':' UserJS-USH-empty'); if( !regExp ) { return; } var menuEl = divEl.firstChild.removeNode(true); divEl.innerHTML = ''; divEl.appendChild(menuEl); if( results.terms.length ) { var d = document, result = d.createElementNS(resolver.xhtmlNS,'UserJS-USH-result'), rBttn = d.createElementNS(resolver.xhtmlNS,'button'); rBttn.setAttribute('form',''); for( var i = 0, term, total, text; (term = results.terms[i]) && (term = term[0]); i++ ) { result = result.cloneNode(false); rBttn = rBttn.cloneNode(false); total = term.total; text = term.text; rBttn.title = (total?strings['_goto']+' "'+text+'"':'"'+text+'" '+strings['_nfound']); if( i < 8 ) { (this.buttons[i] = rBttn).title += ' [ '+(i+1)+' ]'; } rBttn.count = i; rBttn.text = text; rBttn.disabled = !total; rBttn.style.background = (total?term.colour+" !important":''); rBttn.onmouseup = rBttn.onmousedown = results; result.appendChild(rBttn); result.appendChild(d.createTextNode(total?'('+total+')':'('+strings['_nfound']+')')); divEl.appendChild(result); } } } }; this.check = null; this.init = function() { delete this.init; opera.addEventListener('BeforeEvent.message',function(ujsEv) { var ev = ujsEv.event, msg = ev.data, data; if( !!msg.indexOf('USH|') ) { return; } ujsEv.preventDefault(); ev.preventDefault(); switch( msg = msg.substr(4) ) { case 'frameLoaded': ev.source.postMessage('USH|frameIndex|'+frames.length); ev.source.postMessage(searchData); frames[frames.length] = ev.source; break; case 'frameIndex|'+(data=msg.substr(11)): frameIndex = data; break; case 'searchData|'+(data=msg.substr(11)): searchData.assign(data); opera.USH.handleEvent(); break; case 'run|'+(data=msg.substr(4)): data = data.split('|'); opera.USH.run(unescape(data[0]),data[1],data[2]^0); break; } },false); opera.addEventListener('BeforeEvent.keypress',({ enabled: false, keys: {}, event: document.createEvent('UIEvents'), init: function() { var i, j, keys, key, bttns = ['optsBttn','newBttn','hideBttn','closeBttn','mOver'], bttn; for( i = 0, j = 0; (keys = preferences.keyShortcuts[i]) && (bttn = bttns[i]); i++, j = 0 ) { while( key = keys.charCodeAt(j) ) { this.keys[(j?'__':'_')+key] = bttn; j++ } } this.keys.toggle = preferences.keyShortcuts[i].charCodeAt(0); for( i = 0, keys = [33,64,35,36,37,94,38,42], key; key = keys[i]; i++ ) { this.keys['_'+(49+i)] = this.keys['__'+key] = i; } this.event.initEvent('mouseup',true,true); return this; }, handleEvent: function(ujsEv) { var e = ujsEv.event, el = e.target, key = e.which; if( !enabled || (!toolbar.contains(el) && el.forms instanceof NodeList) ) { return; } if( el == toolbar.input ) { if( key == 13 && el.value ) { opera.USH.run(e,'UserJS-USH-newBttn'); } return; } var bttn = this.keys[(e.shiftKey?'__':'_')+key]; bttn = (typeof bttn == 'number')?toolbar.buttons[bttn]:toolbar[bttn]; if( key == this.keys.toggle ) { this.enabled = !this.enabled; } if( this.enabled && bttn ) { ujsEv.preventDefault(); e.preventDefault(); this.event.shiftKey = e.shiftKey; this.event.ctrlKey = e.ctrlKey; bttn.dispatchEvent(this.event); } } }).init(),false); if( self==top ) { searchData.assign(); } opera.addEventListener('AfterEvent.DOMContentLoaded',this,false); } this.handleEvent = function(ujsEv) { if( ujsEv ) { opera.removeEventListener(ujsEv.type,this,false); } if( self!=top && !frameIndex ) { return top.document.postMessage('USH|frameLoaded'); } if( query && searchEngines[0] ) { highlighter.run(); } } this.run = function(e,action,frame) { frame = frame||(e&&e.shiftKey); switch( action ) { case 'UserJS-USH-closeBttn': toolbar.close(); break; case 'UserJS-USH-hideBttn': highlighter.remove(true); break; case 'UserJS-USH-newBttn': query = toolbar.input.value.replace(/^\s*(USHRegExp\s)?\s*/,e&&e.ctrlKey?'USHRegExp ':'$1'); action = 'new'; highlighter.run(); break; case 'newSearch': if( !this.check || this.check == location ) { return; } action = 'new'; frame = true; this.check = null; case 'new': query = e; highlighter.run(); break; case 'newBlank': frame = document.body instanceof HTMLFrameSetElement; enabled = !!(query = ''); highlighter.run(); toolbar.input.focus(true); toolbar.input.select(); } if( !frame ) { return; } if( self!=top ) { return top.document.postMessage('USH|run|'+escape(query)+'|'+action+'|'+frameIndex); } for( var i = 1, f; f = frames[i]; i++ ) { if( i === frame ) { continue; } f.postMessage('USH|run|'+escape(query)+'|'+action); } } function saveVal(key,val) { preferences[key] = val; if( preferences.useCookies && key == 'query' ) { document.cookie = 'UserJS-USH='+encodeURIComponent(val)+';path=/;'+(val?'':'NoExp='+new Date(0).toGMTString()); } } }).init(); |