// ==UserScript== // @name Text Highlighter 2015 // @author erosman and Jefferson "jscher2000" Scher // @namespace JeffersonScher // @version 2.0.1 // @description Automatically highlight user-defined text with Seek function (2015-09-20) // @include https://greasyfork.org/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceURL // @copyright Copyright 2015 Jefferson Scher. Portions created by erosman. // @license BSD 3-clause // @resource mycon http://www.jeffersonscher.com/gm/src/gfrk-TH15-ver201.png // @downloadURL none // ==/UserScript== var script_about = "https://greasyfork.org/en/scripts/3719-text-highlighter-dynamic"; /* --------- Note --------- TO INCLUDE SITES (only Greasy Fork is initially included): Go to Add-ons - User Scripts (Ctrl+Shift+a/Cmd+Shift+a on Firefox Windows/Mac) Click on the Script's Option Under User Settings Tab, Add Included/Excluded Pages that you want the script to run on Click OK Note from erosman: If you find that another script clashes with this script, set Text Highlighter to Execute first. Go to Add-ons - User Scripts ('Ctrl+ Shift + a' on Firefox) Right Click on the Script On the context menu click: Execute first On Add-ons - User Scripts, you can also Click on the Execution Order (top Right) and change the execution order so that Text Highlighter runs before those scripts that clashes with it. --------- History --------- http://userscripts-mirror.org/scripts/show/292083 http://userscripts-mirror.org/topics/187122.html */ (function() { // anonymous function wrapper, used for error checking & limiting scope 'use strict'; if (window.self !== window.top) { return; } // end execution if in a frame // sample keyword+style object to get started var hlobjDefault = { "set100" : { keywords : "scripts|script", type: "string", textcolor : "rgb(0,0,0)", backcolor : "rgb(255,255,128)", fontweight : "inherit", custom : "", enabled : "true", visible : "true", updated : "" }, "set099" : { keywords : "site", type: "word", textcolor : "rgb(0,0,0)", backcolor : "rgb(255,192,255)", fontweight : "inherit", custom : "", enabled : "true", visible : "true", updated : "" }, "set098" : { keywords : "^September \\d{1,2}", type: "regex", textcolor : "rgb(0,0,0)", backcolor : "rgb(192,255,255)", fontweight : "inherit", custom : "", enabled : "true", visible : "true", updated : "" } }; var kwhieditstyle = ["rgb(0,0,255)","rgb(255,255,0)","inherit",""]; // read pref storage: keyword-style sets var hljson = GM_getValue("kwstyles"); if (!hljson || hljson.length == 0){ var hlobj = hlobjDefault; // check for legacy preferences var kwold = GM_getValue("keywords"); if (kwold) if(kwold.length > 0) { hlobj.set100.keywords = kwold.split(',').join('|'); } var hlold = GM_getValue("highlightStyle"); if (hlold) if(hlold.length > 0) { // really should try to parse this, but for now... hlobj.set100.custom = hlold; } // save starting values hljson = JSON.stringify(hlobj); GM_setValue("kwstyles",hljson); } else { var hlobj = JSON.parse(hljson); } // global keys array var hlkeys = Object.keys(hlobj); // read/set other prefs var hlbtnvis = GM_getValue("hlbtnvis"); if (!hlbtnvis){ hlbtnvis = "on"; GM_setValue("hlbtnvis",hlbtnvis); } var hlprecode = GM_getValue("hlprecode"); if (!hlprecode){ hlprecode = true; GM_setValue("hlprecode",hlprecode); } var hlnextset = GM_getValue("hlnextset"); if (!hlnextset){ hlnextset = 101; GM_setValue("hlnextset",hlnextset); } // Inject CSS function insertCSS(setkeys){ for (var j = 0; j < setkeys.length; ++j){ var hlset = setkeys[j]; if (hlobj[hlset].visible == "true"){ var rule = "."+hlset+"{display:inline!important;"; if (hlobj[hlset].textcolor.length > 0) rule += "color:"+hlobj[hlset].textcolor+";"; if (hlobj[hlset].backcolor.length > 0) rule += "background-color:"+hlobj[hlset].backcolor+";"; if (hlobj[hlset].fontweight.length > 0) rule += "font-weight:"+hlobj[hlset].fontweight+";"; if (hlobj[hlset].custom.length > 0) rule += hlobj[hlset].custom+";"; rule += "}"; var setrule = document.querySelector('style[hlset="' + hlset +'"]'); if (!setrule){ var s = document.createElement("style"); s.type = "text/css"; s.setAttribute("hlset", hlset); s.appendChild(document.createTextNode(rule)); document.body.appendChild(s); } else { setrule.innerHTML = rule; } } } } insertCSS(hlkeys); // Main workhorse routine function THmo_doHighlight(el,subset){ if (subset) var keyset = subset; else var keyset = hlkeys; for (var j = 0; j < keyset.length; ++j) { var hlset = keyset[j]; if (hlobj[hlset].visible == "true" && hlobj[hlset].enabled == "true"){ var hlkeywords = hlobj[hlset].keywords; if (hlkeywords.length > 0) { if (hlobj[hlset].type != "regex"){ var rQuantifiers = /[-\/\\^$*+?.()[\]{}]/g; hlkeywords = hlkeywords.replace(rQuantifiers, '\\$&'); if (hlobj[hlset].type == "word"){ hlkeywords = "\\b" + hlkeywords.replace(/\|/g, "\\b|\\b") + "\\b"; } } //console.log("hlset:"+hlset+"\nhlkeywords:"+hlkeywords); var pat = new RegExp('(' + hlkeywords + ')', 'gi'); var span = document.createElement('thdfrag'); span.setAttribute("thdcontain","true"); // getting all text nodes with a few exceptions if (hlprecode){ var snapElements = document.evaluate( './/text()[normalize-space() != "" ' + 'and not(ancestor::style) ' + 'and not(ancestor::script) ' + 'and not(ancestor::textarea) ' + 'and not(ancestor::div[@id="thdtopbar"]) ' + 'and not(ancestor::div[@id="kwhiedit"]) ' + 'and not(parent::thdfrag[@txhidy15])]', el, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); } else { var snapElements = document.evaluate( './/text()[normalize-space() != "" ' + 'and not(ancestor::style) ' + 'and not(ancestor::script) ' + 'and not(ancestor::textarea) ' + 'and not(ancestor::pre) ' + 'and not(ancestor::code) ' + 'and not(ancestor::div[@id="thdtopbar"]) ' + 'and not(ancestor::div[@id="kwhiedit"]) ' + 'and not(parent::thdfrag[@txhidy15])]', el, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); } if (!snapElements.snapshotItem(0)) { break; } for (var i = 0, len = snapElements.snapshotLength; i < len; i++) { var node = snapElements.snapshotItem(i); // check if it contains the keywords if (pat.test(node.nodeValue)) { // create an element, replace the text node with an element var sp = span.cloneNode(true); sp.innerHTML = node.nodeValue.replace(//g, '>').replace(pat, '$1'); node.parentNode.replaceChild(sp, node); // try to un-nest containers if (sp.parentNode.hasAttribute("thdcontain")) sp.outerHTML = sp.innerHTML; } } } } } } // first run THmo_doHighlight(document.body,null); // Add MutationObserver to catch content added dynamically var THmo_MutOb = (window.MutationObserver) ? window.MutationObserver : window.WebKitMutationObserver; if (THmo_MutOb){ var THmo_chgMon = new THmo_MutOb(function(mutationSet){ mutationSet.forEach(function(mutation){ for (var i=0; i

JS

" + "

Click here to manage keyword/highlight sets

" + "

" + " [?Import?]

" + "
Seek
" + "
Options
" + "" + ""; document.body.appendChild(kwhibar); // Attach event handlers document.getElementById("thdtopkeywords").addEventListener("click",thddroptoggle,false); document.getElementById("kwhitbod").addEventListener("click",kwhiformevent,false); document.getElementById("btnkwhiadd").addEventListener("click",kwhinewset,false); document.getElementById("btnkwhiexport").addEventListener("click",kwhiexport,false); document.getElementById("thdtopfindbuttons").addEventListener("click",thdseek,false); document.getElementById("chkhbtn").addEventListener("click",kwhihbtn,false); document.getElementById("chkprecode").addEventListener("click",kwhiprecode,false); // Add spacer at top of body var divsp = document.createElement("div"); divsp.id = "thdtopspacer"; divsp.setAttribute("style","clear:both;display:none"); divsp.style.height = parseInt(27 - parseInt(window.getComputedStyle(document.body,null).getPropertyValue("margin-top"))) + "px"; document.body.insertBefore(divsp, document.body.childNodes[0]); // Switch JS text to icon var JSBTN = document.createElement("img"); JSBTN.src = GM_getResourceURL("mycon"); document.querySelector("#thdtopbar a").textContent = ""; document.querySelector("#thdtopbar a").appendChild(JSBTN); // Add menu item GM_registerMenuCommand("Show Text Highlighter Bar - View, Edit, Add Keywords and Styles", editKW); // Inject H button if (hlbtnvis == "off") var hbtndisp = ' style="display:none"'; else hbtndisp = ''; var dNew = document.createElement("div"); dNew.innerHTML = ''; document.body.appendChild(dNew); document.getElementById("btnshowkwhi").addEventListener("click",editKW,false); function editKW(e){ refreshSetList(); // show form document.getElementById("thdtopbar").style.display = "block"; document.getElementById("thdtopspacer").style.display = "block"; } function thdDropSetList(e){ refreshSetList(); document.getElementById("thdtopdrop").style.display = "block"; } function thddroptoggle(e){ if (document.getElementById("thdtopdrop").style.display == "none") thdDropSetList(); else document.getElementById("thdtopdrop").style.display = "none"; } function refreshSetList(e){ // clear old rows from form document.getElementById("kwhitbod").innerHTML = ""; // populate data - hlobj is global for (var j = 0; j < hlkeys.length; ++j){ var hlset = hlkeys[j]; if (hlobj[hlset].visible == "true"){ if (hlobj[hlset].enabled == "true") var strchk = ' checked=\"checked\"'; else var strchk = ''; var newrow = document.createElement("tr"); var thdtypenote = ''; newrow.setAttribute("kwhiset", hlset); if(hlobj[hlset].type != "string"){ thdtypenote = '' + hlobj[hlset].type + ''; } if (j == 0){ newrow.innerHTML = '
' + hlobj[hlset].keywords + '
' + thdtypenote + '' + ' ' + ' '; } else { newrow.innerHTML = '
' + hlobj[hlset].keywords + '
' + thdtypenote + '' + ' ' + ' '; } document.getElementById("kwhitbod").appendChild(newrow); } } } function kwhiformevent(e){ if (e.target.nodeName == "INPUT"){ // Enabled checkbox var hlsetnum = e.target.getAttribute("kwhiset"); kwhienabledisable(hlsetnum, e.target.checked); } if (e.target.nodeName == "BUTTON"){ // Call up edit form or find bar var hlset = e.target.getAttribute('kwhiset'); if (e.target.textContent == "Edit"){ // set set number attribute document.querySelector('#kwhiedit tr').setAttribute('kwhiset', hlset); // set class for keywords document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').className = hlset; // enter placeholder text & type document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').textContent = hlobj[hlset].keywords; document.getElementById("kwhipattype").selectedIndex = 0; if (hlobj[hlset].type == "word") document.getElementById("kwhipattype").selectedIndex = 1; if (hlobj[hlset].type == "regex") document.getElementById("kwhipattype").selectedIndex = 2; // set style editing to default and override with set rules kwhieditstyle = ["rgb(0,0,255)","rgb(255,255,0)","inherit",""]; // defaults if (hlobj[hlset].textcolor.length > 0) kwhieditstyle[0] = hlobj[hlset].textcolor; if (hlobj[hlset].backcolor.length > 0) kwhieditstyle[1] = hlobj[hlset].backcolor; if (hlobj[hlset].fontweight.length > 0) kwhieditstyle[2] = hlobj[hlset].fontweight; if (hlobj[hlset].custom.length > 0) kwhieditstyle[3] = hlobj[hlset].custom; kwhiShowEditForm(); } if (e.target.textContent == "Seek"){ // Populate current seek set to #thdtopkeywords var divDataTD = e.target.parentNode.previousElementSibling; document.getElementById("thdtopkeywords").innerHTML = "Seeking: " + divDataTD.firstChild.outerHTML; // Store set to seek in #thdtopfindbuttons document.getElementById("thdtopfindbuttons").setAttribute("thdseek", hlset); // Close Keyword Sets form document.getElementById('thdtopdrop').style.display='none'; // Send click event to the "seek first" button document.getElementById('thdtopfindbuttons').children[0].click(); } } } function kwhienabledisable(hlsetnum,enable){ if (enable == false) { // Update object and persist to GM storage hlobj[hlsetnum].enabled = "false"; hljson = JSON.stringify(hlobj); GM_setValue("kwstyles",hljson); // Unhighlight unhighlight(hlsetnum); // Clear seek info from bar if this set is there var seekset = document.getElementById("thdtopfindbuttons").getAttribute("thdseek"); if (seekset){ if(seekset.indexOf("|") > -1) seekset = seekset.split("|")[0]; if (hlsetnum == seekset){ document.getElementById("thdtopfindbuttons").setAttribute("thdseek",""); document.getElementById("thdseekdesc").textContent = "Seek"; document.getElementById("thdtopkeywords").innerHTML = "Click here to manage keyword/highlight sets"; } } } else { // Update object and persist to GM storage hlobj[hlsetnum].enabled = "true"; hljson = JSON.stringify(hlobj); GM_setValue("kwstyles",hljson); // Highlight THmo_doHighlight(document.body,[hlsetnum]); } } function kwhinewset(e,kwtext){ // call up new set form // set set number attribute document.querySelector('#kwhiedit tr').setAttribute('kwhiset', 'new'); // clear class for keywords document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').className = ""; // enter placeholder text & default type if (kwtext) document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').textContent = kwtext; else document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').textContent = "larry|moe|curly"; document.getElementById("kwhipattype").selectedIndex = 0; // set style editing to defaults kwhieditstyle = ["rgb(0,0,255)","rgb(255,255,0)","inherit",""]; kwhiShowEditForm(); } function kwhiShowEditForm(){ var rule = "#stylecontrols>p>span{"; if (kwhieditstyle[0].length > 0) rule += "color:"+kwhieditstyle[0]+";"; if (kwhieditstyle[1].length > 0) rule += "background-color:"+kwhieditstyle[1]+";"; if (kwhieditstyle[2].length > 0) rule += "font-weight:"+kwhieditstyle[2]+";"; if (kwhieditstyle[3].length > 0) rule += kwhieditstyle[3]+";"; document.getElementById("kwhiedittemp").innerHTML = rule + "}"; populateRGB("txt",kwhieditstyle[0]); populateRGB("bkg",kwhieditstyle[1]); document.getElementById("fwsel").value = kwhieditstyle[2]; document.getElementById("kwhicustom").value = kwhieditstyle[3]; // show form document.getElementById("kwhiedit").style.display = "block"; } function kwhiexport(e){ prompt("JSON data\nPress Ctrl+c or right-click to copy\n ", JSON.stringify(hlobj)); } function kwhihbtn(e){ if (e.target.checked == false){ hlbtnvis = "off"; GM_setValue("hlbtnvis",hlbtnvis); document.getElementById("btnshowkwhi").style.display = "none"; } else { hlbtnvis = "on"; GM_setValue("hlbtnvis",hlbtnvis); document.getElementById("btnshowkwhi").style.display = ""; } } function kwhiprecode(e){ if (e.target.checked == false){ // Update var, persist the preference, unhighlight, rehighlight hlprecode = false; GM_setValue("hlprecode",hlprecode); unhighlight(null); THmo_doHighlight(document.body); } else { // Update var, persist the preference, rehighlight hlprecode = true; GM_setValue("hlprecode",hlprecode); THmo_doHighlight(document.body); } } function thdseek(e){ if (e.target.nodeName == "DIV") return; // ignore background clicks var seekset = e.currentTarget.getAttribute("thdseek"); if (!seekset){ // user needs to select a set to seek in thdDropSetList(); } else { var seekparams = seekset.split("|"); var seekmatches = document.querySelectorAll('thdfrag[txhidy15="'+seekparams[0]+'"]'); // Update or add total size of set; FIGURE OUT LATER: what if this changed?? seekparams[1] = seekmatches.length; if (seekmatches.length > 0){ if (e.target.nodeName == "THDFRAG"){ // re-scroll to the current reference thdshow(seekmatches[parseInt(seekparams[2])]); } else { // BUTTON var seekaction = e.target.getAttribute("thdaction"); if (!seekaction) seekaction = "f"; if (seekparams.length == 3){ // User has seeked in this set switch (seekaction){ case "f": seekparams[2] = 0; var rtn = thdshow(seekmatches[parseInt(seekparams[2])]); if (rtn == false) seekagain("n"); break; case "p": if (parseInt(seekparams[2]) > 0) { seekparams[2] = parseInt(seekparams[2]) - 1; var rtn = thdshow(seekmatches[parseInt(seekparams[2])]); if (rtn == false){ if (parseInt(seekparams[2]) > 0) seekagain("p"); else seekfailnotc("No previous match visible"); } } else { seekfailnotc("Already reached first match"); } break; case "n": if (parseInt(seekparams[2]) < (seekmatches.length-1)) { seekparams[2] = parseInt(seekparams[2]) + 1; var rtn = thdshow(seekmatches[parseInt(seekparams[2])]); if (rtn == false){ if (parseInt(seekparams[2]) < (seekmatches.length-1)) seekagain("n"); else seekfailnotc("No later match visible"); } } else { seekparams[2] = (seekmatches.length-1); // in case it's too high, fix that here seekfailnotc("Already reached last match"); } break; case "l": seekparams[2] = (seekmatches.length-1); var rtn = thdshow(seekmatches[parseInt(seekparams[2])]); if (rtn == false) seekagain("p"); break; } } else { seekparams[2] = 0; thdshow(seekmatches[parseInt(seekparams[2])]); } document.getElementById("thdtopfindbuttons").setAttribute("thdseek", seekparams.join("|")); document.getElementById("thdseekdesc").textContent = (parseInt(seekparams[2])+1) + " of " + seekparams[1]; } } else { document.getElementById("thdseekdesc").textContent = "0 of 0"; } } } function thdshow(elt){ // this could be much prettier with animation! elt.scrollIntoView(); var rect = elt.getClientRects()[0]; if (rect){ // scroll down if behind the control bar if (rect.top < 27) window.scroll(0, window.scrollY-27); return true; } else { // match is not visible return false; } } function seekagain(dir){ switch (dir){ case "p": seekfailnotc("Hidden, trying previous match..."); window.setTimeout(function(){document.querySelector('button[thdaction="p"]').click();},250); break; case "n": seekfailnotc("Hidden, trying next match..."); window.setTimeout(function(){document.querySelector('button[thdaction="n"]').click();},250); break; } } var evttimer; function seekfailnotc(txt){ var sfdiv = document.getElementById("thdseekfail"); sfdiv.textContent = txt; sfdiv.style.display = "block"; if (evttimer) window.clearTimeout(evttimer); evttimer = window.setTimeout(function(){document.getElementById("thdseekfail").style.display="none";}, 800); } function unhighlight(setnum){ if (setnum) var tgts = document.querySelectorAll('thdfrag[txhidy15="' + setnum + '"]'); else var tgts = document.querySelectorAll('thdfrag[txhidy15]'); // remove ALL for (var i=0; is var parnode = tgts[i].parentNode, parpar = parnode.parentNode, tgtspan; if (parnode.hasAttribute("thdcontain") && parnode.innerHTML == tgts[i].outerHTML){ parnode.outerHTML = tgts[i].textContent.replace(//g, '>'); tgtspan = parpar; } else { tgts[i].outerHTML = tgts[i].textContent.replace(//g, '>'); tgtspan = parnode; } tgtspan.normalize(); if (tgtspan.hasAttribute("thdcontain")){ parnode = tgtspan.parentNode; if (parnode){ if (parnode.hasAttribute("thdcontain") && parnode.innerHTML == tgtspan.outerHTML && tgtspan.querySelectorAll('thdfrag[txhidy15]').length == 0){ parnode.outerHTML = tgtspan.innerHTML; } else if (parnode.innerHTML == tgtspan.outerHTML && tgtspan.querySelectorAll('thdfrag[txhidy15]').length == 0) { parnode.innerHTML = tgtspan.innerHTML; } } } } } // Set up add/edit form var kwhied = document.createElement("div"); kwhied.id = "kwhiedit"; kwhied.innerHTML = "

Edit/Add Keywords/Highlighting" + "" + "

List longer forms of a word first to match both in full. Example: \"children|child\" will highlight both, but \"child|children\" " + "will only highlight child, it won't expand the selection to children.

" + "" + "
" + "

placeholder

" + "

Match type:

Text color: R: G: B:

Background: R: G: B: " + "

Font-weight:

Custom:

" + "

"; document.body.appendChild(kwhied); // Attach event handlers document.getElementById("btnkwhisave").addEventListener("click",kwhisavechg,false); document.getElementById("btnkwhicancel").addEventListener("click",kwhicancel,false); document.getElementById("btnkwhiremove").addEventListener("click",kwhiremove,false); document.getElementById("stylecontrols").addEventListener("input", updatestyle, false); document.getElementById("btntxtreset").addEventListener("click",kwhicolorreset,false); document.getElementById("btnbkgreset").addEventListener("click",kwhicolorreset,false); document.getElementById("fwsel").addEventListener("change",kwhifwchg,false); document.getElementById("kwhicustomapply").addEventListener("click",kwhicustom,false); function kwhisavechg(e){ // Update object, regenerate CSS if applicable, apply to document var hlset = document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').className; var kwtext = document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').textContent; if (hlset == ""){ // create a new set number var hlset = "set" + hlnextset; hlnextset += 1; GM_setValue("hlnextset",hlnextset); // add the set if (document.getElementById("kwhipattype").value == "regex") kwtext = kwtext.replace(/\\/g, "\\"); hlobj[hlset] = { keywords : kwtext, type: document.getElementById("kwhipattype").value, textcolor : kwhieditstyle[0], backcolor : kwhieditstyle[1], fontweight : kwhieditstyle[2], custom : kwhieditstyle[3], enabled : "true", visible : "true", updated : "" } // Update the global key array hlkeys = Object.keys(hlobj); } else { hlobj[hlset].type = document.getElementById("kwhipattype").value; // Save keyword changes after user confirmation if (kwtext != hlobj[hlset].keywords){ if (confirm("Save updated keywords (and other changes)?")){ if (hlobj[hlset].type != "regex") hlobj[hlset].keywords = kwtext; else hlobj[hlset].keywords = kwtext.replace(/\\/g, "\\"); } else return; } // Save style changes without confirmation hlobj[hlset].textcolor = kwhieditstyle[0]; hlobj[hlset].backcolor = kwhieditstyle[1]; hlobj[hlset].fontweight = kwhieditstyle[2]; hlobj[hlset].custom = kwhieditstyle[3]; // Set updated date/time hlobj[hlset].updated = (new Date()).toJSON(); } // Persist the object hljson = JSON.stringify(hlobj); GM_setValue("kwstyles",hljson); // Update CSS rule and parent form insertCSS([hlset]); refreshSetList(); // Unhighlight, re-highlight, close dialog unhighlight(hlset); THmo_doHighlight(document.body,[hlset]) document.getElementById('kwhiedit').style.display='none'; } function kwhicancel(e){ // Close dialog (fields will be refresh if it is opened again) document.getElementById('kwhiedit').style.display='none'; } function kwhiremove(e){ var hlset = document.querySelector('#kwhiedit td:nth-of-type(1) p:nth-of-type(1)').className; if (hlset == ""){ alert("This set has not been saved and therefore does not need to be hidden, you can just close the dialog to discard it."); } else { if (confirm("Are you sure you want to hide this set instead of editing it to your own liking?")){ hlobj[hlset].visible = "false"; hlobj[hlset].updated = (new Date()).toJSON(); // Persist the object hljson = JSON.stringify(hlobj); GM_setValue("kwstyles",hljson); // Update set list, remove highlighting, close form refreshSetList(); unhighlight(hlset); document.getElementById('kwhiedit').style.display='none'; } } } function kwhicolorreset(e){ // what set is this? var set = document.querySelector('#kwhiedit tr').getAttribute('kwhiset'); // check which button, reset the RGB if (e.target.id == "btntxtreset"){ if (set == "new"){ kwhieditstyle[0] = "rgb(0,0,255)"; } else { kwhieditstyle[0] = hlobj[set].textcolor; } populateRGB("txt",kwhieditstyle[0]); setdivstyle(["txt"]); } if (e.target.id == "btnbkgreset"){ if (set == "new"){ kwhieditstyle[1] = "rgb(255,255,0)"; } else { kwhieditstyle[1] = hlobj[set].backcolor; } populateRGB("bkg",kwhieditstyle[1]); setdivstyle(["bkg"]); } e.target.blur(); } function populateRGB(prop,stylestring){ var rgbvals = stylestring.substr(stylestring.indexOf("(")+1); rgbvals = rgbvals.substr(0,rgbvals.length-1).split(","); document.getElementById(prop+"r").value = parseInt(rgbvals[0]); document.getElementById(prop+"g").value = parseInt(rgbvals[1]); document.getElementById(prop+"b").value = parseInt(rgbvals[2]); } function updatestyle(e){ // validate value and apply change if (e.target.id.indexOf("txt") == 0 || e.target.id.indexOf("bkg") == 0){ if (isNaN(e.target.value)){ alert("Please only use values between 0 and 255"); return; } if (parseInt(e.target.value) != e.target.value){ e.target.value = parseInt(e.target.value); } if (e.target.value < 0){ e.target.value = 0; } if (e.target.value > 255){ e.target.value = 255; } if (e.target.id.indexOf("txt") == 0) setdivstyle(["txt"]); if (e.target.id.indexOf("bkg") == 0) setdivstyle(["bkg"]); } else { if (e.target.id == "kwhicustom") return; console.log("updatestyle on "+e.target.id); } } function setdivstyle(props){ for (var i=0; i 0) rule += "color:"+kwhieditstyle[0]+";"; if (kwhieditstyle[1].length > 0) rule += "background-color:"+kwhieditstyle[1]+";"; if (kwhieditstyle[2].length > 0) rule += "font-weight:"+kwhieditstyle[2]+";"; if (kwhieditstyle[3].length > 0) rule += kwhieditstyle[3]+";"; document.getElementById("kwhiedittemp").innerHTML = rule + "}"; } function kwhifwchg(e){ kwhieditstyle[2] = e.target.value; setdivstyle([]); } function kwhicustom(e){ kwhieditstyle[3] = document.getElementById("kwhicustom").value; setdivstyle([]); } // Context menu options -- do not replace any existing menu! if (!document.body.hasAttribute("contextmenu") && "contextMenu" in document.documentElement){ var cmenu = document.createElement("menu"); cmenu.id = "THDcontext"; cmenu.setAttribute("type", "context"); cmenu.innerHTML = '' + '' + '' + '' + '' + ''; document.body.appendChild(cmenu); document.getElementById("THDshowbar").addEventListener("click",editKW,false); document.getElementById("THDenableset").addEventListener("click",cmenuEnable,false); document.getElementById("THDdisableset").addEventListener("click",cmenuDisable,false); document.getElementById("THDnewset").addEventListener("click",cmenuNewset,false); // attach menu and create event for filtering document.body.setAttribute("contextmenu", "THDcontext"); document.body.addEventListener("contextmenu",cmenuFilter,false); } function cmenuFilter(e){ document.getElementById("THDenableset").setAttribute("disabled","disabled"); document.getElementById("THDenableset").setAttribute("THDtext",""); document.getElementById("THDdisableset").setAttribute("disabled","disabled"); document.getElementById("THDdisableset").setAttribute("THDset",""); var s = window.getSelection(); if (s.isCollapsed) document.getElementById("THDnewset").setAttribute("THDtext",""); else document.getElementById("THDnewset").setAttribute("THDtext",s.getRangeAt(0).toString().trim()); if (e.target.hasAttribute('txhidy15')){ document.getElementById("THDdisableset").removeAttribute("disabled"); document.getElementById("THDdisableset").setAttribute("THDset",e.target.getAttribute('txhidy15')); } else { document.getElementById("THDdisableset").setAttribute("disabled","disabled"); if (!s.isCollapsed){ document.getElementById("THDenableset").removeAttribute("disabled"); document.getElementById("THDenableset").setAttribute("THDtext",s.getRangeAt(0).toString().trim()); } } } function cmenuEnable(e){ var kw = e.target.getAttribute("THDtext").toLowerCase(); var toggled = false; for (var j = 0; j < hlkeys.length; ++j){ var hlset = hlkeys[j]; var kwlist = "|" + hlobj[hlset].keywords.toLowerCase() + "|"; if(kwlist.indexOf("|" + kw + "|") > -1){ if (hlobj[hlset].enabled == "true") break; // already enabled kwhienabledisable(hlset,true); refreshSetList(); toggled = true; break; } } if (toggled == false){ if (document.getElementById("thdtopbar").style.display != "block") editKW(); if (document.getElementById("thdtopdrop").style.display != "block") thdDropSetList(); } } function cmenuDisable(e){ kwhienabledisable(e.target.getAttribute("THDset"),false); refreshSetList(); } function cmenuNewset(e){ //TODO - if there's a selection, get it into the form kwhinewset(e,e.target.getAttribute("THDtext")); } // TESTING ONLY function flushData(){ GM_setValue("kwstyles", ""); } GM_registerMenuCommand("TEST ONLY - flush keyword sets for Text Highlighter", flushData); })(); // end of anonymous function