куда...?
там ниже функция keydown(e) {...
для комбинаций клавиш Ctrl + F
перед gFindBar.close(); добавить gFindBar.clear();
Отредактировано Vitaliy V. (07-10-2021 15:17:46)
Отсутствует
там ниже функция keydown(e) {...
для комбинаций клавиш Ctrl + F
перед gFindBar.close(); добавить gFindBar.clear();
Я так понимаю что если для этого не использую клави..., то можно удалить этот код:
keydown(e) { if (e.ctrlKey && e.code == "KeyF" && !e.altKey && !e.shiftKey) { if (this.timer != null) { e.preventDefault(); return; } this.timer = setTimeout(() => { this.timer = null; }, 1000); if (window.gFindBarInitialized && !gFindBar.hidden) { e.preventDefault(); gFindBar.clear(); gFindBar.close(); } } },
Win7
Отсутствует
если для этого не использую клави..., то можно удалить этот код:
Нет, один этот код удалять нельзя, только вместе со слушателем, и удалять код не обязательно, достаточно отключить слушатель.
// window.addEventListener("keydown", this, true);
// window.removeEventListener("keydown", this, true);
Отсутствует
Нет, один этот код удалять нельзя.
Я это уже понял...
и удалять код не обязательно, достаточно отключить слушатель.
// window.addEventListener("keydown", this, true);
// window.removeEventListener("keydown", this, true);
Спасибо!
Отредактировано kokoss (07-10-2021 16:09:18)
Win7
Отсутствует
Скачал комплект UserChromeFiles - 2021-9-23. Обновил/перезаписал все файлы по нужным папкам.
Скрипты подключились и заработали сразу, а вот стили ни один не подключился.
Ранее в файле custom_style_user.css было прописано следующее содержимое и всё работало:
/* Этот файл для правил CSS с правами USER_SHEET */ /* значки папок закладок желтого цвета */ @import url("./css/Colored-folders-91.css"); /* скрыть элементы меню закладок */ @import url("./css/hide_bookmarks_elements.css"); /* скрыть элементы контекстного меню на странице */ @import url("./css/hide_context_elements.css"); /* убрать history-dropmarker из адресной строки */ @import url("./css/history-dropmarker.css"); /* компактная панель поиска сверху справа */ @import url("./css/findbar_compakt.css"); /* панель быстрого поиска такая хе, как и полного поиска */ @import url("./css/findbar_show_full_quickfindbar.css"); /* в приложении GISMETEO - белый шрифт значка погоды */ @import url("./css/gismeteo.css"); /* изменение высоты панели вкладок, компактное меню (Proton) */ @import url("./css/bar_compact_proton.css");
Отсутствует
Inko7
Так все стили по умолчанию отключены в CustomStylesScripts.jsm (зачем включать пустые файлы, они там только для примера)
можете изменить это в styleschrome (стили подключенные в styleschrome работают там же где и userChrome.css)
ну или в stylesall: [ // Для всех документов
И вместо @import можно просто подключить ваши файлы там же в CustomStylesScripts.jsm, например
{ path: "css/Colored-folders-91.css", type: "USER_SHEET", sheet(f) { preloadSheet(this, f); }, },
Отредактировано Vitaliy V. (10-10-2021 14:44:28)
Отсутствует
Vitaliy V.
вот теперь все стили заработали, спасибо!
получается, раз скрипты заработали сразу, то файлы custom_script.js / custom_script_all_win.js / custom_script_win.js обрабатываются изначально и их прописывать дополнительно не нужно?
Отсутствует
файлы custom_script.js / custom_script_all_win.js / custom_script_win.js обрабатываются изначально и их прописывать дополнительно не нужно?
custom_script.js добавлен в CustomStylesScripts.jsm, но его можно удалить, переименовать,
а custom_script_all_win.js / custom_script_win.js обрабатываются изначально и их прописывать, удалять, переименовывать нельзя
Отсутствует
Vitaliy V.
Вы можете написать скрипт отключающий отображение пунктов контекстного меню, с определенным в скрипте ID, для разных контекстов. С перечислением исключений для каждого добавленного пользователем ID. Что-то типа:
"#context-copy" this.hidden = gContextMenu.onLink || gContextMenu.onMailtoLink || gContextMenu.onImage || gContextMenu.onCanvas;
"#other-addon" this.hidden = gContextMenu.onTextInput || gContextMenu.isContentSelected;
Например, #context-copy появляется везде при выделенном на странице тексте, но главное здесь расширения, очень часто они добавляют свои пункты без учета контекста.
Второй пример, сепараторы, при переупорядочивании меню некоторые сепараторы надо удалить только для определенных контекстов.
И, если будете делать, добавьте примеры, в том числе для контекстов: фрейм, страница, вкладка, адресная строка и textarea (если такой есть отдельно от .onTextInput).
ps^ и есть ли контексты в закладках панели - папка, отдельныя закладка? Видел расширение которое добавляло свой пункт и туда и туда, а нужно было только для папок.
Отредактировано _zt (15-10-2021 13:27:40)
Отсутствует
_zt
не я пас, не охота это делать, что касается расширений это их проблемы, апи позволяет учитывать контекст, все зависит от разраба расширения.
если не заметили недавно обновил ваши скрипты
https://forum.mozilla-russia.org/viewto … 24#p784824
https://forum.mozilla-russia.org/viewto … 55#p783755
Отсутствует
Vitaliy V.
SidebarTabs обновлял, там беда со сплиттером
оставил так и выкинул after
#st_splitter { -moz-appearance: none !important; appearance: none !important; background-color: var(--chrome-content-separator-color, rgba(127,127,127,.5)) !important; background-clip: content-box !important; border-inline: 1px solid transparent !important; min-width: 3px !important; margin-inline: -1px !important; position: relative !important; z-index: 2 !important; -moz-box-ordinal-group: ${this.ST_RIGHT ? "100" : "0"} !important; -moz-box-orient: vertical !important;
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="16" height="16"><path d="M4 1C1.804688 1 0 2.800781 0 5L0 15C0 17.195313 1.804688 19 4 19L6.3125 19L8.0625 23.375C8.207031 23.765625 8.582031 24.027344 9 24.027344C9.417969 24.027344 9.792969 23.765625 9.9375 23.375L11.6875 19L22 19C24.195313 19 26 17.195313 26 15L26 5C26 2.800781 24.195313 1 22 1 Z M 4 3L22 3C23.117188 3 24 3.882813 24 5L24 15C24 16.113281 23.113281 17 22 17L11 17C10.589844 16.996094 10.214844 17.242188 10.0625 17.625L9 20.28125L7.9375 17.625C7.785156 17.242188 7.410156 16.996094 7 17L4 17C2.886719 17 2 16.113281 2 15L2 5C2 3.882813 2.882813 3 4 3Z" fill="#D0D0D0" /></svg>
Отредактировано _zt (16-10-2021 11:38:37)
Отсутствует
оставил так и выкинул after
надо только добавил
border: none !important;
background: none !important;
отображение заголовка перед адресом более удобно, как их местами поменять?
// el.title = title = `${href}${title === "" ? "" : `\nTitle: ${title}`}`;
el.title = title = `${title === "" ? "" : `Title: ${title}\nUrl: `}${href}`;
Но сначала обновите все полностью, я там изменил немного
Отредактировано Vitaliy V. (16-10-2021 14:20:10)
Отсутствует
Dumby Не могли бы пожалуйста поправить вот этот скрипт для 94.0
(async id => ({ delay: 2e3, get limit() { var mb = 1024 * 1024; delete this.limit; return this.limit = this.notMulti ? 770 * mb // not multiprocess, 770MB : 1.50 * 1024 * mb; // multiprocess, 1.50GB }, xul: ` <hbox id="${id}" value="ram" tooltiptext="ЛКМ: Очистить Память" > <label id="${id += "-label"}"/> </hbox> `, css: ` min-height: 17px !important; height: 17px !important; border-radius: 3px !important; padding: 2px 5px 0px !important; font-family: Tahoma !important; color: SaddleBrown !important; font-size: 15px !important; margin-bottom: 2px !important; margin-right: 1px !important; margin-left: 3px !important; `, launch() { var file = Services.dirsvc.get("ProfD", Ci.nsIFile); ["memreduct", "start.vbs"].forEach(file.append); (this.launch = file.launch)(); }, 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(this.xul); this.click = e => e.button || this.launch(); this.notMulti = !Services.appinfo.browserTabsRemoteAutostart; this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); (this.observe = async win => { this.timer.cancel(); await new Promise(win.requestAnimationFrame); var clone = win.document.importNode(df, true); var hbox = clone.firstChild; win.document.getElementById("page-action-buttons").append(clone); hbox.onclick = this.click; hbox.style.cssText = this.css; hbox.firstChild.style.setProperty("margin", "0", "important"); this.notify(); })(win); }, async notify() { var info = await ChromeUtils.requestProcInfo(); var bytes = info.residentSetSize; for(var child of info.children) bytes += child.residentUniqueSize; 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) win.document.getElementById(id).value = this.val; //this.notMulti && bytes > this.limit && this.launch(); }, mgb: bytes => bytes < 1073741824 ? String(Math.round(bytes / 1048576)) : (bytes / 1073741824).toFixed(2) }).init("browser-delayed-startup-finished"))("ucf-mem-indicator");
Отсутствует
поправить вот этот скрипт для
94.0
Заменить residentSetSize и residentUniqueSize на memory
как добавить двойной клик на UCF-кнопку, чтобы вместе с ним не срабатывало событие "click" ?
скрытый текстВыделить кодКод:
try { CustomizableUI.createWidget({ id: "add-additional-personaltoolbar-button", type: "custom", localized: false, label: "Панели, Папки", tooltiptext: `ЛКМ: ★ Закладки\n…+ Alt Домашняя папка ПКМ: ⟳ История\n…+ Alt Папка установки СКМ: Папка профиля\n…+ Alt user_chrome_files`, onBuild(doc) { var trbn = doc.createXULElement("toolbarbutton"); trbn.id = this.id; trbn.tooltipText = this.tooltiptext; trbn.label = this.label; trbn.className = "toolbarbutton-1 chromeclass-toolbar-additional"; trbn.setAttribute("context", false); trbn.style.setProperty("list-style-image", `url("chrome://user_chrome_files/content/vertical_top_bottom_bar/svg/bookmark-16.svg")`, "important"); trbn.addEventListener("dblclick", function(e) { e.view.alert("DBL Click"); }, false); trbn.explorer =(dir, subdir = undefined)=> { var dirs = Services.dirsvc.get(dir, Ci.nsIFile); if (subdir) dirs.append(subdir); if (dirs.exists()) dirs.launch(); }; trbn.bar =(bar)=> { var win = Services.wm.getMostRecentWindow("navigator:browser"); if ("SidebarUI" in win) win.SidebarUI.toggle(bar); else if ("toggleSidebar" in win) win.toggleSidebar(bar); }; trbn.addEventListener("click", function(e) { if (e.button == 0) e.altKey ? trbn.explorer("Home") : trbn.bar("viewBookmarksSidebar") else if (e.button == 1) e.altKey ? trbn.explorer("UChrm", "user_chrome_files") : trbn.explorer("ProfD") else if (e.button == 2) e.altKey ? trbn.explorer("GreD") : trbn.bar("viewHistorySidebar") }, false); return trbn; }, }); } catch(e) {}
С помощью таймаута наверно, как же ещё.
(async (bar, exp, tid, self) => CustomizableUI.createWidget(self = { label: "Панели, Папки", tooltiptext: [ "ЛКМ: ★ Закладки\n…+ Alt Домашняя папка", "ПКМ: ⟳ История\n…+ Alt Папка установки", "СКМ: Папка профиля\n…+ Alt user_chrome_files" ].join("\n"), id: "add-additional-personaltoolbar-button", localized: false, onCreated(btn) { btn.onclick = this.click; btn.style.setProperty("list-style-image", "url(chrome://user_chrome_files/content/vertical_top_bottom_bar/svg/bookmark-16.svg)", "important"); }, exec(num, win) { tid = null; self[num](win); }, context: win => win.document.getElementById(self.id) .dispatchEvent(new win.MouseEvent("contextmenu", self.a)), a: {__proto__: null, bubbles: true, screenX: 0, screenY: 0}, click(e) { if (e.detail > 2) return; var n2 = e.button != 2; var dbl = e.detail == 2; var num = 16 * e.button + 8 * e.ctrlKey + 4 * e.shiftKey + 2 * e.altKey + dbl; if (!self[num]) { if (n2) return; num = "context"; for(var p in self.a) self.a[p] = e[p]; } n2 || e.preventDefault(); var win = e.view; if (dbl) tid &&= win.clearTimeout(tid), self[num](win); else tid = win.setTimeout(self.exec, 300, num, win); }, 0: w => bar(w, "viewBookmarksSidebar"), // ЛКМ 2: () => exp("Home"), // Alt+ЛКМ 16: () => exp("ProfD"), // СКМ 18: () => exp("UChrm", "user_chrome_files"), // Alt+СКМ 32: w => bar(w, "viewHistorySidebar"), // ПКМ 34: () => exp("GreD"), // Alt+ПКМ 1(win) { // Double Left Click win.alert("DBL Click"); }, 33(win) { // Double Right Click win.alert("DBL Right Click"); }, 29(win) { // Ctrl + Shift + Double Middle Click win.alert("Ctrl + Shift + DBL Middle Click"); }, }))( (win, bar) => win.SidebarUI.toggle(bar), (dir, sub) => { dir = Services.dirsvc.get(dir, Ci.nsIFile); sub && dir.append(sub); dir.exists() && dir.launch(); } );
Отсутствует
Заменить residentSetSize и residentUniqueSize на memory
Большое Вам Спасибо!!!
Отсутствует
Vitaliy V.
Подскажите пожалуйста, как в этом скрипте запретить AutoPopup на некоторых кнопках? И спасибо за скрипт!
Add, вроде получилось что хотел, удалил из скрипта часть кода: this.ExtensionParent.WebExtensionPolicy.getByID(id).extension . Правильно ли я это сделал? Нужно было отключить AutoPopup значков расширений.
Add, и ешё вопрос, для чего нужен этот скрипт?
Отредактировано kokoss (12-11-2021 09:54:23)
Win7
Отсутствует
Dumby - Спасибо, скрипт очень компактный и крутой, но в двойной клик на UCF-кнопке правый клик мыши работает неверно.
Вместе с правым кликом в MacOS и вероятно Linux открывается контекстное меню панели, пробовал отключить и не получилось:
var reset = e => e.target.linkedObject = this; var id, lo = {click: e => n2 || reset(e)}; var lin = /macos|linux/.test(e.view.AppConstants.platform); var stop = e => reset(e) && e.preventDefault(); lo.contextmenu = lin ? e => e.ctrlKey || e.shiftKey ? 0 : stop(e) : stop; n2 || reset(e) && e.preventDefault(); ……
Dumby - ещё просьба по твоему скрипту перехвата кликов на кнопках > добавить Двойной клик (у меня не удалось):
Конкретно - добавить двойной клик на "PanelUI-menu-button" (строка 133) и по возможности на "downloads-button"…
Второе (если это возможно) > изменить способ перехвата кнопок со стандартного addEventListener на такой же «продвинутый», как и в новом скрипте,
то есть способом: var num = 16 * e.button + 8 * e.ctrlKey + 4 * e.shiftKey + 2 * e.altKey + dbl;
(async (id, func) => { // дополнительные клики на downloads-button, PanelUI-menu для custom_script_win.js await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"), pui = document.getElementById("PanelUI-menu-button"); if (!btn) return; btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +` ПКМ: Сохранить как единый html всё | выделенное на странице …+ Shift Обзор папки [Загрузки]\n Ролик: Сохранить как файл .txt …+ Shift Сайт: графика Вкл/Выкл\n Колёсико на рисунке: ➜ Сохранить Двойной клик: найти Похожие фото`, PanelUI_help = `Браузер Firefox, версия ${Services.appinfo.platformVersion}\n Колёсико: Развернуть | окно …+ Alt Полный экран Правый клик ⇲ Свернуть …+ Shift Закрыть ✕ …+ Alt Персонализация`; var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } }, showInStatusPanel = (info, time = 5000) => { var win = Services.wm.getMostRecentWindow("navigator:browser"); StatusPanel = win.StatusPanel; if (StatusPanel.update.tid) clearTimeout(StatusPanel.update.tid) else { var {update} = StatusPanel; StatusPanel.update = () => {}; StatusPanel.update.ret = () => { StatusPanel.update = update; StatusPanel.update(); } } StatusPanel.update.tid = setTimeout(StatusPanel.update.ret, time); StatusPanel._label = info; }, saveSelectionToTxt = async () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = id + ":Save:GetSelection"; var receiver = msg => { var title = document.title || gBrowser.selectedTab.label; var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\n\n" + msg.data), title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt', null, false, true, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args) && showInStatusPanel("√ текст сохранён: " + title.slice(0, 60)); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}, 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("saveSelectionToTxt", res); } var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); }, // end save = async () => { // автор: Лекс, правка: Dumby, Dobrov (пути сохранения HTML) var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; if (typeof IOUtils != "object") { // Firefox 78 ESR var {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm"); var PathUtils = {join: (...args) => OS.Path.join(...args)}; var IOUtils = {writeUTF8: (path, txt) => OS.File.writeAtomic(path, new TextEncoder().encode(txt))}; } var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = (type) => { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.slice(0, type).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=|https?:\/\/|www\.|\/.*/g,''); return host.replace(/^ru\.|^m\.|forum\./,'').replace(/^club\.dns/,'dns'); } var msgListener = async msg => { var [fileContent, fileName] = msg.data, dir; try {dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(0, 2); // Dir/subdir: пусто|0 title|1 домен arr[1] = (arr[1] == "0") ? Title(100) : (arr[1] == "1") ? Title(-1) : ""; // имя вкладки или домен arr.forEach(dir.append); // для ucf_save.dirs = "_Web||_Pics|1" HTML сохранится в папку [Загрузки]/_Web/имя вкладки dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(dir.path); dir.append(fileName); await IOUtils[write](dir.path, fileContent) && showInStatusPanel("√ страница записана: " + fileName.slice(0, 60)); var d = await Downloads.createDownload({ source: "about:blank", target: FileUtils.File(dir.path)}); // Fake download (await Downloads.getList(Downloads.ALL)).add(d); d.refresh(d.succeeded = true); // кнопка Загрузки мигает } messageManager.addMessageListener(msgName, msgListener); addDestructor(() => messageManager.removeMessageListener(msgName, msgListener)); var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); }, // end save listener = e => { var trg = e.target; // Downloads Clicks if (e.button == 1) { if (e.shiftKey) { // СКМ + Shift if ( prefs.getIntPref("permissions.default.image", 1) == 1) prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)" else prefs.setIntPref("permissions.default.image", 1), trg.style.filter = ""; BrowserReload(); } else // СКМ Click saveSelectionToTxt(); // сохранить .txt } else if (e.button == 2) { if (e.shiftKey) Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError) // Обзор папки «Загрузки» else // ПКМ Click save(); // Single HTML } }, listener_pui = e => { // PanelUI-menu Clicks if (e.button == 1) { if (e.altKey) window.BrowserFullScreen() else if( window.windowState != window.STATE_MAXIMIZED ) window.maximize() else window.restore(); } else if (e.button == 2) if (e.altKey) return else { e.stopPropagation(); (e.shiftKey) ? window.close() : window.minimize(); } }, // end Clicks keydown_win = e => { // нажатие клавиш if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return; var singlesave = document.getElementById(save_ex); // SingleSave singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID }, {prefs, dirsvc} = Services, tmax = btn.tooltipText.split("\n")[0].length, save_ex = "_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"; btn.setAttribute("context", "event.stopPropagation()"); prefs.setBoolPref("browser.download.autohideButton", false); // не скрывать кнопку Загрузки (async () => { // SingleSave - дополнить подсказку setTimeout((but = document.getElementById(save_ex))=> { if (but) btn.tooltipText = btn.tooltipText + '\n\nAlt⇧S нажатие SingleSave'; if (!/Закрыть/.test(pui.tooltipText)) pui.tooltipText = PanelUI_help; }, 9000); // после запуска ждать от 3 сек })(); btn.addEventListener("click", listener), pui.addEventListener("click", listener_pui); window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { btn.removeEventListener("click", listener), pui.removeEventListener("click", listener_pui); window.removeEventListener("keydown", keydown_win); }}; ucf.unloadlisteners.push(id); })("downloads-button-click-listener", ({io, focus}) => { // SingleHTML не сохраняет svg графику var resolveURL = function (url, base) { try { return io.newURI(url, null, io.newURI(base)).spec; } catch {} }, 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) {} } }, encodeImg = function (src, obj) { var canvas, img, ret = src; if (/^https?:\/\//.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((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png')); } catch (e) {}; if (img != obj) img.src = 'about:blank'; }; return ret; }, toSrc = function (obj) { var strToSrc = function (str) { var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'}; while (chr = str.charAt(i++)) { ret += meta[chr] || chr; }; return '\x22' + ret + '\x22'; }, 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 (obj.hasOwnProperty(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) ? String(obj) : 'null'; case 'Object': return objToSrc(obj); case 'String': return strToSrc(obj); default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null'; } }, mainWin = {}; focus.getFocusedElementForWindow(content, true, mainWin); mainWin = mainWin.value; var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location; var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/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, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href); return prev + encodeImg(url) + next; }); 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) != '#') 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), meta = doc.createElement('meta'), sheets = doc.styleSheets, title = doc.getElementsByTagName('title')[0]; meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (unsafeWin) { if ('$' in unsafeWin) return; var f = doc.createElement('iframe'); f.src = 'about:blank'; f.setAttribute('style', '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 unsafeWin) { if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue; try { str = toSrc(unsafeWin[name]); if (!/\{\s*\[native code\]\s*\}/.test(str)) { script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n')); } } catch (e) {}; }; f.parentNode.removeChild(f); if (script.childNodes.length) this.nextSibling.appendChild(script); }; head.copyScript(win.wrappedJSObject || win); 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))) { var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href); if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url); return prev + url + next; }); style.appendChild(doc.createTextNode(css + '\n')); } } else { this.copyStyle(rule.styleSheet); } } } catch(e) { if (s.ownerNode) style = s.ownerNode.cloneNode(false); }; this.appendChild(style); }; for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]); head.appendChild(doc.createTextNode('\n')); var doctype = '', dt = doc.doctype; if (dt && dt.name) { doctype += '<!DOCTYPE ' + dt.name; if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22'; if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22'; doctype += '>\n'; }; var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop()); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).trim(); fileName += "_" + new Date().toLocaleDateString('ru', {day: 'numeric', month: 'numeric', year: '2-digit'}) +'-'+ new Date().toLocaleTimeString().replace(/:/g, "։"); if (!/\.html?$/.test(fileName)) fileName += '.html'; sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]); }); // END hookClicks
В скрипт Quick Toggle about:config тоже добавить Двойной клик на кнопке (в коде есть ещё Долгое нажатие)
// Quick Toggle Быстрое переключение параметров about:config для custom_script.js (async (name, id, func) => { // https://forum.mozilla-russia.org/viewtopic.php?pid=789824#p789824 if (name == "Object") return CustomizableUI.createWidget(func()); var win = name == "Window", g = Cu.import("resource://gre/modules/Services.jsm", {}); if (g[id]) {if (win) return;} else g[id] = func(); if (win) return CustomizableUI.createWidget(g[id]); addDestructor(r => r[5] == "e" && delete g[id]); g[id].onCreated(this); // BEGIN QuickToggle… })(this.constructor.name, "ToggleAboutConfig", () => { var help = `клик+Alt Библиотека закладок …+ Shift ± zoom Текст/страница ։нажать Антизапрет ⇆ proxy\n ПКМ Меню быстрых настроек ։нажать © Краткая справка …+ Alt Опции about:config\n СКМ Вкладка «Топ сайтов» …+ Alt Восстановить вкладку …+ Shift ● Захват цвета, Zoom ։нажать Консоль браузера\n ⟳ Обновить ↯ Перезапуск ЛкМ: Левый клик, СкМ: Колёсико нажать: долгий клик мыши ≥1 сек`, // ЛКМ+Alt+Shift: настройки User Chrome Files. свободные hotkeys: СКМ+Alt ЛКМ+Alt+⇧ Нет в подсказке: ЛКМ панель Журнала, СКМ+Shift – Пипетка help_ucf = ['chrome://user_chrome_files/content/help.html', 'http://forum.puppyrus.org/index.php?topic=22762'], // Ctrl+Click или правый клик - сброс параметра по-умолчанию // клик по параметру с Shift блокирует авто-закрытие меню // строки с userAlt имеют шрифт italic // refresh: false - reload current tab, true - reload current tab skip cache // restart: false - restart browser, true - restart browser with confirm // Разделитель: Имя меню "—,⟳,↯" Опция, ⟳ обновить страницу, ↯ перезапуск браузера // иконки равны ключам: userChoice:зелёный, userAlt:жёлтый, userPro:серый, нет userChoice:серый, ни один:красный // пути сохранения Html/Pics в [Загрузки]/dir/subdir заданы в ucf_save.dirs="_Html dir|subdir|_Pics dir|subdir" : пусто|0 заголовок|1 домен // ucf_save.dirs="_Web||_Pics|1" save Html: [Загрузки]/_Web/имя страницы.html, save Pic: [Загрузки]/_Pics/имя вкладки/имя картинки {prefs, dirsvc} = Services, db = prefs.getDefaultBranch(""), my_vpn = "https://antizapret.prostovpn.org/proxy.pac", icon_vpn = "hue-rotate(270deg) brightness(95%)", menuactive = (AppConstants.platform == "macosx") ? '#e8e8e8' : '#124', // текст, подсвеченный курсором xul_ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", fonts = ["Arial","Cantarell","DejaVu Sans","Roboto","PT Serif","Segoe UI","Ubuntu","Cambria","Fira Sans","Georgia","Noto Sans","Calibri","Times","системный"], font_pref = (font) => { return font.map(function(name) { // массив с вложениями return (name == font[font.length -1]) ? ["", name,,, `prefs.setIntPref("browser.display.use_document_fonts", 1)`] : [name, name,,, `prefs.setIntPref("browser.display.use_document_fonts", 0)`]; }); }, fontserif = font_pref(fonts), fontsans = [["PT Sans","PT Sans"], ...fontserif], dw; // путь загрузки try {dw = prefs.getComplexValue("browser.download.dir",Ci.nsIFile);} catch {dw = dirsvc.get("DfltDwnld", Ci.nsIFile);}; var secondary = [{ // pref … [apref, lab, akey, hint, js-code] pref: ["dom.disable_open_during_load", "Всплывающие окна"], userChoice: 2, userAlt: true, values: [[true, "Блокировать"], [false, "Разрешить"]] },{ pref: ["browser.safebrowsing.downloads.remote.block_dangerous", "Опасные файлы, сайты",,"browser.safebrowsing.downloads.remote.block_dangerous_host"], userChoice: true, userAlt: false, values: [[true, "Отключить",,,`prefs.setBoolPref('browser.safebrowsing.downloads.remote.block_dangerous_host',true)`], [false, "Загружать",,,`prefs.setBoolPref('browser.safebrowsing.downloads.remote.block_dangerous_host',false)`]] },{ pref: ["permissions.default.image", "Загрузка графики"], userChoice: 1, userAlt: 3, refresh: true, values: [[1, "Разрешена"], [3, "Только с сайта"], [2, "Отключить"]] },{ pref: ["ucf_save.dirs", `Сайт|Графика`,,`\nПути сохранения страниц | графики\n[Загрузки] — папка по-умолчанию${dw ? ":\n"+ dw.path : ""}`], userChoice: "_Сайты||_Фото|1", userAlt: "", userPro: "_Web||_Images|1", values: [ ["", "папка [Загрузки]"], // subdir: пусто | 0 заголовок | 1 домен [`_Сайты||_Фото|1`, "_Сайты|_Фото/имя…"], // _Web/host|_Pics/title [`_Сайты||_Рисунки|1`, "_Сайты|_Рисунки/…"], [`_Web||_Images|`, "_Web|_Images"], [`_Web||_Images|1`, "_Web|_Images/имя"], [`_Web||_Photo|1`, "_Web|_Photo/имя"], [`_Web|1|_Pics|0`, "_Web/сайт|_Pics/…"], [`_Web|1|_Pics|`, "_Web/сайт|_Pics"], [`_Web|1|_Images|0`, "ввести свои пути"]] // здесь нужно открыть about:config },null,{ pref: ["network.cookie.cookieBehavior", "Получать куки",, "\nПерсональные настройки посещённых сайтов"], userChoice: 3, userAlt: 0, userPro: 4, refresh: false, values: [[0, "со всех сайтов"], [3, "кроме не посещённых"], [4, "кроме трекеров"], [1, "кроме сторонних"], [2, "никогда"]] },{ pref: ["network.proxy.autoconfig_url", "Прокси (VPN) URL", "п"], userChoice: my_vpn, userAlt: "127.0.0.1", userPro: "", refresh: true, values: [ ["", "сброшен", ""], [my_vpn, "АнтиЗапрет", "1", "\nНадёжный доступ на заблокированные сайты\n«Режим прокси» меняется на 2", `prefs.setIntPref('network.proxy.type', 2); node.parentNode.parentNode.style.filter = icon_vpn;`], ["https://git.io/ac-anticensority-pac", "ac-anticensority", "2"], // ["localhost", "Tor Browser", "4", "Только для Linux, MacOS\nУстановите сервис: «tor»"], [prefs.getStringPref("user.pacfile", "file:///etc/proxy.pac"), "user .pac файл", "3"], // нужен диалог выбора pac-файла ["127.0.0.1", "local host", "0",, `prefs.setIntPref('network.proxy.type', 0); node.parentNode.parentNode.style.filter = '';`]] },{ pref: ["network.proxy.type", "Режим прокси", "р"], userChoice: 0, userAlt: 2, refresh: true, values: [ [0, "Без прокси", "0", "по-умолчанию"], [5, "Системные (из IE)", "5"], [2, "Автонастройка", "2", "about:config - user.pacfile"], [1, "Ручная настройка", "1", "Используется network.proxy.autoconfig_url"], [4, "Автоопределение", "4"] ] },{ // pref: ["network.proxy.share_proxy_settings", "Все протоколы через прокси"], userAlt: true, refresh: true, // values: [[true, "Да", "", "Прокси для всех протоколов при ручной настройке"], [false, "Нет"]] // },{ pref: ["network.trr.mode", "DNS поверх HTTPS",, "\nШифрование DNS-трафика для\nзащиты персональных данных"], userChoice: 1, userAlt: 2, userPro: 5, refresh: true, values: [ [0, "по-умолчанию", "0"], [1, "автоматически", "1", "используется DNS или DoH, в зависимости от того, что быстрее"], [2, "DoH, затем DNS", "2"], [3, "только DoH", "3"], [4, "DNS и DoH", "4"], [5, "отключить DoH", "5"] ] },null,{ pref: ["browser.zoom.full", "Масштабировать"], userChoice: false, userAlt: true, values: [[true, "всю страницу"], [false, "только текст"]] },{ pref: ["font.name.sans-serif.x-cyrillic", "Шрифт без засечек ",,"\nТакже влияет на всплывающие подсказки\nСистемный: загрузка шрифтов документа"], userAlt: "", values: fontsans },{ pref: ["font.name.serif.x-cyrillic", "Шрифт с засечками"], userAlt: "", values: fontserif },{ pref: ["image.animation_mode", "Анимация изображений"], userChoice: "none", userAlt: "normal", refresh: true, values: [["none", "Выключена"], ["normal", "По циклу"], ["once", "Единожды"]] },null,{ pref: ["media.autoplay.default", "Авто-play аудио/видео"], userChoice: 0, userAlt: 2, userPro: 5, refresh: true, values: [ [0, "Разрешить", "0"], [2, "Спрашивать", "2"], [1, "Запретить", "1"], [5, "Блокировать", "5"]] },{ pref: ["media.autoplay.blocking_policy", "Автозапуск (политика)"], userChoice: 1, userAlt: 2, refresh: true, values: [[1, "Временная", "1"], [2, "По действию", "2"], [0, "Постоянная", "0"]] },{ pref: ["gfx.webrender.all", "Аппаратное ускорение графики"], userChoice: true, refresh: true, values: [[true, "Да"], [false, "Нет"]] },{ pref: ["gfx.webrender.force-disabled", "Web render disabled", , "gfx.webrender.compositor.force-enabled\n\nАппаратная отрисовка страниц видеокартой.\nотключите при разных проблемах с графикой"], userChoice: false, restart: true, values: [ [true, "Да",,, `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", false)`], [false, "Нет",,, `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", true)`]] },null,{ pref: ["network.http.sendRefererHeader", "Referer: для чего"], userChoice: 2, userAlt: 1, values: [[0, "Ни для чего", "0"], [1, "Только ссылки", "1"], [2, "Ссылки, графика", "2"]] },{ pref: ["dom.storage.enabled", "Локальное хранилище",, "\nСохранение персональных данных, по\nкоторым вас можно идентифицировать"], userChoice: false, userAlt: true, values: [[true, "Разрешить"], [false, "Запретить"]] },{ pref: ["privacy.resistFingerprinting", "Изоляция Firstparty-Fingerprint", ,"privacy.firstparty.isolate\n\nЗащита данных пользователя также\nзапрещает запоминать размер окна"], userChoice: false, values: [[true, "Да", , "Защита от слежки",`prefs.setBoolPref('privacy.firstparty.isolate', true);`], [false, "Нет", , "Защита от слежки",`prefs.setBoolPref('privacy.firstparty.isolate', false);`]] },{ pref: ["media.peerconnection.enabled", "WebRTC ваш реальный IP"], userChoice: false, values: [[true, "Выдать"], [false, "Скрыть"]] },null,{ pref: ["browser.tabs.remote.force-enable", "Многопоточный режим вкладок",,"\nПо-умолчанию режим разрешён"], userChoice: null, userAlt: true, userPro: false, values: [[true, "Да"], [false, "Нет"]] },{ pref: ["javascript.enabled", "Выполнять скрипты Java",,"\nПоддержка интерактивных сайтов (и рекламы)"], userChoice: true, refresh: true, values: [[true, "Да"], [false, "Нет"]] },{ pref: ["browser.cache.disk.capacity", "Кэш браузера",,"browser.cache.memory.enable\n\ncache.memory.max_entry_size:\nдиск и память: 5120\nтолько память: -1"], userChoice: 1048576, userAlt: 0, values: [ [1048576, "Диск и Память",,, `prefs.setBoolPref("browser.cache.memory.enable", true); prefs.setBoolPref("browser.cache.disk.enable", true); prefs.setIntPref('browser.cache.memory.max_entry_size', 5120)`], [0, "только Память",,, `prefs.setBoolPref("browser.cache.memory.enable", true); prefs.setBoolPref("browser.cache.disk.enable", false); prefs.setIntPref('browser.cache.memory.max_entry_size', -1)`], [2097152, "только Диск",,, `prefs.setBoolPref("browser.cache.memory.enable", false); prefs.setBoolPref("browser.cache.disk.enable", true)`]] },{ pref: ["dom.enable_performance", "Статус загрузки страницы",,"\nПередача данных разрешит определять\nфакт использования прокси-сервера"], userAlt: true },{ pref: ["general.useragent.override", "User Agent",,"\nот user-агент зависит вид сайтов"], userChoice: null, userAlt: "Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0", userPro: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0", refresh: true, values: [ (arr => { var pref = "general.useragent.override"; var has = prefs.prefHasUserValue(pref); if (has) { var val = prefs.getStringPref(pref); prefs.clearUserPref(pref); } var ua = Cc["@mozilla.org/network/protocol;1?name=http"] .getService(Ci.nsIHttpProtocolHandler).userAgent; // текущий юзерагент has && prefs.setStringPref(pref, val); var find = node => node.pref && node.pref.pref == pref; var redef = (doc, hint) => { var popup = doc.getElementById("ToggleAboutConfig-secondaryPopup"); var menuitem = Array.from(popup.children).find(find).menupopup.firstChild; menuitem.tooltipText = hint ? ua + "\n" + hint : ua; menuitem.setAttribute("oncommand", `event.stopPropagation(); this.closest("toolbarbutton").linkedObject.contextmenu({ preventDefault: Boolean, target: this.parentNode.parentNode });` ); } Object.defineProperty(arr, "0", {enumerable: true, get() { if (Components.stack.formattedStack.includes("createRadios")) { var win = Services.wm.getMostRecentWindow("navigator:browser"); win.setTimeout(redef, 0, win.document, this[3]); } else return ""; }}); return arr; })([null, "По-умолчанию"]), ["Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0", "Firefox Android9"], ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0", "Firefox 68 MacOSX"], ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36", "Chrome61 Win10"], ["Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0", "Firefox 56"], ["Mozilla/5.0 (X11; Linux x86_64; rv:56.0) Gecko/20100101 Firefox/56.0", "Firefox 56 Linux"], ["Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)", "MSIE 6.0 Windows"], ["Mozilla/5.0 (Linux; Android 7.0; PLUS Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36", "Chrome61 Android7"], ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", "Safari 6 MacOSX"], ["Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12 Version/12.16", "Opera12 W8"], ["Mozilla/5.0 (Linux; Android 5.1.1; SM-G928X Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36", "Samsung Galaxy S6"], ["Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73 (KHTML, like Gecko)", "Playstation 4"], ["Xbox (Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", "Xbox One (mobile)"], ["Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", "Microsoft Lumia 950"], ["Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; GT-I8350)", "Windows Phone"], ["Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "GoogleBot"]] },{ pref: ["browser.cache.disk.free_space_soft_limit", "Неактивные вкладки",, "\nПри запуске загружаются все вкладки,\nэто может замедлить работу браузера.\nОптимально - Выгружать старые табы."], userChoice: 5121, userAlt: 5120, userPro: 5122, values: [ [5120, "Загружать",,, `prefs.setBoolPref("browser.sessionstore.restore_on_demand", true); prefs.setBoolPref("browser.tabs.unloadOnLowMemory", false)`], [5121, "Оптимально",, "Выгружать старые вкладки, экономя память", `prefs.setBoolPref("browser.sessionstore.restore_on_demand", true); prefs.setBoolPref("browser.tabs.unloadOnLowMemory", true)`], [5122, "Не загружать",,, `prefs.setBoolPref("browser.sessionstore.restore_on_demand", false); prefs.setBoolPref("browser.tabs.unloadOnLowMemory", true)`]] }]; return { label: "Quick Toggle Settings", id: "ToggleAboutConfig", tooltiptext: help, localized: false, image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADhUlEQVR4AaWUIYzsNhCG91WVelKfqoWrpwMLFxQYGhoGBgYGBgYGGhoGBhoGGhoaBhoaGhqcdIFhf+dGt2n09rpq1ZE+2bHl+eyxd0993yVjNIwxq9F6/WjtaNd5nBnq85g2PMeMo8EwDEUI0Z7+jm/EY2it87ZtuAf1EUqAzZZZcuCxnyOlBFoLkuhnkgdBjBG36YqzP+EaTqgmSckyjrGuK8paWGythVLKfv/9t/O/OkEIC6pZoskCfanQuQYLSTm2/ZQkjSil8Pc8z6iqyp/P58tn2l92wWjGnEuG9gO6uUVtaygnMOQaU+nR+hotjfeugwmaHNv9pJzYOYcQAp+kbVv3cBJrbA45QIQLVLyizRI6t5R8gC0aY+nQZYWK5lT4E3nNn2XaiJX5PAmLXl9fuweBz54X97mCoYR21SwYc8+yjsbrKKGCvAu4TDnne3IO7z2oTP1RwCVKJXGJ+rlHaxu0ocZQahLWaO4lmjtov5eI7yDZFnFqWXQUPL1kFzwaV3GpmqQo+cMlc1li9MBCyacbUnC74MePy3NBiAukFRDLBTd/QWUVUk44BJclx5lMPVYvEJ3e7+CZYN+dSw5TmpiQA1/oPTYip4SV5gANRIloa5Ku/LKeCqhljrHmhLzMSIFYPGLw3N/KCMAAuUYeBUkXLDE9vCIW0K45MbXYoW/aFZdiyxYoM9Y0oiwGaxyBjcAElAHFCETTw40T6tvVXP749eUfBe/v78xdlJaAvNwTGmo1YYiRIME6YosGxWnEaUDQbXFt5adazKO6DEcBX97b29tRAq4tl0XzpZKAkzJFEx31iY1bYuANIBtkW6engl1CRD6JAYrh5Mg90QBRAYsgbkAkksS2VJvT0jXqUj0R7HzOrViCQ1kGILZAUAQl9AxLVl/BDTI24tyK1+/8n/SVYOexVDMlaQAvAHdjOHmQLPS6grxe9ZeviDgKuM/jzIZM38kbbE4ekguGBV7CDwLXy1k/vKJtPf4ODmAPFhbf74mLa5DmFltQwCKJCskIiPNpprTi42+bRcaYTIv3Z/oVhcgpUrIOm1NYbIvZWtjJIliSLgpIFdZZohMvgQRqFyilRimFF0I4+QXik7ZR3vRqqSsRpJSO1jEf/bFXGUsNhAq2uWS63eb0X+NjN/uuforb9UXYXjqEBkkLyMupP85/I/53fDzLsZV6am8zCdR9/C+4MZTbZ2zc/gAAAABJRU5ErkJggg==", onCreated(btn) { btn.setAttribute("image", this.image); var doc = btn.ownerDocument; btn.btn = true; btn.domParent = null; btn.popups = new btn.ownerGlobal.Array(); this.createPopup(doc, btn, "secondary", secondary); this.createCloseMenusOption(doc, btn); if (prefs.getIntPref('network.proxy.type') == 2) btn.style.filter = icon_vpn; // btn.style.cssText = "background-image: -moz-linear-gradient(#c0c8c0, #c0c8c0, #c0c8c0) !important"; btn.linkedObject = this; for(var type of ["command", "contextmenu", "mousedown", "auxclick"]) // события btn.setAttribute("on" + type, `linkedObject.${type}(event)`); this.addSheet(btn); }, addSheet(btn) { var cb = Array.isArray(btn._destructors); var id = cb ? btn.id : "ToggleAboutConfig"; var css = `#${id} menu[_moz-menuactive] { color: ${menuactive} !important; }`; var args = [ "data:text/css;charset=utf-8," + encodeURIComponent(css), Ci.nsIDOMWindowUtils.USER_SHEET ]; if (cb) var destructor = function() { this.removeSheetUsingURIString(...args); } var add = b => b.ownerGlobal.windowUtils.loadSheetUsingURIString(...args); (this.addSheet = !cb ? add : btn => { add(btn); btn._destructors.push({destructor, context: btn.ownerGlobal.windowUtils}); })(btn); }, createPopup(doc, btn, name, data) { var popup = doc.createElementNS(xul_ns, "menupopup"); var prop = name + "Popup"; btn.popups.push(btn[prop] = popup); popup.id = this.id + "-" + prop; for (var type of ["popupshowing", "click"]) popup.setAttribute("on" + type, `parentNode.linkedObject.${type}(event)`); 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, hint] = val; pref.pref = apref; pref.lab = lab || apref; if (hint) pref.hint = hint; } 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`]; var map, set = prefs[`set${str}Pref`]; if (pref.hasVals) { for(var [val, , , , code] of obj.values) code && (map || (map = new Map())).set(val, code); if (map) pref.set = (key, val) => { set(key, val); map.has(val) && eval(map.get(val)); // выполнить код } } if (!map) pref.set = set; 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 = "ToggleAboutConfig.closeMenus"; var data = [null, { pref: [pn, "Закрывать меню этой кнопки"], values: [[true, "Да"], [false, "Нет"]] }]; var setCloseMenus = (e, trg = e.target) => { e.stopPropagation(); var {pref, val} = trg, updPopup = true, clear; switch(e.type) { case "command": pref = (trg = trg.closest("menu")).pref; updPopup = false; break; 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: dimgray !important; list-style-image: url(chrome://browser/skin/menu.svg) !important;"; m.setAttribute("oncommand", "setCloseMenus(event)"); m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus; })(doc, btn); }, UserImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAe1BMVEUAAAB1dXV1dXV1dXV1dXV1dXV1dXV1dXV8fHyRkZGfn5+oqKipqamqqqqysrKzs7O6urq8vLy9vb3ExMTFxcXHx8fNzc3Ozs7Pz8/Q0NDY2NjZ2dna2tre3t7g4ODi4uLj4+Pk5OTl5eXn5+fs7Ozv7+/w8PDx8fHy8vLK4aRZAAAACHRSTlMAGFiAiNDw+LBTincAAACRSURBVBgZBcFBTsMADAAwJ20pqjgM+P8TgQua2Nok2AAAAiIzdfcgkOv2/ub357yaIF8+jwgz969nS7He9pnumf22hrSse1d1V/W+LlIc3d1V3d1HCPsHkWjj+5FUTVdVTdcQtmMNkXrMdT/Dur0KYYy/8wqx7QugHucE+bIFmPPZArkuS+qqqwmIzNTdAwAA/zI6Uy+Vzu5KAAAAAElFTkSuQmCC", // серый UserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABGElEQVR4AWKgPgAQSmbgEsNQFB53GHz43GGcioPF4mCxGCwWi8FiMBgMBoPFYOzOPWf2/cv3Z/3P7Wo2W2VQolIJ59zb/grvlfLnO1lWJ7lmwDn2cEbnY3jciF0XSTUqSfKZRCLP4NB9c9tlyrOE4iXUwMAd2OMZHLiPj2O0uUZcWcQXp3jKsQTAuSeODlxm7grEIRmxZZal2EuhOxjEGR24yNwXqHOe5MQsdtVCq72He+DiIfNQYMxGwJRHhdIzPLs4zwViGw4ypF5MGsiYIBLML/t04D49gja7kz4eyEB6yiQCnhG4zDx/xsa30sUL3RMtgXP5jO9+JApt2L+DZ3C+/o2sbv9l5xsNtYBz7B0HS8qUZSZqAwCSaKMMRS9J3wAAAABJRU5ErkJggg==", // зелёный notUserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABDElEQVR4Aa2TK3CEQBBEt6JwdxKJRJ48GRkZiURGxqt4dV5FnkQikSdXIpHIweE6+8KKyf+7Va92qqe770v493MOoUw8JGJizcSslV+Fm3NRWLxrZUMnzaOAGY0dng/DXVnK+kdpGhKXFI4CZjR2ePC+edu0W3eSYieNPQEPGjvhwUuG7FXuuK+b691uX4Sw2obBmkHbwIOXjC+4qY61D+d5Bq89g5eML6hpxvQd8JLxBXk5uxsM3p05vmBcJhfmnrkzbmaHl4wv6KfL5IKuZHbFecZLxhecxiEuiwVX4nBhPHjJvP0j7QtZe5TaWmqqdG8wo7HD8+m/MWHxUMluDym0wYzGDs/fHqb/Pk9WVkDcHStz1AAAAABJRU5ErkJggg==", // красный UserAltImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABAklEQVR4Aa2TKVDEQBREx3sRiUQi8Wpl5MqVSCQyMhIZGYlciVy5cmQkEhk5runHNQf3kapX9ev36w97hX9/xk3ozGCiScDMjuyr8va6D+syd9LdIOkgYGZHhvNhed4FyxdSmswsaQ/M7MiEg9uWO65r6aV1MCOFCnZkOLh0ygPjMgXpvjc7i5f50HORHRkOLp3yQNSR131uYZMPFbAjw8GlUx5IWk5kLJwiGeQMOzIcoFMfiEEFz+IZMHsHOW8PRO0dHMyxIEK9w8FtX8IYBwe3gPQeOcel0377Vt1w/XNwcOm8/SJtLcxI70OG8+m3kevxKihNucjMjgznbz+m/34eAEg4sZItNtjUAAAAAElFTkSuQmCC", // жёлтый regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/, 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 hint = exists ? val : "Эта опция не указана"; if (hint === "") hint = "[ пустая строка ]"; hint += "\n" + pref.pref; if (pref.hint) hint += "\n" + pref.hint; node.tooltipText = hint; var img, alt = "userAlt" in pref && val == pref.userAlt, pro = "userPro" in pref && val == pref.userPro; if (alt) img = this.UserAltImg; if (pro) img = this.UserImg; if ("userChoice" in pref) if (val == pref.userChoice) node.style.removeProperty("color"), img = this.UserChoiceImg; else { node.style.setProperty("color", "#804040", "important"); if (!alt && !pro) img = this.notUserChoiceImg; } node.nextSibling && node.setAttribute("image", img || this.UserImg); // серый значок, если нет userChoice 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}`; } lab = exists ? lab : '['+ lab +']'; // имя = [имя] если преф не существует 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, hint] = 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 (hint) tip += "\n" + hint; menuitem.tooltipText = tip; popup.append(menuitem); } }, openPopup(popup) { var btn = popup.parentNode; if (btn.domParent != btn.parentNode) { btn.domParent = btn.parentNode; if (btn.matches(".widget-overflow-list > :scope")) var 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 && !Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) return; 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); }, 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.BrowserReloadSkipCache() : win.BrowserReload(); } }, maybeClosePopup(e, trg) { !e.shiftKey && prefs.getBoolPref(this.closePref, undefined) && trg.parentNode.hidePopup(); }, 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; } } }, click(e) { if (e.button) return; var trg = e.target, {pref} = trg; if (!pref) return; }, command(e) { // нажатия левой кнопки мыши var trg = e.target, win = e.view; if (trg.btn) { // LMB if (e.shiftKey) e.altKey ? win.openDialog("chrome://user_chrome_files/content/options/prefs_win.xhtml", "user_chrome_prefs:window", "centerscreen,resizable,dialog=no") // Alt+Shift : e.view.ZoomManager.toggleZoom(); // Alt Пипетка else if (e.altKey) e.view.PlacesCommandHook.showPlacesOrganizer("BookmarksToolbar"); // Shift Библиотека Панель закладок else { // LMB Click var bar = e.target.ownerDocument.querySelector("#ucf-additional-vertical-bar") if (bar) { win.setToolbarVisibility(bar, bar.collapsed); bar.collapsed ? win.SidebarUI.hide() : win.SidebarUI.show("viewHistorySidebar"); } else win.SidebarUI.toggle("viewHistorySidebar"); } return; } 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); }, auxclick(e) { // CKM if (e.button != 1 || !e.target.btn) return; if (e.altKey) e.shiftKey ? this.switchToTab(e, "ya.ru") // Alt+Shift : e.view.undoCloseTab() else if (e.shiftKey) this.eyedropper(e.target) else this.switchToTab(e, "about:newtab"); }, contextmenu(e) { // RMB var trg = e.target, win = e.view; if (trg.btn) { if (e.ctrlKey || e.shiftKey) return; if (e.detail == 2) return trg.secondaryPopup.hidePopup(); // меню быстрых настроек ! e.altKey ? this.openPopup(trg.secondaryPopup) : this.switchToTab(e, "about:config"); } else if ("pref" in trg) { this.maybeClosePopup(e, trg); if (trg.pref.user) prefs.clearUserPref(trg.pref.pref), this.maybeRe(trg); } e.preventDefault(); }, mousedown(e) { var reset = e => e.target.linkedObject = this; var id, lo = {command: reset, mousedown: reset, auxclick: e => e.button != 1 || reset(e)}; var lin = /macos|linux/.test(e.view.AppConstants.platform); var stop = e => reset(e) && e.preventDefault(); lo.contextmenu = lin ? e => e.ctrlKey || e.shiftKey ? dsp(e) : stop(e) : stop; var context = lin ? e => e.button == 2 && e.type.endsWith("p") && this.contextmenu(e) : () => {}; var dsp = (e, timeout) => { var trg = e.target; trg.onmouseup = trg.onmouseleave = null; if (timeout) return this.londPress(e); e.view.clearTimeout(id); reset(e); context(e); } (this.mousedown = e => { var trg = e.target; if (!trg.btn) return; trg.linkedObject = lo; trg.onmouseup = trg.onmouseleave = dsp; id = e.view.setTimeout(dsp, 500, e, true); })(e); }, londPress(e) { // удержание кнопки мыши. на второй долгий клик при отпускании сработает действие на обычный клик этой кнопки var trg = e.target, win = e.view; if (e.button == 0) this.switchProxy(e, my_vpn); if (e.button == 1) trg.ownerDocument.getElementById("key_browserConsole").doCommand(); // Консоль браузера if (e.button == 2) { // RMB Long var newURI = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).convertChromeURL(Services.io.newURI(help_ucf[0])); // .spec = file:/// (newURI.QueryInterface(Ci.nsIFileURL).file.exists()) ? this.switchToTab(e, help_ucf[0]) : this.switchToTab(e, help_ucf[1]); } }, switchProxy(e, pac) { if (prefs.getIntPref('network.proxy.type') == 2) { // выключить prefs.setIntPref('network.proxy.type', 0); prefs.setStringPref("network.proxy.autoconfig_url", "127.0.0.1"); e.target.style.removeProperty("filter"); this.showInStatusPanel("\u{1F6A6} Настройки сети - работа без прокси"); // символ Светофор } else { prefs.setIntPref('network.proxy.type', 2); prefs.setStringPref("network.proxy.autoconfig_url", pac); e.target.style.setProperty("filter", icon_vpn, "important"); this.showInStatusPanel("\u{1F6A6} Заблокированные сайты через «АнтиЗапрет»"); // this.Notify('Proxy', 'Работаем через VPN Антизапрет'); } }, showInStatusPanel(info, ms = 5000) { var win = Services.wm.getMostRecentWindow("navigator:browser"); StatusPanel = win.StatusPanel; if (StatusPanel.update.tid) clearTimeout(StatusPanel.update.tid) else { var {update} = StatusPanel; StatusPanel.update = () => {}; StatusPanel.update.ret = () => { StatusPanel.update = update; StatusPanel.update(); } } StatusPanel.update.tid = setTimeout(StatusPanel.update.ret, ms); StatusPanel._label = info; }, eyedropper(trg) { // Пипетка - захват цвета var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm") .require("devtools/client/menus").menuitems .find(menuitem => menuitem.id == "menu_eyedropper"); (this.eyedropper = target => obj.oncommand({target}))(trg); }, Notify(title, text, ms = 3000){ Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService).showAlertNotification(null, title, text, false, '', null, ms); }, switchToTab(e = this, url) { // открыть вкладку | закрыть, если открыта for(var tab of e.view.gBrowser.tabs) if ( tab.linkedBrowser.currentURI.spec == url ) {e.view.gBrowser.removeTab(tab); return;}; // вкладка найдена, закрыть e.view.switchToTabHavingURI(url, true, {relatedToCurrent: true, triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}); } }; }); // END ToggleAboutConfig
Отредактировано Dobrov (06-11-2021 03:53:55)
Отсутствует
Вместе с правым кликом в MacOS и вероятно Linux открывается контекстное меню панели
Посмотрел на Mint, и точно, так и есть.
Тогда можно попробовать манипуляцию атрибутом "context".
(async (bar, exp, tid, self) => CustomizableUI.createWidget(self = { label: "Панели, Папки", tooltiptext: [ "ЛКМ: ★ Закладки\n…+ Alt Домашняя папка", "ПКМ: ⟳ История\n…+ Alt Папка установки", "СКМ: Папка профиля\n…+ Alt user_chrome_files" ].join("\n"), id: "add-additional-personaltoolbar-button", localized: false, onCreated(btn) { btn.onclick = this.click; btn.toggleAttribute("context"); btn.style.setProperty("list-style-image", "url(chrome://user_chrome_files/content/vertical_top_bottom_bar/svg/bookmark-16.svg)", "important"); }, exec(num, win) { tid = null; self[num](win); }, context(win) { var btn = win.document.getElementById(this.id); btn.removeAttribute("context"); btn.dispatchEvent(new win.MouseEvent("contextmenu", this.a)); btn.toggleAttribute("context"); }, a: {__proto__: null, bubbles: true, screenX: 0, screenY: 0}, click(e) { if (e.detail > 2) return; var n2 = e.button != 2; var dbl = e.detail == 2; var num = 16 * e.button + 8 * e.ctrlKey + 4 * e.shiftKey + 2 * e.altKey + dbl; if (!self[num]) { if (n2) return; num = "context"; for(var p in self.a) self.a[p] = e[p]; } var win = e.view; if (dbl) tid &&= win.clearTimeout(tid), self[num](win); else tid = win.setTimeout(self.exec, 300, num, win); }, 0: w => bar(w, "viewBookmarksSidebar"), // ЛКМ 2: () => exp("Home"), // Alt+ЛКМ 16: () => exp("ProfD"), // СКМ 18: () => exp("UChrm", "user_chrome_files"), // Alt+СКМ 32: w => bar(w, "viewHistorySidebar"), // ПКМ 34: () => exp("GreD"), // Alt+ПКМ 1(win) { // Double Left Click win.alert("DBL Click"); }, 33(win) { // Double Right Click win.alert("DBL Right Click"); }, 29(win) { // Ctrl + Shift + Double Middle Click win.alert("Ctrl + Shift + DBL Middle Click"); }, }))( (win, bar) => win.SidebarUI.toggle(bar), (dir, sub) => { dir = Services.dirsvc.get(dir, Ci.nsIFile); sub && dir.append(sub); dir.exists() && dir.launch(); } );
скрипт перехвата кликов на downloads-button, PanelUI-menu
Там полную раскликовку сделать сложнее,
потому что панельки из них вываливаются по mousedown.
/* listener = e => { var trg = e.target; // Downloads Clicks if (e.button == 1) { if (e.shiftKey) { // СКМ + Shift if ( prefs.getIntPref("permissions.default.image", 1) == 1) prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)" else prefs.setIntPref("permissions.default.image", 1), trg.style.filter = ""; BrowserReload(); } else // СКМ Click saveSelectionToTxt(); // сохранить .txt } else if (e.button == 2) { if (e.shiftKey) Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError) // Обзор папки «Загрузки» else // ПКМ Click save(); // Single HTML } }, listener_pui = e => { // PanelUI-menu Clicks if (e.button == 1) { if (e.altKey) window.BrowserFullScreen() else if( window.windowState != window.STATE_MAXIMIZED ) window.maximize() else window.restore(); } else if (e.button == 2) if (e.altKey) return else { e.stopPropagation(); (e.shiftKey) ? window.close() : window.minimize(); } }, // end Clicks */ tid, allowMousedown, listener = { handleEvent(e) { if (e.detail > 2) return; var btn = e.target; var dbl = e.detail == 2; var num = (btn == pui && 100) + 16 * e.button + 8 * e.ctrlKey + 4 * e.shiftKey + 2 * e.altKey + dbl; if (!this[num]) { if (e.button == 1) return; if (e.button) { num = "context"; for(var p in this.a) this.a[p] = e[p]; } else num = "mousedown"; } if (dbl) tid &&= clearTimeout(tid), this[num](btn); else tid = setTimeout(this.exec, 300, num, btn, this); }, exec(num, btn, self) { tid = null; self[num](btn); }, mousedown(btn) { allowMousedown = true; btn.dispatchEvent(new MouseEvent("mousedown", {})); allowMousedown = false; }, context(btn) { btn.removeAttribute("context"); btn.dispatchEvent(new MouseEvent("contextmenu", this.a)); btn.toggleAttribute("context"); }, a: {__proto__: null, bubbles: true, screenX: 0, screenY: 0}, /*** ======= Downloads Clicks ======= ***/ 16: saveSelectionToTxt, // СКМ Click (сохранить .txt) 20(btn) { // СКМ + Shift var pref = "permissions.default.image"; var one = prefs.getIntPref(pref) == 1; prefs.setIntPref(pref, one ? 2 : 1); btn.style.filter = one ? "hue-rotate(180deg) brightness(95%)" : ""; BrowserReload(); }, 32: save, // ПКМ Click (Single HTML) 36() { // Shift + ПКМ Downloads.getSystemDownloadsDirectory() .then(path => FileUtils.File(path).launch(), Cu.reportError) // Обзор папки «Загрузки» }, 1() { // Double Left Click alert("Double Left Click"); }, 41() { // Ctrl + Double Right Click alert("Ctrl + Double Right Click"); }, 4() { // Shift + ЛКМ alert("Shift + ЛКМ"); }, /*** ======= PanelUI-menu Clicks ======= ***/ 118: BrowserFullScreen, // Alt + СКМ 116() { // СКМ windowState != STATE_MAXIMIZED ? maximize() : restore(); }, 132() { // ПКМ minimize(); }, 136: BrowserTryToCloseWindow, // Shift + ПКМ 134() { // Alt + ПКМ gCustomizeMode.enter(); }, 101() { // Double Left Click alert("Double Left Click"); }, 141() { // Ctrl + Double Right Click alert("Ctrl + Double Right Click"); }, 104() { // Shift + ЛКМ alert("Shift + ЛКМ"); }, }, // end Clicks
/* btn.addEventListener("click", listener), pui.addEventListener("click", listener_pui); window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { btn.removeEventListener("click", listener), pui.removeEventListener("click", listener_pui); window.removeEventListener("keydown", keydown_win); }}; */ var mouseenter = function(e) { this.parentNode.addEventListener("mousedown", stop, true); this.addEventListener("mouseleave", mouseleave, {once: true}); } var mouseleave = function(e) { this.parentNode.removeEventListener("mousedown", stop, true); } var stop = e => { e.button || allowMousedown || e.stopImmediatePropagation(); } var btns = [btn, pui]; for(var b of btns) { b.toggleAttribute("context"), b.addEventListener("click", listener, true), b.addEventListener("mouseenter", mouseenter); } window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { for(var b of btns) { b.removeEventListener("click", listener, true); b.removeEventListener("mouseenter", mouseenter); if (b.matches(":hover")) b.removeEventListener("mouseleave", mouseleave), b.parentNode.removeEventListener("mousedown", stop, true); } window.removeEventListener("keydown", keydown_win); }};
В скрипт Quick Toggle
Уволь.
Отсутствует
Dumby присоеденяюсь к просьбе ВВП https://forum.mozilla-russia.org/viewto … 45#p795945 на счет скрипта памяти
Отсутствует
Dumby - спасибо, я немного переделал код и обновил профиль-сборку скриптов.
А ещё у меня там не работают альт-клики. Насколько я понял, mousedown занят системой
Не системой, а демоном горячих клавиш, которые можно изменить в Настройках из меню.
перетаскивание/Resize окна вместе с Alt - это стандарт, но мета-клавишу можно в настройках поменять на Ctrl или Alt или Win…
Отсутствует
присоеденяюсь к просьбе
Какой просьбе? Нет там никакой просьбы.
Но индикатор и не должен напрямую реагировать ни на какие фишки.
Пара десятков миллисекунд на получение данных о памяти,
затем delay (две секунды) пауза, и так по кругу, вот и вся деятельность.
Дополнительный пинок только при открытии нового окна браузера.
И код рабочий, так что, если фишка действительно чистит память,
то индикатор это покажет, не прям сразу, но не позднее delay.
И да, если вдруг надо поставить (для теста) второй экземпляр кода,
то следует изменить id (в конце, "ucf-mem-indicator"), а то будут накладки.
И ещё там есть вопрос, можно ли сделать подобный индикатор,
но на другом принципе — использовать nsIMemoryReporterManager.
Когда-то давно я уже отвечал на это, целый трактат написал.
Суть — можно, но тогда результат будет включть только память DOM-процессов,
то есть выпадут процессы gpu, socket, rdd, может ещё какие-то подобные.
Отсутствует
egorsemenov06 пишетприсоеденяюсь к просьбе
Какой просьбе? Нет там никакой просьбы.
скрытый текст
Есть сетование на трудности рихтовки и констатация
отсутствия реакции индикатора на очистку памяти фишкой.Но индикатор и не должен напрямую реагировать ни на какие фишки.
Пара десятков миллисекунд на получение данных о памяти,
затем delay (две секунды) пауза, и так по кругу, вот и вся деятельность.
Дополнительный пинок только при открытии нового окна браузера.И код рабочий, так что, если фишка действительно чистит память,
то индикатор это покажет, не прям сразу, но не позднее delay.
И да, если вдруг надо поставить (для теста) второй экземпляр кода,
то следует изменить id (в конце, "ucf-mem-indicator"), а то будут накладки.И ещё там есть вопрос, можно ли сделать подобный индикатор,
но на другом принципе — использовать nsIMemoryReporterManager.Когда-то давно я уже отвечал на это, целый трактат написал.
Суть — можно, но тогда результат будет включть только память DOM-процессов,
то есть выпадут процессы gpu, socket, rdd, может ещё какие-то подобные.
Спасибо! понятно что ни чего не понятно.
Отсутствует
Dumby - Помоги исправить код перехода в "Адаптивный дизайн".
код в сложной кнопке QuickToggle.js работает, но если несколько раз включить/выключить Адаптивный дизайн через кнопку, то это переключение перестаёт работать.
и не работает в простой кнопке, в которую ты мне клики добавил:
responsiveUI(trg) { var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm").require("devtools/client/menus").menuitems.find(menuitem => menuitem.id == "menu_responsiveUI"); (this.responsiveUI = target => obj.oncommand({target}))(trg); },
(async (id, func) => { // дополнительные клики на downloads-button, PanelUI-menu для custom_script_win.js await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"), pui = document.getElementById("PanelUI-menu-button"); if (!btn) return; btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +` Двойной клик: открыть [Загрузки] …на картинке: ⧉ найти Похожие\n Правый клик (Alt+S): Сохранить в единый html всё / выделенное …дважды Картинки вкл/выкл\n Ролик: Сохранить как файл .txt Колёсико на рисунке: ➜ Сохранить`, PanelUI_help = `Клик мыши: меню Firefox ${Services.appinfo.platformVersion} …+ дважды ⊠ закрыть браузер …+ Alt Обновить без кэша …+ Shift ⚑ Краткая справка\n Правый клик ⇲ Свернуть …+ Alt Персонализация Колёсико: Развернуть | окно …+ Alt Полный экран`; var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } }, showInStatusPanel = (info, time = 5000) => { var win = Services.wm.getMostRecentWindow("navigator:browser"); StatusPanel = win.StatusPanel; if (StatusPanel.update.tid) clearTimeout(StatusPanel.update.tid) else { var {update} = StatusPanel; StatusPanel.update = () => {}; StatusPanel.update.ret = () => { StatusPanel.update = update; StatusPanel.update(); } } StatusPanel.update.tid = setTimeout(StatusPanel.update.ret, time); StatusPanel._label = info; }, saveSelectionToTxt = async () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = id + ":Save:GetSelection"; var receiver = msg => { var title = document.title || gBrowser.selectedTab.label; var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\n\n" + msg.data), title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt', null, false, true, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args) && showInStatusPanel("√ текст сохранён: " + title.slice(0, 60)); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}, 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("saveSelectionToTxt", res); } var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); }, // end save = async () => { // автор: Лекс, правка: Dumby, Dobrov (пути сохранения HTML) var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; if (typeof IOUtils != "object") { // Firefox 78 ESR var {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm"); var PathUtils = {join: (...args) => OS.Path.join(...args)}; var IOUtils = {writeUTF8: (path, txt) => OS.File.writeAtomic(path, new TextEncoder().encode(txt))}; } var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = (type) => { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.slice(0, type).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=|https?:\/\/|www\.|\/.*/g,''); return host.replace(/^ru\.|^m\.|forum\./,'').replace(/^club\.dns/,'dns'); } var msgListener = async msg => { var [fileContent, fileName] = msg.data, dir; try {dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(0, 2); // Dir/subdir: пусто|0 title|1 домен arr[1] = (arr[1] == "0") ? Title(100) : (arr[1] == "1") ? Title(-1) : ""; // имя вкладки или домен arr.forEach(dir.append); // для ucf_save.dirs = "_Web||_Pics|1" HTML сохранится в папку [Загрузки]/_Web/имя вкладки dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(dir.path); dir.append(fileName); await IOUtils[write](dir.path, fileContent) && showInStatusPanel("√ страница записана: " + fileName.slice(0, 60)); var d = await Downloads.createDownload({ source: "about:blank", target: FileUtils.File(dir.path)}); // Fake download (await Downloads.getList(Downloads.ALL)).add(d); d.refresh(d.succeeded = true); // кнопка Загрузки мигает } messageManager.addMessageListener(msgName, msgListener); addDestructor(() => messageManager.removeMessageListener(msgName, msgListener)); var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); }, // end save tid, allowMousedown, listener = { handleEvent(e) { if (e.detail > 2) return; var btn = e.target; var dbl = e.detail == 2; var num = (btn == pui && 100) + 16 * e.button + 8 * e.ctrlKey + 4 * e.shiftKey + 2 * e.altKey + dbl; if (!this[num]) { if (e.button == 1) return; if (e.button) { num = "context"; for(var p in this.a) this.a[p] = e[p]; } else num = "mousedown"; } if (dbl) tid &&= clearTimeout(tid), this[num](btn); else tid = setTimeout(this.exec, 300, num, btn, this); }, exec(num, btn, self) { tid = null; self[num](btn); }, mousedown(btn) { allowMousedown = true; btn.dispatchEvent(new MouseEvent("mousedown", {})); allowMousedown = false; }, context(btn) { btn.removeAttribute("context"); btn.dispatchEvent(new MouseEvent("contextmenu", this.a)); btn.toggleAttribute("context"); }, switchToTab(but, url) { // открыть вкладку | закрыть, если открыта for(var tab of but.ownerGlobal.gBrowser.tabs) if ( tab.linkedBrowser.currentURI.spec == url ) {but.ownerGlobal.gBrowser.removeTab(tab); return;}; // вкладка найдена, закрыть but.ownerGlobal.switchToTabHavingURI(url, true, {relatedToCurrent: true, triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}); }, responsiveUI(trg) { var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm").require("devtools/client/menus").menuitems.find(menuitem => menuitem.id == "menu_responsiveUI"); (this.responsiveUI = target => obj.oncommand({target}))(trg); }, a: {__proto__: null, bubbles: true, screenX: 0, screenY: 0}, /*** ======= Downloads Clicks ======= ***/ 16: saveSelectionToTxt, // СКМ Click (сохранить .txt) 1() { // Double Left Click - Обзор папки «Загрузки» Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError) // Обзор папки «Загрузки» }, 32: save, // ПКМ Click (Single HTML) 33(btn) { // Double Right Click var pref = "permissions.default.image"; var one = prefs.getIntPref(pref) == 1; prefs.setIntPref(pref, one ? 2 : 1); btn.style.filter = one ? "hue-rotate(180deg) brightness(95%)" : ""; BrowserReload(); }, 2() { // Alt + ЛКМ }, /*** ======= PanelUI-menu Clicks ======= ***/ 102: BrowserReloadSkipCache, // Alt + Click 104() { // Shift + ЛКМ var help_ucf = ['chrome://user_chrome_files/content/help.html', 'http://forum.puppyrus.org/index.php?topic=22762']; var newURI = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).convertChromeURL(Services.io.newURI(help_ucf[0])); // .spec = file:/// (newURI.QueryInterface(Ci.nsIFileURL).file.exists()) ? this.switchToTab(pui, help_ucf[0]) : this.switchToTab(pui, help_ucf[1]); }, 118: BrowserFullScreen, // Alt + СКМ 116() { // СКМ windowState != STATE_MAXIMIZED ? maximize() : restore(); }, 132() { // ПКМ minimize(); }, 134() { // Alt + ПКМ gCustomizeMode.enter(); }, 101: BrowserTryToCloseWindow, // Double Left Click 133(pui) { // Double Right Click responsiveUI(pui); }, }, // end Clicks keydown_win = e => { // нажатие клавиш if (e.keyCode == 83 && e.altKey) e.shiftKey // Alt+S [+Shift] ? singlesave ? singlesave.click() : save() : save(); // имитировать клик по кнопке, используя её ID }, {prefs, dirsvc} = Services, linux = /macos|linux/.test(AppConstants.platform), save_ex = "_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action", singlesave; prefs.setBoolPref("browser.download.autohideButton", false); // не скрывать кнопку Загрузки (async () => { setTimeout(()=> { // дополнить подсказки singlesave = document.getElementById(save_ex); singlesave ? btn.tooltipText = btn.tooltipText + '\n\nAlt⇧S ⌨ нажатие SingleSave' : 0; if (!/Закрыть/.test(pui.tooltipText)) pui.tooltipText = PanelUI_help; }, linux ? 3000 : 9000); // ожидание для Windows больше })(); var mouseenter = function(e) { this.parentNode.addEventListener("mousedown", stop, true); this.addEventListener("mouseleave", mouseleave, {once: true}); } var mouseleave = function(e) { this.parentNode.removeEventListener("mousedown", stop, true); } var stop = e => { e.button || allowMousedown || e.stopImmediatePropagation(); } var btns = [btn, pui]; for(var b of btns) { b.toggleAttribute("context"), b.addEventListener("click", listener, true), b.addEventListener("mouseenter", mouseenter); } window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { for(var b of btns) { b.removeEventListener("click", listener, true); b.removeEventListener("mouseenter", mouseenter); if (b.matches(":hover")) b.removeEventListener("mouseleave", mouseleave), b.parentNode.removeEventListener("mousedown", stop, true); } window.removeEventListener("keydown", keydown_win); }}; ucf.unloadlisteners.push(id); })("downloads-button-click-listener", ({io, focus}) => { // SingleHTML не сохраняет svg графику var resolveURL = function (url, base) { try { return io.newURI(url, null, io.newURI(base)).spec; } catch {} }, 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) {} } }, encodeImg = function (src, obj) { var canvas, img, ret = src; if (/^https?:\/\//.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((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png')); } catch (e) {}; if (img != obj) img.src = 'about:blank'; }; return ret; }, toSrc = function (obj) { var strToSrc = function (str) { var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'}; while (chr = str.charAt(i++)) { ret += meta[chr] || chr; }; return '\x22' + ret + '\x22'; }, 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 (obj.hasOwnProperty(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) ? String(obj) : 'null'; case 'Object': return objToSrc(obj); case 'String': return strToSrc(obj); default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null'; } }, mainWin = {}; focus.getFocusedElementForWindow(content, true, mainWin); mainWin = mainWin.value; var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location; var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/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, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href); return prev + encodeImg(url) + next; }); 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) != '#') 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), meta = doc.createElement('meta'), sheets = doc.styleSheets, title = doc.getElementsByTagName('title')[0]; meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (unsafeWin) { if ('$' in unsafeWin) return; var f = doc.createElement('iframe'); f.src = 'about:blank'; f.setAttribute('style', '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 unsafeWin) { if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue; try { str = toSrc(unsafeWin[name]); if (!/\{\s*\[native code\]\s*\}/.test(str)) { script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n')); } } catch (e) {}; }; f.parentNode.removeChild(f); if (script.childNodes.length) this.nextSibling.appendChild(script); }; head.copyScript(win.wrappedJSObject || win); 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))) { var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href); if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url); return prev + url + next; }); style.appendChild(doc.createTextNode(css + '\n')); } } else { this.copyStyle(rule.styleSheet); } } } catch(e) { if (s.ownerNode) style = s.ownerNode.cloneNode(false); }; this.appendChild(style); }; for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]); head.appendChild(doc.createTextNode('\n')); var doctype = '', dt = doc.doctype; if (dt && dt.name) { doctype += '<!DOCTYPE ' + dt.name; if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22'; if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22'; doctype += '>\n'; }; var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop()); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).trim(); fileName += "_" + new Date().toLocaleDateString('ru', {day: 'numeric', month: 'numeric', year: '2-digit'}) +'-'+ new Date().toLocaleTimeString().replace(/:/g, "։"); if (!/\.html?$/.test(fileName)) fileName += '.html'; sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]); }); // END hookClicks
Ещё вопрос - как имитировать нажатие клавиш, например "послать" переключения в режим "Адаптивный дизайн" - у меня это Option+Command+M (Win+Alt+M)
пробовал, но не пашет: window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).sendKeyEvent("keypress", 0, "j".charCodeAt(0), 0x08)
Отредактировано Dobrov (11-11-2021 18:07:09)
Отсутствует
не работает
responsiveUI(pui);
this.responsiveUI(pui);
Или (для понимания) без промежуточности
..... 133(pui) { var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm").require("devtools/client/menus").menuitems.find(menuitem => menuitem.id == "menu_responsiveUI"); (this[133] = target => obj.oncommand({target}))(pui); },
не пашет
window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).sendKeyEvent
На FF87 у window нет метода QueryInterface(),
и у nsIDOMWindowUtils нет метода sendKeyEvent().
Отсутствует