Отсутствует
dinn, Andrey_Krropotkin
Да, спасибо. У меня попутно ещё одна кнопка отвалилась "Память/минимизировать в адресной строке".
// https://forum.mozilla-russia.org/viewtopic.php?pid=789048#p789048 // https://forum.mozilla-russia.org/viewtopic.php?pid=789076#p789076 // https://forum.mozilla-russia.org/viewtopic.php?pid=791818#p791818 // https://forum.mozilla-russia.org/viewtopic.php?pid=795879#p795879 // здесь трындёж на 2-3 страницы https://forum.mozilla-russia.org/viewtopic.php?id=9591&p=612 (async id => ({ delay: 2e3, val: "", init(topic, mm) { Services.obs.addObserver(mm = this, topic); Services.obs.addObserver(function quit(s, t) { this.timer?.cancel(); Services.obs.removeObserver(mm, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); }, observe(win) { var df = win.MozXULElement.parseXULToFragment( /* `<hbox id="${id}"><label id="${id += "-label"}"/></hbox>` */ `<hbox id="${id}" tooltiptext="${ "ЛКМ: Минимизировать потребление памяти
ПКМ: about:process
Ctrl+ПКМ: about:debugging#/runtime/this-firefox" }" onclick="event.button || ${ "memoryMinimizationButton.doMinimize(event)" }"><label id="${id += "-label"}"/></hbox>` ); this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); (this.observe = async win => { this.timer.cancel(); await new Promise(ChromeUtils.idleDispatch); /* win.document.getElementById("star-button-box") .after(win.document.importNode(df, true)); this.notify(); })(win); }, */ var clone = win.document.importNode(df, true); clone.firstChild.oncontextmenu = this.about; win.document.getElementById("star-button-box").after(clone); this.notify(); })(win); }, about(e) { var gb = e.view.gBrowser; gb.selectedTab = gb.addTrustedTab(`about:${ e.ctrlKey ? "debugging#/runtime/this-firefox" : "processes" }`); }, async notify() { var info = await ChromeUtils.requestProcInfo(); var bytes = info.memory; for(var child of info.children) bytes += child.memory; this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT); var prev = this.val; if ((this.val = this.mgb(bytes)) != prev) for(var win of CustomizableUI.windows) { var lab = win.document.getElementById(id); if (lab) lab.value = this.val; } }, mgb: bytes => bytes < 1073741824 ? Math.round(bytes / 1048576) + "MB" : (bytes / 1073741824).toFixed(2) + "GB" }).init("browser-delayed-startup-finished"))("ucf-mem-indicator");
Отсутствует
_zt - это не стиль, это делается только скриптом, мозиловский блокируется и заменяется новым. Сделал скрин из глючного зарубежного скрипта undoCloseTab вот отсюда, которым не пользуюсь и в том скрипте намешано так, что ничего не поймешь. Пользуюсь undoCloseTab от Виталия. Там у этого человека еще в 2 скриптах такое же, но я не разобрался и поэтому спросил, может кто сварганит именно на тултипы, где есть ссылки - типа пунктов Журнала, Закладок
А если ты про боковую панель, то в Настройки- Основные есть пункт: Показать боковую панель, я именно про это. Переключает вид боковой панели
xrun1 - да именно про этот скрипт в этом посте, и повторюсь при переключении на новый вид боковой панели - не работает, при старом виде - работает
Отредактировано Andrey_Krropotkin (01-05-2025 09:02:14)
Отсутствует
но 1 и 3 нет
может так
btn.addEventListener(type, this); .. handleEvent(e) { this[e.type](e); }, .. popup.addEventListener(type, this);
Отсутствует
У меня попутно ещё одна кнопка отвалилась "Память/минимизировать в адресной строке"
Там функция из скрипта по ЛКМ не запускалась. С параметром security.browser_xhtml_csp.enabled --> false заработало
Плохой совет дал, если речь об "on" атрибутах. Думаю, никому не составит сложности переделать под addEventListener.
Совет для quick_toggle_about_config_button.js тоже дал, но никто даже не попытался попробовать
Отсутствует
Совет для quick_toggle_about_config_button.js тоже дал, но никто даже не попытался попробовать
Это №1980? Я, например, не понял. Мне надо написать, что закомментировать и что и куда вставить
Код своих кнопок выкладывал выше, №1970 и №1978.
Мне UCF без чужой помощи, как от дохлого осла уши. Те 5 кнопок, что сваял сам, однокомандные и без них смогу обойтись. Сам сложное не напишу и готовое не исправлю. Это продукт для тех, кто разбирается в кишках Firefox. А я простой пользователь, а не потрошитель. Мне готовенькое надо.
Так что, пока сработало с security.browser_xhtml_csp.enabled в false - буду пользоваться своими кнопками. Когда отвалятся - буду искать варианты на замену.
Или предлагай вариант по шаблону выше.
Отсутствует
security.browser_xhtml_csp.* // default values
Если оба поставить в true, то блокировок для скриптов не будет, а только ошибки в консоли
// btn.linkedObject = this; .. // btn.setAttribute("on" + type, `linkedObject.${type}(event)`); btn.addEventListener(type, this); .. // popup.setAttribute("on" + type, `parentNode.linkedObject.${type}(event)`); popup.addEventListener(type, this); .. // m.setAttribute("oncommand", "setCloseMenus(event)"); m.addEventListener("command", setCloseMenus); // m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus; .. handleEvent(e) { this[e.type](e); },
Отсутствует
dinn
Работает, спасибо.
А что с этой?
// https://forum.mozilla-russia.org/viewtopic.php?pid=789048#p789048 // https://forum.mozilla-russia.org/viewtopic.php?pid=789076#p789076 // https://forum.mozilla-russia.org/viewtopic.php?pid=791818#p791818 // https://forum.mozilla-russia.org/viewtopic.php?pid=795879#p795879 // здесь трындёж на 2-3 страницы https://forum.mozilla-russia.org/viewtopic.php?id=9591&p=612 (async id => ({ delay: 2e3, val: "", init(topic, mm) { Services.obs.addObserver(mm = this, topic); Services.obs.addObserver(function quit(s, t) { this.timer?.cancel(); Services.obs.removeObserver(mm, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); }, observe(win) { var df = win.MozXULElement.parseXULToFragment( /* `<hbox id="${id}"><label id="${id += "-label"}"/></hbox>` */ `<hbox id="${id}" tooltiptext="${ "ЛКМ: Минимизировать потребление памяти
ПКМ: about:process
Ctrl+ПКМ: about:debugging#/runtime/this-firefox" }" onclick="event.button || ${ "memoryMinimizationButton.doMinimize(event)" }"><label id="${id += "-label"}"/></hbox>` ); this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); (this.observe = async win => { this.timer.cancel(); await new Promise(ChromeUtils.idleDispatch); /* win.document.getElementById("star-button-box") .after(win.document.importNode(df, true)); this.notify(); })(win); }, */ var clone = win.document.importNode(df, true); clone.firstChild.oncontextmenu = this.about; win.document.getElementById("star-button-box").after(clone); this.notify(); })(win); }, about(e) { var gb = e.view.gBrowser; gb.selectedTab = gb.addTrustedTab(`about:${ e.ctrlKey ? "debugging#/runtime/this-firefox" : "processes" }`); }, async notify() { var info = await ChromeUtils.requestProcInfo(); var bytes = info.memory; for(var child of info.children) bytes += child.memory; this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT); var prev = this.val; if ((this.val = this.mgb(bytes)) != prev) for(var win of CustomizableUI.windows) { var lab = win.document.getElementById(id); if (lab) lab.value = this.val; } }, mgb: bytes => bytes < 1073741824 ? Math.round(bytes / 1048576) + "MB" : (bytes / 1073741824).toFixed(2) + "GB" }).init("browser-delayed-startup-finished"))("ucf-mem-indicator");
Отсутствует
В 139 версии у меня отвалилось несколько скриптов. Но в первую очередь хотелось бы исправить два скрипта.
Первый в консоль пишет: "Content-Security-Policy: Параметры страницы заблокировали выполнение JavaScript eval (script-src), поскольку он нарушает следующую директиву: «script-src chrome: moz-src: resource: 'report-sample'» (Отсутствует 'unsafe-eval')"
Второй в консоль пишет: "EvalError: call to Function() blocked by CSP"
Я знаю, что можно поиграться параметрами about:config - security.browser_xhtml_csp.* и в 139 - security.allow_unsafe_dangerous_privileged_evil_eval, но думаю, что это временное решение и рано или поздно эти параметры выпилят и все равно придется править скрипты.
Просьба к знатокам, помогите исправить эти два скрипта.
// // Сохранять изображение без запроса в указанную папку, из контекстного меню ..... // try { (this.contextsaveimg = { path: "E:\\Download", init(that) { var contextMenu = this.contextMenu = document.querySelector("#contentAreaContextMenu"); if (!contextMenu) return; contextMenu.addEventListener("popupshowing", this); that.setUnloadMap("contextsaveimg", this.destructor, this); }, destructor() { this.contextMenu.removeEventListener("popupshowing", this); }, handleEvent(e) { if (!gContextMenu.onImage || gContextMenu.webExtBrowserType === "popup") return; var menuitem = document.createXULElement("menuitem"); menuitem.setAttribute("id", "ucf_SaveImg"); menuitem.setAttribute("label", "Сохранить изображение в папку: " + this.path); menuitem.addEventListener("click", function(e) { saveImg(); }); menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABAnAAAQJwAAAAAAAAAAAAAAAAEGAQECKAABATsAAAAoAAAAFAAAAAkAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjRRXUVtk8U+Y4TGKUBYrRgmNpcOFR91BQgMWAECBD8AAQEqAAAAGAAAAAwAAAAGAAAAAQAAAAAAAAAAAAAAAEVrp7Nws9//fcr6/3W+9f5wten5ZKHQ7lWGsedDaI7QL0hjtR4sQKERGSaBBgkOXgAAACoAAAAEAAAAAAAAAABKdrK+aqjY/4XO7P+AyfL/fcXy/4HL+/97xPT/eMHy/3e+8f9trt77YpvI8Ux0m98TGymTAAAAJQAAAAAAAAAAVIS7yGWh0/8yTVv/UniH/0htff+L0e//WIab/0x2i/9XiKL/RGp+/zNRYv9dkrP+S26S2QQGClwAAAAGAAAAAGeYxtFxrtr/IDA7/01mbf8sPkP/SWZw/zlSWv88Vl//LkRL/3Wsv/83UVr/XYqe/3+51PQaJDCWAAAAGwAAAAB5qtHajMXk/yY1Pf9fa23/GB8g/2yGjP8mMDL/Sl9k/0RYXP9wmKL/dZ+r/4i6y/+n4PD+TmV5yQECA0UAAAACh7bX46zh8/9tjZj/gpen/4GMk//G4Oj/kJ6f/52clf+svbz/f5id/3yXnv+gx9L/wez1/5u0xuwPExt+AAAAEJTA3ey/7vr/ve35/7Hf8v+w0ub/ubvE/8a4uf/NwLv/083I/9Pl6//T7ff/0O32/9fw9v/a6vL8P0ZYtAAAAC+iy+P2zvX8/831/P/K6e3/y7Kg/+GNZf/vlWr/6Zx3/9qegv/Ino7/t8TQ/7HM4/+itc3yu8ja52BtirQAAAEkqs/l9dv8/f/b/P3/1dzU/9qXcf/slmb/+aFr//+td//+rXb/+aRu/9+1k/+/2uL/RldrtiIrPU0ZITEoAAAAA46017zX8Pf85/7+/+X8+//g7+3+yryw+O6odPz/wYj/9bJ7/+KpgP/nqn3/0tPJ/kRTY6QAAQEYAAAAAAAAAAA6V3Yuboyqj6C81My50ubgo7zR1I92bLbzt3/3/tGZ/8aTZttfY2+PbX2Sn3GFm7EiLDtNAAAABQAAAAAAAAAAAgMEAAUHCgYYJDETIS4+LjMwNU+3e029/NGZ/vHHlPRrSSx/BQUFEAMFBwcEBQcJAQECAgAAAAAAAAAAAAAAAAAAAAAAAAAAEQgAA1wvElSsaz3B9LZ8+fC7gu6WZ0COFg0GGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcTAQrWbS+y7pdZ8eOVWMqUWy91IRIJFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AACf/wAAgH8AAIAfAACADwAAgA8AAIAHAACABwAAgA8AAIAPAADOHwAA/v8AAP//AAD//wAA//8AAA=="); (this.contextMenu.querySelector("#context-sendimage") || this.contextMenu.lastElementChild).after(menuitem); this.handleEvent = () => menuitem.hidden = (!gContextMenu.onImage || gContextMenu.webExtBrowserType === "popup"); function saveImg() { var p = Services.prefs; var data = Object.assign(Object.create(null), { "browser.download.folderList": { type: "Int", set: 2 }, "browser.download.useDownloadDir": { type: "Bool", set: true }, "browser.download.dir": { type: "String", set: this.path } }); var lazy = {PrivateBrowsingUtils}; var save = eval(`(function ${gContextMenu.saveMedia})`.replace("\n false, // don't", "\n true, //")); (menuitem.saveImg = () => { for(var pref in data) { var obj = data[pref], meth = `et${obj.type}Pref`; obj.val = p.prefHasUserValue(pref) ? p["g" + meth](pref) : null; p["s" + meth](pref, obj.set); } try {save.call(gContextMenu);} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } })(); } } }).init(this); } catch(e) { Cu.reportError(e); }
// // Сохранить как PNG ..... // (async func => CustomizableUI.createWidget({ id: "ucf_SaveAsPNG", label: "Сохранить как PNG", tooltiptext: "Сохранить как PNG", localized: false, // defaultArea: CustomizableUI.AREA_NAVBAR, onCreated(btn) { var win = btn.ownerGlobal; new win.Function("_id, xhtmlns, addDestructor", func.toString().slice(7, -1)).call( btn, this.id, "http://www.w3.org/1999/xhtml", destructor => win.addEventListener("unload", destructor, {once: true}) ); btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGwSURBVHjarJPPaxNBGIafmd1km23saqtRaLB6kFYl2ELpRayCVL20RvCmJwk9ePNWvPsXtCA9eNCDeO0hLemPo96LYAuKkRhtsBViEtI0rrt+GyFQ1oMkfjAf883M+8w7w4zyfZ9uwsxms10RzCBNTd3sSLy2lvsDCCKzWMCKGHgotOTAlpamJPm+jCmFL00bmmbD5WlmsKXTdBltB3bcxowaLWJwsTpi4bvNVu1JMmVn5cmcqTB6/DAg3hcjGpUFskjZjlgFKdmvVIiISKlfUhlyQMVPywgDjvX1YCjpOBZ2fZ+9+TuUpxcZuz7Ebl7ArkfM0dgDcOAFCvfwHTi9URJJi2RCqEuPmRxPUXn9imodLo1D6orGjMHW6govZqfDDkYviDXBlZ4vsFsrk8vXqZRWeDY8hz55lvvpGU7sFEn0RhhTtTBg/tETCvlNdj68papsUoND3Lh6iyPOOYrvv/JufYNrqcssbW8zkjwdBnz7/JKL50/x4F4at9GgsFckX/2IefQHZyb6mbl9l2LpE8ff1PnufWkD/t87yC1v/pvi4V8AwZvuNFS33/m3AAMAhEeAiqLmty4AAAAASUVORK5CYII="); } }))(() => { ((main, parts) => this._handleClick = () => { var df = MozXULElement.parseXULToFragment(` <menupopup> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOwSURBVHjaYmBiYuJvamo+xiIsLLL3uaazMUAAMTY3txxjAAFubq7/ZiYm/wECACIA3f8AGhobzGhoaP8QFRr/6enp/wT5+fgBLS0tAOLi4gCnp6cAAoixtrbuFBsb6x+QNnZ2jo0MXz9/+Qdk/wfhO3fu/Gc5cuwoA4NqHEOoszjDrVu3GFiAogxJtiwMagrCQHMeMgAEoHhsdRCG4Tj463+rxGFIqN2CYI7wBpiaWhzPheF5SMhIKliCYiQtyTC4hvSLcu7cHYQQl5SSDyFGa23UWkfvfXTORWNMpiIYH2NV1xXN5gvq9kfqNjtSStF7mkAhBPTXHm3TYL1qsV2+8LyfIaXEbRjAyuzpUOCcI+cMYgzp31hCnft+fgII6Cm95oiICOd///4CFTAwAOWBgBFIM7Lw8vLZM5w7d+7/t2/fwA4DOfDp02d/QQ4GWv1z6tSpU5g+ffrI8OnTJyagFUx2Tu5MsnIyTDk52UyfPn5k/vXr9x+mjx8+MsTFxTGERMUzVK09yCAsn8AwY+ZMhlevX0Pc9PTZM4a3b94wXHjwmaEsu5th87GpQIcyMdy+fZvh79+/DEwfP35giIuPZ3hzbTeDCtcjhngnEwZVVRWGz58/g+ON5dOnz6BYYKioqGY4eOggg5SuBYORkRHDixcvQL5hZNTR0flnY2PD+O8fKAwYgGHwHyTMwMzMwrBt2zZHgAA9Uz1Lw1AUPWlKE1vFlEIFHRoKQgcRtDSLIAiCgoJuiovYP6DopnR1EdRYHO3W6tbg5K5LwclmVQviRwutpSaQtI3P+yIK7/Eu94t77jkPiqIcGUaZ5vlmlvXFbNui12LEBSPo/uU29/EYrYQ1m01WqVRYPn++FQiHI3Mj8RG4jst7wHFcFAoFaFoGsixBliRoGc338dg3AQuKojc2OoZ+vzcZ4JRwQNQAxVIJsVgMuVwO8/OL2D29xPjSHvpCHAf7+36M57iuSzUdnzISg4d3AvxgVqHrJ5BCIcxu7KCdWoLx3MFLaBjOxDJSC1lIsowzXUfVNFEnJflrJi2i1WrBtm1MpzNgAoN5U8TtySE61Sccb6/jIjuF3uMduo5DOWk/l9fwxQr0o+6J+rSqqlxjQq1WQ9kw8PH2CoF5cLtd8gaRSCSwsrqKZDJJu3A8WZbFer2hB2nLAc5ZNBplHFskEsEmSUcURV8q+GXTH5ffBo1OUzNFGUa7/cm4eGcEIbA2MBBW6df8VnC1s3/zv8mfScchaq+GhgavfwBr4dP0kYqtcwAAAABJRU5ErkJggg==" label="Сохранить всю страницу как PNG" value="all"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOwSURBVHjaYmBiYuJvamo+xiIsLLL3uaazMUAAMTY3txxjAAFubq7/ZiYm/wECACIA3f8AGhobzGhoaP8QFRr/6enp/wT5+fgBLS0tAOLi4gCnp6cAAoixtrbuFBsb6x+QNnZ2jo0MXz9/+Qdk/wfhO3fu/Gc5cuwoA4NqHEOoszjDrVu3GFiAogxJtiwMagrCQHMeMgAEoHhsdRCG4Tj463+rxGFIqN2CYI7wBpiaWhzPheF5SMhIKliCYiQtyTC4hvSLcu7cHYQQl5SSDyFGa23UWkfvfXTORWNMpiIYH2NV1xXN5gvq9kfqNjtSStF7mkAhBPTXHm3TYL1qsV2+8LyfIaXEbRjAyuzpUOCcI+cMYgzp31hCnft+fgII6Cm95oiICOd///4CFTAwAOWBgBFIM7Lw8vLZM5w7d+7/t2/fwA4DOfDp02d/QQ4GWv1z6tSpU5g+ffrI8OnTJyagFUx2Tu5MsnIyTDk52UyfPn5k/vXr9x+mjx8+MsTFxTGERMUzVK09yCAsn8AwY+ZMhlevX0Pc9PTZM4a3b94wXHjwmaEsu5th87GpQIcyMdy+fZvh79+/DEwfP35giIuPZ3hzbTeDCtcjhngnEwZVVRWGz58/g+ON5dOnz6BYYKioqGY4eOggg5SuBYORkRHDixcvQL5hZNTR0flnY2PD+O8fKAwYgGHwHyTMwMzMwrBt2zZHgAA9Uz1Lw1AUPWlKE1vFlEIFHRoKQgcRtDSLIAiCgoJuiovYP6DopnR1EdRYHO3W6tbg5K5LwclmVQviRwutpSaQtI3P+yIK7/Eu94t77jkPiqIcGUaZ5vlmlvXFbNui12LEBSPo/uU29/EYrYQ1m01WqVRYPn++FQiHI3Mj8RG4jst7wHFcFAoFaFoGsixBliRoGc338dg3AQuKojc2OoZ+vzcZ4JRwQNQAxVIJsVgMuVwO8/OL2D29xPjSHvpCHAf7+36M57iuSzUdnzISg4d3AvxgVqHrJ5BCIcxu7KCdWoLx3MFLaBjOxDJSC1lIsowzXUfVNFEnJflrJi2i1WrBtm1MpzNgAoN5U8TtySE61Sccb6/jIjuF3uMduo5DOWk/l9fwxQr0o+6J+rSqqlxjQq1WQ9kw8PH2CoF5cLtd8gaRSCSwsrqKZDJJu3A8WZbFer2hB2nLAc5ZNBplHFskEsEmSUcURV8q+GXTH5ffBo1OUzNFGUa7/cm4eGcEIbA2MBBW6df8VnC1s3/zv8mfScchaq+GhgavfwBr4dP0kYqtcwAAAABJRU5ErkJggg==" label="Сохранить видимую часть страницы как PNG" value="page"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKaSURBVHjaYpx94sPD44//CDG9+/SDp8bsBw9AADEmrX7zmQEIGF+//fD/w8dPDAABxNix6/nbcA0GIQYoYGJiZGSQFBdmOHnqLAMrKwsDQAAxJq958/n/f4jsm2//GBifP3v+/8cfiMDDj/8ZmHi5ORl4gPjPn18M///9ZWDh5uVm4GJkYfj56zcD9z9GBoAAYmwH2aL8UwimDRk8+fyfgYWRgZFBgI+b4TsWBR+BtoNcxcDDwwW2R1iQn2HvgcMMX799Y/j6/TvDzz+/GVj+/fvPvO0BC8N/oGpGhv8ML3m0GS59EwWbcP/9XwaAAGSRwQ3CMAxFfxq3TgrqiSMswARMwSJMxZEdGAXBAEiQquICJMFuekDqwTlY38/Wi9kf78OqNTO8kndretBh+1puuvl+R8Dpwm9iruG8xPP/tIGzhULc1OB6voJJXxGjQpumGpsKCc8wEqISwGJfA1P1IYCEmCegkTmqLIELT/8KC+/x+cbxBpEPOl8zbn0q5voWXdcipQQrgZiC/QlQORmzNBAEUfjt7N4ichBUDIKCWNsJhiBiZ2mZf5XC0v/gT7C10lqwNMVBkBC9kKAmt7e+uQtJxBS6cNwy7L2b981bTrz/fnmIxnHTYN081i1F8PQacddDzm0M+UfAYPw/gfyTlqMNVfOJVxIGpfxNgMcZRwoYpkVpe1ezLn/jplc7B2wWb+1gwwfuvxg31lwi7MAimOU4E+IevuXoXt+gILTE1aQ1VBJnwNYR9ltXFKCweM9RWFpYCnjWiukU7dYJLs7PUMyKuglNAZt6GVncZ7SgIU2ZJ8M/bLqVQEFYN9hJPQ5201pgvhztjnk2ZhOYh+esd/vY39ZPZYWBXlURqZ4Qwg8uZXU3gM7p3vAbsXveewxHZWUAAAAASUVORK5CYII=" label="Сохранить выбранный элемент страницы как PNG" value="click"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAL/SURBVHjaYijccvd25ZHvv5n4RSUVQs2vswAEECOIxwACy+8v/3/30Zv/AAHE0Hb6y+//UPDv4///LD/+MjJ8+PqF4cvnnww/vgkxAAQQY8Xhb78YgQCsj5mFgQGm/P+v///fvvj/n+n/fwaGe//vMexg2Mrw7BsDA8vXHwwMPN/5GdQ/mzG8BbIBAoiRfdqvX8xf/rBCDAEaAWL8ByOgmZwMLBXGvxnrzLgYVj9cyfCL+TfDj9+/Gd7//sAQw5vK8PEXAwMTRBsD0Li3DNKikgwC4twM3NIMDF9/fGf4CVTA8u0fM+ODjwwM7qJZDH8/MTBI/GFgUAba/QYo+fEnAwNAADKoXQVhIAjOJYfgsxIR/AwRi/yBlY3gz9j7FUI+wt7CwkbEzs7CNIo2Yl53t3duElDBhYXZZXaWGbHYKW0M4b+cex7WG9FaxmxGfNcfYNH3T+pr/LcSzu1h3Wx11EU2eOkYYRSi7jVgrQeb1TDtzFHkLgu13GQIBgGkJ6GFxva8h6XqX0kgRlF+AfkEw4S7ujEGbKnAzDa6GNEYLvOh2N6wOUGaVXHKayqQsHeiHgyfqKJ51sbxjvAWoG1qWWkYiKJnZhKTpgapK1tEslRw50+4camIGz/ObfcuBP0HBREEn12I+MBUadPM5HomqbWgi8kJydzHOfdctXmU29Vhbhqq8leNfxQyLP6lWgjjdxds9Yxs95ZRVAo+h8yFqEau2fHEKjpKqgojRDg+H0iw1gb212NY2oC/MCxz5DxGaYgPsKrGsnRYUEusnvKb4MNqnBlN5aZD8q54Hb2gP+gj62bohOyKdVxgobTBk3vE7cMzDhYPkVA0NW0xaBrlk6BZtRN20I16SMIWPt0CJlLQowqJStE2YwqnQRbE2ZwazrYURDquL5zcnCINU4xdiYo7QXXo4TesSMaIGGRTJ6jnqBxvkJNwfhFa2Ovu1jlrwXjD2gZ9wITeKVhImEFXgXcIgrvri/udqySztpDZemJurTzK70h/3h1xY3xpvwGLI42vrCwxmAAAAABJRU5ErkJggg==" label="Сохранить выбранную область страницы как PNG" value="clipping"/> </menupopup> `); var popup = df.firstChild; popup.setAttribute("context", ""); popup.addEventListener("command", e => popup.handleCommand(e)); popup.handleCommand = e => { var name = _id + ":DataURLReady"; main = main.replace("%MESSAGE_NAME%", name); var urls = {}, configurable = true, enumerable = true; Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, { configurable, enumerable, get() { var value = `data:;charset=utf-8,({${ encodeURIComponent(main + part) }%0A}).init("${key}")`; Object.defineProperty(urls, key, {configurable, enumerable, value}); return value; } })); var getTabLabel = () => { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); } var listener = msg => { var fp = makeFilePicker(); fp.init( !("inIsolatedMozBrowser" in window.browsingContext.originAttributes) ? window.browsingContext : window , "Сохранить как…", fp.modeSave); fp.appendFilter("", "*.png"); var fileName = getTabLabel(); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '').replace(/\s+/g, '_').slice(0, 100).replace(/^\s+|\s+$/g, ''); var fileDate = (function () { var d = new Date(), z = function(n){return (n < 10 ? '0' : '') + n}; return '[' + z(d.getFullYear()) + '_' + z(d.getMonth()+1) + '_' + z(d.getDate()) + '\u2014' + z(d.getHours()) + '_' + z(d.getMinutes()) + '_' + z(d.getSeconds()) + ']'; })(); fp.defaultString = fileName + "_" + fileDate + ".png"; fp.open(res => res == fp.returnCancel || !fp.file || makeWebBrowserPersist().saveURI( Services.io.newURI(msg.data), document.nodePrincipal, null, null, null, null, null, fp.file, null, null )); } messageManager.addMessageListener(name, listener); addDestructor(() => messageManager.removeMessageListener(name, listener)); (popup.handleCommand = e => gBrowser.selectedBrowser.messageManager .loadFrameScript(urls[e.target.value], false) )(e); } this.append(df); (this._handleClick = () => popup.openPopup(this, "after_start"))(); })(` init(cmd) { cmd.startsWith("c") ? this[cmd].init(this[cmd].parent = this) : this[cmd](); }, capture(win, x, y, width, height) { var canvas = win.document.createElementNS("${xhtmlns}", "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var tryDraw = ind => { try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")} catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);} } tryDraw(17); sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png")); }, `, { all: `all() { var win = content; this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY); }`, page: `page() { var win = content, doc = win.document, body = doc.body, html = doc.documentElement; var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft; var scrY = (body.scrollTop || html.scrollTop) - html.clientTop; this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight); }`, clipping: `clipping: { handleEvent(e) { if (e.button) return false; e.preventDefault(); e.stopPropagation(); switch(e.type) { case "mousedown": this.downX = e.pageX; this.downY = e.pageY; this.bs.left = this.downX + "px"; this.bs.top = this.downY + "px"; this.body.appendChild(this.box); this.flag = true; break; case "mousemove": if (!this.flag) return; this.moveX = e.pageX; this.moveY = e.pageY; if (this.downX > this.moveX) this.bs.left = this.moveX + "px"; if (this.downY > this.moveY) this.bs.top = this.moveY + "px"; this.bs.width = Math.abs(this.moveX - this.downX) + "px"; this.bs.height = Math.abs(this.moveY - this.downY) + "px"; break; case "mouseup": this.uninit(); break; } }, init() { var win = {}; Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, win); this.win = win.value; this.doc = this.win.document; this.body = this.doc.body; if (!HTMLBodyElement.isInstance(this.body)) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!"); return false; } this.flag = null; this.box = this.doc.createElement("div"); this.bs = this.box.style; this.bs.border = "red dashed 1px"; this.bs.position = "absolute"; this.bs.zIndex = "2147483647"; this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor; this.body.style.cursor = "crosshair"; ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)]; this.body.style.cursor = this.defaultCursor; this.body.removeChild(this.box); this.parent.capture.apply(this, pos); ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }`, click: `click: { getPosition() { var html = this.doc.documentElement; var body = this.doc.body; var rect = this.target.getBoundingClientRect(); return [ this.win, Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft, Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop, parseInt(rect.width), parseInt(rect.height) ]; }, highlight() { this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false; this.target.style.cssText += "outline: red 1px solid; outline-offset: 1px; -moz-outline-radius: 2px;"; }, lowlight() { if (this.orgStyle) this.target.style.cssText = this.orgStyle; else this.target.removeAttribute("style"); }, handleEvent(e) { switch(e.type) { case "click": if (e.button) return; e.preventDefault(); e.stopPropagation(); this.lowlight(); this.parent.capture.apply(this, this.getPosition()); this.uninit(); break; case "mouseover": if (this.target) this.lowlight(); this.target = e.target; this.highlight(); break; } }, init() { this.win = content; this.doc = content.document; ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { this.target = false; ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }` }); });
«The Truth Is Out There»
Отсутствует
xrun1 более жесткие условия задашь сам, иначе не минимизировать будет не только по левой, но и по средней и по боковым кнопкам мыши.
// https://forum.mozilla-russia.org/viewtopic.php?pid=789048#p789048 // https://forum.mozilla-russia.org/viewtopic.php?pid=789076#p789076 // https://forum.mozilla-russia.org/viewtopic.php?pid=791818#p791818 // https://forum.mozilla-russia.org/viewtopic.php?pid=795879#p795879 // здесь трындёж на 2-3 страницы https://forum.mozilla-russia.org/viewtopic.php?id=9591&p=612 (async id => ({ delay: 2e3, val: "", init(topic, mm) { Services.obs.addObserver(mm = this, topic); Services.obs.addObserver(function quit(s, t) { this.timer?.cancel(); Services.obs.removeObserver(mm, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); }, observe(win) { var df = win.MozXULElement.parseXULToFragment( /* `<hbox id="${id}"><label id="${id += "-label"}"/></hbox>` */ `<hbox id="${id}" tooltiptext="${ "ЛКМ: Минимизировать потребление памяти
ПКМ: about:process
Ctrl+ПКМ: about:debugging#/runtime/this-firefox" }"><label id="${id += "-label"}"/></hbox>` ); this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); (this.observe = async win => { this.timer.cancel(); await new Promise(ChromeUtils.idleDispatch); /* win.document.getElementById("star-button-box") .after(win.document.importNode(df, true)); this.notify(); })(win); }, */ var clone = win.document.importNode(df, true); clone.firstChild.addEventListener("click", this.memind); win.document.getElementById("star-button-box").after(clone); this.notify(); })(win); }, memind(e) { if (e.button) { var gb = e.view.gBrowser; gb.selectedTab = gb.addTrustedTab(`about:${ e.ctrlKey ? "debugging#/runtime/this-firefox" : "processes" }`); } else e.view.memoryMinimizationButton.doMinimize(e); }, async notify() { var info = await ChromeUtils.requestProcInfo(); var bytes = info.memory; for(var child of info.children) bytes += child.memory; this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT); var prev = this.val; if ((this.val = this.mgb(bytes)) != prev) for(var win of CustomizableUI.windows) { var lab = win.document.getElementById(id); if (lab) lab.value = this.val; } }, mgb: bytes => bytes < 1073741824 ? Math.round(bytes / 1048576) + "MB" : (bytes / 1073741824).toFixed(2) + "GB" }).init("browser-delayed-startup-finished"))("ucf-mem-indicator");
Отредактировано dinn (08-05-2025 16:46:15)
Отсутствует
// Кнопка Save - Основной скрипт в Save_Script.js // Правка Vitaliy V. 2505 // Предыдущая версия // https://forum.mozilla-russia.org/viewtopic.php?pid=809376#p809376 (async () => CustomizableUI.createWidget({ id: "ucf-cbbtn-Save", tooltiptext: "Сохранить страницу\n/ часть / выбранное", nameSaveScript: "Save_Script.js", localized: false, cbu: { types: { 128: "Bool", boolean: "Bool", 64: "Int", number: "Int", 32: "String", string: "String" }, getPrefs(pref) { try { return Services.prefs[`get${ this.types[Services.prefs.getPrefType(pref)] }Pref`](pref); } catch {return null;} }, setPrefs(pref, val) { Services.prefs[`set${this.types[typeof val]}Pref`](pref, val); } }, gClipboard: { get ch() { delete this.ch; return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"] .getService(Ci.nsIClipboardHelper); }, write(str) { this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard); } }, custombuttonsUtils: { writeFile(path, data) { try { if (path.includes(":\\")) path = path.replace(/\//g, "\\"); var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(path); file.exists() && file.remove(false); var strm = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); strm.init(file, 0x04 | 0x08, 420, 0); strm.write(data, data.length); strm.flush(); strm.close(); } catch(ex) { Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n")); } } }, addDestructor(destructor, context) { this._destructors.push({destructor, context}); }, addEventListener(...args) { var trg = args[3]; if (!trg) trg = args[3] = this.ownerGlobal; trg.addEventListener(...args); this._handlers.push(args); }, onCreated(btn) { var win = btn.ownerGlobal; btn._handlers = new win.Array(); btn._destructors = new win.Array(); win.addEventListener("unload", this, {once: true}); btn.self = btn; btn._id = this.id; btn.cbu = this.cbu; btn.xhtmlns = "http://www.w3.org/1999/xhtml"; btn.addDestructor = this.addDestructor.bind(btn); btn.addEventListener = this.addEventListener.bind(btn); btn.gClipboard = this.gClipboard; btn.custombuttonsUtils = this.custombuttonsUtils; Services.scriptloader.loadSubScript(`chrome://user_chrome_files/content/custom_scripts/custom_js/${this.nameSaveScript}`, btn); btn.setAttribute("image", this.image); }, get image() { var img = `${this.id.toLowerCase()}-img`; Services.io.getProtocolHandler("resource") .QueryInterface(Ci.nsIResProtocolHandler) .setSubstitution(img, Services.io.newURI("data:image/svg+xml;base64,77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjYgMjYiIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+DQogIDxwYXRoIGQ9Ik0xOCA5TDE1IDlMMTUgMkwxOCAyIFogTSAyNiA2TDI2IDIzQzI2IDI0LjY1NjI1IDI0LjY1NjI1IDI2IDIzIDI2TDMgMjZDMS4zNDM3NSAyNiAwIDI0LjY1NjI1IDAgMjNMMCAzQzAgMS4zNDM3NSAxLjM0Mzc1IDAgMyAwTDIwIDBDMjAuODI4MTI1IDAgMjEuMjg1MTU2IDAuMDQyOTY4OCAyMy42MjEwOTQgMi4zNzg5MDZDMjUuOTU3MDMxIDQuNzE0ODQ0IDI2IDUuMTcxODc1IDI2IDYgWiBNIDUgOUM1IDkuNTUwNzgxIDUuNDQ5MjE5IDEwIDYgMTBMMTkgMTBDMTkuNTUwNzgxIDEwIDIwIDkuNTUwNzgxIDIwIDlMMjAgMkMyMCAxLjQ0OTIxOSAxOS41NTA3ODEgMSAxOSAxTDYgMUM1LjQ0OTIxOSAxIDUgMS40NDkyMTkgNSAyIFogTSAyMyAxNEMyMyAxMy40NDkyMTkgMjIuNTUwNzgxIDEzIDIyIDEzTDQgMTNDMy40NDkyMTkgMTMgMyAxMy40NDkyMTkgMyAxNEwzIDI0QzMgMjQuNTUwNzgxIDMuNDQ5MjE5IDI1IDQgMjVMMjIgMjVDMjIuNTUwNzgxIDI1IDIzIDI0LjU1MDc4MSAyMyAyNFoiIGZpbGw9IiM4RThFOTgiIC8+DQo8L3N2Zz4=")); delete this.image; return this.image = `resource://${img}`; }, handleEvent(e) { var btn = e.target.getElementById(this.id); for(var args of btn._handlers) args.pop().removeEventListener(...args); delete btn._handlers; for(var {destructor, context} of btn._destructors) try {destructor.call(context, "destructor");} catch(ex) {Cu.reportError(ex);} delete btn._destructors; } }))();
// Скрипт Save // Правка Vitaliy V. 2505 // Предыдущая версия // https://forum.mozilla-russia.org/viewtopic.php?pid=781458#p781458 // https://forum.mozilla-russia.org/viewtopic.php?pid=799602#p799602 // https://forum.mozilla-russia.org/viewtopic.php?pid=799639#p799639 // https://forum.mozilla-russia.org/viewtopic.php?pid=805016#p805016 // Кнопка-виджет в Save_Button.js self.label = "Save"; self.type = "menu"; // Создать меню для кнопки ... var array = [ { label: "Сохранить favicon сайта", func: () => saveFavicon(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAADUElEQVRYCe2WS0gVYRiGZ8pQ8oJZYXbBWkZEBFEUlQlBEi0zwWWLtoEg1ULRRSCRXQgM3VSbCIJAcNMiRGgVRVZSq1DpImam0U1Nz/S80//JOJ6bYUTg4X2+9/u//zL/XM6Z43lLn398BfyFHD8IgjzGV0IVyDfh0hvCA7gP3b7vT+KLJw5cAq3wBTJJYy4waNWi7ICFauETmH66ZAK/61BOGlif8lFCzR9vgsk+NEMCpP4gCK6C9IOwxxYn3we2iSvkgyBpbiOJb2OzdiY1gamNJBdegnQhvhDFVpD6CHnQAaaG+Pi0bWbVQAKk0xpMshekKUKpalGorQO7BbvVR7sOJK11XLWMMLoExkBqtQk0LoLUabW409kFUov10dAtwQI9R6usbp5jScTPkRfDMDxmZjUuVSnAeKRGc47GXOsoY564/BE+AmvhLJyBWc15OJikDY3SWwR/Q+MsuobfiRk8lA4YJi5U4jr4NP4cApBWEraCJvbi6bSTzmXwCr6D5BN2QDEchG6YL65AC0i3o70UjoD0OlpPljNoAKTD0X4Kd0A6H61rp9F2uWv0OTfTVVE+ppAB3UIN0dnKjRcusWOEzfgGysKq5w05N8t3yTfn6eyr6yxwbmZrbrCCPL4B3SvVA4UIqeqRIbNpqrHxNcMJ8Q28Dauet965Waqzsv6oF7qGzXFNb6NL3jkPLb4BvVbVsU0hwmeXr3aezmzMeGyQrTkYrfvRBo+oviI91BIwCHbZcsl171Qf8NJ/ttDtg850EpfULifRCR/gd+AheSh1hIkCG8jBR8GeetJFla5K6h8idjbNJto5ZD0MwUmYBukSYTtch3uQTNUUT0Ev1IO0gnADSqGdY8zgqcUGCmAIpJue+9C4CFKnK80zOpO9jG5Rl94T8udNSlZgYLLX8R7qUqrXcRmd9jrepXVp14GU/etYEwWzmsDURpILz0C6rDFRKF4D6SkhDzrA1BAdm1XOTB+aQbvHgv4gCC6BNEXYbwuRVwTB7P9B/TMapC0lCI0w52G3eVk5k2vhI5jsMk9QSPendIT+E1kdJNMgFioC3ZIPeCYNM0BnXZhpXfUv6NKw8HImHfI87xhUwGbv96cf64Eu6PF9fwZf0v9xBX4BW7VJooPQ4WAAAAAASUVORK5CYII="}, { label: "Копировать favicon сайта в base64", func: () => copyFaviconData(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAC6UlEQVRYCe2VS2hTQRSGJzFFMFRtEUNBaRptpVUEFdyoCxcuRESkBVcGEYRCEQUXQXBpoQjik25EkSxEfCDiSkEUbNGCC1204KOoIBqQplRplRpz/f5wpwwxbZ6ii5b/m/OYM2cmNzdTY+b//vETCFS7v+d5IXrsgD3QBmFIwQDcCAQCH7B/R2zeBW9gNmWYSEKk5ieg6UnI1wiJXsjXexIdNTsEzQ6D1YDvZLEbtQn2Jkh6Oik58M7zvGWarwqaROEHSKcZekB6ahsTbAcpzRADe4grtsbaoHXKsMepXQhTkIaDIP1io4Qg2AIeNEAPDIEUZz4mpyJYHIIxqEYJd/OQG5TgR40xjZCBOyB1MgThAUyA1WacZhiBYVgNG2ATVCY+9laQPtoOBHr0GK/V5mRJXAap14/3K4Anii0h65RoJ/26MI3sJ8mS0xNYT24xvtVy34mQV60uKaW+a6gIGjVABqpRv7u5Tu7Gc/pcq+MUPAPpJ4NiWVyjT6bY4ikJ3+ArWOldsX75lo++Cs6Dftsd2LMgJW03gpWQ9WnCXgXpLUPxr50iNbiIHYdpmIALUO9ssoS4CzpBSjOENY89BtJLhjMg6UA7NV8QKvSyJLDDMJt0AyaZXGub4AdhN9wH/R9own4GKaPB54RdU9BS9BpKlRrfonib24x4DdwGV1MEh9y6gj5Fo1CJXrHoCCyyjfFPwRhcghabn9NSWOkBWJqTvh79nzBE+loWuBuSa4HrcBfWuXM5n2S1B6BFTjPNieogDs/B1WBuU4biPwmKylDuLmCnqDGmGw4YYyKQr082EbAOi0bxY1Cp0ix8bIwJwi6og3xNk3gI+7jUdEHh+tIBwNUggS6ZIWy1ytLgGjT72/1pmNQ7oJ/MOfw2t4K4FfrgC5Sreyxod/sV9Ck6CisKTvpJ5uuhG15AMele2esvrb1h93boA13BmBnpKcWJ9C7UfuP8jmzUCP2Qgkee5y3Nr5mP/+sn8Bs4IBR11QNlKgAAAABJRU5ErkJggg=="}, { separator: ''}, { label: "Сохранить ярлык страницы как …", func: () => saveShortcuts(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACsklEQVRYCe2Xy29MYRjGe6Z0U6UXl2RiTCoV0UU3EguxlBaR7qjoiKWyROzUyr9g0YuNS9jwD4iSSCxQS0NqEjuShhKNykzm83uGd/rN6BzmnDMrTp7f977f7XnPbU4ybW3/+hG04gY45zbiOwy9UILHQRC8JbZWFA7gEnwBX2U692Bry84A83a4CWEqMLk58ZPAVMVvE03vSc7AIByGR2C6k+gJ4FpfPM9Y2i9CX49mzv08yoSMPx8rx+w6mH4rbuYsOASmkzYeK+J22q0eDYurCMuGwDShsVjgpNv6higt0mwPM2T+HJiOhK39qzmcdoPpsjbR6YQO5T6MZZ1zOkmCW6Lp9Ocj5ZgcAOk5TTecgBV4BevMlDzrnCuA6bzNxYq4DcA89MIYFEFapumSOTHraotP0U/m6ysj6INjYMW/k4/+Kt5P7l/5DP2U5ppGG2EI9kLGDMhPQQmkbzTDoMcxSVwC0wxJ5OI5Ni+A6QWJbnuOWAJJxUdINK53grSqa2TNF9cm0GZCVc/IeiAHJZBUXB+ZPjrzYFogydndaiqyMQWzYPpEotvaTRyHEkiV4jKnE8AuOAh7NBYJNtcXLzDWLzPiKOhFI7gijV5AXXmg+dhgqKuYJppUPCtjBrpgGaQizXHQM39J3Kk1scHoApiqxWXM4HrIwwqMgd4Fe+H2a00sMNwAn0FapKlcuW/KWAdUPqPEK271GPDXRcrxOgqms2EmLMrAR5DyYWv/NJfyFuzw8ideXpNSMc3AA+gB6aqa2GA8DqaRtQyZTMNrMM2utS7SGI5Z51wZpIc0NT8t+vXFbzHWHqlYo00Y3gXTnHNOX7hB4gR8AFPyxXVSuG+BAoTpBpPJXrmKG5hvg/tQL/1ELzJY82hsX9TY0IxC+g7sw3gTvIOn/L36SvyvRO/AD94bS0nNXI/tAAAAAElFTkSuQmCC"}, { separator: ''}, { label: "Сохранить страницу как PDF", func: () => savePageToPDF(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACt0lEQVRYCb2XS2sTURTHz8T0aQ21tVHRLtxYqI+F4EY3UVCLi8YHSKG40KWK+Akq6kcQv4Da+liIpbrwRWtF0ZUENyq468JSC8VqtaYl/g5k0pvJTHJ7Mxr+v3vOvXPuOSczk0kiEvIqFAptcA0+w0+w0XeCHsK2kJT2SyTogBy46hsb99pW9IKBbL7N2iCoXjE8gjmopg4ODkELqOYZsp7njWPtRfFNsASqOwwVDUZlI1bjMSX9wuuLivfXE75TtLuwa0B1g3dQUMeS6UBcM/MHNHEEG6lgA61G5Izh27iLIUEtrI3SxGFsqIINhAbVudjEfm0iIyGv/9GAlvUvx26dmMTZwLKZOMRfz5reqA3YkpIlr37nHikyItIIpjYy2QqqXgZ9RrzBVoqbJQu+eioj3FZIeB58Zc0sTpeATPq0fImdhA1mwgj/ecS6ODVAsuPQDZ3gPzVxVy/XBhYo1QrTkAJnuTYwTsU07IMv4CynBnhEf6XiGDTBa3CWUwPFai+K1uYmLIZWmnoa6CfdPNzkk9CMdZJTAxTcTLWMiJyCdTDCmtNDzWkTBS/AR3gCR+EdjNHEb2wvqCZE5CL3yyI2Uqs+AxRJke0c5OAWTMIS7IBjkIApOAOHoKo0uGqAeZDi+tPrOmvt0A9/4DSkYTtchjzshAkR0TODsRQFQr8LWE/CJZgF1RBDyjKtENsDvsq+C5K1krCrkZjHsAf0nT/jul7Fj0U1G6DKQTgAH0BP+VlsbLJp4C3VRsGDE7z7KWxsStbKRME5Yk7CP1EikHXBmHcZfr1u2kjww/DLXW64LnD6Y1KeaWVGPg/ugyrP0LlyVKTsEnC6Zwi4S8AgDMAW5k+xeXBRA5v6YD+ohqkxq04kFNSfWzls3HpPwvbIwuYBAtvA/3u+jO8q3fuJzVdgrVnD9/8CvFxMGTTWer0AAAAASUVORK5CYII="}, { label: "Печать страницы / печать в PDF", func: () => document.querySelector("#mainCommandSet > command#cmd_print").doCommand(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAC6ElEQVRYCd2WzW8NURjGZ6hqKFckNIidhUY/fCysmm7KxkaIhAVNETtJcxf+AURISxMbEZvGBgtBokU3NrpxW410JxVarCiVNKQtx+/Re2TmzseZe29Xmud3zpz3fd53zkzn3ju+52X/M8Ycwn0V3kMBRkDzG9/3Dcdlyy+ngg2M498BpfpOYBS0GbupiSybyrwBTr6LE+gkTN4kwyZYAUn6RkKbsRTY0FtiIZWzgV4q87AAW0AnaGbeA7tBs9YrOU7SVxLBu/Qk0wa4+uUUToGueoArOcBxRPh0R5pI2A1pbmVdB3EqxAUjMRrvA6ujEUNKgKIaaIEuuA7DMA+SnqmU6mIKZz9IMwyriuGKJuo3wAJIF5xNcNXDLEi3nAUOA03OgJUe7PQKnMfBqj3d7c7SaBCkCbcbB84BkKYYlhGqWNTn4CdIfc5GuBrAPjCXnQUOA72Cd7PNYfc8CvJg1egscBho9BikdwzurwBMIyBl+7ymbIAm62EOpN4U62IKVxNYdS9GKx9pdBKs9jo74TwPkj6zm50FDgONBkGaZMh0+x9ilJ46ejvTNGkA+zBfCRWQaIW1oSALYo1wCbaxrEr06AarllAzondBn817zB3gvj2hDu4FPV+BNBpxEx2GoF6yOA2rI+YKAvRpBqt8pAWZIYjTD4J/70qkqIwAPS6C9ItB7xHhaoI3wKUXGE5A0u96uGlxhb8WPoE0VAyHJzJtkFVfMF6D7eEu8St8x8DqSLyLKA49iEyZ9RvnKUoTRd6HMZA+MuhtKeK3v25dZB5AVvkYN0KaDpPU6xiT18Nr3LwOUmGX++EZZFF/UjOK14Gumsnom68uyRsbp2on3IY5SNI0ifrSBorBc7A6WOrJvKbDVuiBGYjTfYI5NWTW/7yDeRysbipXNXTLwTn4AKWaJTBdhOmf7nBUU/XJgw1oWAudxpjXkKTPJM6CH6xd0mM1h3ZjTB+MgU76iLnTGLNmSU/23zf7A6yAD944M8WnAAAAAElFTkSuQmCC"}, { label: "Сохранить страницу / выбор как HTML", func: () => savePageToHTML(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAADCUlEQVRYCb2XTUhUURTH37zU8mORNtpEJTQIQlCrgqiFrkoImk2EYS2jhW3ah5TRqpULoVZtkrJFZbmoGBDsaxXZrhEiamdWZJZW6ky/I+8OZ968N+/Om0j+v3vOvfe8c8+7780dx3EC/gqFQgtchln4CTb6TtB92BWQ0n6IBG3wBuLqMxfut10x4Q/k4puMDYDoKc0kfINKamNyCBpBtEiTSSQSU1h7sXgKVkF0i6aswLBsxEo8pqhlvL6weDPuGseze7AbQDTKHRTEsWTOF7eJ/l2KOIINlb+AJhU5r3wb93dAUCNjExRxGBsofwGBQTUObuR6KaLXCfj7HwXIsuZx7JWO5l8WsKYTB/itjMmLWo8tqq7o1e6Mk6LXcZwG0NpKZweIdtPIGfECWy5elgwYdZdHxBsh4SAYZXSWWI+ATC5MwjikdcIQPxsy7rhhE5XGOR/yzD+EE/CMIpLYWIpVgLfSrGe3YQchlmopIKVWbGUX5LFUvRO1FNCvCsjhyxH+ikLS+NZyrSMJJPkQpEG+LY8xZHQQ5wp0wghYq9pz4CuZn0MHiOZo5HN+CmtUzRdY1Z+CHlZJgdm5e/hToPVId6J8kygqzmHbzxJ0HIwWcWS7P2K1lnUnynejAtT8sPLz+KfhAxyFP2B0kWK3mE6UdaMCZJ6E8q4kxfe4xmE0gb8PkpCF9yDqpLkKVrIqgMVWyfYOjKY9R17Ic/gXYAGMBii6wXQqWbfSpG/uuurvFJ/C8jCKPwODYCRnglVuqyAv6wg2C6Iz3KH8kyG+QxEFnC4wesDYL9OxtiSt+HXMfBOMgegxTRc0w0mYB9EMjTkn1tem3w1GmfVBr6lmB+ROl7gzOQV7uH4BXsIPuAFv4TwcIOYT1kp1vqgl1W/Hz0GZWGCaQQFjpQ4VJQWrrnLZo3aI9cNEpSlxyZeAOyBaoSk5I0p2gDuT53ibDLLN/djtXPAEuwJxVM9FfXAIRGOs8UWcUFiw1h+npAjUa0Y3hy6sJwhsAfPzfA0/ruTaHBdfgma9hvH/Ag7EeepKNPfrAAAAAElFTkSuQmCC"}, { label: "Сохранить URL, страницу / выбор как TXT", func: () => saveSelectionToTxt(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACKElEQVRYCe2XP0scQRjGd2WjpRAQi4ipvOvSCpIujX8gEkIasVA5CxG0igGLhFj4MfQ7CPkGp5Upki5nYQKiiCAnCpp4cP6eeIOb2ZlZMeddocfzm3nned+dnZudO70osl71ej2GWfgKF/C/0hzbTFKybuUeUvgZ7kuf7LvGaYO7PmP8M4qiBD7CITRDvUyyAjXoj+P4gD4rFjACRsVsxd0cJiyC0XB6lo70gLgT7ltd6RvYC0jnWhK3fQE6bMF3yoN7ScE0SIscoDM8Pcd3MnJYp74cqklCyUauQD8D0geaM3gBxiP0apNMGbxKvJmbxAlhBaSaGjgG4xF6pWu9yUyCrR0Ho2Km4I4GE6Y/huPpaTrSg3bEuY+A1b9iYQsgTXKoTvHeMJiKwq85avfDJddfuXk1zyl4DVIXzSkMgPEInVpyupaZuwPU6+/BFr10qQb2wHiETp073ZDJ1j4ewswGsStjmMsgjXKwTvAmGMxDnlap/xIqSkLJRq6XfgikJ2qgD4xH6JWu9SaVuM0CflG4AdJvNbADxiP0Std6k5kEW/t4CF278hZzFaRBDlWVnSoxeA8hDVO7GypQLlGTQzf5Akim/ikD4xE61el0LdNMaNn/DCuM1kC6UAPfwXiETlWdbshkax/eIWz7/wP2Av6EHlGTcubL7O909iHU4aqRka8fqEfEzVBPYxLN/a0RuzsOYkt/nGZWwQJi0Lv/Qd8saa5S5mYYV1bQVfz1oDyqAAAAAElFTkSuQmCC"}, { separator: ''}, { label: "Копировать изображение / текст в base64", func: () => copyFileToBase(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAAEEfUpiAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAM/SURBVEhL7ZdfZNZRGMfPuzFGIyJGdBExRaTxXqQRXY0ouxgjIiKi7hsxIrqLXUVEKV1EjGU0pYgxIpaIXYwRJbqIkbfP95zn+fn9eX/vu3d7I+nL933Ov+d5zu+c5zznvOGPoNVqvbNiRKPUMGUygc5JKybVsrowoJ9cxyv9UB+DTZUb1qABD+FMo9FoUl+m/B0Ow3ow8LAVu4CRs+amggE6DiA35Ts1lSBNpzX5pBNKHXfgCJyBcZG0lPuQz+GgfaIUNqBcv4ftYQPTStbgnsndIW6FgMsniIPwM9RWjDPny8juQPmtz7kTNKY8zr9xEG7ReRKOwgc2+HjqTk4kyxvmBrbgEJ1v4Cbli7E1hFP6QXkBEbfB6jKe9kk/Ag3al0dwKDaEcAaFHypIIbZUIWe9Iz+DfwD5RdT5fQF9ERdZxJtWroVnDZ0YRZ+Unxr3w+3BVrVrJLaDUsJeK9832RaMmzBHhUykA38aeStVC8gCSZCypEejQ2twIhVj1lDyvRprISyZlPKoFedMZpCBj6kY5rG+AVcor6WmDApxeV/A2KQYW4EMaPWFKyYF9yjvOqna4sexIYRZY4Tn9tcIbaGS/wjUMf6Ax0v0KXUdhatQht24cvG5GAcUdGw1YAJKeUHKSEExIqg9mxnIl7cPZlSImTiD3WAnBrQm/UnpfwWydNAOLLaHhO/YF/iJHdbd2BdUJoBThY3O5rHY0B6rTCIf+P0Bzm97mEFdluetqwDaOz9+ekA+I+t4+hnXdTXFV/5K1d6BPUWqH8IlbM1buQBPBWOIfD7VVaAcom04Ar/BdbiMIZ34jsCenPmrYAUdz5AV+AQuIHrZU6WaSmoVsKX4UY4XFLCyXQtPBHtMCj9RapZJ+1n1xRFsFY4qLy/ariHc+VfoT5xa+ATiw8kwjKHKCWAS8QimWoS2LQM6M4jpVAu6yabRiTFEnwe2WHjReDbXW9fvC+EuA8etHEFdX5yfmB5sEWbU91lO9Zchu047oZAHMKTr5AZUAqqDVuI6DvQQjkDvGaLX6yXeZ5VE5MCoLshDUIaV+dZR0DO2Z2Ar/+SZw062erW3kZzBNfgSKpp35LwbdnId/kcfEcJvJ7yZGHuzI6wAAAAASUVORK5CYII="}, { separator: ''}, { label: "(Меню ПКМ) Сохр./добавить текст в файл", value: "Save.SelectionToFile" }, { label: "(Меню ПКМ) Открыть текст в редакторе", value: "Save.TextToEditor"}, ]; var menuPopup = self.appendChild(document.createXULElement("menupopup")); array.forEach((m,i)=> { if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return }; var mItem = menuPopup.appendChild(document.createXULElement("menuitem")); mItem.setAttribute("label", m.label); mItem.setAttribute("class", "menuitem-iconic"); if ("image" in m) mItem.setAttribute("image", m.image || array[i-1].image); if ("value" in m) { mItem.setAttribute('type', 'checkbox'); mItem.setAttribute('checked', cbu.getPrefs(m.value) ); mItem.onclick =()=> cbu.setPrefs(m.value, !cbu.getPrefs(m.value)); } if ("func" in m) mItem.addEventListener("command", m.func); }); menuPopup.onclick = e => e.stopPropagation(); function aDate() { var t=new Date(); var y=1900+t.getYear(); var min=t.getMinutes(); if (min<10){min="0"+min}; var h=t.getHours(); var m=t.getMonth();switch(m){case 0: m="января";break;case 1: m="февраля";break;case 2: m="марта";break;case 3: m="апреля";break;case 4: m="мая";break;case 5: m="июня";break;case 6: m="июля";break;case 7: m="августа";break;case 8: m="сентября";break;case 9: m="октября";break;case 10: m="ноября";break;default: m="декабря";} var d=t.getDate(); var curdate=d+" "+m+" "+y+" "+"г"; var myfilename=curdate; return myfilename; } // Копировать favicon сайта в base64 function FaviconToBase(image) { var canvas = document.createElementNS(xhtmlns, 'canvas'); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight; var ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); var base64 = canvas.toDataURL(); gClipboard.write(base64); var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var alertName = "FaviconToBase"; as.showAlertNotification( base64, "Скрипт Save - FaviconToBase", "Значок скопирован как base64", false, "", null, alertName ); setTimeout(as.closeAlert, 5e3, alertName); }; // Сохранить страницу / выбор как HTML function savePageToHTML() { var vert = String.raw`javascript:(function(){var getSelWin=function(w){if(w.getSelection().toString())return w;for(var i=0,f,r;f=w.frames[i];i++){try{if(r=getSelWin(f))return r}catch(e){}}};var selWin=getSelWin(window),win=selWin||window,doc=win.document,loc=win.location;var qualifyURL=function(url,base){if(!url||/^([a-z]+:|%23)/.test(url))return url;var a=doc.createElement('a');if(base){a.href=base;a.href=a.protocol+(url.charAt(0)=='/'%3F(url.charAt(1)=='/'%3F'':'//'+a.host):'//'+a.host+a.pathname.slice(0,(url.charAt(0)!='%3F'&&a.pathname.lastIndexOf('/')+1)||a.pathname.length))+url}else{a.href=url};return a.href};var encodeImg=function(src,obj){var canvas,img,ret=src;if(/^https%3F:%5C/%5C//.test(src)){canvas=doc.createElement('canvas');if(!obj||obj.nodeName.toLowerCase()!='img'){img=doc.createElement('img');img.src=src}else{img=obj};if(img.complete)try{canvas.width=img.width;canvas.height=img.height;canvas.getContext('2d').drawImage(img,0,0);ret=canvas.toDataURL((/%5C.jpe%3Fg/i.test(src)%3F'image/jpeg':'image/png'))}catch(e){};if(img!=obj)img.src='about:blank'};return ret};var toSrc=function(obj){var strToSrc=function(str){var chr,ret='',i=0,meta={'%5Cb':'%5C%5Cb','%5Ct':'%5C%5Ct','%5Cn':'%5C%5Cn','%5Cf':'%5C%5Cf','%5Cr':'%5C%5Cr','%5Cx22':'%5C%5C%5Cx22','%5C%5C':'%5C%5C%5C%5C'};while(chr=str.charAt(i++)){ret+=meta[chr]||chr};return'%5Cx22'+ret+'%5Cx22'},arrToSrc=function(arr){var ret=[];for(var i=0;i<arr.length;i++){ret[i]=toSrc(arr[i])||'null'};return'['+ret.join(',')+']'},objToSrc=function(obj){var val,ret=[];for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj,prop)&&(val=toSrc(obj[prop])))ret.push(strToSrc(prop)+': '+val)};return'{'+ret.join(',')+'}'};switch(Object.prototype.toString.call(obj).slice(8,-1)){case'Array':return arrToSrc(obj);case'Boolean':case'Function':case'RegExp':return obj.toString();case'Date':return'new Date('+obj.getTime()+')';case'Math':return'Math';case'Number':return isFinite(obj)%3FString(obj):'null';case'Object':return objToSrc(obj);case'String':return strToSrc(obj);default:return obj%3F(obj.nodeType==1&&obj.id%3F'document.getElementById('+strToSrc(obj.id)+')':'{}'):'null'}};var ele,pEle,clone,reUrl=/(url%5C(%5Cx22%3F)(.+%3F)(%5Cx22%3F%5C))/g;if(selWin){var rng=win.getSelection().getRangeAt(0);pEle=rng.commonAncestorContainer;ele=rng.cloneContents()}else{pEle=doc.documentElement;ele=(doc.body||doc.getElementsByTagName('body')[0]).cloneNode(true)};while(pEle){if(pEle.nodeType==1){clone=pEle.cloneNode(false);clone.appendChild(ele);ele=clone};pEle=pEle.parentNode};var sel=doc.createElement('div');sel.appendChild(ele);for(var el,all=sel.getElementsByTagName('*'),i=all.length;i--;){el=all[i];if(el.style&&el.style.backgroundImage)el.style.backgroundImage=el.style.backgroundImage.replace(reUrl,function(a,b,c,d){return b+encodeImg(qualifyURL(c))+d});switch(el.nodeName.toLowerCase()){case'link':case'style':case'script':el.parentNode.removeChild(el);break;case'a':case'area':if(el.hasAttribute('href')&&el.getAttribute('href').charAt(0)!='%23')el.href=el.href;break;case'img':case'input':if(el.hasAttribute('src'))el.src=encodeImg(el.src,el);break;case'audio':case'video':case'embed':case'frame':case'iframe':if(el.hasAttribute('src'))el.src=el.src;break;case'object':if(el.hasAttribute('data'))el.data=el.data;break;case'form':if(el.hasAttribute('action'))el.action=el.action;break}};var head=ele.insertBefore(doc.createElement('head'),ele.firstChild);var meta=doc.createElement('meta');meta.httpEquiv='content-type';meta.content='text/html; charset=utf-8';head.appendChild(meta);var title=doc.getElementsByTagName('title')[0];if(title)head.appendChild(title.cloneNode(true));head.copyScript=function(){if('$'in win)return;var f=doc.createElement('iframe');f.src='about:blank';f.style.cssText ='position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;';doc.documentElement.appendChild(f);var str,script=doc.createElement('script');script.type='text/javascript';for(var name in win){if(name in f.contentWindow||!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name))continue;try{str=toSrc(win[name]);if(!/%5C{%5Cs*%5C[native code%5C]%5Cs*%5C}/.test(str)){script.appendChild(doc.createTextNode('var '+name+' = '+str.replace(/<%5C/(script>)/ig,'<%5C%5C/$1')+';%5Cn'))}}catch(e){}};f.parentNode.removeChild(f);if(script.childNodes.length)this.nextSibling.appendChild(script)};head.copyScript();head.copyStyle=function(s){if(!s)return;var style=doc.createElement('style');style.type='text/css';if(s.media&&s.media.mediaText)style.media=s.media.mediaText;try{for(var i=0,rule;rule=s.cssRules[i];i++){if(rule.type!=3){if((!rule.selectorText||rule.selectorText.indexOf(':')!=-1)||(!sel.querySelector||sel.querySelector(rule.selectorText))){style.appendChild(doc.createTextNode(rule.cssText.replace(reUrl,function(a,b,c,d){var url=qualifyURL(c,s.href);if(rule.type==1&&rule.style&&rule.style.backgroundImage)url=encodeImg(url);return b+url+d})+'%5Cn'))}}else{this.copyStyle(rule.styleSheet)}}}catch(e){if(s.ownerNode)style=s.ownerNode.cloneNode(false)};this.appendChild(style)};var sheets=doc.styleSheets;for(var j=0;j<sheets.length;j++)head.copyStyle(sheets[j]);head.appendChild(doc.createTextNode('%5Cn'));var doctype='',dt=doc.doctype;if(dt&&dt.name){doctype+='<!DOCTYPE '+dt.name;if(dt.publicId)doctype+=' PUBLIC %5Cx22'+dt.publicId+'%5Cx22';if(dt.systemId)doctype+=' %5Cx22'+dt.systemId+'%5Cx22';doctype+='>%5Cn'};var href = 'data:text/html;charset=utf-8,' + encodeURIComponent(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->');var a = document.documentElement.appendChild(document.createElement("a"));a.setAttribute("href", href);var name = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());name=name.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');name += (function () {var d = new Date(), z=function(n){return '_' + (n < 10 ? '0' : '') + n};return z(d.getHours()) + z(d.getMinutes()) + z(d.getSeconds());})();a.setAttribute("download", name + ".html");a.click();a.remove();})();`; gBrowser.fixupAndLoadURIString(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}); }; // Получить имя файла async function pick(fileName) { try { var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile); await IOUtils.makeDirectory(file.path); } catch { file = Services.dirsvc.get("Desk", Ci.nsIFile); } var fp = makeFilePicker(); fp.init(window.browsingContext, "", fp.modeSave); fp.displayDirectory = file; fp.defaultString = fileName; return await new Promise(fp.open) != fp.returnCancel && fp.file; } // Сохранить favicon сайта function saveFavicon() { var dn = "favicon"; var re = /^data:(image\/[^;,]+)/i; var ms = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); (saveFavicon = async () => { var url = gBrowser.selectedTab.image; if (!url) return; if (re.test(url)) { try {var name = gBrowser.currentURI.host || dn;} catch {name = dn;} name += "." + ms.getPrimaryExtension(RegExp.$1, "ico"); } else var name = Services.io.newURI(url).QueryInterface(Ci.nsIURL).fileName; var file = await pick(name); file && IOUtils.write(file.path, new Uint8Array(await (await fetch(url)).arrayBuffer())); })(); } // Сохранить ярлык страницы как … function saveShortcuts() { var img = self.getAttribute("image"); var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); (saveShortcuts = async () => { var file = await pick(getTabLabel() + ".url"); if (file) await IOUtils.writeUTF8(file.path, `[InternetShortcut]\r\nURL=${gBrowser.currentURI.spec}\r\n`), as.showAlertNotification( gBrowser.selectedTab.image || img, file.leafName, "Сохранил в: " + file.parent.path ); })(); } // Копировать изображение или текстовой файл в base64 ... function copyFileToBase(){ var fp = window.makeFilePicker(); fp.init(window.browsingContext, "Открыть файл", fp.modeOpen); fp.appendFilter( "Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml;\ *.xhtml; *.json; *.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg;\ *.svgz; *.tif; *.tiff; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp"); fp.open(re=> { if ( re != fp.returnOK ) return; var file = fp.file; var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); inputStream.init(file, 0x01, 0o600, 0); var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); stream.setInputStream(inputStream); var encoded = btoa(stream.readBytes(stream.available())); var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file); var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded; gClipboard.write(dataURI); var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var alertName = "FileToBase"; as.showAlertNotification( dataURI, "Скрипт Save - FileToBase", "Файл скопирован как base64", false, "", null, alertName ); setTimeout(as.closeAlert, 5e3, alertName); }); }; // Сохранить страницу как PDF, скриптом ... function savePageToPDF() { var ps = Ci.nsIPrintSettings, cfg = { paperWidth: 8.5, paperHeight: 11, paperSizeUnit: ps.kPaperSizeInches, // kPaperSizeMillimeters marginLeft: .2, marginRight: .2, marginTop: .2, marginBottom: .2, edgeLeft: .1, edgeRight: .1, edgeTop: 0, edgeBottom: 0, headerStrLeft: "&T", headerStrCenter: "", headerStrRight: "&U", footerStrLeft: "&PT", footerStrCenter: "", footerStrRight: "&D", printBGColors: true, printBGImages: false, scaling: 1, shrinkToFit: true, // overrides scaling orientation: ps.kPortraitOrientation, // kLandscapeOrientation printerName: "", printSilent: true, printToFile: true, showPrintProgress: false, isInitializedFromPrefs: false, isInitializedFromPrinter: false, outputFormat: ps.kOutputFormatPDF, outputDestination: ps.kOutputDestinationFile, }; ps = Cc["@mozilla.org/gfx/printsettings-service;1"] .getService(Ci.nsIPrintSettingsService).createNewPrintSettings(); for(var key in cfg) if (key in ps) ps[key] = cfg[key]; (savePageToPDF = async () => { try { var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile); await IOUtils.makeDirectory(file.path); } catch { file = Services.dirsvc.get("Desk", Ci.nsIFile); } file.append(`Snap ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")}.pdf`); ps.toFileName = file.path; await gBrowser.selectedBrowser.browsingContext.print(ps); //file.launch(); })(); }; // Копировать favicon сайта в base64 ... function copyFaviconData() { var img = new Image(); img.src = gBrowser.selectedTab.image; FaviconToBase(img); }; // Сохранить URL, страницу / выбор как TXT ... function saveSelectionToTxt() { // [129+] l11 = length >= 11; https://forum.mozilla-russia.org/profile.php?id=71856 var {length} = saveURL, splice = length > 9, l11 = length >= 11; var msgName = _id + ":Save:GetSelection"; var receiver = msg => { var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + msg.data), getTabLabel() + ' ' + aDate().replace(/:/g, ".") + ".txt", null, false, false, null, window.document ]; splice && args.splice(5, 0, null) && l11 && args.splice(1, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("NAME", res); } var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("NAME", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // Добавляем в контекстного меню страницы новые пункты ... ((contextMenu, el)=> { // в контекстное меню выделенного текста ... var saveItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el); saveItem.id = "content-saveItem"; saveItem.setAttribute("label", "Сохр./добавить текст в файл"); saveItem.setAttribute("class", "menuitem-iconic"); saveItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); saveItem.onclick =()=> saveSelectionToFile(); var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el); editorItem.id = "content-editorItem"; editorItem.setAttribute("label", "Открыть текст в редакторе"); editorItem.setAttribute("class", "menuitem-iconic"); editorItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcXFz/Wlpa/1paWv9aWlr/Wlpa/1paWv9aWlr/Wlpa/1paWv9aWlr/Wlpa/1paWv9cXFz/AAAAAAAAAAAAAAAAXFxc//n7+f39/v3+/f79/v7+/v7+/v7+/v7+/f7+/v3+/v78/v7+/P////v////2XV1d/wAAAAAAAAAAAAAAAF9fX//7/fv/FVcX/wBIAv8ASAL/AEgC/wBIAv8ASAL/AEgC/wBIAv8VVxf//f78/2BgYP8AAAAAAAAAAAAAAABhYWH/+/78/zRtNf8otUX/KLVF/yi1Rf8otUX/ZLal/ypBSf9Upcv/NG01//z+/P9kZGT/AAAAAAAAAAAAAAAAZGRk//v+/P9Yh1n/MtB1/zLQdf8y0HX/MtB1/3PZrv9Tpcz/AXfF/2WYiP/8/v3/Z2dn/wAAAAAAAAAAAAAAAGZmZv/8/v3/gKSB/zvdof873aH/O92h/zvdof873aH/Fsj4/wSo6/8Ldr3//f7+/2tra/8AAAAAAAAAAAAAAABpaWn//P/+/6fAqP9C4bn/QuG5/0Lhuf9C4bn/QuG5/1vkxf8GwP7/AXfH/5HD4v9ubm7/AAAAAAAAAAAAAAAAa2tr//z//v/L2sz/lt7S/5be0v+W3tL/lt7S/5be0v+W3tL/Ms34/wSv8P8Abr7/cnJy/wAAAAAAAAAAAAAAAG5ubv/9/v7/6vDq/2Xo3f9l6N3/Zejd/2Xo3f9l6N3/Zejd/2Xo3f8GwP7/AXvJ/1uPsP8AAAAAAAAAAAAAAABwcHD//v////Hu5//l4NT/5eDU/+Xg1P/l4NT/5eDU/+Xg1P/l4NT/XNT5/wS39/8Abr//5PH2GgAAAAAAAAAAc3Nz/////////////v79//7+/f/+/v3//v79//7+/f/+/v3//v79//////8Gwf7/AYPN/xh+wukAAAAAAAAAAHV1df//////7Onh/+Xg1P/l4NT/5eDU/+Xg1P/l4NT/gYGB/4CAgP+AgID/U67L/wS2+P8AbcD/4ezzIAAAAAB4eHj///////39/P///////////////////////Pv6/4CAgP/9/f3//f39/4GBgf4Nwv3+UI+q/4x+d9IAAAAAenp6//////+Wlpf/9/X0/5OTlP/18/L/k5OU//Lv7f+AgID//f39/4GBgf6EhIRd8OXhU8yplP9yWU7/zsjCXH19ff+3t7f/////KLq6uv////8ourq6/////yi6urr/gICA/4GBgf6EhIRdAAAAAAAAAACxqMC5HhmE/wAAdP+AgID/gICA/56entOBgYH/n5+f1oGBgf+fn5/WgYGB/4GBgf+EhIRJAAAAAAAAAAAAAAAA5Of3EAcKj/8AAHP/AAesQQAHrEEAB6xBAAesQQAHrEEAB6xBAAesQQAHrEEAB6xBAAOsQQADrEEAAaxBAAGsQQAArEEAGKxBADisQQ=="); editorItem.onclick =()=> textToEditor(); // устанавливаем где и при каких настройках показывать новые пункты .... addEventListener('popupshowing', e=> { if (e.target != e.currentTarget) return; var sel = gContextMenu.isTextSelected; saveItem.hidden = !sel || !cbu.getPrefs("Save.SelectionToFile"); editorItem.hidden = !sel || !cbu.getPrefs("Save.TextToEditor"); }, false, contextMenu); // удалять новые пункти при изменениях .... addDestructor(()=> { saveItem.remove(); editorItem.remove(); }); })(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open")); // Сохранить или добавить выделенный текст в файл в папке загрузок, если назначена, // иначе на Рабочий стол ............. function saveSelectionToFile() { var line = ".".repeat(62) + "\n"; var hint = "Нажмите чтобы открыть файл"; var prfx = "Выбранный текст сохранен в файл "; var img = self.getAttribute("image"); var desk = Services.dirsvc.get("Desk", Ci.nsIFile); var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); (saveSelectionToFile = async () => { var time = aDate(), url = gBrowser.currentURI.displaySpec; var text = `${line}${getTabLabel()} - ${time}\n${url}\n\n${ gContextMenu.contentData.selectionInfo.fullText }\n\n\n`; try { var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile); var msg = prfx + "в папку " + file.leafName; await IOUtils.makeDirectory(file.path); } catch(ex) { file && Cu.reportError(ex); file = desk.clone(); var msg = prfx + "на рабочий стол"; } file.append(`Save - ${time}.txt`); await IOUtils.writeUTF8(file.path, text, {mode: file.exists() ? "append" : "create"}); var name = "sstf-" + Cu.now(); as.showAlertNotification( gBrowser.selectedTab.image || img, msg, hint, true, "", (s, t) => t == "alertclickcallback" && file.launch(), name ); setTimeout(as.closeAlert, 8e3, name); })(); }; // Создать текстовой файл с выбранным текстом в папке загрузок, если назначена, // иначе на Рабочий стол, и открыть в редакторе ... function textToEditor() { let browserMM = gBrowser.selectedBrowser.messageManager; browserMM.addMessageListener('getSelect', function listener(message) { // создать текст для записи var text = convertFromUnicode("UTF-8", message.data); try {var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {file = Services.dirsvc.get("Desk", Ci.nsIFile);} file.append("TextToEditor.txt"); custombuttonsUtils.writeFile(file.path, text); file.launch(); browserMM.removeMessageListener('getSelect', listener, true); }); browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false); }; // Конвертировать текст в юникод ... function convertFromUnicode(charset, str) { var converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); }; // Получить название вкладки без не сохраняемых символов и лишних пробелов ... function getTabLabel() { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); }; ((main, parts) => this.onmousedown = e => { if (e.button) return; this.onmousedown = null; var df = MozXULElement.parseXULToFragment(` <menugroup orient="vertical"> <menuseparator/> <menuitem class="menuitem-iconic" image="data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACpElEQVRYCe2XT4hNURzHz8UwwxRGwxTKZPGksCGLWXg2ZmbjlVJqZKMUlpZKycZaycpGZFiIUiQZJcpCYsdi1jSjZIZJM6/n8y3nde6f887p3sbbeH0/5/zO7/zO7/7euefe3jOm4NNqtfrhCnyGnxCjHwQ9hOGClPEuEgzAByirWRYeiL1ikg1k8W18EyC9onkM36GTBpi8BH0gzdE0kiSZoo8XFx+CJZDu0uQK9GUjVvF0bS1gjfnirX+FNf72e+hXgnSdb9CSEcnXTFwv4wcUMUrvVbaAtU7kjGPHmL8LgvrwPaKII/SFWlXodZwsHmI4CdshJ3ZpZ86ZdqxhqCLGiX1pMp9gAcSr+kP0VdTLYt2OOkV8xG4rewvaE7EGO2RzNANrNjKvg9pD31bMDjwj+gWshyLtMMZMwz2oG2NWg6stDLaBtJtG74g39HnxbRpgVctHlPOQ8DxYNdwsdvtc33LYz31J/1UBvuub4Blg3/ayehyka5xiveEOMqib8OcJ8alTn10SLIAF++EqSDdpFkCPpfUx9Eovs44FdP0WpEpnu5frKaiR26orT0Hqi7qD4Bmg7BEWnALpAodqHt8og2MQ0i3iX3cKChbA4hqcAekizTzsA+vD9OotM5UL0K+baRJJTTWgX0jWx9ArrfVO5ibY2v+HsGhXDuM8C9JpDtUcO3WUwUkI6QbxU52CYg7hMAmOg3SORvd1F731YXr1lJnKBcyS5B1IS2rgC1gfplda653MTbC1XT+Ev5yqBh27qrnZSaD3iDN0THZgEEr9MXHSpEzyJXAfpEWaTW5A6hByYmcImCRgAk7AVsb6TbiIXUY9LBqDEZDucI1vMrxwwap/TklRqPd4N3gv7E4Q2A/273kTu6y09hOLL8M69xrW/gOmqWkAQxEbGgAAAABJRU5ErkJggg==" label="Сохранить всю страницу как PNG" value="all"/> <menuitem class="menuitem-iconic" image="data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAC1klEQVRYCb2XO2gUQRjHd+OeMZpCTxIFAz5ATwVtfKDEIpUGES6oiBDUQiWFvU1QEBEbO7HSRohERYIBKxEU9bQSuULC2YiFYIjiKzHKGdffd2SO2b3Z3dnNmfD/zXwz871u5y7HOY7hz/f9drgIb2EKbPQdp/uw1pDSfosEeShDVn0icIdtRTfsSPAQe/0gesbwAL5CnPIcnoc2EP1gKLqu+5jZXhRfCX9ANMzQ0GBUNnzFn6muaazeKH+136KM2XkL8wIQXeMV+GJYMh7yW8R6hCb2MUcq3MBizXNCs23M3wanNvZGaWIvs1HhBoxOc9xsJV6a6HEMf/PRgJRV17FVFjrNbGBGT2ywl7Enb9Qcc11e3YoxuEMJWhfj8p6zO9DjOM5C0LWCRReINjPI/4gXzI2iUBGUCsqDjQLEqVv5mmYCz4BSUfdp0Rf/0X4UldvqCgj+AH0QpbGog6R9qwb4hzRJolFouqwa4PLkY7QtZfVXNP4rKcaqAZKshueQRhtxrkCs5utNGNmEF3kSPJDP+Z7gVuJKYhKdrBqYvctSYrYMDqmugDdjDk7DFdiUoV5DiNUT0KKGsA/DNzhGE2t4OtPYmWX9BCi2nSpH4CycgE7YAHOSdQNU2QWiGwxdIPpIY61wGWrfB8wH4CYMikMSXpKDdp7D9kF0kqHM4x+n0HXsU3AI+yXzcXgHJUgnEhi/DSULZztBVJIB+mAA/sITEFUZBsGTGAXrAigFvg2VT23GI7IBceD8KYjkx8obMeAeeHAQ1otfGPYjGwh0Gg7U1yTZz3o3jMEkfIZLMMxV+MwjkFrhBn5qGTqwK6D0BeMqnKPgFHMadWrO0ry21ExeZQdk+mGipQmY5HPhLoiqDMt1h8AT4JVN4HAbh344CqtYP2SuQhblCOqFbhDdooZcndhmKJiHMjRbr0m41Fw1tItjO6if5zPYWSWxFYIvwJJQmdryH5Bn0+cd0zmPAAAAAElFTkSuQmCC" label="Сохранить видимую часть как PNG" value="page"/> <menuitem class="menuitem-iconic" image="data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACe0lEQVRYCc2Xv2sUQRTHZ2M0RgNq9M5gVLAxENBOIaRJmhiri2ChpLCy8h+wEsTGf8BK0EZJVBAF04hwoMFGSBDSxP9AohBMTJR4rJ8HzuXt7uwys3scHt/vvDdv3q/dmbu9NcbxieN4AN6DX+BP6IMfOL2CZxwp/U0kGISfYVl8I/CCb8Uo7UjwE2yzUPCB4Q1ch0UYZPEO7IeCDYZGFEVNpD8oPgT/QMEcQ6bBvGz4ij+ijW206Tx/a++xyj95DrkHCh5wBbEonvya8tvP/CVNXELmIt3AAeW5pnQf9bfDqR/ba5qYQjqRbsDpVNHYR7w0MWEcn240IGXtdpyXiWYnG2jpxA79CDY5qHuRbfS2terKM1JMGGP2QY3jTE5CwSiD/EZ8RGbBYWlAi5GsRzkLCW9Bi4bO0skt0HnT+ru0wc671YCtl5GVG+C+Xof1TGZPQ+UGqPMILtHEGDIYnWhAnhfDVG7GcXwVGQTvryHJD5H5LDwFT8BjsAZtjj70efxu8gx5jO4FG+zjvIDTOCyCPMge0sQmTbwocrRrIVsgT0obVySliftFDnotpIElHVigb7F2A3ohZAtmyHgaDsE6tGfgNrpcNcJsM1zh9i8iw8HeBf8UE/MLCjYYJl1VsY9Ai4b2CdkCHaf1FpMVeJErbyKD0Bvk7Xa+jPkTxeX2o4ahcgMUfh9WMundk5x2f/bfNbCl7kFN6VXVukqwqfSkyvekBku9mCQz7c7IF8HnULDDcHR31ZjEIeRAreEwj8MsvAaHmb9F7sAykD+g0wSOQ8FTanwXJZcUrPpySgonlrEezi2sF3AcgPb1vIVeFhK7SvBdeFDXsPpfv6YmkcwUIdAAAAAASUVORK5CYII=" label="Сохранить выбранный элемент как PNG" value="click"/> <menuitem class="menuitem-iconic" image="data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAABrklEQVRYCe2Xu0oDQRSGZ71HU2gkKmhjJQjaWdmk0nRpBR/BdxDEZ/ANFC+FKFiJYCHYiqW+gSSCeEViWL8DzmYyOyvLbkg14f/n/HP2zDkns0uyo5TjE4ZhEe7CR/gB0+CVoDM470iZ3kWCEryHWdFg4UraioEdyOJ9fJtQcMNwAV/gfyhxcRsWoOCNoRYEwTU2PSg+A3+g4JAh1mBSNmIlHhPhC1VNitf+Pi3+7BK2Hwr2+AahiJR8suJGmJ/SxDo2EXYDo0Zk3dBp5LcjqIDvnCbWsE7YDTiDcjqHWS9NVJTj04sGpKy+HcsyMdnNBlpmYoeewCcP6iA2wkCk8otjUlSUUkPQxDSTOShYZJDfiFtsHDwsNaixEI/I5iHhFtSomVm6eQvMvLa+sh163qsGdL2Y9Q34HfA74HfA74DfAb8D9g58Gv+XZUPnlVNGgndDd0peWcow08GkM1N7Rr4AnkBBk2GyfVWpjndCDiJ1Ao4IkKPZBnaW+SW2CbNAXkCrLFyFggNqPItIJAXzHk5J4cQd3vHEwuYFAotQH89b6KyQtQ8s3oFjZg2tfwH5w9EYtWehDwAAAABJRU5ErkJggg==" label="Сохранить выбранную область как PNG" value="clipping"/> </menugroup> `); var menugroup = df.firstChild; menugroup.setAttribute("context", ""); menugroup.handleCommand = e => { var name = _id + ":DataURLReady"; main = main.replace("%MESSAGE_NAME%", name); var urls = {}, configurable = true, enumerable = true; Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, { configurable, enumerable, get() { var value = `data:;charset=utf-8,({${ encodeURIComponent(main + part) }%0A}).init("${key}")`; Object.defineProperty(urls, key, {configurable, enumerable, value}); return value; }})); var getTabLabel = () => { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); } var listener = msg => { var fp = makeFilePicker(); fp.init(window.browsingContext, "Сохранить как…", fp.modeSave); fp.appendFilter("", "*.png"); fp.defaultString = getTabLabel() + ".png"; fp.open(res => { if (res == fp.returnCancel || !fp.file) return; var wbp = makeWebBrowserPersist(), args = [ Services.io.newURI(msg.data), document.nodePrincipal, null, null, null, null, fp.file, null ]; //wbp.saveURI.length == 9 && splice(args); var {length} = wbp.saveURI; length >= 9 && splice(args); length == 10 && args.splice(3, 0, null); wbp.saveURI(...args); }); } var splice = arr => { var fox74 = parseInt(Services.appinfo.platformVersion) >= 74; var args = [fox74 ? 7 : 2, 0, fox74 ? Ci.nsIContentPolicy.TYPE_IMAGE : null]; (splice = arr => arr.splice(...args))(arr); } messageManager.addMessageListener(name, listener); addDestructor(() => messageManager.removeMessageListener(name, listener)); (menugroup.handleCommand = e => gBrowser.selectedBrowser.messageManager .loadFrameScript(urls[e.target.value], false) )(e); } menugroup.addEventListener("command", e => menugroup.handleCommand(e)); menuPopup.querySelector('menuitem[label*="ярлык"]').after(df); })(` init(cmd) { cmd.startsWith("c") ? this[cmd].init(this[cmd].parent = this) : this[cmd](); }, capture(win, x, y, width, height) { var canvas = win.document.createElementNS("${xhtmlns}", "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var tryDraw = ind => { try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")} catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);} } tryDraw(17); sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png")); }, `, { all: `all() { var win = content; this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY); }`, page: `page() { var win = content, doc = win.document, body = doc.body, html = doc.documentElement; var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft; var scrY = (body.scrollTop || html.scrollTop) - html.clientTop; this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight); }`, clipping: `clipping: { handleEvent(e) { if (e.button) return false; e.preventDefault(); e.stopPropagation(); switch(e.type) { case "mousedown": this.downX = e.pageX; this.downY = e.pageY; this.bs.left = this.downX + "px"; this.bs.top = this.downY + "px"; this.body.appendChild(this.box); this.flag = true; break; case "mousemove": if (!this.flag) return; this.moveX = e.pageX; this.moveY = e.pageY; if (this.downX > this.moveX) this.bs.left = this.moveX + "px"; if (this.downY > this.moveY) this.bs.top = this.moveY + "px"; this.bs.width = Math.abs(this.moveX - this.downX) + "px"; this.bs.height = Math.abs(this.moveY - this.downY) + "px"; break; case "mouseup": this.uninit(); break; } }, init() { var win = {}; Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, win); this.win = win.value; this.doc = this.win.document; this.body = this.doc.body; if (!HTMLBodyElement.isInstance(this.body)) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!"); return false; } this.flag = null; this.box = this.doc.createElement("div"); this.bs = this.box.style; this.bs.border = "#0f0 dashed 2px"; this.bs.position = "absolute"; this.bs.zIndex = "2147483647"; this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor; this.body.style.cursor = "crosshair"; ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)]; this.body.style.cursor = this.defaultCursor; this.body.removeChild(this.box); this.parent.capture.apply(this, pos); ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }`, click: `click: { getPosition() { var html = this.doc.documentElement; var body = this.doc.body; var rect = this.target.getBoundingClientRect(); return [ this.win, Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft, Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop, parseInt(rect.width), parseInt(rect.height) ]; }, highlight() { this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false; this.target.style.cssText += "outline: red 2px solid; outline-offset: 2px; -moz-outline-radius: 2px;"; }, lowlight() { if (this.orgStyle) this.target.style.cssText = this.orgStyle; else this.target.removeAttribute("style"); }, handleEvent(e) { switch(e.type){ case "click": if (e.button) return; e.preventDefault(); e.stopPropagation(); this.lowlight(); this.parent.capture.apply(this, this.getPosition()); this.uninit(); break; case "mouseover": if (this.target) this.lowlight(); this.target = e.target; this.highlight(); break; } }, init() { this.win = content; this.doc = content.document; ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { this.target = false; ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }` });
Добавлено 08-05-2025 23:33:33
// Пункт конт.меню закладок "Экспорт папки в HTML" - от Dumby // https://forum.mozilla-russia.org/viewtopic.php?pid=803127#p803127 // + правка от VitalyV под 139+ (async topic => { var imp = m => ChromeUtils.importESModule(`resource://gre/modules/${m}.sys.mjs`)[m]; var exporter = { get dps() { delete this.dps; return this.dps = imp("DownloadPaths"); }, get exporter() { delete this.exporter; return this.exporter = UcfPrefs.dbg.ref("BookmarkExporter", imp("BookmarkHTMLUtils").exportToFile); }, async export(popup) { var win = popup.ownerGlobal, tn = popup.triggerNode; var node, pu = win.PlacesUtils, bm = pu.bookmarks; if (tn.nodeName == "treechildren") node = popup._view.selectedNode; else if (tn.id == "OtherBookmarks") node = {bookmarkGuid: bm.unfiledGuid, title: tn.getAttribute("label")}; else node = tn._placesNode || popup._view.result.root; var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(win.browsingContext, win.PlacesUIUtils.promptLocalization.formatValueSync("places-bookmarks-export"), fp.modeSave); fp.appendFilters(fp.filterHTML); fp.defaultString = (node.title ? this.dps.sanitize(node.title) : "untitled") + ".html"; if (await new Promise(fp.open) == fp.returnCancel) return; var tree = await pu.promiseBookmarksTree(pu.getConcreteItemGuid(node), {includeItemIds: true}); tree.title = bm.getLocalizedTitle(tree); var bookmarks = {children: [ {root: "toolbarFolder"}, {root: "unfiledBookmarksFolder"}, {root: "bookmarksMenuFolder", children: [tree], guid: bm.menuGuid} ]}; new this.exporter(bookmarks).exportToFile(fp.file.path); }, observe(doc) { var popup = doc.querySelector("menupopup#placesContext"); if (!popup) return; var menuitem = doc.createXULElement("menuitem"); for(let args of Object.entries({ label: "Экспорт папки в HTML", selection: "folder", "node-type": "folder", "selection-type": "single|none", id: "placesContext_exportFolder", })) menuitem.setAttribute(...args); menuitem.addEventListener("command", e => exporter.export(e.currentTarget.parentElement)); menuitem.exporter = this; doc.getElementById("placesContext_openSeparator").before(menuitem); } }; Services.obs.addObserver(exporter, topic); Services.obs.addObserver(function quit(s, t) { Services.obs.removeObserver(quit, t); Services.obs.removeObserver(exporter, topic); }, "quit-application-granted"); })("chrome-document-loaded");
Добавлено 08-05-2025 23:36:01
To be continued... Как напишете чего нибудь.
Отредактировано _zt (08-05-2025 23:36:01)
Отсутствует
// Quick Toggle от Damby - Быстрое переключение параметров about:config // от https://forum.mozilla-russia.org/viewtopic.php?pid=784165#p784165 // и до https://forum.mozilla-russia.org/viewtopic.php?pid=789795#p789795 // + перепись скрипта от VitalyV 250425 (async ( id = "QuickToggleAboutConfigSettings", label = "Quick Toggle Settings", tooltiptext = "Quick Toggle Settings\n\nЛКМ Первое меню\nПКМ Второе меню", image = "chrome://user_chrome_files/content/custom_styles/svg/QuickToggle.svg", //============================================================================= {prefs} = Services, db = prefs.getDefaultBranch(""), pv = parseInt(Services.appinfo.platformVersion), xul_ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", //============================================================================= // ЛКМ по пункту - переключает параметр на userChoice // или между userChoice и userAlt (если второй есть) // // Ctrl+ЛКМ или ПКМ по пункту - сброс параметра по-умолчанию FF // или его удаление, если параметр добавлен польз-лем\расширением\скриптом // // Первый символ в названии // ! Маловероятно, но может сломать что-то на сайтах // ? Баги Firefox // • Связан с последующим // ^ Связан с предыдущим // // Следующий символ после длинного дефиса, в названии: // "молния" - перезагрузка, // "песочные часы" - обновление страницы, // "короткий дефис" - отсутствие действия // // userChoice: // ваше значение (зеленая метка) // // userAlt: // альтернативное ваше значение (желтая метка) // // Иконки назначаются в в секции UserChoiceImg и ниже // // refresh: // false - перезагрука текущей вкладки // true - перезагрука текущей вкладки минуя кэш // // restart: // false - перезапуск браузера // true - перезапуск браузера с подтверждением (отмена - отменяет только // перезапуск браузера, преф переключится, но может не применится) // Структуру заполнения смотрите в примерах. // Третий блок в значениях - это памятка в подменю, он не обязателен, // тем более что значение есть в подсказке (тултипе). primary = [ { pref: ["network.proxy.type", "• Настройки прокси"], userChoice: 5, userAlt: 1, refresh: true, values: [ [0, "Не проксировать", "0"], [5, "Системные (IE)", "5"], [2, "Авто (proxi.pac)", "2"], [1, "Прописанные", "1"], [4, "Автоопределение", "4"] ]}, null, { pref: ["browser.zoom.full", "Масштабировать"], userChoice: false, userAlt: true, refresh: true, values: [[true, "Весь контент"], [false, "Только текст"]] }, null, { pref: ["permissions.default.image", "Загружать web-графику"], userChoice: 1, userAlt: 2, refresh: true, values: [ [1, "Да", "1"], [3, "С сайта", "3"], [2, "Нет", "2"] ]} ], //============================================================================= secondary = [ { pref: ["network.trr.mode", "• DoH DNS (режим trr)"], userChoice: 3, userAlt: 0, refresh: true, values: [ [3, "Строгий"], [2, "DoH первым"], [5, "Явно отключен"], [0, "Отключен"] ]},{ pref: ["network.trr.uri", "^ DoH DNS провайдер"], userChoice: "https://firefox.dns.nextdns.io/", userAlt: "https://doh.dns.sb/dns-query", refresh: true, values: [ ["https://cloudflare-dns.com/dns-query", "Cloudflare"], ["https://mozilla.cloudflare-dns.com/dns-query", "Fx Cloudflare"], ["https://dns.comss.one/dns-query", "Comss DNS"], ["https://dns.google/dns-query", "Google DNS"], ["https://firefox.dns.nextdns.io/", "Fx NextDNS"] ]},{ pref: ["network.trr.exclude-etc-hosts", "^ DoH учитывает HOSTS"], userChoice: true, userAlt: false, restart: true, values: [[true, "Да"], [false, "Нет"]] }, null, { pref: ["dom.security.https_only_mode", "Режим Только HTTPS"], userChoice: false, refresh: true, values: [[true, "Скучно без проблем"], [false, "Нет"]] } ], //============================================================================= ) => CustomizableUI.createWidget({ id, label, tooltiptext, localized: false, onCreated(btn) { btn.setAttribute("image", image); var doc = btn.ownerDocument; btn.btn = true; btn.domParent = null; btn.popups = new btn.ownerGlobal.Array(); this.createPopup(doc, btn, "primary", primary); this.createPopup(doc, btn, "secondary", secondary); this.createCloseMenusOption(doc, btn); for(var type of ["command", "contextmenu"]) btn.addEventListener(type, this); }, handleEvent(e) { this[e.type](e); }, createPopup(doc, btn, name, data) { var popup = doc.createElementNS(xul_ns, "menupopup"); var prop = name + "Popup"; btn.popups.push(btn[prop] = popup); popup.id = `${id}-${prop}`; for (var type of ["popupshowing", "click"]) popup.addEventListener(type, this); for(var obj of data) popup.append(this.createElement(doc, obj)); btn.append(popup); }, map: {b: "Bool", n: "Int", s: "String"}, createElement(doc, obj) { if (!obj) return doc.createElementNS(xul_ns, "menuseparator"); var pref = doc.ownerGlobal.Object.create(null), node, img, bool; for(var [key, val] of Object.entries(obj)) { if (key == "pref") { var [apref, lab, akey, ttt] = val; pref.pref = apref; pref.lab = lab || apref; if (ttt) pref.ttt = ttt; } else if (key == "image") img = val, pref.img = true; else if (key != "values") pref[key] = val; else pref.hasVals = true; } var type = prefs.getPrefType(pref.pref); var str = this.map[type == prefs.PREF_INVALID ? obj.values ? (typeof obj.values[0][0])[0] : "b" : type == prefs.PREF_BOOL ? "b" : type == prefs.PREF_INT ? "n" : "s" ]; pref.get = prefs[`get${str}Pref`]; pref.set = prefs[`set${str}Pref`]; node = doc.createElementNS(xul_ns, "menu"); node.className = "menu-iconic"; node.setAttribute("closemenu", "none"); img && node.setAttribute("image", img); akey && node.setAttribute("accesskey", akey); (node.pref = pref).vals = doc.ownerGlobal.Object.create(null); this.createRadios(doc, str.startsWith("B") && !pref.hasVals ? [[true, "true"], [false, "false"]] : obj.values, node.appendChild(doc.createElementNS(xul_ns, "menupopup")) ); if ("userChoice" in obj) pref.noAlt = !("userAlt" in obj); return node; }, createCloseMenusOption(doc, btn) { var pn = this.closePref = `${id}.closeMenus`; var data = [null, { pref: [pn, "Автозакрытие этого меню"], values: [[true, "Да"], [false, "Нет"]] }]; var setCloseMenus = e => { e.stopPropagation(); var trg = e.target, {pref, val} = trg, updPopup = true, clear; switch(e.type) { case "click": if (e.button) return; break; case "contextmenu": e.preventDefault(); clear = pref; } if (!pref) return; if (clear) prefs.clearUserPref(pn); else if (!updPopup && val === pref.val) return; else pref.set(pn, val !== undefined ? val : !pref.val); this.upd(trg); updPopup && this.popupshowing(null, trg.querySelector("menupopup")); }; (this.createCloseMenusOption = (doc, btn) => { for(var obj of data) btn.secondaryPopup.append(this.createElement(doc, obj)); var m = btn.secondaryPopup.lastChild; m.style.cssText = "fill: lightblue !important; list-style-image: url(chrome://browser/skin/menu.svg) !important;"; m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus; })(doc, btn); }, UserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHqSURBVDhPpVJBTxNBGH1LLakxVEJQQIkhlZCAJDYR/BGScNCDwZMcuEji2ZP+BD14MCGciDEaEw8e1At3QGLlwAUOFtm6tut2uwtb2t3p8GbZ0iXlVF/y5ttkv+/Nmzej5XI5/A+6otoxTh1ks9mwhniJHvRiBAHXLjRIEy7yeIqjqAPNuXYHS5jGVby7PTT27eHo7Or9zL3Va/19Xyj5FsuYjLpOcdbBG9xFGh+fZRaGJ5O3tB7tMrcXcGQZP+pb8tXuyjpdPcA89HYHynYazxdvzg5nkgOapFsPNleXP+uY6L6hzYxMT+EC5vCVa4SWAM880Ju4cyVxUXNkERUeuyJLIR1+O6wTqcEEUngEA5eiqZgAAxtMpfur0sIBLA7+hS2NkK5UGVpsqgEJjLMkT4biAkzbE27D5u7/ZAFWSB1l0iRtUokyEj+aCBEXMHcOA70Y/IElfsMUeyiJPIpBHiZZEvv4Vcsrge9Mi1ZO0BJQ98yw9w4tWT4yYNV1ki78AuyggHLNwLZjC1Txnpl60VRMQD2SBl5sGsHaT88XJd+DEzioCAd6rYpN1xf7Jj5T4BMe00eE9pf4GteZ8Ry6mbYKDDyzxAblP4TDT1BUbc2585+yumd1Vc201ZmV7djObQKdopVBRwCOAVyl9qcQtNEaAAAAAElFTkSuQmCC", notUserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHqSURBVDhPpVJNSxtRFD1PJ9GMMVpaKyWhRGwRFy7Utv+gVFyUgoWif8Ct+APMsvQX+BuUWhdBcOvSDwi1XVhK0WgmTr4mmphoJvPRe5NnxhLdpAcO9828d869794nXNfF/6BLxo7RqiAcDjciYx3oDwFRBxikT4ey5CtAcg64aZ4ANE1rxDaDLeB176Aae/zx/ZR/NDqEuu1UD39oxsZ2wnIRmwV+8rl7DeLAGzXg+/pidSWivBwVCPQDvH91AfPot/tn6fOedW3NzTT0TYNWD7hsVfWtjH1ZjCjPggImFV25AKpE+xr+6CMxsvzpVXePmE8AipR5Bnzn4bcT0yJoCZSyQDkPXOrEDDHXYG8k0B18/nSBdvukzDPghqlB/xOUi4BBgiIJDUleF0lmVaEo7ngd8EnZP2N0uiolBwXKmksDegrISubovvyPWauR3kPLgBb5q+O8hnMyOD8jJoknTaZPKZLRSQp2+eaA6q9JmWcwTHPWv2cT0E0XGcqos4lkhgz4X7Jql3O1NZNaK2WewSQ9EtqIHcWPd5FybWQNoECNNApkdgmcwv61k47TbDbf0VykrP0hfaPlADAfCmFBERiHQN2sY79UwTqLP1BX+NyDL5HBc+ZR3Xab78xl383cZtAp7o6xAwB/AT+Y7GFJS/NjAAAAAElFTkSuQmCC", UserAltImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAH7SURBVDhPpVJLa1NBFP5mJolNcrWhtiq9Betjk0VFfNS1O7ciXbQguBDXxR9g3Lnown8g3SqCi24K/gCxVbqogiBaxdyY5nFrkt5H5j7GmZvxphDdxA8+Dgzn+86Zcw4RQuB/QHUcG2kHpmkmUWHtEo6DY55mUCIhYkHQOlXA97vv4esUWJaVxBGDp2Vcz54klakbN69kZ8wZRHHsVT9b7e2tHdFH5eEuPqi8vxqsLWDxmIGX5+8/mMufPkdA8zIBiMMuvNo3sbf+bCt2cWd1V+kHBukMVNuFE3h08d7SXHF6glC4oHFXGnTBmA9j1iBnb9+6xvJYfryIjJYdGaL889TlC1cLkyFhQQek3wThjYSUt8GCX9Iky/JniitGF0WtGhpQgdLEJJvO8AMpUgIbtK/JbflmI0cc2Y0oy/JZLRsaEIKYcCemXgvUlVXdOpj/c0Bnf0BXdhXxQEsSpAZqVU7NtkRPJh5aoAmrCYnzA9SpIbDr4G74Lsihr2VDA7Xn5kdvx2mGgnr7soNaSubXQb0GelUv8lt4Pj8rJ6yRGqgjERyVT68P3rarJIo6HojrJOS2h8Yejb6+OdyIe3i1tIlIy0YP6ckCTCOH5WIJKxmGsnwKeB/bbgcvlHj1Cxoq75+XqKD2rFb1Z9rqz6rto5VHDMZFOoPxAPwGQ077rbKVfhEAAAAASUVORK5CYII=", upd(node) { var {pref} = node, def = false, user = false, val; if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) { var pn = pref.pref; try {val = pref.defVal = db[pref.get.name](pn); def = true} catch(ex) {def = false;} var user = prefs.prefHasUserValue(pn); if (user) try {val = pref.get(pn, undefined);} catch(ex) {} } if (val == pref.val && def == pref.def && user == pref.user) return; pref.val = val; pref.def = def; pref.user = user; var exists = def || user; var ttt = exists ? val : "Этот преф не существует"; if (ttt === "") ttt = "[ empty_string ]"; ttt += "\n" + pref.pref; if (pref.ttt) ttt += "\n" + pref.ttt; node.tooltipText = ttt; var img, alt = "userAlt" in pref && val == pref.userAlt; if (alt) img = this.UserAltImg; if ("userChoice" in pref) if (val == pref.userChoice) //node.style.removeProperty("color"), img = this.UserChoiceImg; else { //node.style.setProperty("color", "maroon", "important"); if (!alt) img = this.notUserChoiceImg; } if (!pref.img) img ? node.setAttribute("image", img) : node.removeAttribute("image"); user ? node.style.setProperty("font-style", "italic", "important") : node.style.removeProperty("font-style"); var {lab} = pref; if (exists && pref.hasVals) { if (val in pref.vals) var sfx = pref.vals[val] || val; else var sfx = user ? "Другое" : "По умолчанию"; lab += ` ${"restart" in pref ? "— ↯" : "refresh" in pref ? "— ⧖" : "— -"} "${sfx}"`; } node.setAttribute("label", lab); }, createRadios(doc, vals, popup) { for(var arr of vals) { if (!arr) { popup.append(doc.createElementNS(xul_ns, "menuseparator")); continue; } var [val, lab, key, ttt] = arr; var menuitem = doc.createElementNS(xul_ns, "menuitem"); menuitem.setAttribute("type", "radio"); menuitem.setAttribute("closemenu", "none"); menuitem.style.setProperty("font-style", "italic", "important"), menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab); key && menuitem.setAttribute("accesskey", key); var tip = menuitem.val = val; if (ttt) tip += "\n" + ttt; menuitem.tooltipText = tip; popup.append(menuitem); } }, openPopup(popup) { var btn = popup.parentNode; if (btn.domParent != btn.parentNode) { btn.domParent = btn.parentNode; var pos; if (btn.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} = btn.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; for(var p of btn.popups) p.setAttribute("position", pos); } popup.openPopup(btn); }, maybeRestart(node, conf) { if (conf) { node.ownerGlobal.event.preventDefault(); if (!Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) { var popup = node.closest("menupopup"); return popup.openPopup(popup.parentNode); } } var cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancel, "quit-application-requested", "restart"); return cancel.data ? Services.prompt.alert(null, this.label, "Запрос на выход отменен.") : this.restart(); }, async restart() { var meth = Services.appinfo.inSafeMode ? "restartInSafeMode" : "quit"; Services.startup[meth](Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); }, regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/, maybeRe(node, fe) { var {pref} = node; if ("restart" in pref) { if (this.maybeRestart(node, pref.restart)) return; } else this.popupshowing(fe, node.parentNode); if ("refresh" in pref) { var win = node.ownerGlobal; if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh ? win.BrowserCommands.reloadSkipCache() : win.BrowserCommands.reload(); } }, maybeClosePopup(e, trg) { !e.ctrlKey && prefs.getBoolPref(this.closePref, undefined) && trg.parentNode.hidePopup(); }, command(e) { var trg = e.target; if (trg.btn) return trg.secondaryPopup.state == "closed" && this.openPopup(trg.primaryPopup); var menu = trg.closest("menu"), newVal = trg.val; this.maybeClosePopup(e, menu); if (newVal != menu.pref.val) menu.pref.set(menu.pref.pref, newVal), this.maybeRe(menu, true); }, popupshowing(e, trg = e.target) { if (trg.state == "closed") return; if (trg.id) { for(var node of trg.children) { if (node.nodeName.endsWith("r")) continue; this.upd(node); !e && node.open && this.popupshowing(null, node.querySelector("menupopup")); } return; } var {pref} = trg.closest("menu"), findChecked = true; var findDef = "defVal" in pref; var checked = trg.querySelector("[checked]"); if (checked) { if (checked.val == pref.val) { if (findDef) findChecked = false; else return; } else checked.removeAttribute("checked"); } if (findDef) { var def = trg.querySelector("menuitem:not([style*=font-style]"); if (def) if (def.val == pref.defVal) { if (findChecked) findDef = false; else return; } else def.style.setProperty("font-style", "italic", "important"); } for(var node of trg.children) if ("val" in node) { if (findChecked && node.val == pref.val) { node.setAttribute("checked", true); if (findDef) findChecked = false; else break; } if (findDef && node.val == pref.defVal) { node.style.removeProperty("font-style"); if (findChecked) findDef = false; else break; } } }, contextmenu(e) { e.preventDefault(); var trg = e.target; if (trg.btn) { if (e.ctrlKey || e.shiftKey) return; if (e.detail == 2) return trg.secondaryPopup.hidePopup(); this.openPopup(trg.secondaryPopup); } else if ("pref" in trg) { this.maybeClosePopup(e, trg); if (trg.pref.user) prefs.clearUserPref(trg.pref.pref), this.maybeRe(trg); } }, click(e) { if (e.button) return; var trg = e.target, {pref} = trg; if (!pref) return; this.maybeClosePopup(e, trg); if (!("noAlt" in pref)) return; if (pref.val == pref.userChoice) if (pref.noAlt) return; else pref.set(pref.pref, pref.userAlt); else pref.set(pref.pref, pref.userChoice); this.maybeRe(trg); }, }))();
Добавлено 09-05-2025 05:41:58
// Mem_Indicator от Dumby // https://forum.mozilla-russia.org/viewtopic.php?pid=789048#p789048 // + правка VitalyV под 140 // Показывает суммарный жор памяти, (как в about:processes) // Для custom_script.js в user_chrome_files (async id => ({ delay: 2e3, val: "", init(topic, mm) { Services.obs.addObserver(mm = this, topic); Services.obs.addObserver(function quit(s, t) { this.timer?.cancel(); Services.obs.removeObserver(mm, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); }, observe(win) { var df = win.MozXULElement.parseXULToFragment( // ЛКМ на кнопке - вызов ucf_MemoryMinimizationButton.uc.js `<hbox id="${id}" tooltiptext= " ЛКМ Минимизировать память
 ПКМ Диспетчер процессов
Ctrl+ПКМ Открыть about:memory" ><label id="${id += "-label"}"/></hbox>` ); this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); (this.observe = async win => { this.timer.cancel(); await new Promise(ChromeUtils.idleDispatch); // ПКМ, Ctrl+ПКМ var ind = win.document.importNode(df, true); var {firstChild} = ind; firstChild.oncontextmenu = this.about; firstChild.onclick = e => e.button || win.memoryMinimizationButton?.doMinimize(); win.document.getElementById("star-button-box").after(ind); this.notify(); })(win); }, about(e) { var gb = e.view.gBrowser; gb.selectedTab = gb.addTrustedTab(`about:${ e.ctrlKey ? "memory" : "processes" }`); }, //************************// async notify() { var info = await ChromeUtils.requestProcInfo(); var bytes = info.memory; for(var child of info.children) bytes += child.memory; this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT); var prev = this.val; if ((this.val = this.mgb(bytes)) != prev) for(var win of CustomizableUI.windows) { var lab = win.document.getElementById(id); if (lab) lab.value = this.val; } }, mgb: bytes => bytes < 1073741824 ? Math.round(bytes / 1048576) + "MB" : (bytes / 1073741824).toFixed(2) + "GB" }).init("browser-delayed-startup-finished"))("ucf-mem-indicator");
// Vitaliy V. - 250502 // Подключать в двух местах // // UcfStylesScripts.scriptschrome.load // { path: "memoryMinimizationButton.js", }, // // UcfStylesScriptsChild.scriptscontent.pageshow // { path: "memoryMinimizationButton.js", urlregxp: /about:processes\?memoryMinimizationButton/, }, var memoryMinimizationButton = { doMinimize: function(event) { function doGlobalGC() { Services.obs.notifyObservers(null, "child-gc-request"); Cu.forceGC(); } function doCC() { Services.obs.notifyObservers(null, "child-cc-request"); if (typeof window.windowUtils != "undefined") window.windowUtils.cycleCollect(); else window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIDOMWindowUtils).cycleCollect(); } function doMemMinimize(event) { memoryMinimizationButton.kill(); Services.obs.notifyObservers(null, "child-mmu-request"); } doGlobalGC(); doCC(); // Всплывашка setTimeout((event)=> {doMemMinimize(event);}, 1000, event); var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); alertsService.showAlertNotification("chrome://user_chrome_files/content/custom_styles/svg/memory_slot.svg", "Скрипт Memory Minimization", "Память освобождена успешно!"); setTimeout(() => alertsService.closeAlert(), 2000); }, kill: function() { var tab = gBrowser.addTrustedTab("about:processes?memoryMinimizationButton"); gBrowser.hideTab(tab); setTimeout(() => { gBrowser.removeTab(tab); }, 8000); } } if (location.href == "about:processes?memoryMinimizationButton") { Services.console.logStringMessage("killing start"); setTimeout(() => { let closeButtons = document.querySelectorAll("tr.process > td.close-icon"); for(let closeButton of closeButtons) { let row = closeButton.parentNode; let canKill = true; if (row.querySelector("favicon")?.getAttribute("style")?.includes("link.svg")) { canKill = false; break; } for (let childRow = row.nextSibling; childRow && !childRow.classList.contains("process"); childRow = childRow.nextSibling ) { let win = childRow.win; if (win?.tab?.tab?.selected) { canKill = false; break; } } if (canKill) Control._handleKill(closeButton); } }, 5000); }
Добавлено 09-05-2025 05:48:45
// 126+ Функция Ctrl+Shift+R по ПКМ на стандартной кнопке обновления страницы // https://forum.mozilla-russia.org/viewtopic.php?pid=784200#p784200 // 13x+ скрипт переписан VitalyV - 250509 (async ( id = Symbol("reloadskipcache"), description1 = "ЛКМ Обновить страницу Ctrl+R", description2 = "СКМ Дублировать вкладку Ctrl+ЛКМ", description3 = "ПКМ Обновить минуя кэш Ctrl+Shift+R", ) => (this[id] = { init() { var node = this.node = CustomizableUI.getWidget("stop-reload-button").forWindow(window).node.querySelector("#reload-button"); if (!node) return; var tooltipid = "ucf-reload-button-shortcut-tooltip"; document.querySelector("#dynamic-shortcut-tooltip")?.after(MozXULElement.parseXULToFragment(` <tooltip id="${tooltipid}"> <description class="tooltip-label">${description1}</description> <description class="tooltip-label">${description2}</description> <description class="tooltip-label">${description3}</description> </tooltip> `)); node.tooltip = tooltipid; node.setAttribute("context", ""); node.addEventListener("click", this); setUnloadMap(id, this.destructor, this); }, handleEvent(e) { if (e.button != 2) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); BrowserCommands.reloadSkipCache(); }, destructor() { this.node.removeEventListener("click", this); }, }).init())();
Добавлено 09-05-2025 05:58:07
// Bookmarks Star Tooltip Helper от Dumby (fx112) // https://forum.mozilla-russia.org/viewtopic.php?pid=789303#p789303 // https://forum.mozilla-russia.org/viewtopic.php?pid=804649#p804649 // 13x+ Замена unloadlisteners // Показывает информативную подсказку при наведении на звездочку в адресной строке // Для custom_script_win.js в user_chrome_files (async (id, sel) => { var g = Cu.getGlobalForObject(Cu), stt = g[id]; if (!stt) { var {obs, prefs} = Services, {bookmarks: bm, observers: pobs} = PlacesUtils; stt = g[id] = { bm, pref: `ucf.${id}Guid`, async init() { this.args = [b => this.bguids.add(b.parentGuid), {concurrent: true}]; this.pobsArgs = [ ["bookmark-added", "bookmark-moved"], this.record = this.record.bind(this) ]; pobs.addListener(...this.pobsArgs); obs.addObserver(this, "quit-application-granted"); var guid = prefs.getCharPref(this.pref, ""); if (!guid) try {var [guid] = await PlacesUtils.metadata.get( PlacesUIUtils.LAST_USED_FOLDERS_META_KEY, [] )} catch {} this.guids.push(guid || await PlacesUIUtils.defaultParentGuid || bm.unfiledGuid); }, observe() { pobs.removeListener(...this.pobsArgs); obs.removeObserver(this, "quit-application-granted"); prefs.setCharPref(this.pref, this.guids[0]); }, record(events) { for(var e of events) if ( e.itemType == bm.TYPE_BOOKMARK && e.source == bm.SOURCES.DEFAULT && !(e.type == "bookmark-moved" && e.parentGuid == e.oldParentGuid) ) this.guids[0] = e.parentGuid; }, bguids: new g.Set(), guids: new g.Array(), fetch(win) { this.bguids.clear(); return bm.fetch({url: win.gBrowser.currentURI.spec}, ...this.args); }, tt(de) { var kids = InspectorUtils.getChildrenForNode; return (this.tt = kids.length == 2 ? de => { var list = kids(de, true); return list.item(list.length - 1); } : de => kids(de, true, false).at(-1) )(de); } }; stt.init(); var func = id => this[id].handleEvent = async function(e) { var win = e.view; var star = e.target; star.tooltipText = "\u3164"; var starred = star.hasAttribute("starred"); starred && await this.fetch(win); var result = []; for(var guid of (starred ? this.bguids : this.guids)) { var arr = [], num = 50; while(--num) { if (!star.matches(":hover")) return; var res = await this.bm.fetch(guid); if (!res) break; if ((guid = res.parentGuid) == this.bm.rootGuid) { arr.unshift(this.bm.getLocalizedTitle(res)); break; } arr.unshift(res.title || "[Безымянная папка]"); } arr.length && result.push(arr.join("\\")); } if (!star.matches(":hover")) return; if (!result.length) return win.document.l10n.translateElements([star]); var text = result.join("\n"); if (starred) { var m = result.length > 1; // две строки text = `Заклад${m ? "ки" : "ка"} в:\n${text}`; } else text = "Последняя в:\n" + text; star.defaultTT.state == "open" ? star.defaultTT.label = text : star.tooltipText = text; } var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})("${id}")`); g.ChromeUtils.compileScript(url).then(ps => ps.executeInGlobal(g)); } await delayedStartupPromise; var tt = stt.tt(document.documentElement); var stars = Array.from(document.querySelectorAll(sel)); for(var star of stars) star.defaultTT = tt, star.addEventListener("mouseenter", stt); var destructor = () => { for(var star of stars) star.removeEventListener("mouseenter", stt); } var ucf = window.ucf_custom_scripts_win; if (ucf) ucf.setUnloadMap(id, destructor, this); else window.addEventListener("unload", destructor, {once: true}); })("ucfBookmarksStarFTooltipHelper", "#star-button, #context-bookmarkpage");
// Открытие менеджера куков по ПКМ на звездочке в адресной строке // https://forum.mozilla-russia.org/viewtopic.php?pid=792269#p792269 // При открытии окна обновляется один раз, если не закрывая окна вызвать // повторно, данные обновятся и будут далее обновляться с интервалом 5с // Реинкарнация от Dumby, цель - исправление бага с размером окна // https://forum.mozilla-russia.org/viewtopic.php?pid=802777#p802777 // 13x+ Замена unloadlisteners (this.viewcookieswithrightclick = { init(that) { var star = this.star = document.querySelector("#star-button-box"); if (!star) return; star.addEventListener("contextmenu", this, true); star.addEventListener("click", this, true); //that.unloadlisteners.push("viewcookieswithrightclick"); setUnloadMap(Symbol("viewcookieswithrightclick"), this.destructor, this); }, handleEvent(e) { if (e.button != 2) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); if (e.type != "click") return; this.viewCookies(); }, getETDL(uri) { var eTLD = ""; try { eTLD = Services.eTLD.getBaseDomain(uri); } catch (e) { try { eTLD = uri.asciiHost; } catch (e) {} } return eTLD; }, async viewCookies() { var sds = "chrome://ucfsdswnd/content/sds.xhtml"; var type = "Browser:SiteDataSettings", g = Cu.getGlobalForObject(Cu); if (!Object.hasOwn(g, sds)) { var xhtml = (await (await fetch("chrome://browser/content/preferences/dialogs/siteDataSettings.xhtml")).text()) .replace(/(persist=".+)"/, `$1 screenX screenY sizemode" windowtype="${type}"`); g[sds] = Cc["@mozilla.org/addons/addon-manager-startup;1"] .getService(Ci.amIAddonManagerStartup).registerChrome( Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)), [["override", sds, "data:application/xhtml+xml," + encodeURIComponent(xhtml)]] ); } (this.viewCookies = async () => { var uri = gBrowser.selectedBrowser.currentURI; try { let _uri = ReaderMode.getOriginalUrl(uri.spec); if (_uri) uri = Services.io.newURI(_uri); } catch(e) {} uri = this.getETDL(uri); var _win = Services.wm.getMostRecentWindow(type); await SiteDataManager.updateSites(); if (!_win) await new Promise(resolve => (_win = openDialog(sds, type, "chrome,dialog=no,resizable")) .addEventListener("DOMContentLoaded", resolve, {once: true}) ); else if ("_gSiteDataSettings" in _win) _win._gSiteDataSettings(); else { Services.scriptloader.loadSubScript("data:," + encodeURIComponent(` var _gSiteDataSettings = gSiteDataSettings._gSiteDataSettings = (function() { SiteDataManager.getSites().then(sites => { this._sites = sites; var sortCol = document.querySelector("treecol[data-isCurrentSortCol=true]"); this._sortSites(this._sites, sortCol); this._buildSitesList(this._sites); }); }).bind(gSiteDataSettings); _gSiteDataSettings(); var updateSetInterval = setInterval(async () => { await SiteDataManager.updateSites(); _gSiteDataSettings(); }, 5000); let removeBtns = document.querySelectorAll("#removeSelected, #removeAll"); var updateClearInterval = () => { clearInterval(updateSetInterval); for (let btn of removeBtns) btn.removeEventListener("command", updateClearInterval); updateClearInterval = null; }; for (let btn of removeBtns) btn.addEventListener("command", updateClearInterval); `), _win); _win.addEventListener("unload", () => { _win.updateClearInterval?.(); }, { once: true }); } _win.focus(); var filter = _win.document.getElementById("searchBox"); if (!filter) return; filter.value = uri; filter.focus(); filter.dispatchEvent(new _win.Event("input", { bubbles: true })); })(); }, destructor() { this.star.removeEventListener("contextmenu", this, true); this.star.removeEventListener("click", this, true); }, }).init(this);
Добавлено 09-05-2025 06:01:46
// Открытие окна "информации о странице" на вкладке разрешений, // по клику ПКМ в адресной строке на боксе с иконками разрешений // (и сайта, если добавлено скриптом FavIcon in URL-bar). // https://forum.mozilla-russia.org/viewtopic.php?pid=783003#p783003 // Открываемую вкладку можно изменить ниже. // 13x+ Замена unloadlisteners (this.openpermissionswithrightclick = { init(that) { var identitybox = this.identitybox = document.querySelector("#identity-box"); if (!identitybox) return; identitybox.addEventListener("contextmenu", this, true); identitybox.addEventListener("click", this, true); //that.unloadlisteners.push("openpermissionswithrightclick"); setUnloadMap(Symbol("openpermissionswithrightclick"), this.destructor, this); }, handleEvent(e) { if (e.button != 2) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); if (e.type != "click") return; this.browserpageinfo(null, "permTab"); }, browserpageinfo() { this.browserpageinfo = ("BrowserCommands" in window) ? () => { BrowserCommands.pageInfo(...arguments) } : () => { BrowserPageInfo(...arguments) } this.browserpageinfo(...arguments); }, destructor() { this.identitybox.removeEventListener("contextmenu", this, true); this.identitybox.removeEventListener("click", this, true); } }).init(this);
Отредактировано _zt (09-05-2025 18:16:22)
Отсутствует
C простыми unloadlisteners я думаю понятно.
//that.unloadlisteners.push("xxxxxxxxxxxxxx");
setUnloadMap(Symbol("xxxxxxxxxxxxxx"), this.destructor, this);
и, в подключении - , ucfobj: true, }, если еще не так.
Добавлено 09-05-2025 06:13:16
Ну и до кучи:
cleardownloadsbutton.js
menusrestartitems.js
Добавлено 09-05-2025 06:16:56
// Открытие окна "Инструменты браузера" // по ПКМ на иконке developer-button // VitalyV 250428 (async ( id = Symbol("openbrowsertoolbox"), tooltipText = "ЛКМ Меню инструментов\nПКМ Инструменты браузера", ) => (this[id] = { async init() { await window.delayedStartupPromise; var btn = this.btn = CustomizableUI.getWidget("developer-button")?.forWindow(window).node; if (!btn) return; btn.setAttribute("context", ""); btn.tooltipText = tooltipText; btn.addEventListener("click", this); setUnloadMap(id, this.destructor, this); }, handleEvent(e) { if (e.button != 2) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); var {prefs} = Services, chr = "devtools.chrome.enabled", rem = "devtools.debugger.remote-enabled"; if (!prefs.getBoolPref(chr) || !prefs.getBoolPref(rem)) { prefs.setBoolPref(chr, true); prefs.setBoolPref(rem, true); } document.querySelector("#devtoolsKeyset > key#key_browserToolbox")?.doCommand(); }, destructor() { this.btn.removeEventListener("click", this); }, }).init())();
Добавлено 09-05-2025 06:25:48
// Счетчик вкладок в адресной строке // https://forum.mozilla-russia.org/viewtopic.php?pid=797189#p797189 // 13x+ Замена unloadlisteners от VitalyV (async style => { await document.documentReadyForIdle; var tabCounter = document.createXULElement("button"); tabCounter.id = "tabCounter"; tabCounter.setAttribute("tooltiptext", "Количество открытых вкладок"); var urlbarIcons = document.getElementById("page-action-buttons"); urlbarIcons.insertBefore(tabCounter, urlbarIcons.lastChild); var flag = "--reg-flag-ex"; if (!windowUtils.getVisitedDependentComputedStyle(tabCounter, "", flag)) { var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var uri = Services.io.newURI("data:text/css," + encodeURIComponent( `@-moz-document url(${location}) {${ style.replace("{", `{\n\t\t${flag}: 1;`).replace(/;$/gm, " !important;") }}` )); sss.loadAndRegisterSheet(uri, sss.USER_SHEET); } var tid, lab = () => { tid = null; tabCounter.label = gBrowser.tabs.length; } var count = () => { tid && clearTimeout(tid); tid = setTimeout(lab, 150); } lab(); var tc = gBrowser.tabContainer; tc.addEventListener("TabOpen", count); tc.addEventListener("TabClose", count); ucf_custom_scripts_win.setUnloadMap(Symbol(), () => { tc.removeEventListener("TabOpen", count); tc.removeEventListener("TabClose", count); }, this); })(` #tabCounter { appearance: none; min-width: 22px; min-height: 22px; max-height: 22px; text-align: center; color: silver; background-color: inherit; border: none; padding: 0; margin: 0; } `);
Отредактировано _zt (09-05-2025 06:35:41)
Отсутствует
_zt а нет у вас кнопки ToggleRestartlessAddons с правками для 139+?
// http://infocatcher.ucoz.net/js/cb/toggleRestartlessAddons.js // https://forum.mozilla-russia.org/viewtopic.php?id=57948 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Toggle_Restartless_Add-ons // Toggle Restartless Add-ons button for Custom Buttons // (code for "initialization" section) // Also the code can be used from main window context (as Mouse Gestures code, for example) // Also you can check for add-ons updates using right-click: // copy all code from // https://github.com/Infocatcher/Custom_Buttons/blob/master/Check_for_Addons_Updates/checkForAddonsUpdates.js // after "//== Check for Addons Updates begin" // See "var style = " to modify styles for specific add-ons // (c) Infocatcher 2013-2019 // version 0.1.3pre4 - 2020-01-01 var options = { addonTypes: ["extension", "plugin"], // Possible values: "extension", "plugin" // From extensions: "userstyle" (Stylish), "greasemonkey-user-script" (Greasemonkey), "userscript" (Scriptish) // (swap to reorder in the menu) showVersions: 1, // 0 - don't show versions // 1 - show after name: "Addon Name 1.2" // 2 - show as "acceltext" (in place for hotkey text) showHidden: 0, // 0 - don't show hidden add-ons // -1 - show only enabled hidden add-ons (e.g. to track new items) // 1 - show all hidden add-ons sort: { enabled: 0, clickToPlay: 0, disabled: 1 // Sort order: // 0, 0, 0 - sort add-ons of each type alphabetically // 0, 0, 1 - show enabled add-ons (of each type) first // 0, 1, 2 - enabled add-ons, then click-to-play and then disabled }, closeMenu: false, // Close menu after left-click closeMenuClickToPlay: false // Close menu after left-click, for click to play plugins // Use Shift+click to invert closeMenu* behavior }; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var mp = document.createElementNS(xulns, "menupopup"); addEventListener("popupshowing", () => mp.updateMenu(), false, mp); addEventListener("command", mp.onmousedown = mp.onclick = e => { if (!e.button || e.type.endsWith("k")) mp.handleEvent(e); }, false, mp); mp.toggleAttribute("context"); addEventListener("popuphidden", () => mp.destroyMenu(), false, mp); var tb = this.parentNode; if(tb && tb.getAttribute("orient") == "vertical") { // https://addons.mozilla.org/firefox/addon/vertical-toolbar/ var isRight = tb.parentNode.getAttribute("placement") == "right"; mp.setAttribute("position", isRight ? "start_before" : "end_before"); } var cleanupTimer = 0; mp.updateMenu = function() { clearTimeout(cleanupTimer); addStyle(); getRestartlessAddons(options.addonTypes, function(addons) { var df = document.createDocumentFragment(); var prevType; function sortPosition(addon) { if("STATE_ASK_TO_ACTIVATE" in AddonManager && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) return options.sort.clickToPlay; if(addon.isActive) return options.sort.enabled; return options.sort.disabled; } function key(addon) { return options.addonTypes.indexOf(addon.type) + "\n" + sortPosition(addon) + "\n" + addon.name.toLowerCase(); } addons.sort(function(a, b) { var ka = key(a); var kb = key(b); return ka == kb ? 0 : ka < kb ? -1 : 1; }).forEach(function(addon) { var type = addon.type; if(prevType && type != prevType) df.appendChild(document.createElementNS(xulns, "menuseparator")); prevType = type; var icon = addon.iconURL || addon.icon64URL; var mi = document.createElementNS(xulns, "menuitem"); mi.className = "menuitem-iconic"; var label = addon.name; if(options.showVersions == 1) label += " " + addon.version; else if(options.showVersions == 2) mi.setAttribute("acceltext", addon.version); mi.setAttribute("label", label); mi.setAttribute("image", icon || mp.icons[type] || ""); if(!icon && mp.icons.useSVG) mi.style.fill = "currentColor"; var tip = addon.description || ""; var delay = "delayedStartupAddons" in Services && Services.delayedStartupAddons[addon.id] || null; var isDelayed = delay !== null; mi.classList.toggle("toggleRestartlessAddons-isDelayed", isDelayed); if(isDelayed) tip = "[Delayed Startup: " + delay.toLocaleString() + "]" + (tip ? "\n" + tip : ""); tip && mi.setAttribute("tooltiptext", tip); mi.classList.toggle("toggleRestartlessAddons-isHidden", addon.hidden || false); setDisabled(mi, addon.userDisabled); mi._cbAddon = addon; df.appendChild(mi); }); mp.textContent = ""; mp.appendChild(df); }); }; mp.handleEvent = function(e) { var mi = e.target; if(!("_cbAddon" in mi)) return; var addon = mi._cbAddon; if(e.type == "mousedown") { var closeMenu = isAskToActivateAddon(addon) ? options.closeMenuClickToPlay : options.closeMenu; if(e.shiftKey) closeMenu = !closeMenu; mi.setAttribute("closemenu", closeMenu ? "auto" : "none"); return; } var hasMdf = hasModifier(e); if(e.type == "command" && (!hasMdf || e.shiftKey)) { let newDis = setNewDisabled(addon); setDisabled(mi, newDis); } else if(e.type == "command" && hasMdf || e.type == "click" && e.button == 1) { openAddonPage(addon); closeMenus(mi); } else if(e.type == "click" && e.button == 2) { if(openAddonOptions(addon)) closeMenus(mi); } }; mp.destroyMenu = function() { removeStyle(); clearTimeout(cleanupTimer); cleanupTimer = setTimeout(function() { mp.textContent = ""; }, 5000); }; mp.icons = { get platformVersion() { delete this.platformVersion; return this.platformVersion = parseFloat(Services.appinfo.platformVersion); }, get useSVG() { delete this.useSVG; return this.useSVG = Services.appinfo.name == "Firefox" && this.platformVersion >= 57; }, get plugin() { delete this.plugin; var v = this.useSVG && this.platformVersion; return this.plugin = v >= 88 && "chrome://global/skin/icons/plugin.svg" || v >= 81 && "chrome://global/skin/plugins/plugin.svg" || v >= 65 && "chrome://global/skin/plugins/pluginGeneric.svg" || v >= 57 && "chrome://mozapps/skin/plugins/pluginGeneric.svg" || "chrome://mozapps/skin/plugins/pluginGeneric-16.png"; }, get extension() { delete this.extension; return this.extension = this.useSVG ? this.platformVersion >= 76 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" // Or chrome://mozapps/skin/extensions/extension.svg : "chrome://mozapps/skin/extensions/extensionGeneric-16.svg" : "chrome://mozapps/skin/extensions/extensionGeneric-16.png"; } }; function isAskToActivateAddon(addon) { return addon.type == "plugin" && "STATE_ASK_TO_ACTIVATE" in AddonManager && Services.prefs.getBoolPref("plugins.click_to_play", true); } function setNewDisabled(addon) { var newDis = getNewDisabled(addon); var oldDis = addon.userDisabled; if(Components.interfaces.nsIWebTransportHash) { // random, Fx 123+ var func = function() { func = false; } var thread = Services.tm.currentThread; var meth = newDis ? "disable" : "enable"; addon[meth]({allowSystemAddons: true}).finally(func); while(func) thread.processNextEvent(true); } else try { addon.userDisabled = newDis; } catch(e) { // Error: Cannot disable hidden add-on firefox@getpocket.com _log("Can't set addon.userDisabled to " + newDis + ", error:\n" + e); if(addon.hidden) setNewDisabledRaw(addon, newDis); } var realDis = addon.userDisabled; if(realDis != newDis && addon.type == "extension") { // Firefox 62+? Weird things happens setNewDisabledRaw(addon, newDis); realDis = addon.userDisabled; } if(realDis != newDis) { // We can't enable vulnerable plugins let err = "Can't set addon.userDisabled to " + newDis + ", real value: " + realDis; if(newDis) { _log(err + "\nSTATE_ASK_TO_ACTIVATE not supported?"); newDis = false; } else { _log(err + "\nVulnerable plugin?"); if(oldDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = true; else newDis = AddonManager.STATE_ASK_TO_ACTIVATE; } addon.userDisabled = newDis; } ensureSpecialDisabled(addon, newDis); return addon.userDisabled; } function getNewDisabled(addon) { // disabled -> STATE_ASK_TO_ACTIVATE -> enabled -> ... var curDis = addon.userDisabled; var newDis; if("STATE_ASK_TO_ACTIVATE" in AddonManager && curDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = false; else if(!curDis) newDis = true; else { if(isAskToActivateAddon(addon)) newDis = AddonManager.STATE_ASK_TO_ACTIVATE; else newDis = false; } return newDis; } function setNewDisabledRaw(addon, newDis) { _log("Let's try set addon.userDisabled using raw hack"); if("lazy" in g) g = g.lazy; if("XPIDatabase" in g && "updateAddonDisabledState" in g.XPIDatabase) { // Firefox 61+ let rawAddon = g.XPIDatabase.getAddons().find(function(rawAddon) { return rawAddon.id == addon.id; }); g.XPIDatabase.updateAddonDisabledState( rawAddon, g.XPIDatabase.updateAddonDisabledState.length == 1 // Firefox 74+ ? { userDisabled: newDis } : newDis ); } else if("eval" in g) { // See "set userDisabled(val)" let addonFor = g.eval("addonFor"); let rawAddon = addonFor(addon); //rawAddon.userDisabled = newDis; g.XPIProvider.updateAddonDisabledState(rawAddon, newDis); } else { // Firefox 57+? See https://forum.mozilla-russia.org/viewtopic.php?pid=745272#p745272 updateAddonDisabledState(addon, newDis); } } function updateAddonDisabledState(addon, newDis) { var key = "_cbToggleRestartlessAddonsData"; var url = URL.createObjectURL(new Blob([ "XPIProvider.updateAddonDisabledState(addonFor(this." + key + "[0]), this." + key + "[1]); delete this." + key + ";" ])); addDestructor(function() { URL.revokeObjectURL(url); }); (updateAddonDisabledState = function(addon, newDis) { nsvo[key] = [addon, newDis]; Services.scriptloader.loadSubScript(url, nsvo); })(addon, newDis); } function setDisabled(mi, disabled) { var askToActivate = "STATE_ASK_TO_ACTIVATE" in AddonManager && disabled == AddonManager.STATE_ASK_TO_ACTIVATE; var cl = mi.classList; cl.toggle("toggleRestartlessAddons-askToActivate", askToActivate); cl.toggle("toggleRestartlessAddons-disabled", disabled && !askToActivate); } function ensureSpecialDisabled(addon, newDis) { if(addon.id == "screenshots@mozilla.org") Services.prefs.setBoolPref("extensions.screenshots.disabled", newDis); } if( this instanceof XULElement // Custom Buttons && typeof event == "object" && !("type" in event) && typeof _phase == "string" && _phase == "init" // Initialization ) { this.type = "menu"; this.orient = "horizontal"; this.appendChild(mp); this.onmouseover = function(e) { if(e.target != this) return; Array.prototype.some.call( this.parentNode.getElementsByTagName("*"), function(node) { if( node != this && node.namespaceURI == xulns // See https://github.com/Infocatcher/Custom_Buttons/issues/28 //&& node.boxObject //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && "open" in node && node.open && node.getElementsByTagName("menupopup").length ) { node.open = false; this.open = true; return true; } return false; }, this ); }; this.onmousedown = function(e) { if(e.target == this && e.button == 0 && hasModifier(e)) e.preventDefault(); }; this.oncontextmenu = function(e) { if(e.target == this && !hasModifier(e) && hasUpdater()) e.preventDefault(); }; this.onclick = function(e) { if(e.target != this) return; if(e.button == 0 && hasModifier(e) || e.button == 1) openAddonsManager(); else if(e.button == 2 && !hasModifier(e) && hasUpdater()) checkForAddonsUpdates.call(this); }; } else { // Mouse gestures or something other... let e; if(typeof event == "object" && event instanceof Event && "screenX" in event) // FireGestures e = event; else if( this instanceof Components.interfaces.nsIDOMChromeWindow && "mgGestureState" in window && "endEvent" in mgGestureState // Mouse Gestures Redox ) e = mgGestureState.endEvent; else { let anchor = this instanceof XULElement && this || window.gBrowser && gBrowser.selectedBrowser || document.documentElement; if("boxObject" in anchor) { let bo = anchor.boxObject; e = { screenX: bo.screenX, screenY: bo.screenY }; if(this instanceof XULElement) e.screenY += bo.height; } } if(!e || !("screenX" in e)) throw new Error("[Toggle Restartless Add-ons]: Can't get event object"); document.documentElement.appendChild(mp); mp.addEventListener("popuphidden", function destroy(e) { mp.removeEventListener(e.type, destroy, false); setTimeout(function() { mp.destroyMenu(); mp.parentNode.removeChild(mp); }, 0); }, false); mp.openPopupAtScreen(e.screenX, e.screenY); } function getRestartlessAddons(addonTypes, callback, context) { if(!("AddonManager" in window)); var then, promise = AddonManager.getAddonsByTypes(addonTypes, then = function(addons) { callback.call(context, addons.filter(function(addon) { var ops = addon.operationsRequiringRestart; return !addon.appDisabled && !(ops & AddonManager.OP_NEEDS_RESTART_ENABLE || ops & AddonManager.OP_NEEDS_RESTART_DISABLE) && ( !addon.hidden || options.showHidden > 0 || options.showHidden == -1 && !addon.userDisabled ) && (addon.iconURL || "").substr(0, 29) != "resource://search-extensions/"; })); }); promise && typeof promise.then == "function" && promise.then(then, Components.utils.reportError); // Firefox 61+ } function openAddonOptions(addon) { // Based on code from chrome://mozapps/content/extensions/extensions.js // Firefox 21.0a1 (2013-01-27) var optionsURL = addon.optionsURL; if(!addon.isActive || !optionsURL) return false; if(addon.type == "plugin") // No options for now! return false; if( addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_INFO || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_BROWSER || NaN) ) openAddonPage(addon, true); else if(addon.optionsType == AddonManager.OPTIONS_TYPE_TAB && "switchToTabHavingURI" in window) switchToTabHavingURI(optionsURL, true); else { let windows = Services.wm.getEnumerator(null); while(windows.hasMoreElements()) { let win = windows.getNext(); if(win.document.documentURI == optionsURL) { win.focus(); return true; } } // Note: original code checks browser.preferences.instantApply and may open modal windows window.openDialog(optionsURL, "", "chrome,titlebar,toolbar,centerscreen,dialog=no"); } return true; } function openAddonsManager(view) { var openAddonsMgr = window.BrowserOpenAddonsMgr || window.BrowserAddonUI.openAddonsMgr // Firefox || window.openAddonsMgr // Thunderbird || window.toEM; // SeaMonkey openAddonsMgr(view); } function openAddonPage(addon, scrollToPreferences) { var platformVersion = parseFloat( Services.appinfo.name == "Pale Moon" ? Services.appinfo.version : Services.appinfo.platformVersion ); scrollToPreferences = scrollToPreferences && platformVersion >= 12 ? "/preferences" : ""; openAddonsManager("addons://detail/" + encodeURIComponent(addon.id) + scrollToPreferences); } function hasModifier(e) { return e.ctrlKey || e.shiftKey || e.altKey || e.metaKey; } function addStyle() { if(addStyle.hasOwnProperty("_style")) return; var style = '\ .toggleRestartlessAddons-isDelayed > .menu-iconic-text {\n\ opacity: 0.75;\n\ color: #070;\n\ }\n\ .toggleRestartlessAddons-isHidden > .menu-iconic-text {\n\ color: #609;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-left {\n\ opacity: 0.4;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-text,\n\ .toggleRestartlessAddons-disabled > .menu-accel-container {\n\ opacity: 0.5;\n\ }\n\ .toggleRestartlessAddons-askToActivate {\n\ color: -moz-nativehyperlinktext;\n\ }'; addStyle._style = document.insertBefore( document.createProcessingInstruction( "xml-stylesheet", 'href="' + "data:text/css," + encodeURIComponent(style) + '" type="text/css"' ), document.documentElement ); } function removeStyle() { if(!addStyle.hasOwnProperty("_style")) return; var s = addStyle._style; s.parentNode.removeChild(s); delete addStyle._style; } function closeMenus(node) { // Based on function closeMenus from chrome://browser/content/utilityOverlay.js for(; node && "tagName" in node; node = node.parentNode) { if( node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.localName == "menupopup" || node.localName == "popup") ) node.hidePopup(); } } function _log(s) { if(typeof LOG == "function") // Custom Buttons LOG(s); else // Or something else Services.console.logStringMessage("Toggle Restartless Add-ons: " + s); } function hasUpdater() { var has = checkForAddonsUpdates.toString().indexOf("about:addons") != -1; hasUpdater = function() { return has; }; return has; } function checkForAddonsUpdates() { //== Check for Addons Updates begin // http://infocatcher.ucoz.net/js/cb/checkForAddonsUpdates.js // https://forum.mozilla-russia.org/viewtopic.php?id=57958 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Check_for_Addons_Updates // Check for Addons Updates button for Custom Buttons // (code for "code" section) // (c) Infocatcher 2012-2021 // version 0.1.6pre4 - 2021-03-28 // Button just open hidden tab with about:addons and trigger built-in "Check for Updates" function. // And show tab, if found updates. (function() { var btn = this instanceof XULElement ? this : { // Launched not from custom button image: "", // Base64-encoded icon (if empty, will be used "imgLoading") label: "Check for Addons Updates", tooltipText: "" }; if("_cb_disabled" in btn) return; btn._cb_disabled = true; var app = Services.appinfo.name; var pv = parseFloat(Services.appinfo.platformVersion); var ADDONS_URL = "about:addons"; var progressIcon = new ProgressIcon(btn); var image = btn.image || progressIcon.imgLoading; var tip = btn.tooltipText; btn.tooltipText = "Open " + ADDONS_URL + "…"; var tab, browser, gBrowser; var tbTabInfo, tbTab; var trgWindow = Services.wm.getMostRecentWindow("navigator:browser") || app == "Thunderbird" && Services.wm.getMostRecentWindow("mail:3pane") || window; var trgDocument = trgWindow.document; var tabmail = trgDocument.getElementById("tabmail"); if(tabmail && app == "Thunderbird") { // Note: SeaMonkey doesn't support content tabs in mail window let addonsWin; let receivePong = function(subject, topic, data) { addonsWin = subject; }; Services.obs.addObserver(receivePong, "EM-pong", false); Services.obs.notifyObservers(null, "EM-ping", ""); Services.obs.removeObserver(receivePong, "EM-pong"); if(addonsWin) { let rootWindow = addonsWin .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIDOMWindow); tabmail = rootWindow.document.getElementById("tabmail"); tbTabInfo = tabmail.getBrowserForDocument(addonsWin); tbTab = tab = tbTabInfo.tabNode; processAddonsTab(addonsWin); } else { Services.obs.addObserver(function observer(subject, topic, data) { Services.obs.removeObserver(observer, topic); if(subject.document.readyState == "complete") processAddonsTab(subject); else { subject.addEventListener("load", function onLoad(e) { subject.removeEventListener(e.type, onLoad, false); processAddonsTab(subject); }, false); } }, "EM-loaded", false); // See openAddonsMgr() -> openContentTab() tbTabInfo = tabmail.openTab("contentTab", { contentPage: ADDONS_URL, clickHandler: "specialTabs.siteClickHandler(event, /addons\.mozilla\.org/);", background: true }); tbTab = tab = tbTabInfo.tabNode; tbTab.collapsed = true; // Note: dontSelectHiddenTab() not implemented } } else if("gBrowser" in trgWindow && trgWindow.gBrowser.tabs) { let isPending = false; let ws = Services.wm.getEnumerator("navigator:browser"); windowsLoop: while(ws.hasMoreElements()) { let w = ws.getNext(); let tabs = w.gBrowser.tabs; for(let i = 0, l = tabs.length; i < l; ++i) { let t = tabs[i]; if( !t.closing && t.linkedBrowser && t.linkedBrowser.currentURI.spec == ADDONS_URL ) { tab = t; break windowsLoop; } } } gBrowser = trgWindow.gBrowser; if(!tab) { tab = gBrowser.addTab(ADDONS_URL, { triggeringPrincipal: "Services" in window // Firefox 63+ && Services.scriptSecurityManager && Services.scriptSecurityManager.getSystemPrincipal() }); tab.collapsed = true; tab.closing = true; // See "visibleTabs" getter in chrome://browser/content/tabbrowser.xml trgWindow.addEventListener("TabSelect", dontSelectHiddenTab, false); } else if( tab.getAttribute("pending") == "true" // Gecko >= 9.0 || tab.linkedBrowser.contentDocument.readyState == "uninitialized" // || tab.linkedBrowser.__SS_restoreState == 1 ) isPending = true; browser = tab.linkedBrowser; if( isPending || browser.webProgress.isLoadingDocument || browser.currentURI.spec == "about:blank" // Firefox 79+ ) { browser.addEventListener("load", processAddonsTab, true); if(isPending) { if(pv >= 41) { // Workaround to correctly restore pending tab // See https://github.com/Infocatcher/Custom_Buttons/issues/39 let selTab = gBrowser.selectedTab; gBrowser.selectedTab = tab; gBrowser.selectedTab = selTab; } else { browser.reload(); } } } else { processAddonsTab(); } } else { progressIcon.restore(); btn.tooltipText = tip; delete btn._cb_disabled; Services.prompt.alert(window, btn.label, "Error: Can't find supported window!"); return; } function processAddonsTab(e, again) { var doc; if(e && e instanceof Components.interfaces.nsIDOMWindow) { doc = e.document; } else if(e) { doc = e.target; if(doc.location != ADDONS_URL) return; browser.removeEventListener(e.type, processAddonsTab, true); } else { doc = browser.contentDocument; } btn.tooltipText = "Process " + ADDONS_URL + "…"; progressIcon.loading(); var origAttr = "_cb_checkForAddonsUpdates_origImage"; if(!tab.hasAttribute(origAttr)) { var link = doc.querySelector('link[rel="shortcut icon"]'); // Not loaded yet? tab.setAttribute(origAttr, link && link.href || tab.image); } tab.image = image; var fu = $("cmd_findAllUpdates"); if(!fu) { // Firefox 72+ var win = doc.defaultView; var vb = doc.getElementById("html-view-browser"); if(!vb) { if(!HTMLHtmlElement.isInstance(doc.documentElement)) { // Firefox 87+ win.setTimeout(processAddonsTab, 20, win); return; } vb = browser; } if(!again) { // Strange errors happens // chrome://mozapps/content/extensions/aboutaddons.js // getTelemetryViewName() -> el.closest(...) is null win.setTimeout(processAddonsTab, 20, win, true); return; } var vbDoc = vb.contentDocument; fu = vbDoc.querySelector('[action="check-for-updates"]'); var um = vbDoc.getElementById("updates-message"); } var notFound = $("updates-noneFound") || { get hidden() { return um.getAttribute("state") != "none-found"; } }; var updated = $("updates-installed") || { get hidden() { return um.getAttribute("state") != "installed"; } }; // Avoid getting false results from the past update check (may not be required for "noneFound") if(um) { // Firefox 72+ um.hidden = true; um.removeAttribute("state"); } else { notFound.hidden = updated.hidden = true; } //fu.doCommand(); fu.click(); function localize(node, key, callback) { if(um) { // Firefox 72+ doc.l10n.formatValue(key).then(function(s) { callback(s || key); }, Components.utils.reportError); return; } callback(node.getAttribute("value") || key); } var inProgress = $("updates-progress") || { get hidden() { return um.getAttribute("state") != "updating"; } }; localize(inProgress, "addon-updates-updating", function(s) { btn.tooltipText = s; }); var waitTimer = setInterval(function() { if(!doc.defaultView || doc.defaultView.closed) { stopWait(); notify("Tab with add-ons manager was closed!"); return; } if(!inProgress.hidden) return; var autoUpdate = $("utils-autoUpdateDefault") || vbDoc.querySelector('[action="set-update-automatically"]'); var autoUpdateChecked = autoUpdate.getAttribute("checked") == "true" || autoUpdate.checked; var found = $("updates-manualUpdatesFound-btn") || { get hidden() { return um.getAttribute("state") != "manual-updates-found"; } }; if( autoUpdateChecked ? notFound.hidden && updated.hidden : notFound.hidden && found.hidden ) // Too early? return; stopWait(); if(!tbTab) tab.closing = false; function removeTab() { if(!tab.collapsed) return; if(tbTab) { tabmail.closeTab(tbTabInfo, true /*aNoUndo*/); return; } gBrowser.removeTab(tab); (function forgetClosedTab(isSecondTry) { var ss = "nsISessionStore" in Components.interfaces ? ( Components.classes["@mozilla.org/browser/sessionstore;1"] || Components.classes["@mozilla.org/suite/sessionstore;1"] ).getService(Components.interfaces.nsISessionStore) : trgWindow.SessionStore; // Firefox 61+ https://bugzilla.mozilla.org/show_bug.cgi?id=1450559 if(!("forgetClosedTab" in ss)) return; var closedTabs = (ss.getClosedTabDataForWindow(window)); for(let i = 0, l = closedTabs.length; i < l; ++i) { let closedTab = closedTabs[i]; let state = closedTab.state; if(state.entries[state.index - 1].url == ADDONS_URL) { ss.forgetClosedTab(window, i); return; } } if(!isSecondTry) // May be needed in SeaMonkey setTimeout(forgetClosedTab, 0, true); })(); } if(!notFound.hidden) { removeTab(); localize(notFound, "addon-updates-none-found", function(s) { notify(s); }); return; } if(autoUpdateChecked) { removeTab(); localize(updated, "addon-updates-installed", function(s) { notify(s); }); return; } tab.collapsed = false; var cats = $("categories"); var upds = $("category-availableUpdates"); if(cats && upds) { if(vb && cats.selectedItem == upds) // Only for Firefox 72+ cats.selectedItem = $("category-extension"); // Trick to force update cats.selectedItem = upds; } else { // Firefox 76+ ? vbDoc.querySelector('.category[name="available-updates"]').click(); } var tabWin = tab.ownerDocument.defaultView; if(tbTab) tabmail.switchToTab(tbTabInfo); else tabWin.gBrowser.selectedTab = tab; setTimeout(function() { tabWin.focus(); doc.defaultView.focus(); var al = $("addon-list") || vb; al.focus(); }, 0); }, 50); function $(id) { return doc.getElementById(id); } function stopWait() { clearInterval(waitTimer); progressIcon.restore(); btn.tooltipText = tip; if(tab.image == image) tab.image = tab.getAttribute(origAttr); tab.removeAttribute(origAttr); trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false); setTimeout(function() { delete btn._cb_disabled; }, 500); } function notify(msg) { Components.classes["@mozilla.org/alerts-service;1"] .getService(Components.interfaces.nsIAlertsService) .showAlertNotification( app == "Firefox" && pv >= 57 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" : "chrome://mozapps/skin/extensions/extensionGeneric.png", btn.label, msg, false, "", null ); } } function dontSelectHiddenTab(e) { // <tab /><tab collapsed="true" /> // Close first tab: collapsed tab becomes selected var trgTab = e.originalTarget || e.target; if(trgTab != tab) return; if(/\n(?:BrowserOpenAddonsMgr|toEM)@chrome:\/\//.test(new Error().stack)) { // User open Add-ons Manager, show tab trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false); setTimeout(function() { // Hidden tab can't be selected, so select it manually... tab.collapsed = tab.closing = false; gBrowser.selectedTab = tab; }, 0); } function done(t) { if(!t.hidden && !t.closing) { e.preventDefault(); e.stopPropagation(); return gBrowser.selectedTab = t; } return false; } for(var t = tab.nextSibling; t; t = t.nextSibling) if(done(t)) return; for(var t = tab.previousSibling; t; t = t.previousSibling) if(done(t)) return; } function ProgressIcon(btn) { var {icon} = btn, origIcon = icon.src; var box = btn.ownerDocument.createXULElement("hbox"); box.toggleAttribute("busy"); box.toggleAttribute("fadein"); box.className = "tab-throbber"; var s = btn.style, r = btn.getBoundingClientRect(); s.setProperty("min-width", r.width + "px", "important"); s.setProperty("min-height", r.height + "px", "important"); Object.defineProperty(btn, "open", {configurable: true}); icon.replaceWith(box); icon.src = "chrome://global/skin/icons/loading.svg"; this.loading = () => { box.replaceWith(icon); s.removeProperty("min-width"); s.removeProperty("min-height"); } this.restore = () => { icon.src = origIcon; delete btn.open; } } }).call(this); //== Check for Addons Updates end } this.tooltipText = "Переключатель джетпаков" + "\nПКМ – проверить обновления" + "\nСКМ – открыть страницу дополнений" + "\n\nВ меню: \nЛКМ – включить/выключить дополнение без закрытия меню" + "\nShift+ЛКМ – включить/выключить дополнение" + "\nСКМ – открыть страницу дополнения в управлении дополнениями" + "\nПКМ – открыть настройки дополнения (если есть)";
(async () => CustomizableUI.createWidget({ label: "Дополнения", id: "ucf-cbbtn-ToggleRestartlessAddons", localized: false, onCreated(btn) { var icon = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:none;stroke:context-fill rgb(39, 174, 129);stroke-opacity:context-fill-opacity;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;' d='M12.9 15.3H3.2c-.88 0-1.6-.6-1.6-1.4v-2.7c0-.4.33-.6.74-.6h1.72c.7 0 1.25-.64 1.25-1.2 0-.64-.55-1.15-1.25-1.15H2.34c-.41 0-.74-.32-.74-.68V5.84c0-.81.72-1.48 1.6-1.48h2.36V3.13c0-1.21.93-2.297 2.21-2.419C9.23.57 10.5 1.62 10.5 2.98v1.38h2.4c.9 0 1.5.67 1.5 1.48v8.06c0 .8-.6 1.4-1.5 1.4z'/></svg>"; var subst = this.id.toLowerCase() + "-icon"; Services.io.getProtocolHandler("resource") .QueryInterface(Ci.nsIResProtocolHandler) .setSubstitution(subst, Services.io.newURI(icon)); icon = "resource://" + subst; var e = Object.create(null); var ael = (t, l, c, trg) => trg.addEventListener(t, l, c); var code = Cu.readUTF8URI(Services.io.newURI( "chrome://user_chrome_files/content/custom_scripts/custom_script/ucf-cbbtn-ToggleRestartlessAddons.js" )); (this.onCreated = async btn => { btn.image = icon; var win = btn.ownerGlobal; await new Promise(win.setTimeout); new win.Function("self,event,_phase,addEventListener", code) .call(btn, btn, e, "init", ael); })(btn); } }))();
Отсутствует
В 139 версии у меня отвалилось несколько скриптов. Но в первую очередь хотелось бы исправить два скрипта.
Первый в консоль пишет: "Content-Security-Policy: Параметры страницы заблокировали выполнение JavaScript eval (script-src), поскольку он нарушает следующую директиву: «script-src chrome: moz-src: resource: 'report-sample'» (Отсутствует 'unsafe-eval')"
Второй в консоль пишет: "EvalError: call to Function() blocked by CSP"Я знаю, что можно поиграться параметрами about:config - security.browser_xhtml_csp.* и в 139 - security.allow_unsafe_dangerous_privileged_evil_eval, но думаю, что это временное решение и рано или поздно эти параметры выпилят и все равно придется править скрипты.
Просьба к знатокам, помогите исправить эти два скрипта.
скрытый текстВыделить кодКод:
// // Сохранять изображение без запроса в указанную папку, из контекстного меню ..... // try { (this.contextsaveimg = { path: "E:\\Download", init(that) { var contextMenu = this.contextMenu = document.querySelector("#contentAreaContextMenu"); if (!contextMenu) return; contextMenu.addEventListener("popupshowing", this); that.setUnloadMap("contextsaveimg", this.destructor, this); }, destructor() { this.contextMenu.removeEventListener("popupshowing", this); }, handleEvent(e) { if (!gContextMenu.onImage || gContextMenu.webExtBrowserType === "popup") return; var menuitem = document.createXULElement("menuitem"); menuitem.setAttribute("id", "ucf_SaveImg"); menuitem.setAttribute("label", "Сохранить изображение в папку: " + this.path); menuitem.addEventListener("click", function(e) { saveImg(); }); menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABAnAAAQJwAAAAAAAAAAAAAAAAEGAQECKAABATsAAAAoAAAAFAAAAAkAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjRRXUVtk8U+Y4TGKUBYrRgmNpcOFR91BQgMWAECBD8AAQEqAAAAGAAAAAwAAAAGAAAAAQAAAAAAAAAAAAAAAEVrp7Nws9//fcr6/3W+9f5wten5ZKHQ7lWGsedDaI7QL0hjtR4sQKERGSaBBgkOXgAAACoAAAAEAAAAAAAAAABKdrK+aqjY/4XO7P+AyfL/fcXy/4HL+/97xPT/eMHy/3e+8f9trt77YpvI8Ux0m98TGymTAAAAJQAAAAAAAAAAVIS7yGWh0/8yTVv/UniH/0htff+L0e//WIab/0x2i/9XiKL/RGp+/zNRYv9dkrP+S26S2QQGClwAAAAGAAAAAGeYxtFxrtr/IDA7/01mbf8sPkP/SWZw/zlSWv88Vl//LkRL/3Wsv/83UVr/XYqe/3+51PQaJDCWAAAAGwAAAAB5qtHajMXk/yY1Pf9fa23/GB8g/2yGjP8mMDL/Sl9k/0RYXP9wmKL/dZ+r/4i6y/+n4PD+TmV5yQECA0UAAAACh7bX46zh8/9tjZj/gpen/4GMk//G4Oj/kJ6f/52clf+svbz/f5id/3yXnv+gx9L/wez1/5u0xuwPExt+AAAAEJTA3ey/7vr/ve35/7Hf8v+w0ub/ubvE/8a4uf/NwLv/083I/9Pl6//T7ff/0O32/9fw9v/a6vL8P0ZYtAAAAC+iy+P2zvX8/831/P/K6e3/y7Kg/+GNZf/vlWr/6Zx3/9qegv/Ino7/t8TQ/7HM4/+itc3yu8ja52BtirQAAAEkqs/l9dv8/f/b/P3/1dzU/9qXcf/slmb/+aFr//+td//+rXb/+aRu/9+1k/+/2uL/RldrtiIrPU0ZITEoAAAAA46017zX8Pf85/7+/+X8+//g7+3+yryw+O6odPz/wYj/9bJ7/+KpgP/nqn3/0tPJ/kRTY6QAAQEYAAAAAAAAAAA6V3Yuboyqj6C81My50ubgo7zR1I92bLbzt3/3/tGZ/8aTZttfY2+PbX2Sn3GFm7EiLDtNAAAABQAAAAAAAAAAAgMEAAUHCgYYJDETIS4+LjMwNU+3e029/NGZ/vHHlPRrSSx/BQUFEAMFBwcEBQcJAQECAgAAAAAAAAAAAAAAAAAAAAAAAAAAEQgAA1wvElSsaz3B9LZ8+fC7gu6WZ0COFg0GGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcTAQrWbS+y7pdZ8eOVWMqUWy91IRIJFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AACf/wAAgH8AAIAfAACADwAAgA8AAIAHAACABwAAgA8AAIAPAADOHwAA/v8AAP//AAD//wAA//8AAA=="); (this.contextMenu.querySelector("#context-sendimage") || this.contextMenu.lastElementChild).after(menuitem); this.handleEvent = () => menuitem.hidden = (!gContextMenu.onImage || gContextMenu.webExtBrowserType === "popup"); function saveImg() { var p = Services.prefs; var data = Object.assign(Object.create(null), { "browser.download.folderList": { type: "Int", set: 2 }, "browser.download.useDownloadDir": { type: "Bool", set: true }, "browser.download.dir": { type: "String", set: this.path } }); var lazy = {PrivateBrowsingUtils}; var save = eval(`(function ${gContextMenu.saveMedia})`.replace("\n false, // don't", "\n true, //")); (menuitem.saveImg = () => { for(var pref in data) { var obj = data[pref], meth = `et${obj.type}Pref`; obj.val = p.prefHasUserValue(pref) ? p["g" + meth](pref) : null; p["s" + meth](pref, obj.set); } try {save.call(gContextMenu);} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } })(); } } }).init(this); } catch(e) { Cu.reportError(e); }скрытый текстВыделить кодКод:
// // Сохранить как PNG ..... // (async func => CustomizableUI.createWidget({ id: "ucf_SaveAsPNG", label: "Сохранить как PNG", tooltiptext: "Сохранить как PNG", localized: false, // defaultArea: CustomizableUI.AREA_NAVBAR, onCreated(btn) { var win = btn.ownerGlobal; new win.Function("_id, xhtmlns, addDestructor", func.toString().slice(7, -1)).call( btn, this.id, "http://www.w3.org/1999/xhtml", destructor => win.addEventListener("unload", destructor, {once: true}) ); btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGwSURBVHjarJPPaxNBGIafmd1km23saqtRaLB6kFYl2ELpRayCVL20RvCmJwk9ePNWvPsXtCA9eNCDeO0hLemPo96LYAuKkRhtsBViEtI0rrt+GyFQ1oMkfjAf883M+8w7w4zyfZ9uwsxms10RzCBNTd3sSLy2lvsDCCKzWMCKGHgotOTAlpamJPm+jCmFL00bmmbD5WlmsKXTdBltB3bcxowaLWJwsTpi4bvNVu1JMmVn5cmcqTB6/DAg3hcjGpUFskjZjlgFKdmvVIiISKlfUhlyQMVPywgDjvX1YCjpOBZ2fZ+9+TuUpxcZuz7Ebl7ArkfM0dgDcOAFCvfwHTi9URJJi2RCqEuPmRxPUXn9imodLo1D6orGjMHW6govZqfDDkYviDXBlZ4vsFsrk8vXqZRWeDY8hz55lvvpGU7sFEn0RhhTtTBg/tETCvlNdj68papsUoND3Lh6iyPOOYrvv/JufYNrqcssbW8zkjwdBnz7/JKL50/x4F4at9GgsFckX/2IefQHZyb6mbl9l2LpE8ff1PnufWkD/t87yC1v/pvi4V8AwZvuNFS33/m3AAMAhEeAiqLmty4AAAAASUVORK5CYII="); } }))(() => { ((main, parts) => this._handleClick = () => { var df = MozXULElement.parseXULToFragment(` <menupopup> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOwSURBVHjaYmBiYuJvamo+xiIsLLL3uaazMUAAMTY3txxjAAFubq7/ZiYm/wECACIA3f8AGhobzGhoaP8QFRr/6enp/wT5+fgBLS0tAOLi4gCnp6cAAoixtrbuFBsb6x+QNnZ2jo0MXz9/+Qdk/wfhO3fu/Gc5cuwoA4NqHEOoszjDrVu3GFiAogxJtiwMagrCQHMeMgAEoHhsdRCG4Tj463+rxGFIqN2CYI7wBpiaWhzPheF5SMhIKliCYiQtyTC4hvSLcu7cHYQQl5SSDyFGa23UWkfvfXTORWNMpiIYH2NV1xXN5gvq9kfqNjtSStF7mkAhBPTXHm3TYL1qsV2+8LyfIaXEbRjAyuzpUOCcI+cMYgzp31hCnft+fgII6Cm95oiICOd///4CFTAwAOWBgBFIM7Lw8vLZM5w7d+7/t2/fwA4DOfDp02d/QQ4GWv1z6tSpU5g+ffrI8OnTJyagFUx2Tu5MsnIyTDk52UyfPn5k/vXr9x+mjx8+MsTFxTGERMUzVK09yCAsn8AwY+ZMhlevX0Pc9PTZM4a3b94wXHjwmaEsu5th87GpQIcyMdy+fZvh79+/DEwfP35giIuPZ3hzbTeDCtcjhngnEwZVVRWGz58/g+ON5dOnz6BYYKioqGY4eOggg5SuBYORkRHDixcvQL5hZNTR0flnY2PD+O8fKAwYgGHwHyTMwMzMwrBt2zZHgAA9Uz1Lw1AUPWlKE1vFlEIFHRoKQgcRtDSLIAiCgoJuiovYP6DopnR1EdRYHO3W6tbg5K5LwclmVQviRwutpSaQtI3P+yIK7/Eu94t77jkPiqIcGUaZ5vlmlvXFbNui12LEBSPo/uU29/EYrYQ1m01WqVRYPn++FQiHI3Mj8RG4jst7wHFcFAoFaFoGsixBliRoGc338dg3AQuKojc2OoZ+vzcZ4JRwQNQAxVIJsVgMuVwO8/OL2D29xPjSHvpCHAf7+36M57iuSzUdnzISg4d3AvxgVqHrJ5BCIcxu7KCdWoLx3MFLaBjOxDJSC1lIsowzXUfVNFEnJflrJi2i1WrBtm1MpzNgAoN5U8TtySE61Sccb6/jIjuF3uMduo5DOWk/l9fwxQr0o+6J+rSqqlxjQq1WQ9kw8PH2CoF5cLtd8gaRSCSwsrqKZDJJu3A8WZbFer2hB2nLAc5ZNBplHFskEsEmSUcURV8q+GXTH5ffBo1OUzNFGUa7/cm4eGcEIbA2MBBW6df8VnC1s3/zv8mfScchaq+GhgavfwBr4dP0kYqtcwAAAABJRU5ErkJggg==" label="Сохранить всю страницу как PNG" value="all"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOwSURBVHjaYmBiYuJvamo+xiIsLLL3uaazMUAAMTY3txxjAAFubq7/ZiYm/wECACIA3f8AGhobzGhoaP8QFRr/6enp/wT5+fgBLS0tAOLi4gCnp6cAAoixtrbuFBsb6x+QNnZ2jo0MXz9/+Qdk/wfhO3fu/Gc5cuwoA4NqHEOoszjDrVu3GFiAogxJtiwMagrCQHMeMgAEoHhsdRCG4Tj463+rxGFIqN2CYI7wBpiaWhzPheF5SMhIKliCYiQtyTC4hvSLcu7cHYQQl5SSDyFGa23UWkfvfXTORWNMpiIYH2NV1xXN5gvq9kfqNjtSStF7mkAhBPTXHm3TYL1qsV2+8LyfIaXEbRjAyuzpUOCcI+cMYgzp31hCnft+fgII6Cm95oiICOd///4CFTAwAOWBgBFIM7Lw8vLZM5w7d+7/t2/fwA4DOfDp02d/QQ4GWv1z6tSpU5g+ffrI8OnTJyagFUx2Tu5MsnIyTDk52UyfPn5k/vXr9x+mjx8+MsTFxTGERMUzVK09yCAsn8AwY+ZMhlevX0Pc9PTZM4a3b94wXHjwmaEsu5th87GpQIcyMdy+fZvh79+/DEwfP35giIuPZ3hzbTeDCtcjhngnEwZVVRWGz58/g+ON5dOnz6BYYKioqGY4eOggg5SuBYORkRHDixcvQL5hZNTR0flnY2PD+O8fKAwYgGHwHyTMwMzMwrBt2zZHgAA9Uz1Lw1AUPWlKE1vFlEIFHRoKQgcRtDSLIAiCgoJuiovYP6DopnR1EdRYHO3W6tbg5K5LwclmVQviRwutpSaQtI3P+yIK7/Eu94t77jkPiqIcGUaZ5vlmlvXFbNui12LEBSPo/uU29/EYrYQ1m01WqVRYPn++FQiHI3Mj8RG4jst7wHFcFAoFaFoGsixBliRoGc338dg3AQuKojc2OoZ+vzcZ4JRwQNQAxVIJsVgMuVwO8/OL2D29xPjSHvpCHAf7+36M57iuSzUdnzISg4d3AvxgVqHrJ5BCIcxu7KCdWoLx3MFLaBjOxDJSC1lIsowzXUfVNFEnJflrJi2i1WrBtm1MpzNgAoN5U8TtySE61Sccb6/jIjuF3uMduo5DOWk/l9fwxQr0o+6J+rSqqlxjQq1WQ9kw8PH2CoF5cLtd8gaRSCSwsrqKZDJJu3A8WZbFer2hB2nLAc5ZNBplHFskEsEmSUcURV8q+GXTH5ffBo1OUzNFGUa7/cm4eGcEIbA2MBBW6df8VnC1s3/zv8mfScchaq+GhgavfwBr4dP0kYqtcwAAAABJRU5ErkJggg==" label="Сохранить видимую часть страницы как PNG" value="page"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKaSURBVHjaYpx94sPD44//CDG9+/SDp8bsBw9AADEmrX7zmQEIGF+//fD/w8dPDAABxNix6/nbcA0GIQYoYGJiZGSQFBdmOHnqLAMrKwsDQAAxJq958/n/f4jsm2//GBifP3v+/8cfiMDDj/8ZmHi5ORl4gPjPn18M///9ZWDh5uVm4GJkYfj56zcD9z9GBoAAYmwH2aL8UwimDRk8+fyfgYWRgZFBgI+b4TsWBR+BtoNcxcDDwwW2R1iQn2HvgcMMX799Y/j6/TvDzz+/GVj+/fvPvO0BC8N/oGpGhv8ML3m0GS59EwWbcP/9XwaAAGSRwQ3CMAxFfxq3TgrqiSMswARMwSJMxZEdGAXBAEiQquICJMFuekDqwTlY38/Wi9kf78OqNTO8kndretBh+1puuvl+R8Dpwm9iruG8xPP/tIGzhULc1OB6voJJXxGjQpumGpsKCc8wEqISwGJfA1P1IYCEmCegkTmqLIELT/8KC+/x+cbxBpEPOl8zbn0q5voWXdcipQQrgZiC/QlQORmzNBAEUfjt7N4ichBUDIKCWNsJhiBiZ2mZf5XC0v/gT7C10lqwNMVBkBC9kKAmt7e+uQtJxBS6cNwy7L2b981bTrz/fnmIxnHTYN081i1F8PQacddDzm0M+UfAYPw/gfyTlqMNVfOJVxIGpfxNgMcZRwoYpkVpe1ezLn/jplc7B2wWb+1gwwfuvxg31lwi7MAimOU4E+IevuXoXt+gILTE1aQ1VBJnwNYR9ltXFKCweM9RWFpYCnjWiukU7dYJLs7PUMyKuglNAZt6GVncZ7SgIU2ZJ8M/bLqVQEFYN9hJPQ5201pgvhztjnk2ZhOYh+esd/vY39ZPZYWBXlURqZ4Qwg8uZXU3gM7p3vAbsXveewxHZWUAAAAASUVORK5CYII=" label="Сохранить выбранный элемент страницы как PNG" value="click"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAL/SURBVHjaYijccvd25ZHvv5n4RSUVQs2vswAEECOIxwACy+8v/3/30Zv/AAHE0Hb6y+//UPDv4///LD/+MjJ8+PqF4cvnnww/vgkxAAQQY8Xhb78YgQCsj5mFgQGm/P+v///fvvj/n+n/fwaGe//vMexg2Mrw7BsDA8vXHwwMPN/5GdQ/mzG8BbIBAoiRfdqvX8xf/rBCDAEaAWL8ByOgmZwMLBXGvxnrzLgYVj9cyfCL+TfDj9+/Gd7//sAQw5vK8PEXAwMTRBsD0Li3DNKikgwC4twM3NIMDF9/fGf4CVTA8u0fM+ODjwwM7qJZDH8/MTBI/GFgUAba/QYo+fEnAwNAADKoXQVhIAjOJYfgsxIR/AwRi/yBlY3gz9j7FUI+wt7CwkbEzs7CNIo2Yl53t3duElDBhYXZZXaWGbHYKW0M4b+cex7WG9FaxmxGfNcfYNH3T+pr/LcSzu1h3Wx11EU2eOkYYRSi7jVgrQeb1TDtzFHkLgu13GQIBgGkJ6GFxva8h6XqX0kgRlF+AfkEw4S7ujEGbKnAzDa6GNEYLvOh2N6wOUGaVXHKayqQsHeiHgyfqKJ51sbxjvAWoG1qWWkYiKJnZhKTpgapK1tEslRw50+4camIGz/ObfcuBP0HBREEn12I+MBUadPM5HomqbWgi8kJydzHOfdctXmU29Vhbhqq8leNfxQyLP6lWgjjdxds9Yxs95ZRVAo+h8yFqEau2fHEKjpKqgojRDg+H0iw1gb212NY2oC/MCxz5DxGaYgPsKrGsnRYUEusnvKb4MNqnBlN5aZD8q54Hb2gP+gj62bohOyKdVxgobTBk3vE7cMzDhYPkVA0NW0xaBrlk6BZtRN20I16SMIWPt0CJlLQowqJStE2YwqnQRbE2ZwazrYURDquL5zcnCINU4xdiYo7QXXo4TesSMaIGGRTJ6jnqBxvkJNwfhFa2Ovu1jlrwXjD2gZ9wITeKVhImEFXgXcIgrvri/udqySztpDZemJurTzK70h/3h1xY3xpvwGLI42vrCwxmAAAAABJRU5ErkJggg==" label="Сохранить выбранную область страницы как PNG" value="clipping"/> </menupopup> `); var popup = df.firstChild; popup.setAttribute("context", ""); popup.addEventListener("command", e => popup.handleCommand(e)); popup.handleCommand = e => { var name = _id + ":DataURLReady"; main = main.replace("%MESSAGE_NAME%", name); var urls = {}, configurable = true, enumerable = true; Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, { configurable, enumerable, get() { var value = `data:;charset=utf-8,({${ encodeURIComponent(main + part) }%0A}).init("${key}")`; Object.defineProperty(urls, key, {configurable, enumerable, value}); return value; } })); var getTabLabel = () => { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); } var listener = msg => { var fp = makeFilePicker(); fp.init( !("inIsolatedMozBrowser" in window.browsingContext.originAttributes) ? window.browsingContext : window , "Сохранить как…", fp.modeSave); fp.appendFilter("", "*.png"); var fileName = getTabLabel(); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '').replace(/\s+/g, '_').slice(0, 100).replace(/^\s+|\s+$/g, ''); var fileDate = (function () { var d = new Date(), z = function(n){return (n < 10 ? '0' : '') + n}; return '[' + z(d.getFullYear()) + '_' + z(d.getMonth()+1) + '_' + z(d.getDate()) + '\u2014' + z(d.getHours()) + '_' + z(d.getMinutes()) + '_' + z(d.getSeconds()) + ']'; })(); fp.defaultString = fileName + "_" + fileDate + ".png"; fp.open(res => res == fp.returnCancel || !fp.file || makeWebBrowserPersist().saveURI( Services.io.newURI(msg.data), document.nodePrincipal, null, null, null, null, null, fp.file, null, null )); } messageManager.addMessageListener(name, listener); addDestructor(() => messageManager.removeMessageListener(name, listener)); (popup.handleCommand = e => gBrowser.selectedBrowser.messageManager .loadFrameScript(urls[e.target.value], false) )(e); } this.append(df); (this._handleClick = () => popup.openPopup(this, "after_start"))(); })(` init(cmd) { cmd.startsWith("c") ? this[cmd].init(this[cmd].parent = this) : this[cmd](); }, capture(win, x, y, width, height) { var canvas = win.document.createElementNS("${xhtmlns}", "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var tryDraw = ind => { try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")} catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);} } tryDraw(17); sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png")); }, `, { all: `all() { var win = content; this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY); }`, page: `page() { var win = content, doc = win.document, body = doc.body, html = doc.documentElement; var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft; var scrY = (body.scrollTop || html.scrollTop) - html.clientTop; this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight); }`, clipping: `clipping: { handleEvent(e) { if (e.button) return false; e.preventDefault(); e.stopPropagation(); switch(e.type) { case "mousedown": this.downX = e.pageX; this.downY = e.pageY; this.bs.left = this.downX + "px"; this.bs.top = this.downY + "px"; this.body.appendChild(this.box); this.flag = true; break; case "mousemove": if (!this.flag) return; this.moveX = e.pageX; this.moveY = e.pageY; if (this.downX > this.moveX) this.bs.left = this.moveX + "px"; if (this.downY > this.moveY) this.bs.top = this.moveY + "px"; this.bs.width = Math.abs(this.moveX - this.downX) + "px"; this.bs.height = Math.abs(this.moveY - this.downY) + "px"; break; case "mouseup": this.uninit(); break; } }, init() { var win = {}; Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, win); this.win = win.value; this.doc = this.win.document; this.body = this.doc.body; if (!HTMLBodyElement.isInstance(this.body)) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!"); return false; } this.flag = null; this.box = this.doc.createElement("div"); this.bs = this.box.style; this.bs.border = "red dashed 1px"; this.bs.position = "absolute"; this.bs.zIndex = "2147483647"; this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor; this.body.style.cursor = "crosshair"; ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)]; this.body.style.cursor = this.defaultCursor; this.body.removeChild(this.box); this.parent.capture.apply(this, pos); ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }`, click: `click: { getPosition() { var html = this.doc.documentElement; var body = this.doc.body; var rect = this.target.getBoundingClientRect(); return [ this.win, Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft, Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop, parseInt(rect.width), parseInt(rect.height) ]; }, highlight() { this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false; this.target.style.cssText += "outline: red 1px solid; outline-offset: 1px; -moz-outline-radius: 2px;"; }, lowlight() { if (this.orgStyle) this.target.style.cssText = this.orgStyle; else this.target.removeAttribute("style"); }, handleEvent(e) { switch(e.type) { case "click": if (e.button) return; e.preventDefault(); e.stopPropagation(); this.lowlight(); this.parent.capture.apply(this, this.getPosition()); this.uninit(); break; case "mouseover": if (this.target) this.lowlight(); this.target = e.target; this.highlight(); break; } }, init() { this.win = content; this.doc = content.document; ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { this.target = false; ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }` }); });
Похоже, что про скрипты потихоньку можно забывать.
Судя по всему, после ухода с форума Dumby и Виталия, других альтруистов, среди знатоков по скриптам, нет и помощи больше ждать не от кого.
Отредактировано unter_officer (09-05-2025 14:08:27)
«The Truth Is Out There»
Отсутствует
Save чем не устраивает?
Ставить такой крутой комбайн ради четырех функций? Как-то....
add: Разве что попробовать убрать из Save всё для меня лишнее.
Отредактировано unter_officer (09-05-2025 23:14:16)
«The Truth Is Out There»
Отсутствует
_zt
Дело в том, что когда-то Dumby кто-то попросил вырезать из Save только эти четыре функции для PNG.
А потом уже я просил Dumby переделать этот отделенный от Save скрипт из СВ в UCF.
Просто не всем нужен такой навороченный комбайн как Save.
Отредактировано unter_officer (09-05-2025 19:31:34)
«The Truth Is Out There»
Отсутствует
Похоже, что про скрипты потихоньку можно забывать.Судя по всему, после ухода с форума Dumby и Виталия, других альтруистов, среди знатоков по скриптам, нет и помощи больше ждать не от кого.
их понять можно.один из-за того что в основном тут росияне а второй "тащить весь форум на себе" не захотел
а сечас в скриншотер неплохой.
Отсутствует
Нашёл у себя ещё 2 отвалившихся в 138 скрипта.
custom_script_win.js
// Пункт для контекстного меню адресной строки, подставляющий модификаторы поиска (this.searchmodifiers = { init(that) { var urlbar = this.urlbar = gURLBar.textbox; if (!urlbar) return; urlbar.addEventListener("popupshowing", this); // that.unloadlisteners.push("searchmodifiers"); setUnloadMap(Symbol("searchmodifiers"), this.destructor, this); }, handleEvent(e) { if (e.originalTarget != this.popup) return; this.urlbar.removeEventListener("popupshowing", this); this.urlbar = null; var sep = this.popup.querySelector("menuseparator.menuseparator-add-engine") || this.popup.lastElementChild; var menu = this.append("menu", sep, {label: "Вставить ^ * + % ~ # @"}, "before"); this.append("menuseparator", menu, null, "before"); var popup = this.append("menupopup", menu, {oncommand: "insert(event);"}, "append"); popup.addEventListener("popupshowing", this, { once: true }); this.handleEvent = e => { var df = document.createDocumentFragment(); for (let label of [ "^ История (журнал)", "* Закладки", "+ Страницы с метками", "% Вкладки (текущие, открытые)", "~ Набранные", "# Названия", "@ Действия(по доступным тегам)" ]) this.append("menuitem", df, {label}, "append"); popup.append(df); var ed = gURLBar.inputField.editor .QueryInterface(Ci.nsIEditor || Ci.nsIPlaintextEditor); popup.insert = e => { var str = e.target.label[0] + " "; // если раскомментировать строки ниже, добавляет пробел в конец (не пустого) url // var val = gURLBar.inputField.value; // if (val && !val.endsWith(" ")) str = " " + str; // ed.endOfDocument(); ed.insertText(str); }; }; }, get popup() { delete this.popup; return this.popup = gURLBar.inputField.parentNode.menupopup; }, append(name, parent, attrs, func) { var elm = document.createXULElement(name); if (attrs) for (let a in attrs) elm.setAttribute(a, attrs[a]); parent[func](elm); return elm; }, destructor() { this.urlbar?.removeEventListener("popupshowing", this); }, }).init(this);
// Добавить подменю "Поиск изображения в" в контекстном меню изображений (this.searchimagecontextmenu = { handleEvent(evt) { if (evt.target != this.contextMenu || !gContextMenu?.imageInfo?.currentSrc) return; var array = [ ['Google', 'https://www.google.lv/favicon.ico', 'https://www.google.com/searchbyimage?&image_url='], ['Яндекс', 'https://yastatic.net/morda-logo/i/favicon_islands.ico', 'https://yandex.ru/images/search?rpt=imageview&url='], ['Bing', 'https://www.bing.com/s/a/bing_p.ico', 'https://www.bing.com/images/search?view=detailv2&iss=sbi&form=SBIHMP&sbisrc=UrlPaste&q=imgurl:'], ['Tineye', 'https://tineye.com/favicon.ico', 'https://tineye.com/search?pluginver=bookmark_1.0&url='], ]; var menu = document.createXULElement("menu"); menu.setAttribute("label", "Поиск изображения в ..."); menu.setAttribute("class", "menu-iconic"); menu.setAttribute("image", array[1][1]); menu.setAttribute("onclick", "_searcclick(event);"); menu._searcclick = function(e) { if (e.target != this) return; gBrowser.selectedTab = gBrowser.addTrustedTab(this._searcharg[2] + encodeURIComponent(gContextMenu.imageInfo.currentSrc), { index: gBrowser.selectedTab._tPos + 1 } ); this.parentNode.hidePopup(); } menu._searcharg = array[0]; var menuPopup = document.createXULElement("menupopup"); menu.append(menuPopup); array.forEach(m=> { var mItem = document.createXULElement("menuitem"); mItem.setAttribute("label", m[0]); mItem.setAttribute("image", m[1]); mItem.setAttribute("class", "menuitem-iconic"); mItem.setAttribute("oncommand", "gBrowser.selectedTab = gBrowser.addTrustedTab(_searcharg[2] + encodeURIComponent(gContextMenu.imageInfo.currentSrc), { index: gBrowser.selectedTab._tPos + 1 } );"); mItem._searcharg = m; menuPopup.append(mItem); }); var mItem = document.createXULElement("menuitem"); mItem.setAttribute("label", 'Искать во всех поисковиках'); mItem.setAttribute("oncommand", "_searcharg.forEach(m => { gBrowser.selectedTab = gBrowser.addTrustedTab(m[2] + encodeURIComponent(gContextMenu.imageInfo.currentSrc), { index: gBrowser.selectedTab._tPos + 1 } );});"); mItem._searcharg = array; menuPopup.append(mItem); this.contextMenu.querySelector("#context-copyimage-contents")?.before(menu); this.popupshowing = e => { if (e.target != this.contextMenu) return; menu.hidden = !gContextMenu?.imageInfo?.currentSrc; }; this.popuphiding = e => { if (e.target != this.contextMenu) return; menu.hidden = true; }; this.contextMenu.addEventListener("popuphiding", this); this.handleEvent = e => { this[e.type](e); }; }, init(that) { var contextMenu = this.contextMenu = document.querySelector("#contentAreaContextMenu"); if (!contextMenu) return; contextMenu.addEventListener("popupshowing", this); // that.unloadlisteners.push("searchimagecontextmenu"); setUnloadMap(Symbol("searchimagecontextmenu"), this.destructor, this); }, на яндексе и бинге. destructor() { this.contextMenu.removeEventListener("popupshowing", this); this.contextMenu.removeEventListener("popuphiding", this); }, }).init(this);
Отсутствует