From 95fed02660104d65d0ac1dd5dd9a2b07e73c8a8e Mon Sep 17 00:00:00 2001 From: marcin-l Date: Wed, 16 Nov 2022 09:33:09 +0100 Subject: [PATCH 01/12] dev sync --- .gitignore | 1 + .vscode/settings.json | 52 +- PegaDevTools.code-workspace | 9 +- README.md | 2 +- agilestudio/agilestudio.js | 2 +- background.js | 242 +++++++-- devstudio/datapage.js | 31 +- devstudio/devstudio.css | 12 +- devstudio/devstudio.js | 63 +-- devstudio/devstudio_activity.js | 4 +- devstudio/devstudio_data.js | 1 + devstudio/devstudio_datatransform.js | 9 +- devstudio/devstudio_flow.js | 8 +- devstudio/devstudio_function.js | 7 +- devstudio/devstudio_paragraph.js | 96 ++-- devstudio/devstudio_report.js | 2 +- devstudio/devstudio_rule.js | 7 +- devstudio/devstudio_ruleform_popup.js | 2 + devstudio/devstudio_ruleset.js | 1 + devstudio/devstudio_tabs.js | 104 ++++ devstudio/logfile.js | 4 +- devstudio/refactorClass.js | 6 + js/copyDPcall.js | 6 +- js/injectFlowType.js | 1 - js/makeRuleNamesLonger.js | 42 +- js/mouseScrollTabs.js | 11 + jsconfig.json | 7 + manifest.json | 43 +- resources/contextmenu.min.css | 1 - resources/contextmenu.min.js | 1 - resources/ctxmenu.min.js | 2 + resources/favicon.png | Bin 0 -> 3975 bytes resources/registerWithServiceWorker.js | 1 + resources/shared.css | 64 ++- resources/shared.js | 508 +++++++++---------- settings.html | 21 + settings.js | 41 +- tracer/tracerNameContextMenu.html | 0 tracer/tracer_PegaRulesetSelection.html | 23 + tracer/tracer_button.html | 12 + tracer/tracer_event.css | 5 + tracer/tracer_event.js | 175 ++++++- tracer/tracer_menuRow.js | 628 ++++++++++++++---------- tracer/tracer_options.js | 25 +- tracer/tracer_page.js | 69 +-- 45 files changed, 1547 insertions(+), 804 deletions(-) create mode 100644 devstudio/devstudio_tabs.js create mode 100644 devstudio/refactorClass.js create mode 100644 js/mouseScrollTabs.js create mode 100644 jsconfig.json delete mode 100644 resources/contextmenu.min.css delete mode 100644 resources/contextmenu.min.js create mode 100644 resources/ctxmenu.min.js create mode 100644 resources/favicon.png create mode 100644 resources/registerWithServiceWorker.js create mode 100644 tracer/tracerNameContextMenu.html create mode 100644 tracer/tracer_PegaRulesetSelection.html diff --git a/.gitignore b/.gitignore index 01e2c181..79ea7099 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ resources/codemirror/css.html resources/codemirror/htmlmixed.html resources/codemirror/javascript.html resources/codemirror/jsxjava.html + diff --git a/.vscode/settings.json b/.vscode/settings.json index 0a156472..140a58b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,56 @@ { "cSpell.ignoreWords": [ "filtertable", - "openlanding" + "openlanding", + "Recordkey" + ], + "cSpell.words": [ + "agilestudio", + "bgcolor", + "closetag", + "Cntr", + "codemirror", + "contextmenu", + "ctxmenu", + "datapage", + "datatransform", + "deploymentmanager", + "devstudio", + "endregion", + "foldcode", + "foldgutter", + "fullscreen", + "htmlmixed", + "Huebee", + "inanchor", + "logfile", + "Marcin", + "matchtags", + "OOTB", + "origprocess", + "pagesort", + "Pega", + "pegacloud", + "prweb", + "rightborder", + "ruleform", + "ruleset", + "rulesets", + "rulespecific", + "Subflow", + "TABANCHOR", + "TABSPAN", + "tabtitle", + "threadname", + "tracertop", + "uicolors", + "valign", + + "bsimplelayout", + "editaction", + "Leśniak", + + + "Tinycon" ] } \ No newline at end of file diff --git a/PegaDevTools.code-workspace b/PegaDevTools.code-workspace index a8cb3c66..e5329a95 100644 --- a/PegaDevTools.code-workspace +++ b/PegaDevTools.code-workspace @@ -9,12 +9,15 @@ "*.yaml": "home-assistant" }, "cSpell.words": [ + "agilestudio", "closetag", "cntr", "codemirror", "Copypz", + "copypzinskey", "datapage", "devstudio", + "favico", "foldcode", "foldgutter", "fullscreen", @@ -24,16 +27,20 @@ "inanchor", "lesniak", "marcin", + "Marcin", "matchtags", "nocopy", "ootb", + "OOTB", "pagesort", "prweb", + "pzInskey", "Recordkey", "str", "t", "tabanchor", - "tooltiptext" + "tooltiptext", + "tracertop" ], "favorites.resources": [ { diff --git a/README.md b/README.md index 1680ac43..5d218b28 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Tracer feature to navigate to first Error and Message is based on Piotr Olejnicz ### Third-party libraries (MIT license) - [arrive.js](https://github.com/uzairfarooq/arrive) - [CodeMirror](https://codemirror.net/) -- [ContextmenuJS](https://github.com/m-thalmann/contextmenujs) +- [ctxmenu.js](https://github.com/nkappler/ctxmenu) - [Huebee](https://huebee.buzz) - [jQuery](https://jquery.com/) - [jQuery.FilterTable](https://github.com/sunnywalker/jQuery.FilterTable) diff --git a/agilestudio/agilestudio.js b/agilestudio/agilestudio.js index ba3e0159..5814583f 100644 --- a/agilestudio/agilestudio.js +++ b/agilestudio/agilestudio.js @@ -1,5 +1,5 @@ if(window.location.href.includes("agilestudio")) { - + PDT.setScriptsApplied(); console.log("agilestudio.js"); if (PDT.isAgilestudioEnabled()) { diff --git a/background.js b/background.js index b1e1daeb..a702da35 100644 --- a/background.js +++ b/background.js @@ -1,4 +1,20 @@ -var browser = (browser)? browser : chrome; +if (typeof browser === "undefined") { + var browser = chrome; +} + + + +//TODO: modularize +// try { +// importScripts('/path/file.js', '/path2/file2.js' /*, and so on */); +// } catch (e) { +// console.error(e); +//} +// chrome.webNavigation.onCompleted.addListener(info => { +// if (changeInfo.status === "complete") { +// // ... +// } +// }); function injectScript(injectedScript, tabId, frameId) { browser.scripting.executeScript({ @@ -17,20 +33,49 @@ function appendScript(appendedScript, tabId, frameId) { } var tracerIsRunningAppended = false; + // handle content script messages -browser.runtime.onMessage.addListener(async (request, sender, sendResponse) => { +browser.runtime.onMessage.addListener(async (request, sender, sendResponse) => { console.debug(request); - if (request.purpose == "getFrameId") + if (request.purpose == "getSettings") { + sendResponse(getSettings()); + } + else if (request.purpose == "reloadSettings") { + initSettings(); + } + else if (request.purpose == "getFrameId") sendResponse({ frameId: sender.frameId }); - else if (request.purpose == "paragraphRule") { - injectScriptsToIframe(sender.tab.id, sender.frameId, paragraphScriptList); - sendResponse("ok "); - } else if (request.purpose == "appendScript") { + // else if (request.purpose == "paragraphRule") { + // injectScriptsToIframe(sender.tab.id, sender.frameId, paragraphScriptList); + // sendResponse("ok "); + //} + else if (request.purpose == "appendScript") { appendScript(request.appendedScript, sender.tab.id, sender.frameId); - sendResponse("appending to tab " + sender.tab.id + " frame " + sender.frameId); + sendResponse("appending to tab " + sender.tab.id + " frame " + sender.frameId); + } else if (request.purpose == "reloadContentScripts") { + if(loadedFrames.has(sender.tab.id + "-" + sender.frameId)) { + reloadContentScripts(sender.tab.id, sender.frameId, loadedFrames.get(sender.tab.id + "-" + sender.frameId)); + sendResponse("reloading content scripts " + sender.tab.id + " frame " + sender.frameId); + } else { + console.log(sender.tab.id + "-" + sender.frameId + " not found in loadedFrames"); + } } else if (request.purpose == "injectScript") { injectScript(request.injectedScript, sender.tab.id, sender.frameId); sendResponse("injecting " + request.injectedScript + " to tab " + sender.tab.id + " frame " + sender.frameId); + } else if (request.purpose == "loaded") { + if(request.url != "about:blank" && !loadedFrames.has(sender.tab.id + "-" + sender.frameId)) { + loadedFrames.set(sender.tab.id + "-" + sender.frameId, request.url); + console.log("Registered " + sender.tab.id + "-" + sender.frameId + ": " + request.url); + } + // else { + // if(loadedFrames.has(sender.tab.id + "-" + sender.frameId) && (request.url.includes("DeleteCheckOut") || request.url.includes("ReloadHarness"))) { + // reloadContentScripts(sender.tab.id, sender.frameId, loadedFrames.get(sender.tab.id + "-" + sender.frameId)); + // sendResponse("Reloading content scripts tab " + sender.tab.id + " frame " + sender.frameId); + // } else { + // console.log(sender.tab.id + "-" + sender.frameId + " not found in loadedFrames"); + // } + // } + } else if (request.purpose == "tracerState" && arrDevTabs.get(sender.origin)) { //TODO: try Long-lived connections https://developer.chrome.com/docs/extensions/mv3/messaging/#connect @@ -72,7 +117,7 @@ function tracerIsRunning() { let tracerIndicator = document.querySelector("div#PDTTracerIndicator"); document.querySelector("button#PDTDevTracerPlayPause").addEventListener("click", function(event) { browser.runtime.sendMessage({ purpose: "tracerStop"}) }); - let titleTimerId = setInterval(function () { + let _titleTimerId = setInterval(function () { heartbeat = document.querySelector("input#PDTTracerHeartbeat").value; if (hasHeartbeat && (heartbeat === "off" || (Math.floor(Date.now() / 1000) - heartbeat) > 4)) { console.log("PDT Tracer heartbeat lost " + heartbeat + " " + Math.floor(Date.now() / 1000)); @@ -120,48 +165,143 @@ function tracerStop() { document.getElementById("Pause").click(); } -const injectScriptsToIframe = (tabId, frameId, scriptList) => { - browser.scripting.executeScript({ - files: scriptList, - target: { tabId: tabId, frameIds: [frameId] }, - world: "MAIN", +function matchToRegEx(match) { + let regEx = match.replace(/[{}()\[\]\\.+?^$|]/g, "\\$&").replace(/\*/g, '.*?'); + return regEx; +} + +function reloadContentScripts(tabId, frameId, url) { + let frameIndex = tabId + "-" + frameId; + // if(processedFrames.has(frameIndex)) { + // console.log("frameIndex " + frameIndex + " " + processedFrames.get(frameIndex) + " " + Date.now()); + // } + if(processedFrames.has(frameIndex) && (Math.floor(Date.now() - processedFrames.get(frameIndex))/1000) < 2 ) + return false; + processedFrames.set(frameIndex, Date.now()); + console.log("PDT reloadContentScripts tabId " + tabId + ", frameId" + frameId + ", URL " + url); + let manifest = browser.runtime.getManifest(); + let contentScripts = manifest.content_scripts; + if(contentScripts.length == 0) + return false; + + contentScripts.forEach(contentScript => { + let isAMatch = false; + + contentScript.matches.forEach(match => { + if(!isAMatch) { + let matchRegEx = matchToRegEx(match); + let regEx = new RegExp(matchRegEx); + isAMatch = regEx.test(url); + } + }); + + // contentScript.js = contentScript.js.filter(function(value){ + // return !value.includes("registerWithServiceWorker"); + // }); + + if(contentScript.js.includes("resources/shared.js") || contentScript.js.includes("resources/registerWithServiceWorker.js")) + isAMatch = false; + + if(isAMatch && contentScript.js.length>0) { + console.log(contentScript); + + browser.scripting.executeScript({ + files: contentScript.js, + target: { tabId: tabId, frameIds: [frameId] }, + world: "ISOLATED", + }); + + // if(contentScript.css) { + // contentScript.css.forEach(css => + // chrome.scripting.insertCSS(tabId, { + // file: css.value + // }) + // ) + // } + } + }) + +} + + +function pingFrame(tabId, frameId) { + browser.tabs.sendMessage( + tabId, + { purpose: "PingContent" }, + { frameId: frameId } + ); + console.log("Pinging content tab " + tabId + " frameId " + frameId); +} + +function initSettings() { + browser.storage.sync.get(["settings", "siteConfig"], (data) => { + settings = data.settings; + if(typeof settings === "undefined") settings = {}; + if(typeof settings.tracer === "undefined") settings.tracer = {}; + if(typeof settings.clipboard === "undefined") settings.clipboard = {}; + if(typeof settings.devstudio === "undefined") settings.devstudio = {}; + settings.siteConfig = new Map(); + + if (data.siteConfig) { + for (let i = 0; i < data.siteConfig.length; i++) { + if(data.siteConfig[i].color) { + data.siteConfig[i].color = data.siteConfig[i].color.replace("#", ''); + if (data.siteConfig[i].color.length === 3) { + data.siteConfig[i].color = data.siteConfig[i].color.split('').map((hex) => { + return hex + hex; + }).join(''); + } + if(data.siteConfig[i].color[0] != "#") + data.siteConfig[i].color = "#" + data.siteConfig[i].color; + } + + siteConfig.set(data.siteConfig[i].site, data.siteConfig[i]); + } + } }); +} - // scriptList.forEach((script) => { - // console.log("PDT executeScript tabId: " + tabId + ", frameId: " + frameId + ": " + `${script}`); - // browser.scripting.executeScript({ - // files: [injectedScript], - // target: { tabId: tabId, frameIds: [frameId] }, - // world: "MAIN" - // }); - - // browser.tabs.executeScript(tabId, { - // file: `${script}`, - // runAt: 'document_end', - // frameId: frameId - // //If the script injection fails (without the tab permission and so on) and is not checked in the callback` runtime.lastError `, - // //It's a mistake. There is no other complicated logic in this example. You don't need to record the tab of successful injection. You can fool it like this. - // }, () => void browser.runtime.lastError); +function getSettings(site) { + let settingsForSite = settings; + if(siteConfig.has(site)) + settingsForSite.siteConfig = siteConfig.get(site); + else + settingsForSite.siteConfig = {}; + return settingsForSite; +} + +let arrDevTabs = new Map(), arrTracerTabs = new Map(), loadedFrames = new Map(), processedFrames = new Map(), settings = {}, siteConfig = new Map(); + +async function setup() { + browser.runtime.onInstalled.addListener(async () => { + let url = browser.runtime.getURL("settings.html"); + await browser.tabs.create({ url }); + }); + + browser.webRequest.onCompleted.addListener( + function(details) { + console.debug(details); + if(details.frameType == "sub_frame" && details.frameId && loadedFrames.has(details.tabId + "-" + details.frameId)) + pingFrame(details.tabId, details.frameId); + }, + {urls: [""]}, + ["responseHeaders"] + ); + + initSettings(); + + // //FEATURE: toggle certain options from extension context menu + // browser.contextMenus.create({ + // title: "Toggle", + // id: "toggleMenu", + // "contexts": ["all"] + // }); + + // browser.contextMenus.create({ + // title: "Hide tab close button", + // "contexts": ["all"], + // parentId: "toggleMenu" // }); -}; - -var arrDevTabs = new Map(), arrTracerTabs = new Map(); - -const paragraphScriptList = [ - "resources/codemirror/codemirror.js", - "resources/codemirror/foldcode.js", - "resources/codemirror/foldgutter.js", - "resources/codemirror/brace-fold.js", - "resources/codemirror/indent-fold.js", - "resources/codemirror/comment-fold.js", - "resources/codemirror/xml-fold.js", - "resources/codemirror/matchtags.js", - "resources/codemirror/closetag.js", - "resources/codemirror/fullscreen.js", - "resources/codemirror/active-line.js", - "resources/codemirror/xml.js", - "resources/codemirror/javascript.js", - "resources/codemirror/css.js", - "resources/codemirror/htmlmixed.js", - "devstudio/devstudio_paragraph.js", -]; \ No newline at end of file +} + +setup(); diff --git a/devstudio/datapage.js b/devstudio/datapage.js index c49b39d9..f537ef12 100644 --- a/devstudio/datapage.js +++ b/devstudio/datapage.js @@ -1,20 +1,23 @@ +PDT.setScriptsApplied(); console.log("PDT: devstudio/datapage.js"); +document.arrive("div[node_name='pzRuleFormParameters'] h2", {onceOnly: true, existing: true}, () => { + injectScript("/js/", "CopyDPCall.js"); -//appendScript(copyToClipboard); -injectScript("/js/", "CopyDPCall.js"); + //same as CopyDPCall.js + var dpCallString = document.querySelector("span[title='Page Name']").innerText + "["; + document.querySelectorAll("div[node_name='pzRuleFormParameters'] div#gridBody_right table.gridTable tr.cellCont").forEach(function (row) { + if (row.querySelector("input") && row.querySelector("input").value) { + dpCallString += row.querySelector("input").value + ": \"" + "\", " + } + }); + if (dpCallString.endsWith(", ")) dpCallString = dpCallString.substring(0, dpCallString.length - 2); + dpCallString += "]"; + + document.querySelector("div[node_name='pzRuleFormParameters'] h2").insertAdjacentHTML( + "afterend", + '
' + dpCallString + '
' + ); -//same as CopyDPCall.js -var dpCallString = document.querySelector("span[title='Page Name']").innerText + "["; -document.querySelectorAll("div[node_name='pzRuleFormParameters'] div#gridBody_right table.gridTable tr.cellCont").forEach(function (row) { - if (row.querySelector("input") && row.querySelector("input").value) { - dpCallString += row.querySelector("input").value + ": \"" + "\", " - } }); -if (dpCallString.endsWith(", ")) dpCallString = dpCallString.substring(0, dpCallString.length - 2); -dpCallString += "]"; -document.querySelector("div[node_name='pzRuleFormParameters'] h2").insertAdjacentHTML( - "afterend", - '
' + dpCallString + '
' -); diff --git a/devstudio/devstudio.css b/devstudio/devstudio.css index 8d10da0c..468c91ec 100644 --- a/devstudio/devstudio.css +++ b/devstudio/devstudio.css @@ -2,14 +2,20 @@ padding-left: 7px !important; } - .header-layout.flex.content>.flex.content-item.system-search, .header-layout.flex.content>.flex.content-item.with-icon { border-right-width: 0 !important; margin: 0 !important; } - /* remove reserved space in recents explorer, giving more space for item description */ div[node_name='pzRecentExplorer'] div[node_name='pyFatListItems'] div.explorer-list-item > div { - padding-left: 0 !important; + padding-left: 2px !important; +} + +div[node_name='pzRecentExplorer'] div[node_name='pyFatListItems'] > div { + padding: 0 !important; +} + +div.workspace-app-name { + margin-right: 4px !important; } \ No newline at end of file diff --git a/devstudio/devstudio.js b/devstudio/devstudio.js index 9f87a788..c70f170b 100644 --- a/devstudio/devstudio.js +++ b/devstudio/devstudio.js @@ -9,14 +9,14 @@ function applyPDTCustomization() { globalConfig.settings && globalConfig.settings.useSiteLabelForBrowserTitle ) { - var newTitle = siteConfig.label + " Pega"; + let newTitle = siteConfig.label + " Pega"; if (siteConfig.version) newTitle += " " + siteConfig.version.slice(0, 1) + "." + siteConfig.version.slice(1, 2); parent.document.title = newTitle; } //FEATURE: environment header - var productionEnvElement = document.querySelector( + let productionEnvElement = document.querySelector( "div[data-ui-meta*='D_pzGetCurrentSystemRecord.pyActiveProductionLevelName']" ); if (productionEnvElement) { @@ -43,9 +43,7 @@ function applyPDTCustomization() { ); } - if ( - globalConfig.settings && globalConfig.settings.hideEnvironmentHeader - ) { + if (globalConfig.settings && globalConfig.settings.hideEnvironmentHeader) { if (productionEnvElement) productionEnvElement.style.display = "none"; } @@ -57,7 +55,7 @@ function applyPDTCustomization() { siteConfig.color.replace("#", ''); } } - var settings; + let settings; if (globalConfig && globalConfig.settings) { settings = globalConfig.settings; } @@ -70,46 +68,11 @@ function applyPDTCustomization() { alterTracerOpenBehavior(settings.tracer.openBehavior); } - //FEATURE: hide close button - if (PDT.settings.devstudio.hideCloseButton) - injectStyles("div.tStrCntr ul #close {display: none}"); - - if (PDT.settings.devstudio.longerRuleNames) { - //inject script which will apply it for newly opened tabs - injectScript("/js/", "makeRuleNamesLonger.js"); - injectStyles( - ".Temporary_top_tabs .Temporary_top_tabsList LI span#TABANCHOR { padding-right: 4px !important; padding-left: 4px; !important}" - ); - } - - if (PDT.settings.devstudio.expandTabOnHover) { - //inject script which will apply it for newly opened tabs - injectScript("/js/", "expandTabOnHover.js"); - } - - if (PDT.settings.devstudio.checkoutIndicator) { - showCheckoutIndicator(); - } - addHeaderShortcuts(); customizeText(); injectSidebarToggle(); - - //FEATURE: close tab on middle click - if (PDT.settings.devstudio.closeTabMiddleClick) { - //inject script which will apply it for newly opened tabs - injectScript("/js/", "closeTabMiddleClick.js"); - - // apply for existing tabs - document.querySelectorAll("div.tStrCntr ul table#RULE_KEY span[data-stl='1'], div.tStrCntr ul table#RULE_KEY svg").forEach(function (elem) { - elem.addEventListener("mousedown", function (e) { - console.log(e); - if (e && (e.which == 2 || e.button == 4)) - this.parentNode.parentNode.querySelector('#close').click(); - }) - }) - } } + PDT.alterFavicon(); } @@ -150,20 +113,16 @@ function showCheckoutIndicator() { if (containerTabListIndicator) { const containerTabListCallbackIndicator = function ( mutationsList, - observer + _observer ) { mutationsList.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (DEBUG) console.log(node.nodeName); + let elem; document.querySelectorAll("iframe").forEach((iframe) => { - if ( - iframe.contentWindow.document.querySelectorAll( - "button[title^='Check in']" - ).length > 0 - ) - var elem = document.querySelector( - "div.tStrCntr ul li[aria-label='" + iframe.title + "'] td span" - ); + if (iframe.contentWindow.document.querySelectorAll("button[title^='Check in']").length > 0) { + elem = document.querySelector("div.tStrCntr ul li[aria-label='" + iframe.title + "'] td span"); + } if (elem && !elem.innerText.startsWith("*")) { elem.innerText = "*" + elem.innerText; if (DEBUG) console.log(iframe.title); @@ -224,7 +183,7 @@ function customizeText() { document.querySelector("div.alerts a").innerHTML = document.querySelector("div.alerts a").innerHTML.replace(document.querySelector("div.alerts a").textContent, ''); //FEATURE: shorten Live Data - var DataInspectorButton = document.querySelector( + let DataInspectorButton = document.querySelector( "div a[data-test-id='DataInspectorButton']" ); if (DataInspectorButton) { diff --git a/devstudio/devstudio_activity.js b/devstudio/devstudio_activity.js index 3f0935c5..94363720 100644 --- a/devstudio/devstudio_activity.js +++ b/devstudio/devstudio_activity.js @@ -1,3 +1,5 @@ // console.log("PDT: devstudio/devstudio_activity.js"); +//PDT.setScriptsApplied(); //document.querySelectorAll("table ul.gridNode li.gridRow[pl_index]") -// //injectRuleExport(); \ No newline at end of file +// //injectRuleExport(); + diff --git a/devstudio/devstudio_data.js b/devstudio/devstudio_data.js index ab09af56..4b78f9c6 100644 --- a/devstudio/devstudio_data.js +++ b/devstudio/devstudio_data.js @@ -1,6 +1,7 @@ console.log("PDT: devstudio/devstudio_data.js"); +PDT.setScriptsApplied(); //TODO: to be reviewed diff --git a/devstudio/devstudio_datatransform.js b/devstudio/devstudio_datatransform.js index 59623bf6..923648b1 100644 --- a/devstudio/devstudio_datatransform.js +++ b/devstudio/devstudio_datatransform.js @@ -1,8 +1,7 @@ +PDT.setScriptsApplied(); console.log("PDT: devstudio/devstudio_datatransform.js"); - -var selection = document.querySelector("div[data-node-id='pzRuleFormRuleset'] div.primary-navigation-links"); -if(selection) { - selection.insertAdjacentHTML("beforeend", "Export"); +document.arrive("div[data-node-id='pzRuleFormRuleset'] div.primary-navigation-links", {onceOnly: true, existing: true}, (selection) => { + selection.insertAdjacentHTML("beforeend", " Export"); injectScript("/js/", "copyDataTransform.js"); -} +}); diff --git a/devstudio/devstudio_flow.js b/devstudio/devstudio_flow.js index ec88f841..b5c7b9e8 100644 --- a/devstudio/devstudio_flow.js +++ b/devstudio/devstudio_flow.js @@ -1,6 +1,6 @@ console.log("PDT: devstudio/devstudio_flow.js"); +PDT.setScriptsApplied(); -injectSidebarToggle(); -injectCloseShortcut(); - -injectScript("/js/", "injectFlowType.js"); \ No newline at end of file +document.arrive("div.gfw-breadcrumbs ul li", {onceOnly: true, existing: true}, () => { + injectScript("/js/", "injectFlowType.js"); +}); diff --git a/devstudio/devstudio_function.js b/devstudio/devstudio_function.js index 89f381fa..ae8e785c 100644 --- a/devstudio/devstudio_function.js +++ b/devstudio/devstudio_function.js @@ -1,8 +1,7 @@ +PDT.setScriptsApplied(); console.log("PDT: devstudio/devstudio_function.js"); - -var cms = document.querySelector("a.ce-expand"); -if(cms) { +document.arrive("a.ce-expand", {onceOnly: true, existing: true}, () => { injectScript("/js/", "formatJava.js"); cms.insertAdjacentHTML('beforebegin', ''); -} +}); diff --git a/devstudio/devstudio_paragraph.js b/devstudio/devstudio_paragraph.js index a91619e6..734ef3be 100644 --- a/devstudio/devstudio_paragraph.js +++ b/devstudio/devstudio_paragraph.js @@ -1,31 +1,42 @@ + +PDT.setScriptsApplied(); console.log("PDT: devstudio/devstudio_paragraph.js"); -var tries = 0; -var mainDiv; +/* //TODO: currently broken. does not work on reload +document.arrive("span.TextAreaContainer textarea", {onceOnly: true, existing: true}, () => { + applyCodeMirror(); +}); + +// var tries = 0; +// var mainDiv; -function addObserver() { - const paragraphSection = document.querySelector("div[node_name='pzViewParagraph']"); +// function addObserver() { +// const paragraphSection = document.querySelector("div[node_name='pzViewParagraph']"); - const paragraphCallback = function (mutationsList, observer) { - mutationsList.forEach((mutation) => { - applyCodeMirror(); - }); - }; +// const paragraphCallback = function (mutationsList, observer) { +// mutationsList.forEach((mutation) => { +// applyCodeMirror(); +// }); +// }; - const paragraphObserver = new MutationObserver(paragraphCallback); - paragraphObserver.observe(paragraphSection, { - childList: true, - }) -} +// const paragraphObserver = new MutationObserver(paragraphCallback); +// paragraphObserver.observe(paragraphSection, { +// childList: true, +// }) +// } +if(typeof myCodeMirror !== "undefined") + myCodeMirror.destroy(); -var myCodeMirror; +let myCodeMirror; function applyCodeMirror() { //injectStyles(".CodeMirror { height: auto;}"); - var tarea = document.querySelector("span.TextAreaContainer textarea"); - if (tarea) { + if(document.querySelector("divCodeMirror-wrap")) + document.querySelector("divCodeMirror-wrap").remove(); + let textArea = document.querySelector("span.TextAreaContainer textarea"); + if (textArea) { console.log("PDT: devstudio/devstudio_paragraph.js applying CodeMirror"); - myCodeMirror = CodeMirror.fromTextArea(tarea, { + myCodeMirror = CodeMirror.fromTextArea(textArea, { mode: "htmlmixed", lineNumbers: true, lineWrapping: true, @@ -56,32 +67,33 @@ function applyCodeMirror() { } -function waitUntilRenderRS() { - mainDiv = document.querySelector("div[node_name='pzViewParagraph']"); - if (mainDiv) { - applyCodeMirror(); - addObserver(); - } else { - tries = tries + 1; - console.log(tries); - if (tries > 10) return; - setTimeout(() => { - waitUntilRenderRS(); - }, 500); - } -} +// function waitUntilRenderRS() { +// mainDiv = document.querySelector("div[node_name='pzViewParagraph']"); +// if (mainDiv) { +// applyCodeMirror(); +// addObserver(); +// } else { +// tries = tries + 1; +// console.log(tries); +// if (tries > 10) return; +// setTimeout(() => { +// waitUntilRenderRS(); +// }, 500); +// } +// } -waitUntilRenderRS(); +// waitUntilRenderRS(); -var dom_observer = new MutationObserver(function(mutationsList) { - mutationsList.forEach((mutation) => { - console.log(mutation); - }); -}); -var container = document.documentElement || document.body; -console.log(container); -var config = { attributes: true, childList: true }; -dom_observer.observe(container, config); +// var dom_observer = new MutationObserver(function(mutationsList) { +// mutationsList.forEach((mutation) => { +// console.log(mutation); +// }); +// }); +// var container = document.documentElement || document.body; +// console.log(container); +// var config = { attributes: true, childList: true }; +// dom_observer.observe(container, config); +*/ \ No newline at end of file diff --git a/devstudio/devstudio_report.js b/devstudio/devstudio_report.js index 186d9023..a776a26d 100644 --- a/devstudio/devstudio_report.js +++ b/devstudio/devstudio_report.js @@ -1,3 +1,3 @@ console.log("PDT: devstudio/devstudio_report.js"); - +PDT.setScriptsApplied(); injectRuleExport(); \ No newline at end of file diff --git a/devstudio/devstudio_rule.js b/devstudio/devstudio_rule.js index d28e49e8..fffc9211 100644 --- a/devstudio/devstudio_rule.js +++ b/devstudio/devstudio_rule.js @@ -1,5 +1,7 @@ console.log("PDT: devstudio/devstudio_rule.js"); +PDT.setScriptsApplied(); + var tries = 0; var mainDiv; @@ -27,7 +29,7 @@ function siteConfigCallback(siteConfig, globalConfig) { //FEATURE: copy rule info (name, class, ruleset) in a format to be pasted into a table if($('a.custom_RuleOpener').eq(0)) { - $('a.custom_RuleOpener').eq(0).after(''); + $('a.custom_RuleOpener').eq(0).after(''); } //FEATURE: copy class name @@ -60,4 +62,5 @@ function waitUntilRenderRS() { waitUntilRenderRS(); injectSidebarToggle(); -injectCloseShortcut(); \ No newline at end of file +injectCloseShortcut(); + diff --git a/devstudio/devstudio_ruleform_popup.js b/devstudio/devstudio_ruleform_popup.js index cbfb06d6..a24d7228 100644 --- a/devstudio/devstudio_ruleform_popup.js +++ b/devstudio/devstudio_ruleform_popup.js @@ -1,4 +1,5 @@ console.log("PDT: devstudio/devstudio_ruleform_popup.js"); +PDT.setScriptsApplied(); var tries = 0; var mainDiv; @@ -60,4 +61,5 @@ function waitUntilRender() { } } +//TODO: use arrive.js waitUntilRender(); diff --git a/devstudio/devstudio_ruleset.js b/devstudio/devstudio_ruleset.js index 0f0d31d0..b7b4af32 100644 --- a/devstudio/devstudio_ruleset.js +++ b/devstudio/devstudio_ruleset.js @@ -1,4 +1,5 @@ console.log("PDT: devstudio/devstudio_ruleset.js"); +PDT.setScriptsApplied(); var tries = 0, pagerDiv; var rsvListObserver; diff --git a/devstudio/devstudio_tabs.js b/devstudio/devstudio_tabs.js new file mode 100644 index 00000000..067eb046 --- /dev/null +++ b/devstudio/devstudio_tabs.js @@ -0,0 +1,104 @@ +console.log("PDT: devstudio/devstudio_tabs.js"); + +function applyTabMenu() { + let tabClicked; + + let menuDefinition = [ + { + text: "⇐ Move left", + action: () => { + if(tabClicked.previousSibling && tabClicked.previousSibling.getAttribute("section_index") !="1") + tabClicked.parentElement.insertBefore(tabClicked, tabClicked.previousSibling) + } + }, + { + text: "⇒ Move right", + action: () => { + if(tabClicked.nextSibling && tabClicked.parentElement && !(tabClicked.nextSibling.classList.contains("rightborder"))) + tabClicked.parentElement.insertBefore(tabClicked.nextSibling, tabClicked) + } + }, + { isDivider: true }, + { + text: "⚐ Mark", + action: () => { + tabClicked.querySelectorAll("span#TABANCHOR, span#TABSPAN").forEach((s) => { + if(s.style.backgroundColor == "rgb(169, 7, 30)") + s.style.backgroundColor = null; + else + s.style.backgroundColor = "rgb(169, 7, 30)"; + }) + } + }, + { isDivider: true }, + { + text: "⦻ Close tab", + action: () => { if(tabClicked.querySelector('#close')) tabClicked.querySelector('#close').click(); } + }, + { isDivider: true }, + { + text: "☓ Close this menu", + action: () => { /* empty action just closes menu */ } + } + ] + + //FEATURE: menus + $("div.dc-header div.pegaTabGrp div.tStrCntr ul").on( + "contextmenu", + "li", + function (evt) { + evt.preventDefault(); + tabClicked = this; + ctxmenu.show(menuDefinition, evt); + }); +} + +document.arrive("body[data-PDTSettings='loaded']", {onceOnly: true, existing: true}, () => { + if(PDT.settings.devstudio.useTabMenu) { + applyTabMenu(); + } + + //FEATURE: scroll tabs with mouse wheel + if (PDT.settings.devstudio.mouseScrollTabs) { + injectScript("/js/", "mouseScrollTabs.js"); + } + + //FEATURE: expand tabs on hover + if (PDT.settings.devstudio.expandTabOnHover) { + //inject script which will apply it for newly opened tabs + injectScript("/js/", "expandTabOnHover.js"); + } + + //FEATURE: checkout indicator + if (PDT.settings.devstudio.checkoutIndicator) { + showCheckoutIndicator(); + } + + //FEATURE: close tab on middle click + if (PDT.settings.devstudio.closeTabMiddleClick) { + //inject script which will apply it for newly opened tabs + injectScript("/js/", "closeTabMiddleClick.js"); + + // apply for existing tabs + document.querySelectorAll("div.tStrCntr ul table#RULE_KEY span[data-stl='1'], div.tStrCntr ul table#RULE_KEY svg").forEach(function (elem) { + elem.addEventListener("mousedown", function (e) { + console.log(e); + if (e && (e.which == 2 || e.button == 4)) + this.parentNode.parentNode.querySelector('#close').click(); + }) + }) + } + + //FEATURE: hide close button + if (PDT.settings.devstudio.hideCloseButton) + injectStyles("div.tStrCntr ul #close {display: none}"); + + if (PDT.settings.devstudio.longerRuleNames) { + //inject script which will apply it for newly opened tabs + injectScript("/js/", "makeRuleNamesLonger.js"); + + injectStyles( + ".Temporary_top_tabs .Temporary_top_tabsList LI span#TABANCHOR { padding-right: 4px !important; padding-left: 4px; !important}" + ); + } +}); diff --git a/devstudio/logfile.js b/devstudio/logfile.js index 67baee82..1104ca90 100644 --- a/devstudio/logfile.js +++ b/devstudio/logfile.js @@ -5,8 +5,8 @@ if(document.querySelector("div#LogContentDiv > div b.page").nextElementSibling = window.scrollTo(0, document.body.scrollHeight); } -var pager = document.querySelector("div#LogContentDiv > div").cloneNode(true); -var target = document.querySelector("div#LogContentDiv"); +let pager = document.querySelector("div#LogContentDiv > div").cloneNode(true); +let target = document.querySelector("div#LogContentDiv"); if(target) { target.insertBefore(pager, target.firstChild); } diff --git a/devstudio/refactorClass.js b/devstudio/refactorClass.js new file mode 100644 index 00000000..5474827d --- /dev/null +++ b/devstudio/refactorClass.js @@ -0,0 +1,6 @@ +console.log("PDT: devstudio/refactorClass.js"); + +document.querySelectorAll("div.repeatContainer").forEach((e) => { + e.insertAdjacentHTML('beforebegin', ''); + } +) \ No newline at end of file diff --git a/js/copyDPcall.js b/js/copyDPcall.js index bfbcfbf2..5db4a6db 100644 --- a/js/copyDPcall.js +++ b/js/copyDPcall.js @@ -1,4 +1,4 @@ -function CopyDPCall(nocopy) { +function CopyDPCall(noCopy) { dpCallString = document.querySelector("span[title='Page Name']").innerText + "["; document.querySelectorAll("div[node_name='pzRuleFormParameters'] div#gridBody_right table.gridTable tr.cellCont").forEach(function (row) { if (row.querySelector("input") && row.querySelector("input").value) { @@ -7,11 +7,11 @@ function CopyDPCall(nocopy) { }); if (dpCallString.endsWith(", ")) dpCallString = dpCallString.substring(0, dpCallString.length - 2); dpCallString += "]"; - if(!nocopy) { + if(!noCopy) { copyToClipboard(dpCallString); //let user know - var status = document.getElementById('status'); + let status = document.getElementById('status'); status.textContent = 'copied'; setTimeout(function () { status.textContent = ''; diff --git a/js/injectFlowType.js b/js/injectFlowType.js index fe8d2a94..290c774d 100644 --- a/js/injectFlowType.js +++ b/js/injectFlowType.js @@ -1,4 +1,3 @@ - if(typeof flowTypeCategory !== 'undefined' && flowTypeCategory !== null) { let flowType = flowTypeCategory; if(flowType.includes("Standard")) diff --git a/js/makeRuleNamesLonger.js b/js/makeRuleNamesLonger.js index 74472e47..7f4bc082 100644 --- a/js/makeRuleNamesLonger.js +++ b/js/makeRuleNamesLonger.js @@ -1,26 +1,30 @@ const containerTabListNames = document.querySelector("div.tStrCntr ul"); -const containerTabListCallbackNames = function (mutationsList, _observer) { - mutationsList.forEach((mutation) => { - if(mutation.attributeName == "aria-label"){ - if (mutation.target.nodeName == "LI") { - mutation.target.classList.add("PDTmakeRuleNamesLonger"); - let title = mutation.target.getAttribute("aria-label"); - if (title) { - title = title.length > 20 ? title.substring(0, 20) + "..." : title; - mutation.target.querySelector("span[inanchor]").innerText = title; +if(containerTabListNames) { + + const containerTabListCallbackNames = function (mutationsList, _observer) { + mutationsList.forEach((mutation) => { + if(mutation.attributeName == "aria-label"){ + if (mutation.target.nodeName == "LI") { + mutation.target.classList.add("PDTmakeRuleNamesLonger"); + let title = mutation.target.getAttribute("aria-label"); + if (title) { + title = title.length > 20 ? title.substring(0, 20) + "..." : title; + mutation.target.querySelector("span[inanchor]").innerText = title; + } } } - } - }); -}; + }); + }; -const containerTabListNamesObserver = new MutationObserver(containerTabListCallbackNames); -containerTabListNamesObserver.observe(containerTabListNames, - { - attributeFilter: [ "aria-label"], - subtree: true - } -); + const containerTabListNamesObserver = new MutationObserver(containerTabListCallbackNames); + + containerTabListNamesObserver.observe(containerTabListNames, + { + attributeFilter: [ "aria-label"], + subtree: true + } + ); +} console.log("PDT: makeRuleNamesLonger.js loaded"); diff --git a/js/mouseScrollTabs.js b/js/mouseScrollTabs.js new file mode 100644 index 00000000..dcf0da09 --- /dev/null +++ b/js/mouseScrollTabs.js @@ -0,0 +1,11 @@ +function scrollHorizontally(e) { + e.currentTarget.scrollLeft -= e.wheelDelta; + e.preventDefault(); +} + +let tabListContainer = document.querySelector("div.dc-header div.pegaTabGrp div.tStrCntr"); +if (tabListContainer && tabListContainer.addEventListener) { + tabListContainer.addEventListener('wheel', scrollHorizontally, false); +} + +console.log("PDT: mouseScrollTabs.js loaded"); \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000..173db8ec --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,7 @@ +{ + "typeAcquisition": { + "include": [ + "chrome" + ] + } + } \ No newline at end of file diff --git a/manifest.json b/manifest.json index c2862c5c..344069ed 100644 --- a/manifest.json +++ b/manifest.json @@ -10,7 +10,8 @@ "contextMenus", "storage", "notifications", - "scripting" + "scripting", + "webRequest" ], "host_permissions": [""], "incognito":"spanning", @@ -37,10 +38,11 @@ "resources/shared.css" ], "js": [ - "resources/jquery-3.4.1.min.js", - "resources/tinycon.min.js", - "resources/arrive.min.js", - "resources/shared.js" + "resources/jquery-3.4.1.min.js", + "resources/arrive.min.js", + "resources/shared.js", + "resources/tinycon.min.js" + ], "all_frames": true, "match_about_blank": true, @@ -53,12 +55,12 @@ "exclude_globs": [ "*blank.htm*" ], - "js": [ - "resources/main.js" + "js": [ + "resources/registerWithServiceWorker.js" ], - "match_about_blank": false, - "run_at": "document_end" - }, + "all_frames": true, + "run_at": "document_idle" + }, { "matches": [ "*://*/prweb/*!STANDARD*", @@ -69,7 +71,9 @@ "*agile*" ], "js": [ - "devstudio/devstudio.js" + "resources/ctxmenu.min.js", + "devstudio/devstudio.js", + "devstudio/devstudio_tabs.js" ], "css": [ "devstudio/devstudio.css" @@ -231,11 +235,10 @@ "js": [ "resources/jquery-3.4.1.min.js", "resources/jquery.filtertable.min.js", - "resources/contextmenu.min.js", + "resources/ctxmenu.min.js", "tracer/tracer_event.js" ], "css": [ - "resources/contextmenu.min.css", "tracer/tracer_event.css" ], "all_frames": true, @@ -333,6 +336,14 @@ "match_about_blank": true, "run_at": "document_end" }, + { + "matches": [ + "*://*/prweb/*/*RefactorClass*PegaAccel-Management-Refactor-Class*" + ], + "js": [ + "devstudio/refactorClass.js" + ] + }, { "matches": [ "*://*.pegacloud.net/prweb/*/*" @@ -357,9 +368,11 @@ "clipboard/*", "tracer/*", "devstudio/*", - "js/*" + "js/*", + "/*" ], "matches": [""] } ] -} \ No newline at end of file +} + diff --git a/resources/contextmenu.min.css b/resources/contextmenu.min.css deleted file mode 100644 index 6d694713..00000000 --- a/resources/contextmenu.min.css +++ /dev/null @@ -1 +0,0 @@ -.cm_container{position:fixed;opacity:0;transform:scale(0);transition:transform 0.1s;transform-origin:top left;padding:0}.cm_container.display{opacity:1;transform:scale(1)}.cm_container,.cm_container *{box-sizing:border-box}.cm_container *{position:relative}.cm_container ul{list-style-type:none;padding:0;margin:0;background-color:#eee;box-shadow:0 0 5px #333}.cm_container li{padding:5px 10px;padding-right:1.7em;cursor:pointer;white-space:nowrap}.cm_container li:hover{background-color:#bbb}.cm_container li .cm_icon_span{width:1.5em;height:1.2em;vertical-align:bottom;display:inline-block;border-right:1px solid #aaa;margin-right:5px;padding-right:5px;text-align:center}.cm_container li .cm_sub_span{width:1em;display:inline-block;text-align:center;position:absolute;top:50%;right:.5em;transform:translateY(-50%)}.cm_container li>ul{position:absolute;top:0;left:100%;opacity:0;transition:opacity 0.2s;visibility:hidden}.cm_container li:hover>ul{opacity:1;visibility:visible}.cm_container li.cm_divider{border-bottom:1px solid #aaa;margin:5px;padding:0;cursor:default}.cm_container li.cm_divider:hover{background-color:inherit}.cm_container.cm_border_right>ul ul{left:unset;right:100%}.cm_container.cm_border_bottom>ul ul{top:unset;bottom:0}.cm_container li[disabled=""]{color:#777;cursor:default}.cm_container li[disabled=""]:hover{background-color:inherit} diff --git a/resources/contextmenu.min.js b/resources/contextmenu.min.js deleted file mode 100644 index fe15bb7f..00000000 --- a/resources/contextmenu.min.js +++ /dev/null @@ -1 +0,0 @@ -function ContextMenu(a,b){function c(h){var j=document.createElement("ul");return h.forEach(function(k){var l=document.createElement("li");if(l.menu=f,"undefined"==typeof k.type){var m=document.createElement("span");m.className="cm_icon_span",m.innerHTML=""==ContextUtil.getProperty(k,"icon","")?ContextUtil.getProperty(b,"default_icon",""):ContextUtil.getProperty(k,"icon","");var n=document.createElement("span");n.className="cm_text",n.innerHTML=""==ContextUtil.getProperty(k,"text","")?ContextUtil.getProperty(b,"default_text","item"):ContextUtil.getProperty(k,"text","");var o=document.createElement("span");if(o.className="cm_sub_span","undefined"!=typeof k.sub&&(""==ContextUtil.getProperty(b,"sub_icon","")?o.innerHTML="›":o.innerHTML=ContextUtil.getProperty(b,"sub_icon","")),l.appendChild(m),l.appendChild(n),l.appendChild(o),!ContextUtil.getProperty(k,"enabled",!0))l.setAttribute("disabled","");else{if("object"==typeof k.events)for(var p=Object.keys(k.events),q=0;qc&&(c=g.offsetWidth),g.offsetHeight>d&&(d=g.offsetHeight);for(var h=c,j=d,f=0;fh&&(h=c+l.width),d+l.height>j&&(j=d+l.height)}}return{width:h,height:j}}}; diff --git a/resources/ctxmenu.min.js b/resources/ctxmenu.min.js new file mode 100644 index 00000000..454da95e --- /dev/null +++ b/resources/ctxmenu.min.js @@ -0,0 +1,2 @@ +!function(){"use strict";function e(){for(var e=0,t=0,n=arguments.length;t"+t(e.text)+"",o=t(e.element);o?n.append(o):n.innerHTML=i||r,n.title=t(e.tooltip)||"",e.style&&n.setAttribute("style",t(e.style));e.icon&&(n.classList.add("icon"),n.innerHTML+='')}(e,a),!n(e))return a.classList.add("heading"),a;if(d(e))return a.classList.add("disabled"),o(e)&&a.classList.add("submenu"),a;if(a.classList.add("interactive"),r(e)){var c=document.createElement("a");return c.append.apply(c,Array.from(a.childNodes)),c.href=t(e.href),e.hasOwnProperty("download")&&(c.download=t(e.download)),e.hasOwnProperty("target")&&(c.target=t(e.target)),a.append(c),a}return i(e)?(a.addEventListener("click",e.action),a):(a.classList.add("submenu"),a)}var s="r",u="d";function l(e,t){var n=p(),i=window.visualViewport,r=i.width,o=i.height;Object.assign(e.style,{maxHeight:o/n.y+"px",maxWidth:r/n.x+"px"});var a=function(e){var t=e.cloneNode(!0);t.style.visibility="hidden",document.body.appendChild(t);var n=f(t);return document.body.removeChild(t),n}(e);a.width=Math.trunc(a.width)+1,a.height=Math.trunc(a.height)+1;var d={x:0,y:0};if(t instanceof Element){var c=f(t),l=c.x,m=c.width,v=c.y;d={x:"r"===s?l+m:l-a.width,y:v},t.className.includes("submenu")&&(d.y+="d"===u?4:-12);var y=h(a,d);d.x!==y.x&&(s="r"===s?"l":"r",d.x="r"===s?l+m:l-a.width),d.y!==y.y&&(u="u"===u?"d":"u",d.y=y.y),d=h(a,d)}else{var x=""!==document.body.style.transform?document.body.getBoundingClientRect():{x:0,y:0};d=h(a,{x:(t.clientX-x.x)/n.x,y:(t.clientY-x.y)/n.y})}Object.assign(e.style,{left:d.x+"px",top:d.y+"px",width:a.width+"px",height:a.height+"px"})}function h(e,t){var n=window.visualViewport,i=n.width,r=n.height,o=""!==document.body.style.transform?document.body.getBoundingClientRect():{left:0,top:0},a=o.left,d=o.top,c=p(),l=-a/c.x,h=-d/c.y,f=(i-a)/c.x,m=(r-d)/c.y;return{x:"r"===s?t.x+e.width>f?f-e.width:t.x:t.xm?m-e.height:t.y:t.y ul");r&&r.parentElement!==n&&this.hide(r),n.appendChild(this.generateDOM(t,n))},i.addStylesToDom=function(){var e=function(){if("loading"===document.readyState)return document.addEventListener("readystatechange",e);var t=document.createElement("style");t.innerHTML='html{min-height:100%}.ctxmenu{position:fixed;border:1px solid #999;padding:2px 0;box-shadow:#aaa 3px 3px 3px;background:#fff;margin:0;z-index:9999;overflow-y:auto;font:15px Verdana, sans-serif;box-sizing:border-box}.ctxmenu li{margin:1px 0;display:block;position:relative;user-select:none}.ctxmenu li.heading{font-weight:bold;margin-left:-5px}.ctxmenu li span{display:block;padding:2px 20px;cursor:default}.ctxmenu li a{color:inherit;text-decoration:none}.ctxmenu li.icon{padding-left:15px}.ctxmenu img.icon{position:absolute;width:18px;left:10px;top:2px}.ctxmenu li.disabled{color:#ccc}.ctxmenu li.divider{border-bottom:1px solid #aaa;margin:5px 0}.ctxmenu li.interactive:hover{background:rgba(0, 0, 0, .1)}.ctxmenu li.submenu::after{content:"";position:absolute;display:block;top:0;bottom:0;right:.4em;margin:auto .1rem auto auto;border-right:1px solid #000;border-top:1px solid #000;transform:rotate(45deg);width:.3rem;height:.3rem}.ctxmenu li.submenu.disabled::after{border-color:#ccc}',document.head.insertBefore(t,document.head.childNodes[0]),e=function(){}};e()},i}().getInstance(); +/*! ctxMenu v1.5.0 | (c) Nikolaj Kappler | https://github.com/nkappler/ctxmenu/blob/master/LICENSE !*/window.ctxmenu=m}(); diff --git a/resources/favicon.png b/resources/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..082a5b2c022f7c056e9d826eaf2dda41a4024f7c GIT binary patch literal 3975 zcmZ`+cQhM-^G_l{t=coTmRPY>kOV<$uU3t!qC>5!S&FDu1+`V}G*(fwYSoTiv(&1s zHA~dq{rSG%U%&T#zkBcQ^KQJmd++Z4IJ}9GE!YbQZLuWx}`|)5h&(9RE0SC31xeK8e<# zv-?`1`&!b}mrYMF`S8rRfIcU1V|Huv`M}|BUG`~)SIV!mEU$~7DyaZA&+Hv>cPtmT9x~Tkiz(Swy*UX|E82X^_G;86M|5IqV zm}#OgQMfk+E@)jZeEs5DR(rF3EV#XLrS{R4T0cc7-t+Gw@48@t4#5sm-X16re&8%< zeR6HlNTGU*zI~F%wAS}f_T^x>kf2V^Jz-VLqIj*+`_DhmOF?@WzbD(n`H(KkMU`%$Q|yYZ4eeL-{sxu zWNcX{(h&Y+8qM4qZOSX_lN7ZY&sfBS7N<~E#z>tWV)Tg!;E=(*YDk1F4OoYTYQpzA zG`sJBt)#|WAe$?aT^g70j=j9Zmf5F7kKiV6gZwxpHxbBkrnJdX(h%ja2>9un*&Y@r zL4JV&+i7+WqoK1tPzg(N%LLcPaE}+;%Qn6UkKqg}zRh2fE#15NE&ck+Lk)9KC{3Mk zfI`^Ax0Hsn98&v4Y90aD1y?;oYOD)WJW*FZV^bV2u}|a_j>F8ae+gd!EBs#CVvzYP zCT6{kF||YA!E#|l ztZT=E{IlXjN-K4Kv*6?)_VIHDwhs(79V%99?1xxzc~1kXp-~Hc{ou~ z;rx`WB5J*UZIBk1e=eM!PsnrA9?szk4y0h>3bw2ojT*Lq@Y6MgmEHcsT;iwoqt)k` z37df*iY?Jh{l1;9`_)0pSqYGgM||_+-)_GSo=ScA8nSjmK}ia&2UF5*POmY8+)VIqBY0*mmSyJYuwx5H@57?JA6b0nRYGxiCoa3-`j=hXKeEn80A&6GhpPnobfJ?8*k?~w6*D^8Tj~-nijz9g?gJw+j zyw+gg6f4qTVBoMRqE^ctll!PM@n=nu3G=4S)M8Y{j7fFUHF8uilzIGW)%Zm+%4q*N-Eu;}A0dBKM9dtwNE_Tb>ubiX*h~l@Y>sXNO#WzvT|LC$dUT# zg*8J!Raq<H|_O0tPH++zdN4c7l zi;r!a5l!cxu5vedNCnV`v7(gwXgPUH+C}o}){xcPkjocR zJCk8yqMFb7HNx))sk)qv7mHdWMp+x{VxK`wOhT-bva+bZuJ3eMZdts3IFMvEO^J3H1B9VJLms{#XHd8=_W!&o|XLPEmd zKhHtUIWQ{E4R;0PaR7z;bd1Bf2P%Eu(?Biz%5C=>xDsH2HoR6Bt&dL$q}p4bFxgw? z>t$`(#k^0cS{ghN65CT^zi6QPHnvH!FZ)4V|ANQ!FTB0jbEp70D5NevTV9Fa*knpI@mSiVGpm~zwghsi|1rNO})2E ze{3p)f^&HND`!(XsbOwB(d7{`Z$x zntwGlr53`Z?=`>iUuM2&ItOb`?#GWaPKn_syKX%pgG>@F-m zx+nm=3ZLOMAcfV<_l&f(ihsz^@J4v5w7RUk>bDw z61f05^oAstU2!vSr+JNcin$cOdiVHT6FkmpQ?%k&O5=;C1K^qVU5>SQ6f;fTGghH2 z*-}+&m9b^n5VsE)X1u-Zsmjj_BNPeORP0PTGzp&+sn;x1YFWA5S52#aqovt^Rpx{9 zOg^E0w~tOy2OIrq)9J>4!Svvg4Wv!XJdI7D7HP|~Ihzg{&=3G|r%vdYEpbzC5^;JZ zd8YEsZ+k7HN#ADm(T%a3TC{mJT^@!y#P%P`AATk*we2)|tMxfVZVORexisdBcYtl2 zkyh^n7w|jy2_0{c+hVvPloZA7m)q@J*MW2CQj2O|;?eJ7eEsx>K)=W$G&3gvG;j)2QgUR!im=|(Qytg#TJl;#IO|E+_ z4nY@MP8Asj`-t=WQwzO3dM~vju;CA}4~1*?c0y9EqTSyb~!tz&naOS}BZfrC}eUDewtft(Jb`_uTXOmANtOFvlk;9g6P zDC`u}Q&zCK$YuU59PisXtCBv-Pf@%LD=7XWeTv+@yD)-aV!y&HO!CbsmZ$4uHn#(MgQe z0D0^(<$18nGJ_V<>oXLO!z4+%((AFSM@RPGc1QDLfz)DG$p{Bo_nE+?o8YRFpMJ-W zlgcIA$H{-tzUYoh7*L>6g?aLjha?#PiWN<1bhoxun-Ln2UVt!yu% z2^k4j{JwbTIcPWEf=bzE9_wc?1C(j-Anxi)cUF8Jm&4=4L(VMyiKTCoZ^x_EpTefz zTN|NKZBw@%l+{Cx6c_p?1B$h+nn8~Qpw)Fi*IfT64nmxLNK91!%9KO;bZYtU)&%NkoXHjguUiP*gIGEn;le(yLcBIaQxgb^}8> zg#Ab3E&!M(pKz{W_s(N>3Q=$YNSu~GthUSH4=R``rF5oa3@6_ppim|NAy9PJkmUoo zy!Ovzy}uh1l|3$P!eaF`j{lwy_o|w>?`GNIPX4sb~~wT&>P In)WaM2ZV}U9RL6T literal 0 HcmV?d00001 diff --git a/resources/registerWithServiceWorker.js b/resources/registerWithServiceWorker.js new file mode 100644 index 00000000..13592aaa --- /dev/null +++ b/resources/registerWithServiceWorker.js @@ -0,0 +1 @@ +browser.runtime.sendMessage({ purpose: "loaded", url: window.location.href }); diff --git a/resources/shared.css b/resources/shared.css index cfa91bd5..8f8e77f1 100644 --- a/resources/shared.css +++ b/resources/shared.css @@ -1,4 +1,4 @@ -.PegaDevToolsButton { +/* .PegaDevToolsButton { border: 3px solid; border-radius: 5px; margin-right: 7px; @@ -14,6 +14,11 @@ background: orange; } +.PegaDevToolsButtonGrey { + border-color: darkgrey; + background: darkgrey; +} */ + .pz-pi.pi-clipboard, .pi.pi-clipboard, .pz-pi.pi-tracer, @@ -28,6 +33,11 @@ border: 1px solid red !important; } +.PegaDevToolsTextBlue { + color: blue; + border: 1px solid blue !important; +} + /*can be moved to tracer-event.css*/ .PegaDevToolsTracerCloseBottom { position: absolute; @@ -71,23 +81,23 @@ div[data-node-id="pzRuntimeToolsTopBar"] div.layout-content-pz-inline-middle { } .right { - transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -} + transform: rotate(-45deg); +} .left { - transform: rotate(135deg); -webkit-transform: rotate(135deg); + transform: rotate(135deg); } .up { - transform: rotate(-135deg); -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); } .down { - transform: rotate(45deg); -webkit-transform: rotate(45deg); + transform: rotate(45deg); } .rightPill { @@ -120,6 +130,10 @@ div[data-node-id="pzRuntimeToolsTopBar"] div.layout-content-pz-inline-middle { background-color: green; } +.greyPDT button { + background-color: darkgrey; +} + /*** 3-column layout ***/ .PDTcolumn { @@ -178,4 +192,42 @@ div#PDTTracerIndicator button { .margin-bottom-small { margin-bottom: 4px; +} + +.PDTdropdown { + display: none; + position: fixed; + z-index: 1; + background-color: whitesmoke; + overflow: auto; + min-width: 160px; + box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); + overflow-y: scroll; + height: 400px; +} + +.PDTdropdown a { + color: black; + padding: 2px; + text-decoration: none; + display: block; +} + +.PDTdropdown a:hover { + background-color: #ddd; +} + +.initiallyHidden { + display: none; +} + +.pulse { + animation-duration: 2s; + animation-name: fadeInOut; + animation-iteration-count: 2; +} + +.pulse2 { + transition: background-color 0.5s ease; + background-color: darkseagreen !important; } \ No newline at end of file diff --git a/resources/shared.js b/resources/shared.js index 1bd17c5f..40ac211c 100644 --- a/resources/shared.js +++ b/resources/shared.js @@ -1,32 +1,237 @@ console.log("PDT: resources/shared.js"); +browser = window.browser || window.chrome; + +// //TODO: deprecated? +// window.browser = (function () { +// return window.msBrowser || window.browser || window.browser; +// })(); + +class PDT { + static { + } + + static init() { + this.settings = {}; + + browser.storage.sync.get(["settings", "siteConfig"], (data) => { + //this.settings = await getObjectFromLocalStorage("settings"); + + this.settings = data.settings; + if(typeof this.settings === "undefined") this.settings = {}; + if(typeof this.settings.tracer === "undefined") this.settings.tracer = {}; + if(typeof this.settings.clipboard === "undefined") this.settings.clipboard = {}; + if(typeof this.settings.devstudio === "undefined") this.settings.devstudio = {}; + + //var siteConfigs = await getObjectFromLocalStorage("siteConfig"); + + this.hasConfigForSite = false; + if (data.siteConfig) { + for (let i = 0; i < data.siteConfig.length; i++) { + if (window.location.href.includes(data.siteConfig[i].site)) { + this.siteConfig = data.siteConfig[i]; + this.hasConfigForSite = true; + if(this.siteConfig.color) { + this.siteConfig.color = this.siteConfig.color.replace("#", ''); + if (this.siteConfig.color.length === 3) { + this.siteConfig.color = this.siteConfig.color.split('').map((hex) => { + return hex + hex; + }).join(''); + } + if(this.siteConfig.color[0] != "#") + this.siteConfig.color = "#" + this.siteConfig.color; + } + break; + } + } + } + + document.arrive("body", { onceOnly: true, existing: true}, (elem) => { + let skip = PDT.shouldSkipContentForDocument(elem); + if(!skip) + elem.setAttribute("data-PDTSettings", "loaded"); + else + PDT.debug("skipped data-PDTSettings"); + }); + + PDT.debug("storage settings load"); + + }); + } + + save() { + browser.storage.sync.set({ settings: this.settings }); + } + + get(key) { + return this.settings[key]; + } + + static isTracerEnabled() { + return !(this.settings.tracer.disabled); + } + + static isClipboardEnabled() { + return !(this.settings.clipboard.disabled); + } + + static isDevstudioEnabled() { + return !(this.settings.devstudio && this.settings.devstudio.disabled); + } + + static isAgilestudioEnabled() { + return (this.settings.agilestudio && this.settings.agilestudio.enabled); + } + + static isDeploymentManagerEnabled() { + return (this.settings.deploymentmanager && this.settings.deploymentmanager.enabled); + } + + static isDebugEnabled() { + return this.settings.debug; + } + + static isInTracer() { + return (window.location.href.includes("Tracer")); + } + + static hasConfigForSite; + + static debug(msg) { + if(this.isDebugEnabled()) console.log(msg); + } + + static log(msg) { + console.log(msg); + } + + static isDigit(n) { + return !!([!0, !0, !0, !0, !0, !0, !0, !0, !0, !0][n]); + } + + static contrastTextColor(backgroundColor) { + //https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + const getColorLuminance = function(clr) { + clr = clr / 255; + if(clr <= 0.03928) + return clr / 12.92; + else + return ((clr + 0.055) / 1.055) ** 2.4; + } + + backgroundColor = backgroundColor.replace("#", ""); + let r = parseInt(backgroundColor.substring(0, 2), 16); + let g = parseInt(backgroundColor.substring(2, 4), 16); + let b = parseInt(backgroundColor.substring(4, 6), 16); + let rs = getColorLuminance(r); + let gs = getColorLuminance(g); + let bs = getColorLuminance(b); + + let L = (0.2126 * rs) + (0.7152 * gs) + (0.0722 * bs); + + //https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef + //const contrastThreshold = 0.0525; // 0.0525 is contrast ratio between white and black + const contrastThreshold = 0.3; // favor more lighter text + + return (L > contrastThreshold) ? "#000000" : "#FFFFFF"; + } + + static tabColorCoding = new Map([ + ['RULE-HTML-SECTION', 'green'], + ['RULE-OBJ-ACTIVITY', 'red'], + ['RULE-OBJ-MODEL', 'blue'], + ]); + + + static alterFavicon(forceSmall = false, forceLargeLabel = "", forceColor = "") { + //favicon fallback + let favicon = document.querySelector("link[rel~='icon']"); + if (!favicon) { + favicon = document.createElement('link'); + favicon.rel = 'icon'; + favicon.href = "images/pzPegaIcon.ico"; + favicon.name = "faviconFallback" + document.getElementsByTagName('head')[0].appendChild(favicon); + } + + if(this.hasConfigForSite || forceColor) { + if(forceLargeLabel || (this.settings.favicon == "large" && this.siteConfig.label && !forceSmall)) { + Tinycon.setOptions({ + width: 16, + height: 16, + background: (forceColor || this.siteConfig.color), + color: this.contrastTextColor(forceColor || this.siteConfig.color), + fallback: true + }); + let faviconLabel = forceLargeLabel; + if(!faviconLabel) { + faviconLabel = this.siteConfig.label[0]; + if(this.siteConfig.label.length>1) { + if(PDT.isDigit(this.siteConfig.label.slice(-1))) + faviconLabel += this.siteConfig.label.slice(-1); + } + if(faviconLabel.length == 1) + faviconLabel += " "; + } + Tinycon.setBubble(faviconLabel); + } else { + Tinycon.setOptions({ + width: 16, + height: 3, + background: this.siteConfig.color, + fallback: true + }); + Tinycon.setBubble(" "); + } + } + } + + static setScriptsApplied() { + if(!document.querySelector("input#PDTContent")) + document.querySelector("div[data-node-id='RuleFormHeader'], body").insertAdjacentHTML("beforeend",''); + } + + //TODO: not really working, probably CKE starts with empty body + static shouldSkipContentForDocument(document){ + //CKE editor loads a body element which causes hidden input to be appended to paragraph source + let skip = false; + document.classList.forEach((className) => { if(className.includes("cke")) skip = true; }); + if(skip) { + if(document.querySelector("body")) + document.querySelector("body").setAttribute("data-PDTskipContent", true); + else + PDT.debug("could not set data-PDTskipContent"); + } + return skip; + } +} +if(typeof PDT.settings === "undefined") + PDT.init(); + function getFrameId() { - chrome.runtime.sendMessage({ purpose: "getFrameId" }, function (response) { + browser.runtime.sendMessage({ purpose: "getFrameId" }, function (response) { console.log("FrameId: " + response.frameId); return response.frameId; }); } -function applyContentScripts(purpose) { - chrome.runtime.sendMessage( - { purpose: purpose, tabId: getCurrentTabId() }, - function (response) { - console.log(response); - } - ); -} +// function applyContentScripts(purpose) { +// browser.runtime.sendMessage( +// { purpose: purpose, tabId: getCurrentTabId() }, +// function (response) { +// console.log(response); +// } +// ); +// } const injectScriptsToIframe = (tabId, frameId, scriptList) => { scriptList.forEach((script) => { console.log( - "PDT executeScript tabId: " + - tabId + - ", frameId: " + - frameId + - ": " + - `${script}` + "PDT executeScript tabId: " + tabId + + ", frameId: " + frameId + + ": " + `${script}` ); - chrome.tabs.executeScript( + browser.tabs.executeScript( tabId, { file: `${script}`, @@ -35,48 +240,16 @@ const injectScriptsToIframe = (tabId, frameId, scriptList) => { //If the script injection fails (without the tab permission and so on) and is not checked in the callback` runtime.lastError `, //It's a mistake. There is no other complicated logic in this example. You don't need to record the tab of successful injection. You can fool it like this. }, - () => void chrome.runtime.lastError + () => void browser.runtime.lastError ); }); }; -//applyContentScripts("paragraphRule"); - -const paragraphScriptList = [ - "resources/codemirror/codemirror.js", - "resources/codemirror/foldcode.js", - "resources/codemirror/foldgutter.js", - "resources/codemirror/brace-fold.js", - "resources/codemirror/indent-fold.js", - "resources/codemirror/comment-fold.js", - "resources/codemirror/xml-fold.js", - "resources/codemirror/matchtags.js", - "resources/codemirror/closetag.js", - "resources/codemirror/fullscreen.js", - "resources/codemirror/active-line.js", - "resources/codemirror/xml.js", - "resources/codemirror/javascript.js", - "resources/codemirror/css.js", - "resources/codemirror/htmlmixed.js", - "devstudio/devstudio_paragraph.js", -]; - -//injectScriptsToIframe(null, getFrameId(), paragraphScriptList); - -//TODO: deprecated? -window.browser = (function () { - return window.msBrowser || window.browser || window.chrome; -})(); - const DEBUG = false; -if ( - $( - 'body[class^="channels-express"] div[data-node-id="pzRuntimeToolsTopBar"] div.layout-content-pz-inline-middle' - ).length -) { +if ($('body[class^="channels-express"] div[data-node-id="pzRuntimeToolsTopBar"] div.layout-content-pz-inline-middle').length) { //change order to match Dev Studio - var tracerRef = $( + let tracerRef = $( 'div[data-node-id="pzRuntimeToolsTopBar"] div.layout-content-pz-inline-middle div:has(i.pi-tracer)' ); $( @@ -97,8 +270,8 @@ if ( var copyToClipboard = function copyToClipboard(textContent) { // create hidden text element, if it doesn't already exist - var targetId = "_hiddenCopyText_"; - var target = document.createElement("textarea"); + let targetId = "_hiddenCopyText_"; + let target = document.createElement("textarea"); target.style.position = "absolute"; target.style.left = "-9999px"; target.style.top = "0"; @@ -107,12 +280,12 @@ var copyToClipboard = function copyToClipboard(textContent) { target.textContent = textContent; // select the content - var currentFocus = document.activeElement; + let currentFocus = document.activeElement; target.focus(); target.setSelectionRange(0, target.value.length); // copy the selection - var succeed; + let succeed; try { succeed = document.execCommand("copy"); } catch (e) { @@ -128,7 +301,7 @@ var copyToClipboard = function copyToClipboard(textContent) { }; function messageServiceWorker(purpose) { - chrome.runtime.sendMessage( + browser.runtime.sendMessage( { purpose: purpose } ); } @@ -137,7 +310,7 @@ function messageServiceWorker(purpose) { function appendScript(appendedScript) { if(PDT.isDebugEnabled) console.log("PDT: appendScript: " + appendedScript); - chrome.runtime.sendMessage( + browser.runtime.sendMessage( { purpose: "appendScript", appendedScript: appendedScript }, function (response) { console.log(response); @@ -146,7 +319,7 @@ function appendScript(appendedScript) { } function injectScript(aBasePath, aScriptURL) { - chrome.runtime.sendMessage( + browser.runtime.sendMessage( { purpose: "injectScript", injectedScript: aBasePath+aScriptURL }, function (response) { console.log(response); @@ -163,52 +336,32 @@ function injectCloseShortcut() { injectScript("/js/", "closeShortcut.js"); } -// deprecated? +//TODO: deprecated? function executeScript(injectedCode) { - var scriptEl = document.createElement("script"); + let scriptEl = document.createElement("script"); scriptEl.appendChild(document.createTextNode("(" + injectedCode + ")();")); (document.body || document.head || document.documentElement).appendChild( scriptEl ); } -function extractClassName(sinput, getFull) { - if (sinput) { - var idx = sinput.indexOf("("); - sinput = sinput.substring(idx != -1 ? idx + 1 : 0); - if (sinput[sinput.length - 1] === ")") - sinput = sinput.substring(0, sinput.length - 1); - if (getFull) return sinput; - if (sinput.includes("Work-")) sinput = sinput.split("Work-")[1]; - else if (sinput.includes("Assign-")) sinput = sinput.split("Assign-")[1]; - else if (sinput.includes("-")) { - var sinputLength = sinput.split("-").length; - sinput = (sinputLength>3)? sinput.split("-")[sinputLength - 2] + "-" + sinput.split("-")[sinputLength - 1] : sinput.split("-")[sinputLength - 1]; +function extractClassName(sInput, getFull) { + if (sInput) { + let idx = sInput.indexOf("("); + sInput = sInput.substring(idx != -1 ? idx + 1 : 0); + if (sInput[sInput.length - 1] === ")") + sInput = sInput.substring(0, sInput.length - 1); + if (getFull) return sInput; + if (sInput.includes("Work-")) sInput = sInput.split("Work-")[1]; + else if (sInput.includes("Assign-")) sInput = sInput.split("Assign-")[1]; + else if (sInput.includes("-")) { + let sInputLength = sInput.split("-").length; + sInput = (sInputLength>3)? sInput.split("-")[sInputLength - 2] + "-" + sInput.split("-")[sInputLength - 1] : sInput.split("-")[sInputLength - 1]; } - return sinput; + return sInput; } } -var showElem = function (elem) { - //show an element - elem.style.display = "block"; -}; - -var hideElem = function (elem) { - //hide an element - elem.style.display = "none"; -}; - -var toggleElem = function (elem) { - //toggle element visibility - if (window.getComputedStyle(elem).display === "block") { - // if the element is visible, hide it - hide(elem); - return; - } - show(elem); //otherwise show it -}; - function injectStyles(rule) { $("
", { //html: '­' @@ -224,10 +377,10 @@ function replaceInnerHTML(elem, html) { function siteConfig(callback) { //get label and color config - chrome.storage.sync.get(["siteConfig", "settings"], (data) => { + browser.storage.sync.get(["siteConfig", "settings"], (data) => { console.log(data); //find config for current url - var configForSiteFound = false; + let configForSiteFound = false; if (data.siteConfig) { for (let i = 0; i < data.siteConfig.length; i++) { if (window.location.href.includes(data.siteConfig[i].site)) { @@ -248,7 +401,7 @@ function siteConfig(callback) { //TODO: ugly, try not to use it function sleep(milliseconds) { - var start = new Date().getTime(); + let start = new Date().getTime(); while (new Date() < start + milliseconds) {} return 0; } @@ -269,7 +422,7 @@ function isInDevStudio() { } function injectRuleExport() { - var selection = document.querySelector("div[data-node-id='pzRuleFormRuleset'] div.primary-navigation-links"); + let selection = document.querySelector("div[data-node-id='pzRuleFormRuleset'] div.primary-navigation-links"); if(selection) { selection.insertAdjacentHTML("beforeend", "Export"); injectScript("/js/", "copyRuleTableContent.js"); @@ -279,7 +432,7 @@ function injectRuleExport() { const getObjectFromStorage = async function (key) { return new Promise((resolve, reject) => { try { - chrome.storage.sync.get(key, function (value) { + browser.storage.sync.get(key, function (value) { resolve(value[key]); }); } catch (ex) { @@ -288,154 +441,17 @@ const getObjectFromStorage = async function (key) { }); }; -class PDT { - - static { - - } - - static init() { - this.settings = {}; - - chrome.storage.sync.get(["settings", "siteConfig"], (data) => { - //this.settings = await getObjectFromLocalStorage("settings"); - - this.settings = data.settings; - if(! this.settings.tracer) this.settings.tracer = {}; - if(! this.settings.clipboard) this.settings.clipboard = {}; - if(! this.settings.devstudio) this.settings.devstudio = {}; - PDT.debug("storage settings load"); - - //var siteConfigs = await getObjectFromLocalStorage("siteConfig"); - - this.hasConfigForSite = false; - if (data.siteConfig) { - for (let i = 0; i < data.siteConfig.length; i++) { - if (window.location.href.includes(data.siteConfig[i].site)) { - this.siteConfig = data.siteConfig[i]; - this.hasConfigForSite = true; - if(this.siteConfig.color) { - this.siteConfig.color = this.siteConfig.color.replace("#", ''); - if (this.siteConfig.color.length === 3) { - this.siteConfig.color = this.siteConfig.color.split('').map(function (hex) { - return hex + hex; - }).join(''); - } - if(this.siteConfig.color[0] != "#") - this.siteConfig.color = "#" + this.siteConfig.color; - } - break; - } - } - } - }); - } - - save() { - chrome.storage.sync.set({ settings: this.settings }); - } - - get(key) { - return this.settings[key]; - } - - static isTracerEnabled() { - return !(this.settings.tracer.disabled); - } - - static isClipboardEnabled() { - return !(this.settings.clipboard.disabled); - } - - static isDevstudioEnabled() { - return !(this.settings.devstudio && this.settings.devstudio.disabled); - } - - static isAgilestudioEnabled() { - return (this.settings.agilestudio && this.settings.agilestudio.enabled); - } - - static isDeploymentManagerEnabled() { - return (this.settings.deploymentmanager && this.settings.deploymentmanager.enabled); - } - - static isDebugEnabled() { - return this.settings.debug; - } - - static isInTracer() { - return (window.location.href.includes("Tracer")); - } - - static hasConfigForSite; - - static debug(msg) { - if(this.isDebugEnabled()) console.log(msg); - } - - static isDigit(n) { - return !!([!0, !0, !0, !0, !0, !0, !0, !0, !0, !0][n]); - } - - static contrastTextColor(backgroundColor) { - //https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - const getColorLuminance = function(clr) { - clr = clr / 255; - if(clr <= 0.03928) - return clr / 12.92; - else - return ((clr + 0.055) / 1.055) ** 2.4; +browser.runtime.onMessage.addListener(function(msg) { + if(msg.purpose == "PingContent") { + if (document.querySelector("input#PDTContent")) { + //messageServiceWorker('OK'); } - - backgroundColor = backgroundColor.replace("#", ""); - var r = parseInt(backgroundColor.substring(0, 2), 16); - var g = parseInt(backgroundColor.substring(2, 4), 16); - var b = parseInt(backgroundColor.substring(4, 6), 16); - var rs = getColorLuminance(r); - var gs = getColorLuminance(g); - var bs = getColorLuminance(b); - - var L = (0.2126 * rs) + (0.7152 * gs) + (0.0722 * bs); - - //https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef - //const contrastThreshold = 0.0525; // 0.0525 is contrast ratio between white and black - const contrastThreshold = 0.3; // favor more lighter text - - return (L > contrastThreshold) ? "#000000" : "#FFFFFF"; - } - - static alterFavicon(forceSmall = false, forceLargeLabel = "", forceColor = "") { - if(this.hasConfigForSite || forceColor) { - if(forceLargeLabel || (this.settings.favicon == "large" && this.siteConfig.label && !forceSmall)) { - Tinycon.setOptions({ - width: 16, - height: 16, - background: (forceColor || this.siteConfig.color), - color: this.contrastTextColor(forceColor || this.siteConfig.color), - fallback: true - }); - let faviconLabel = forceLargeLabel; - if(!faviconLabel) { - faviconLabel = this.siteConfig.label[0]; - if(this.siteConfig.label.length>1) { - if(PDT.isDigit(this.siteConfig.label.slice(-1))) - faviconLabel += this.siteConfig.label.slice(-1); - } - if(faviconLabel.length == 1) - faviconLabel += " "; - } - Tinycon.setBubble(faviconLabel); - } else { - Tinycon.setOptions({ - width: 16, - height: 3, - background: this.siteConfig.color, - fallback: true - }); - Tinycon.setBubble(" "); - } + else if(document.querySelector("body") && document.querySelector("body").hasAttribute("data-PDTskipContent")) { + //messageServiceWorker('OK'); + } + else { + console.log("PDT requesting content script reload"); + messageServiceWorker('reloadContentScripts'); } } -} - -PDT.init(); \ No newline at end of file +}) \ No newline at end of file diff --git a/settings.html b/settings.html index cb326780..1c133c7b 100644 --- a/settings.html +++ b/settings.html @@ -180,6 +180,27 @@


+ + +
+ + +
+ + +