Created
          May 31, 2022 10:16 
        
      - 
      
- 
        Save arbakker/83145e4567995c0ed93713eed166db55 to your computer and use it in GitHub Desktop. 
    NGR - improved xml metadata view - greasemonkey userscript #greasemonkey #js #userscript #NGR #geonetwork
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | // ==UserScript== | |
| // @name NGR - improved xml metadata view | |
| // @version 1.0.4 | |
| // @grant GM.info | |
| // @require https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js | |
| // @match https://nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search* | |
| // @match https://ngr.acceptatie.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search* | |
| // @run-at document-end | |
| // ==/UserScript== | |
| // run in your browser with https://www.tampermonkey.net/ | |
| var customCSS = ` | |
| code span{ | |
| font-family: Menlo, Monaco, Consolas, "Courier New", monospace !important; /* highlightjs spans causes font change */ | |
| } | |
| pre{ | |
| background-color: #fdf6e3; /* bg color of solarized light */ | |
| margin-top:1em; | |
| } | |
| .hljs{ | |
| background: unset; | |
| } | |
| // solarized light highlight | |
| .hljs{display:block;overflow-x:auto;padding:.5em;background:#fdf6e3;color:#657b83}.hljs-comment,.hljs-quote{color:#93a1a1}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#859900}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#2aa198}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#268bd2}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#b58900}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#eee8d5}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} | |
| ` | |
| function GM_addStyle(cssStr) { | |
| var D = document; | |
| var newNode = D.createElement('style'); | |
| newNode.textContent = cssStr; | |
| var targ = D.getElementsByTagName('head')[0] || D.body || D.documentElement; | |
| targ.appendChild(newNode); | |
| } | |
| // see https://stackoverflow.com/a/33928558/1763690 | |
| function copyToClipboard(text) { | |
| if (window.clipboardData && window.clipboardData.setData) { | |
| // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible. | |
| return clipboardData.setData("Text", text) | |
| } | |
| else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { | |
| var textarea = document.createElement("textarea") | |
| textarea.textContent = text | |
| textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in Microsoft Edge. | |
| document.body.appendChild(textarea) | |
| textarea.select() | |
| try { | |
| return document.execCommand("copy"); // Security exception may be thrown by some browsers. | |
| } | |
| catch (ex) { | |
| console.warn("Copy to clipboard failed.", ex) | |
| return false | |
| } | |
| finally { | |
| document.body.removeChild(textarea) | |
| } | |
| } | |
| } | |
| function queryMetadata(selector) { | |
| let parser = new DOMParser() | |
| let xmlEl = document.getElementById("xml") | |
| let xmlDoc = parser.parseFromString(xmlEl.innerText, "text/xml") | |
| console.log(xmlDoc) | |
| let el = xmlDoc.querySelector(selector) | |
| if (el) { | |
| return el | |
| } | |
| return null | |
| } | |
| function queryAll(selector) { | |
| let parser = new DOMParser() | |
| let xmlEl = document.getElementById("xml") | |
| let xmlDoc = parser.parseFromString(xmlEl.innerText, "text/xml") | |
| return xmlDoc.querySelectorAll(selector) | |
| } | |
| function getParams(url) { | |
| var params = {}; | |
| var parser = document.createElement('a'); | |
| parser.href = url; | |
| var query = parser.search.substring(1); | |
| var vars = query.split('&'); | |
| for (var i = 0; i < vars.length; i++) { | |
| var pair = vars[i].split('='); | |
| params[pair[0]] = decodeURIComponent(pair[1]); | |
| } | |
| return params; | |
| }; | |
| function createButton(id, text, title, anchor=false) { | |
| let btn = document.createElement("button") | |
| if (anchor){ | |
| btn = document.createElement("a") | |
| } | |
| btn.id = id | |
| btn.innerText = text | |
| btn.classList.add("btn") | |
| btn.classList.add("btn-default") | |
| btn.title = title | |
| return btn | |
| } | |
| function showCopyError(query) { | |
| let querySlash = query.replaceAll(" ", "/") | |
| alert(`could not locate //${querySlash} element in metadata`) | |
| } | |
| function copySucces() { | |
| let icon = document.getElementById("copy-succes") | |
| icon.style.display = "inline-block" | |
| setTimeout(function () { icon.style.display = "none" }, 1000); | |
| } | |
| function copySuccesMd() { | |
| let icon = document.getElementById("copy-succes-md") | |
| icon.style.display = "inline-block" | |
| setTimeout(function () { icon.style.display = "none" }, 1000); | |
| } | |
| function getMenuItem(id, text, title) { | |
| let menuItem = document.createElement("li") | |
| menuItem.setAttribute("role", "menuitem") | |
| let menuA = document.createElement("a") | |
| menuA.id = id | |
| menuA.title = title | |
| let menuSpan = document.createElement("span") | |
| menuSpan.innerText = text | |
| menuA.appendChild(menuSpan) | |
| menuItem.appendChild(menuA) | |
| return menuItem | |
| } | |
| function is_service_record(){ | |
| // <gmd:hierarchyLevel> | |
| // <gmd:MD_ScopeCode @codeListValue | |
| let query = "hierarchyLevel MD_ScopeCode" | |
| let result = queryMetadata(query) | |
| let scopeString = result.getAttribute("codeListValue") | |
| console.log(scopeString) | |
| return scopeString == "service" | |
| } | |
| function initCodeBlock() { | |
| if (window.location.hash.includes("&output=xml")) { | |
| new Promise(function (resolve, reject) { | |
| setTimeout(resolve, | |
| 2000) | |
| }).then(function () { | |
| let codeDiv = document.getElementById("gn-metadata-display") | |
| if (codeDiv.firstElementChild && codeDiv.firstElementChild.tagName === "LINK") { | |
| codeDiv.removeChild(codeDiv.firstElementChild) | |
| } | |
| let groupDiv = document.createElement("div") | |
| groupDiv.classList.add("btn-group") | |
| groupDiv.innerHTML = '<div class="btn-group" id="mdxmltools-btn-group"><button type="button" title="Copy metadata elements"' + | |
| 'class="btn btn-default dropdown-toggle" data-toggle="dropdown"><i id="copy-succes" style="display:none;"' + | |
| 'class="fa fa-fw fa-check"></i><span>Copy md elements</span><span class="caret"></span></button>' + | |
| '<ul role="menu" class="dropdown-menu" id="mdxmltools-menuitems"></ul>' + | |
| '</div>' | |
| let ul = groupDiv.firstChild.lastChild | |
| let codeEl = document.querySelector("code.html") | |
| if (codeEl) { | |
| let unescapedXml = codeEl.innerHTML | |
| let xml = codeEl.innerHTML.replaceAll("&amp;", | |
| "&") | |
| codeEl.innerHTML = xml | |
| let xmlDiv = document.getElementById("xml") | |
| if (!xmlDiv) { | |
| xmlDiv = document.createElement("div") | |
| xmlDiv.id = "xml" | |
| xmlDiv.style.display = "none" // Prevent scrolling to bottom of page in Microsoft Edge. | |
| document.body.appendChild(xmlDiv) | |
| } | |
| xmlDiv.innerHTML = unescapedXml | |
| } | |
| hljs.highlightBlock(codeEl) | |
| // copy md button | |
| let btn = createButton("copy-metadata", "Copy metadata", "Copy metadata to clipboard") | |
| btn.innerHTML = '<i id="copy-succes-md" style="display:none;" class="fa fa-fw fa-check"></i><span>Copy metadata</span>' | |
| btn.addEventListener("click", function () { | |
| let xmlEl = document.getElementById("xml") | |
| copyToClipboard(xmlEl.innerText) | |
| copySuccesMd() | |
| }) | |
| // copy online resource | |
| let menuItem = getMenuItem("copy-onlineresource", "Copy onlineResource", "Copy onlineResource to clipboard") | |
| ul.appendChild(menuItem) | |
| menuItem.firstChild.addEventListener("click", function () { | |
| try { | |
| const query = "MD_DigitalTransferOptions onLine CI_OnlineResource linkage URL" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| copyToClipboard(result.textContent) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| } catch (ex) { | |
| console.log(ex) | |
| } | |
| }) | |
| // copy md id | |
| let menuItem2 = getMenuItem("copy-mdid", "Copy metadata id", "Copy metadata identifier to clipboard") | |
| ul.appendChild(menuItem2) | |
| let menuA2 = | |
| menuItem2.firstChild.addEventListener("click", function () { | |
| let query = "fileIdentifier CharacterString" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| copyToClipboard(result.textContent) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| }) | |
| // copy ds id | |
| let menuItem3 = getMenuItem("copy-did", "Copy dataset source id", "Copy dataset source identifier to clipboard") | |
| ul.appendChild(menuItem3) | |
| menuItem3.firstChild.addEventListener("click", function () { | |
| let sourceId ='' | |
| let query = '' | |
| if (! is_service_record()){ | |
| query = "identifier MD_Identifier code CharacterString" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| console.log(result) | |
| sourceId = result.textContent | |
| } | |
| }else{ | |
| query = "operatesOn" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| sourceId = result.getAttribute("uuidref") | |
| } | |
| } | |
| if(sourceId){ | |
| copyToClipboard(sourceId) | |
| copySucces() | |
| }else{ | |
| showCopyError(query) | |
| } | |
| }) | |
| let menuItem4 = getMenuItem("copy-title", "Copy title", "Copy service metadataa title to clipboard") | |
| ul.appendChild(menuItem4) | |
| menuItem4.firstChild.addEventListener("click", function () { | |
| let query = "CI_Citation title CharacterString" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| copyToClipboard(result.textContent) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| }) | |
| if (is_service_record()){ | |
| let menuItem5 = getMenuItem("copy-layers", "Copy layers", "Copy layers from service to clipboard") | |
| ul.appendChild(menuItem5) | |
| menuItem5.firstChild.addEventListener("click", function () { | |
| let query = "SV_CoupledResource ScopedName" | |
| let layers = [] | |
| let result = queryAll(query) | |
| result.forEach(function (el) { layers.push(el.textContent) }) | |
| let unique = [...new Set(layers)]; | |
| let layersString = Array.from(unique).join(', ') | |
| if (layersString) { | |
| copyToClipboard(layersString) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| }) | |
| } | |
| // copy ds md id | |
| if (is_service_record()){ | |
| let menuItem6 = getMenuItem("copy-dmdid", "Copy dataset metadata id", "Copy dataset metadata identifier to clipboard") | |
| ul.appendChild(menuItem6) | |
| menuItem6.firstChild.addEventListener("click", function () { | |
| let query = "operatesOn" | |
| let result = queryMetadata(query) | |
| if (result) { | |
| let mdUrl = result.getAttribute("xlink:href") | |
| let params = getParams(mdUrl) | |
| let mdId = "" | |
| let succes = false | |
| if (params["id"] !== undefined) { | |
| mdId = params["id"] | |
| succes = true | |
| } else if (params["uuid"] !== undefined) { | |
| mdId = params["uuid"] | |
| succes = true | |
| } | |
| if (succes) { | |
| copyToClipboard(mdId) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| } else { | |
| showCopyError(query) | |
| } | |
| }) | |
| } | |
| let menuItem7 = getMenuItem("copy-csw-url", "Copy GetRecordById URL", "Copy CSW GetRecordById URL") | |
| ul.appendChild(menuItem7) | |
| menuItem7.firstChild.addEventListener("click", function () { | |
| let query = "fileIdentifier CharacterString" | |
| let result = queryMetadata(query) | |
| if (result){ | |
| let mdId = result.textContent | |
| let prot = window.location.protocol | |
| let host= window.location.host | |
| let path = window.location.pathname.replace("catalog.search", "csw") | |
| // https://ngr.acceptatie.nationaalgeoregister.nl/geonetwork/srv/dut/csw? | |
| let query = `service=CSW&request=GetRecordById&version=2.0.2&outputSchema=http://www.isotc211.org/2005/gmd&elementSetName=full&id=${mdId}#MD_DataIdentification` | |
| let getRecordUrl = `${prot}//${host}${path}?${query}` | |
| copyToClipboard(getRecordUrl) | |
| copySucces() | |
| } else { | |
| showCopyError(query) | |
| } | |
| }) | |
| let parent = document.querySelector(".btn-toolbar") | |
| parent.appendChild(btn) | |
| parent.appendChild(groupDiv) | |
| }) | |
| } else { | |
| let mdbtn = document.getElementById('copy-metadata') | |
| if (mdbtn){ | |
| mdbtn.parentNode.removeChild(mdbtn) | |
| let btnGroup = document.getElementById("mdxmltools-btn-group") | |
| btnGroup.parentNode.removeChild(btnGroup) | |
| } | |
| } | |
| } | |
| var buttonAdded = false | |
| function initLinkButton(){ | |
| new Promise(function (resolve, reject) { | |
| setTimeout(resolve, | |
| 2000) | |
| }).then(function () { | |
| let anchors = document.querySelectorAll("div.gn-related-resources p.text-muted a") | |
| console.log(anchors) | |
| for (let i = 0; i < anchors.length; i++) { | |
| let anchor = anchors[i] | |
| const myRe = /.*\?.*?service=(wms|wfs)/gi; | |
| let matches = anchor.href.matchAll(myRe) | |
| for (const match of matches) { | |
| console.log('match', match); | |
| console.log('match.index',match.index) | |
| let svcType = match[1] | |
| let btn = createButton(anchor.href, "PDOK Reviewer", "Bekijk deze service in de PDOK Reviewer", true) | |
| let url = `https://super-funicular-1f6dee8a.pages.github.io/#/${svcType.toLowerCase()}/${encodeURIComponent(anchor.href)}` | |
| let exBtn = document.getElementById(anchor.href) | |
| if (exBtn){ | |
| return | |
| } | |
| btn.href = url | |
| btn.target = '_blank' | |
| btn.style.margin = '1em' | |
| // anchor.parentNode.parentNode.parentNode.insertBefore(btn, anchor.parentNode.parentNode); | |
| let insertNode = document.querySelector("div.gn-related-resources") | |
| console.log(insertNode) | |
| insertNode.insertBefore(btn, insertNode.firstChild.nextSibling.nextSibling) | |
| buttonAdded = true | |
| } | |
| } | |
| }) | |
| } | |
| function initScript() { | |
| let scriptName = GM.info.script.name | |
| console.log(`running ${scriptName} on document-end`) | |
| console.log(customCSS) | |
| GM_addStyle(customCSS) | |
| initCodeBlock() | |
| initLinkButton() | |
| } | |
| window.addEventListener('hashchange', function () { | |
| initScript() | |
| }) | |
| initScript() | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment