diff --git a/mb. MERGE HELPOR 2.user.js b/mb. MERGE HELPOR 2.user.js index e889d0dd..97363ee1 100644 --- a/mb. MERGE HELPOR 2.user.js +++ b/mb. MERGE HELPOR 2.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name mb. MERGE HELPOR 2 -// @version 2020.9.24.1247 +// @version 2020.11.29 // @changelog https://github.com/jesus2099/konami-command/commits/master/mb.%20MERGE%20HELPOR%202.user.js // @description musicbrainz.org: Merge helper highlights last clicked, shows info, indicates oldest MBID, manages (remove) entity merge list; merge queue (clear before add) tool; don’t reload page for nothing when nothing is checked // @homepage http://userscripts-mirror.org/scripts/show/124579 @@ -31,173 +31,182 @@ var lastTick = new Date().getTime(); var WSrate = 1000; if (mergeType) { /* main merge tool */ - mergeType = mergeType[1].replace(/_/, "-"); - var showEntityInfo = true; - var entities = {}; - var minrowid; - var lastCB; - var mergeForm = document.querySelector("div#content > form[action*='/merge']"); - if (mergeForm) { - /* entity merge pages progressively abandon ul layout in favour of table.tbl - * area ul (but only for admins) - * artist ul - * event table.tbl - * label table.tbl - * place table.tbl - * recording table.tbl - * release table.tbl - * release group table.tbl - * series table.tbl - * work table.tbl - * what else ? */ - mergeForm.addEventListener("submit", function(event) { - var editNote = this.querySelector("textarea[name='merge.edit_note']"); - if (event.submitter && event.submitter.classList.contains("positive")) { - // Script only triggered by Submit (button.positive), not Cancel (button.negative) - if (editNote && editNote.value && editNote.value.match(/\w{4,}/g) && editNote.value.match(/\w{4,}/g).length > 3) { - editNote.style.removeProperty("background-color"); - editNote.value = editNote.value.replace(/(^[\n\r\s\t]+|[\n\r\s\t]+$)/g, "").replace(/\n?(\s*—[\s\S]+)?Merging\sinto\soldest\s\[MBID\]\s\([\'\d,\s←+]+\)\.(\n|$)/g, "").replace(/(^[\n\r\s\t]+|[\n\r\s\t]+$)/g, "");//linked in mb_ELEPHANT-EDITOR.user.js - var mergeTargets = mergeForm.querySelectorAll("form > table.tbl > tbody input[type='radio'][name='merge.target'], form > ul > li input[type='radio'][name='merge.target']"); - var mergeTarget; - var sortedTargets = []; - for (var t = 0; t < mergeTargets.length; t++) { - var id = parseInt(mergeTargets[t].value, 10); - if (mergeTargets[t].checked) { - mergeTarget = id; - } - if (sortedTargets.length == 0 || id > sortedTargets[sortedTargets.length - 1]) { - sortedTargets.push(id); - } else if (id < sortedTargets[0]) { - sortedTargets.unshift(id); - } else { - for (var s = 0; s < sortedTargets.length; s++) { - if (id < sortedTargets[s]) { - sortedTargets.splice(s, 0, id); - break; + var deferScript = setInterval(function() { + // Make sure no more React funny stuff will redraw content (on /recording/merge for the moment) + if (!document.querySelector("p.loading-message")) { + clearInterval(deferScript); + findUsefulMergeInfo(); + } + }, 500); + function findUsefulMergeInfo() { + mergeType = mergeType[1].replace(/_/, "-"); + var showEntityInfo = true; + var entities = {}; + var minrowid; + var lastCB; + var mergeForm = document.querySelector("div#content > form[action*='/merge']"); + if (mergeForm) { + /* entity merge pages progressively abandon ul layout in favour of table.tbl + * area ul (but only for admins) + * artist ul + * event table.tbl + * label table.tbl + * place table.tbl + * recording table.tbl + * release table.tbl + * release group table.tbl + * series table.tbl + * work table.tbl + * what else ? */ + mergeForm.addEventListener("submit", function(event) { + var editNote = this.querySelector("textarea[name='merge.edit_note']"); + if (event.submitter && event.submitter.classList.contains("positive")) { + // Script only triggered by Submit (button.positive), not Cancel (button.negative) + if (editNote && editNote.value && editNote.value.match(/\w{4,}/g) && editNote.value.match(/\w{4,}/g).length > 3) { + editNote.style.removeProperty("background-color"); + editNote.value = editNote.value.replace(/(^[\n\r\s\t]+|[\n\r\s\t]+$)/g, "").replace(/\n?(\s*—[\s\S]+)?Merging\sinto\soldest\s\[MBID\]\s\([\'\d,\s←+]+\)\.(\n|$)/g, "").replace(/(^[\n\r\s\t]+|[\n\r\s\t]+$)/g, "");//linked in mb_ELEPHANT-EDITOR.user.js + var mergeTargets = mergeForm.querySelectorAll("form > table.tbl > tbody input[type='radio'][name='merge.target'], form > ul > li input[type='radio'][name='merge.target']"); + var mergeTarget; + var sortedTargets = []; + for (var t = 0; t < mergeTargets.length; t++) { + var id = parseInt(mergeTargets[t].value, 10); + if (mergeTargets[t].checked) { + mergeTarget = id; + } + if (sortedTargets.length == 0 || id > sortedTargets[sortedTargets.length - 1]) { + sortedTargets.push(id); + } else if (id < sortedTargets[0]) { + sortedTargets.unshift(id); + } else { + for (var s = 0; s < sortedTargets.length; s++) { + if (id < sortedTargets[s]) { + sortedTargets.splice(s, 0, id); + break; + } } } } - } - if (mergeTarget && mergeTarget == sortedTargets[0]) { - mergeTargets = "'''" + thousandSeparator(mergeTarget) + "'''"; - for (var i = 1; i < sortedTargets.length; i++) { - mergeTargets += (i == 1 ? " ← " : " + ") + thousandSeparator(sortedTargets[i]); + if (mergeTarget && mergeTarget == sortedTargets[0]) { + mergeTargets = "'''" + thousandSeparator(mergeTarget) + "'''"; + for (var i = 1; i < sortedTargets.length; i++) { + mergeTargets += (i == 1 ? " ← " : " + ") + thousandSeparator(sortedTargets[i]); + } + editNote.value = (editNote.value ? editNote.value + "\n — \n" : "") + "Merging into oldest [MBID] (" + mergeTargets + ")."; } - editNote.value = (editNote.value ? editNote.value + "\n — \n" : "") + "Merging into oldest [MBID] (" + mergeTargets + ")."; + } else { + alert("Merging entities is a destructive edit that is impossible to undo without losing ISRCs, AcoustIDs, edit histories, etc.\n\nPlease make sure your edit note makes it clear why you are sure that these entities are exactly the same versions, mixes, cuts, etc."); + editNote.style.setProperty("background-color", "pink"); + return stop(event); } + } + }); + var tbl = mergeForm.querySelector("table.tbl"); + var entityRows = mergeForm.getElementsByTagName("li"); + if (tbl) { + entityRows = mergeForm.querySelectorAll("form table.tbl > tbody > tr"); + var headers = tbl.querySelector("thead tr"); + if (showEntityInfo && mergeType.match(/(release|release-group)/)) { + headers.appendChild(document.createElement("th")).appendChild(document.createTextNode("Information")); } else { - alert("Merging entities is a destructive edit that is impossible to undo without losing ISRCs, AcoustIDs, edit histories, etc.\n\nPlease make sure your edit note makes it clear why you are sure that these entities are exactly the same versions, mixes, cuts, etc."); - editNote.style.setProperty("background-color", "pink"); - return stop(event); + showEntityInfo = false; } + var rowids = document.createElement("th"); + rowids.setAttribute("id", userjs + "rowidsHeader"); + rowids.style.setProperty("text-align", "right"); + rowids.appendChild(document.createTextNode("MBID age (row ID) ")); + headers.appendChild(rowids); + var batchRemove = headers.appendChild(document.createElement("th")).appendChild(createA("Remove selected entities", null, "Remove selected " + mergeType + "s from merge")); + batchRemove.addEventListener("click", removeFromMerge); } - }); - var tbl = mergeForm.querySelector("table.tbl"); - var entityRows = mergeForm.getElementsByTagName("li"); - if (tbl) { - entityRows = mergeForm.querySelectorAll("form > table.tbl > tbody > tr"); - var headers = tbl.querySelector("thead tr"); - if (showEntityInfo && mergeType.match(/(release|release-group)/)) { - headers.appendChild(document.createElement("th")).appendChild(document.createTextNode("Information")); - } else { - showEntityInfo = false; - } - var rowids = document.createElement("th"); - rowids.setAttribute("id", userjs + "rowidsHeader"); - rowids.style.setProperty("text-align", "right"); - rowids.appendChild(document.createTextNode("MBID age (row ID) ")); - headers.appendChild(rowids); - var batchRemove = headers.appendChild(document.createElement("th")).appendChild(createA("Remove selected entities", null, "Remove selected " + mergeType + "s from merge")); - batchRemove.addEventListener("click", removeFromMerge); - } - var rowIDzone = []; - for (var row = 0; row < entityRows.length; row++) { - var a = entityRows[row].querySelector("a[href^='/" + mergeType + "/']"); - var rad = entityRows[row].querySelector("input[type='radio'][name='merge.target']"); - if (a && rad) { - if (showEntityInfo) { - addZone(entityRows[row], "entInfo" + rad.value); - } - entities[rad.value] = {a: a, rad: rad, row: entityRows[row], rowid: parseInt(rad.value, 10)}; - minrowid = row == 0 ? entities[rad.value].rowid : Math.min(minrowid, entities[rad.value].rowid); - if (document.referrer) { - var lmbid = a.getAttribute("href").match(rembid); - var rmbid = document.referrer.match(rembid); - if (lmbid && rmbid && lmbid[0] == rmbid[0]) { - if (tbl) { - var tds = entityRows[row].querySelectorAll("td"); - for (var td = 0; td < tds.length; td++) { - tds[td].style.setProperty("background-color", "#FF6"); + var rowIDzone = []; + for (var row = 0; row < entityRows.length; row++) { + var a = entityRows[row].querySelector("a[href^='/" + mergeType + "/']"); + var rad = entityRows[row].querySelector("input[type='radio'][name='merge.target']"); + if (a && rad) { + if (showEntityInfo) { + addZone(tbl, entityRows[row], "entInfo" + rad.value); + } + entities[rad.value] = {a: a, rad: rad, row: entityRows[row], rowid: parseInt(rad.value, 10)}; + minrowid = row == 0 ? entities[rad.value].rowid : Math.min(minrowid, entities[rad.value].rowid); + if (document.referrer) { + var lmbid = a.getAttribute("href").match(rembid); + var rmbid = document.referrer.match(rembid); + if (lmbid && rmbid && lmbid[0] == rmbid[0]) { + if (tbl) { + var tds = entityRows[row].querySelectorAll("td"); + for (var td = 0; td < tds.length; td++) { + tds[td].style.setProperty("background-color", "#FF6"); + } + } else { + entityRows[row].style.setProperty("background-color", "#FF6"); } - } else { - entityRows[row].style.setProperty("background-color", "#FF6"); + entityRows[row].style.setProperty("border", "thin dashed black"); + entityRows[row].setAttribute("title", "LAST CLICK"); + rad.click(); } - entityRows[row].style.setProperty("border", "thin dashed black"); - entityRows[row].setAttribute("title", "LAST CLICK"); - rad.click(); } + entities[rad.value].rowidzone = addZone(tbl, entityRows[row], "rowID"+row); + entities[rad.value].rowidzone.style.setProperty("text-align", "right"); + entities[rad.value].rowidzone.appendChild(rowIDLink(mergeType.replace(/-/, "_"), rad.value)); + var removeZone = addZone(tbl, entityRows[row], "remove" + row); + var batchRemove = document.createElement("label"); + var removeCB = batchRemove.appendChild(document.createElement("input")); + removeCB.setAttribute("type", "checkbox"); + removeCB.setAttribute("ref", "remove"); + removeCB.setAttribute("value", rad.value); + batchRemove.addEventListener("click", rangeClick); + batchRemove.appendChild(document.createTextNode("remove")); + removeZone.appendChild(batchRemove); + removeZone.appendChild(document.createTextNode(" (")); + removeZone.appendChild(createA("now", null, "remove this and all selected " + mergeType + "s from merge")).addEventListener("click", removeFromMerge); + removeZone.appendChild(document.createTextNode(")")); } - entities[rad.value].rowidzone = addZone(entityRows[row], "rowID"+row); - entities[rad.value].rowidzone.style.setProperty("text-align", "right"); - entities[rad.value].rowidzone.appendChild(rowIDLink(mergeType.replace(/-/, "_"), rad.value)); - var removeZone = addZone(entityRows[row], "remove" + row); - var batchRemove = document.createElement("label"); - var removeCB = batchRemove.appendChild(document.createElement("input")); - removeCB.setAttribute("type", "checkbox"); - removeCB.setAttribute("ref", "remove"); - removeCB.setAttribute("value", rad.value); - batchRemove.addEventListener("click", rangeClick); - batchRemove.appendChild(document.createTextNode("remove")); - removeZone.appendChild(batchRemove); - removeZone.appendChild(document.createTextNode(" (")); - removeZone.appendChild(createA("now", null, "remove this and all selected " + mergeType + "s from merge")).addEventListener("click", removeFromMerge); - removeZone.appendChild(document.createTextNode(")")); } - } - if (minrowid) { - minrowid += ""; - entities[minrowid].row.style.setProperty("text-shadow", "0px 0px 8px #0C0"); - entities[minrowid].rowidzone.style.setProperty("color", "#060"); - entities[minrowid].rowidzone.insertBefore(document.createTextNode(" (oldest) "), entities[minrowid].rowidzone.firstChild); - var rowidsHeader = document.getElementById(userjs + "rowidsHeader"); - var sortButton = createA(rowidsHeader ? rowidsHeader.textContent : "SORT!", null, "Sort those " + mergeType + "s (oldest ID first)"); - sortButton.addEventListener("click", function(e) { - sortBy("rowid"); - }); - if (rowidsHeader) { - rowidsHeader.replaceChild(sortButton, rowidsHeader.firstChild); - } else { - mergeForm.insertBefore(sortButton, mergeForm.firstChild); + if (minrowid) { + minrowid += ""; + entities[minrowid].row.style.setProperty("text-shadow", "0px 0px 8px #0C0"); + entities[minrowid].rowidzone.style.setProperty("color", "#060"); + entities[minrowid].rowidzone.insertBefore(document.createTextNode(" (oldest) "), entities[minrowid].rowidzone.firstChild); + var rowidsHeader = document.getElementById(userjs + "rowidsHeader"); + var sortButton = createA(rowidsHeader ? rowidsHeader.textContent : "SORT!", null, "Sort those " + mergeType + "s (oldest ID first)"); + sortButton.addEventListener("click", function(e) { + sortBy("rowid"); + }); + if (rowidsHeader) { + rowidsHeader.replaceChild(sortButton, rowidsHeader.firstChild); + } else { + mergeForm.insertBefore(sortButton, mergeForm.firstChild); + } + entities[minrowid].rowidzone.querySelector("a[href$='conditions.0.args.0=" + entities[minrowid].rowid + "']").style.setProperty("background-color", "#6F6"); + entities[minrowid].rad.click(); } - entities[minrowid].rowidzone.querySelector("a[href$='conditions.0.args.0=" + entities[minrowid].rowid + "']").style.setProperty("background-color", "#6F6"); - entities[minrowid].rad.click(); - } - if (showEntityInfo) { - loadEntInfo(); - } - if (mergeType == "release") { - /* make the release each medium is from a clickable link */ - for (var releases = {}, mediums = document.querySelectorAll("input[id$='.release_id'][type='hidden']"), m = 0; m < mediums.length; m++) { - if (!releases[mediums[m].value]) { - releases[mediums[m].value] = {fragment: document.createDocumentFragment()}; - var releaseCell = getSibling(document.querySelector("form > table.tbl > tbody input[type='radio'][name='merge.target'][value='" + mediums[m].value + "']").parentNode, "td"); - releases[mediums[m].value].format = releaseCell.parentNode.getElementsByTagName("td")[3].textContent.replace(/\s/g, "").replace(/"/g, "″"); - for (var c = 0; c < releaseCell.childNodes.length; c++) { - releases[mediums[m].value].fragment.appendChild(releaseCell.childNodes[c].cloneNode(true)); + if (showEntityInfo) { + loadEntInfo(); + } + if (mergeType == "release") { + /* make the release each medium is from a clickable link */ + for (var releases = {}, mediums = document.querySelectorAll("input[id$='.release_id'][type='hidden']"), m = 0; m < mediums.length; m++) { + if (!releases[mediums[m].value]) { + releases[mediums[m].value] = {fragment: document.createDocumentFragment()}; + var releaseCell = getSibling(document.querySelector("form > table.tbl > tbody input[type='radio'][name='merge.target'][value='" + mediums[m].value + "']").parentNode, "td"); + releases[mediums[m].value].format = releaseCell.parentNode.getElementsByTagName("td")[3].textContent.replace(/\s/g, "").replace(/"/g, "″"); + for (var c = 0; c < releaseCell.childNodes.length; c++) { + releases[mediums[m].value].fragment.appendChild(releaseCell.childNodes[c].cloneNode(true)); + } + removeNode(releases[mediums[m].value].fragment.querySelector("div.jesus2099userjs154481")); + var a = releases[mediums[m].value].fragment.querySelector("a[href^='/release/']"); + a.setAttribute("target", "_blank"); + a.style.setProperty("color", self.getComputedStyle(releaseCell.getElementsByTagName("a")[0]).getPropertyValue("color")); + releases[mediums[m].value].title = a.textContent; } - removeNode(releases[mediums[m].value].fragment.querySelector("div.jesus2099userjs154481")); - var a = releases[mediums[m].value].fragment.querySelector("a[href^='/release/']"); - a.setAttribute("target", "_blank"); - a.style.setProperty("color", self.getComputedStyle(releaseCell.getElementsByTagName("a")[0]).getPropertyValue("color")); - releases[mediums[m].value].title = a.textContent; + var text = mediums[m].parentNode.lastChild.textContent.trim(); + mediums[m].parentNode.replaceChild(createTag("fragment", {}, [ + " " + text.substring(1, text.lastIndexOf(releases[mediums[m].value].title)), + releases[mediums[m].value].fragment.cloneNode(true), + createTag("span", {a: {class: "comment"}}, " (" + releases[mediums[m].value].format + ")"), + text.substring(text.lastIndexOf(releases[mediums[m].value].title) + releases[mediums[m].value].title.length, text.length - 1) + ]), mediums[m].parentNode.lastChild); } - var text = mediums[m].parentNode.lastChild.textContent.trim(); - mediums[m].parentNode.replaceChild(createTag("fragment", {}, [ - " " + text.substring(1, text.lastIndexOf(releases[mediums[m].value].title)), - releases[mediums[m].value].fragment.cloneNode(true), - createTag("span", {a: {class: "comment"}}, " (" + releases[mediums[m].value].format + ")"), - text.substring(text.lastIndexOf(releases[mediums[m].value].title) + releases[mediums[m].value].title.length, text.length - 1) - ]), mediums[m].parentNode.lastChild); } } } @@ -472,7 +481,7 @@ function loadimg(txt) { } return img; } -function addZone(par, id) { +function addZone(tbl, par, id) { par.appendChild(document.createTextNode(" ")); var zone = par.appendChild(document.createElement(tbl ? "td" : "span")); zone.setAttribute("id", userjs + id); diff --git a/mb_COLLECTION-HIGHLIGHTER.user.js b/mb_COLLECTION-HIGHLIGHTER.user.js index a5898bb4..a86e04c3 100644 --- a/mb_COLLECTION-HIGHLIGHTER.user.js +++ b/mb_COLLECTION-HIGHLIGHTER.user.js @@ -2,7 +2,7 @@ var meta = {raw: function() { // ==UserScript== // @name mb. COLLECTION HIGHLIGHTER -// @version 2020.10.18.3 +// @version 2020.11.29 // @description musicbrainz.org: Highlights releases, release-groups, etc. that you have in your collections (anyone’s collection can be loaded) everywhere // @compatible vivaldi(2.4.1488.38)+violentmonkey my setup (office) // @compatible vivaldi(1.0.435.46)+violentmonkey my setup (home, xp) @@ -56,7 +56,7 @@ if (cat) { var MBWSRate = 999; /* -------- CONFIGURATION END (don’t edit below) -------- */ var prefix = "collectionHighlighter"; - var DEBUG = false; + var DEBUG = localStorage.getItem("jesus2099debug"); var dialogprefix = "..:: " + meta.nameAndVersion.replace(/ /g, " :: ") + " ::..\n\n"; var maxRetry = 20; var retryPause = 5000; @@ -210,43 +210,53 @@ if (cat) { // ############################################################################ // # COLLECT LINKS TO HIGHLIGHT / DECORATE # // ############################################################################ - stuff = {}; - // Annotation link trim spaces and protocol + "//" + host - for (var annotationLinks = document.querySelectorAll("div#content div.annotation a"), l = 0; l < annotationLinks.length; l++) { - annotationLinks[l].setAttribute("href", annotationLinks[l].getAttribute("href").trim().replace(/^((https?:)?\/\/(\w+\.)?musicbrainz\.org)\//, "/")); - } - for (var stu = 0; stu < collectedStuff.length; stu++) { - var cstuff = collectedStuff[stu]; - stuff[cstuff] = {}; - var uphill = ""; - var downhill = cat == "release" && cstuff == "label" ? "" : "[count(ancestor::xhtml:div[contains(@id, 'sidebar')])=0]"; - if (!highlightInEditNotes && (cat == "edit" || cat == "edits")) { - downhill += "[count(ancestor::xhtml:div[contains(@class, 'edit-notes')])=0]"; + var deferScript = setInterval(function() { + debug("Interval " + deferScript); + // Make sure no more React funny stuff will redraw content (on /recording/merge for the moment) + if (!document.querySelector("p.loading-message")) { + clearInterval(deferScript); + findOwnedStuff(); } - var root = cat == "track" /* acoustid.org */ ? "//musicbrainz.org/" : "/"; - var path = uphill + "//xhtml:a[starts-with(@href, '" + root + cstuff + "/')]" + downhill; - var xp = document.evaluate(path, document, nsr, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0; i < xp.snapshotLength; i++) { - var mbid = xp.snapshotItem(i).getAttribute("href").match(new RegExp("/" + cstuff + "/(" + strMBID + ")$")); - if (mbid) { - mbid = mbid[1]; - if (!stuff[cstuff].loaded) { - stuff[cstuff].rawids = GM_getValue(cstuff + "s"); - if (stuff[cstuff].rawids) { - stuff[cstuff].ids = stuff[cstuff].rawids.split(" "); - debug(" \n" + stuff[cstuff].ids.length + " " + cstuff.toUpperCase() + (stuff[cstuff].ids.length == 1 ? "" : "S") + " loaded (" + cstuff + "s)\nMatching: " + path, true); - } else { debug(" \nNo " + cstuff.toUpperCase() + "S in highlighter (" + cstuff + "s)", true); } - stuff[cstuff].loaded = true; - } - if (stuff[cstuff].ids && stuff[cstuff].ids.indexOf(mbid) > -1) { - debug(mbid + " ● “" + xp.snapshotItem(i).textContent + "”", true); - decorate(xp.snapshotItem(i)); - } + }, 500); + } +} +function findOwnedStuff() { + stuff = {}; + // Annotation link trim spaces and protocol + "//" + host + for (var annotationLinks = document.querySelectorAll("div#content div.annotation a"), l = 0; l < annotationLinks.length; l++) { + annotationLinks[l].setAttribute("href", annotationLinks[l].getAttribute("href").trim().replace(/^((https?:)?\/\/(\w+\.)?musicbrainz\.org)\//, "/")); + } + for (var stu = 0; stu < collectedStuff.length; stu++) { + var cstuff = collectedStuff[stu]; + stuff[cstuff] = {}; + var uphill = ""; + var downhill = cat == "release" && cstuff == "label" ? "" : "[count(ancestor::xhtml:div[contains(@id, 'sidebar')])=0]"; + if (!highlightInEditNotes && (cat == "edit" || cat == "edits")) { + downhill += "[count(ancestor::xhtml:div[contains(@class, 'edit-notes')])=0]"; + } + var root = cat == "track" /* acoustid.org */ ? "//musicbrainz.org/" : "/"; + var path = uphill + "//xhtml:a[starts-with(@href, '" + root + cstuff + "/')]" + downhill; + var xp = document.evaluate(path, document, nsr, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0; i < xp.snapshotLength; i++) { + var mbid = xp.snapshotItem(i).getAttribute("href").match(new RegExp("/" + cstuff + "/(" + strMBID + ")$")); + if (mbid) { + mbid = mbid[1]; + if (!stuff[cstuff].loaded) { + stuff[cstuff].rawids = GM_getValue(cstuff + "s"); + if (stuff[cstuff].rawids) { + stuff[cstuff].ids = stuff[cstuff].rawids.split(" "); + debug(" \n" + stuff[cstuff].ids.length + " " + cstuff.toUpperCase() + (stuff[cstuff].ids.length == 1 ? "" : "S") + " loaded (" + cstuff + "s)\nMatching: " + path, true); + } else { debug(" \nNo " + cstuff.toUpperCase() + "S in highlighter (" + cstuff + "s)", true); } + stuff[cstuff].loaded = true; + } + if (stuff[cstuff].ids && stuff[cstuff].ids.indexOf(mbid) > -1) { + debug(mbid + " ● “" + xp.snapshotItem(i).textContent + "”", true); + decorate(xp.snapshotItem(i)); } } } - debug(""); } + debug(""); } // ############################################################################ // # #