rubel, xrun1 винды у меня нет уже 4 года, проверял только на Linux и MacOS. в Firefox 87 всё работает.
Может кэш удалить правым кликом по штатной UCF-кнопке "Перезапустить приложение"?
Или нужен config.js, в котором есть bootstrap поддержка для CustomButtons.
// Этот скрипт можно использовать для создания кнопок с помощью CustomizableUI.createWidget (() => { // загрузка внешних скриптов var loadscript = name => { try { Services.scriptloader.loadSubScript(`chrome://user_chrome_files/content/custom_scripts/${name}`,globalThis,"UTF-8"); return true; } catch(e) {} }; loadscript("ucf_FavDir.js"); })(); (async url => ChromeUtils.import(url))( "chrome://user_chrome_files/content/custom_scripts/AppMenuTbbSaveHTMLChild.jsm" );
Отредактировано Dobrov (17-05-2021 16:40:29)
Отсутствует
Аналогично, у меня тоже "не взлетело"
А у меня вспорхнуло added: Меню шире стало, но это поправимо.
3.в файл custom_script.js в самый верх добавляю
Только я вниз добавил. Путь такой же как у вас. Сохранение работает.
Подключал к самой адекватной в 8-ой линейке 86. ОС 7, но вряд ли это критично. config.js обычный из user_chrome_files, без bootstrap.
В 90 тоже работает
Отредактировано sandro79 (17-05-2021 18:56:34)
Отсутствует
sandro79
Спасибо за помощь, все сделал по-твоему, поместил в самый низ ну и кодировка была ANSI у фйла AppMenuTbbSaveHTMLChild.jsm.
Теперь все работает как положено, все сохраняет и стили и картинки.
Dumby
Спасибо за вашу работу.
Отсутствует
Dumby
Имею код , но если боковуха уже открыта , то при ЛКМ она сходу закрывается...Как бы избежать?
/*Initialization Code*/ this.onclick = this.oncontextmenu = function(event) { if (event.button == 0) { SidebarUI.toggle('viewHistorySidebar'); if (custombuttons.confirmBox(null, "Вниманиее ! Очистка Истории!", "Да", "Отмена") ) { SidebarUI.toggle('viewHistorySidebar'); PlacesUtils.history.clear(); } SidebarUI.hide(); } if(event.button == 1 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ SidebarUI.toggle('viewHistorySidebar'); } if(event.button == 2 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ Sanitizer.showUI(window); CustomizableUI.setToolbarVisibility("PersonalToolbar", document.querySelector("#PersonalToolbar").closed); var s = "browser.zoom.full"; cbu.setPrefs(s, cbu.getPrefs(s) == true ? true : true); var s = "intl.accept_languages"; cbu.setPrefs(s, cbu.getPrefs(s) == "ru" ? "ru": "ru"); var s = "media.autoplay.default"; cbu.setPrefs(s, cbu.getPrefs(s) == 5 ? 5: 5); SidebarUI.hide(); var s = "extensions.long_left_click.timeContent"; cbu.setPrefs(s, cbu.getPrefs(s) == 350 ? 350: 350); document.querySelector( "#mainPopupSet > tooltip[onpopupshowing*=undoCloseTabsList]" )?.undoCloseTabsList.updUI(); } }; this.oncontextmenu =e=> { e.button && !e.ctrlKey && e.preventDefault() }; this.tooltipText = "ЛКМ: Очистка Истории\nСКМ: Боковая история \nПКМ: Окно очистки всего";
Отсутствует
Не в интересе дело, а в том, что расширение Image Picka не подгружает картинки, по которым не кликали, то есть оно бесполезно!
Список url-ов же. Меняете p на o (в ссылках типа https://static.doramatv.live/uploads/pics/04/88/836_p.jpg) и кидаете в любой даунлоадер.
Отсутствует
нельзя ли в скрипт "Сохранить картинку перетаскиванием" добавить ещё сохранение картинки по событию двойной click
Нет, добавить нельзя. Объяснял же — нету в этом процессе
никакой картинки и никакого события клика на ней.
Ладно, уговорил попробовать переписать с двойным click'ом. Тоже JSM'ка,
назвать как-нибудь, например, MouseImgSaver.jsm и импортировать из custom_script.js
Предыдущий код отключить не забудь.
var EXPORTED_SYMBOLS = ["MouseImgSaverChild", "MouseImgSaverParent"]; var u = {get it() { delete this.it; return this.it = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools); }}; for(let name of ["E10SUtils", "PrivateBrowsingUtils"]) ChromeUtils.defineModuleGetter(u, name, `resource://gre/modules/${name}.jsm`); class MouseImgSaverChild extends JSWindowActorChild { handleEvent(e) { if (e.button) return; var trg = e.explicitOriginalTarget; trg.nodeType == Node.ELEMENT_NODE && trg instanceof Ci.nsIImageLoadingContent && this[e.type](trg, e); } handleDragEvent(e) { this[e.type](e); } dragstart(trg, e) { this.trg = trg; this.x = e.screenX; this.y = e.screenY; this.drag("add"); this.handleEvent = this.handleDragEvent; this.checkTextLinkyTool(trg.ownerDocument); } events = ["dragover", "drop", "dragend"]; drag(meth = (delete this.handleEvent, delete this.trg, "remove")) { meth += "EventListener"; var win = this.contentWindow; for(var type of this.events) win[meth](type, this, true); } drop() { this.drag(); } dragover(e) { var {x, y} = this, cx = e.screenX, cy = e.screenY, dx = cx - x, ax = Math.abs(dx), ay = Math.abs(cy - y); if (ax < 10 && ay < 10) return; if (dx < 0 || ax < ay) return this.drag(); this.x = cx; this.y = cy; } dragend(e) { var dt = e.dataTransfer, {trg} = this; this.drag(); dt.mozUserCancelled || this.send(trg, e.screenX); } dblclick(trg) { trg.matches(":any-link :scope") || this.send(trg); } send(trg, sx) { var uri = trg.currentURI; if (!uri) return; var doc = trg.ownerDocument; var cookieJarSettings = u.E10SUtils .serializeCookieJarSettings(doc.cookieJarSettings); var referrerInfo = Cc["@mozilla.org/referrer-info;1"] .createInstance(Ci.nsIReferrerInfo); referrerInfo.initWithElement(trg); referrerInfo = u.E10SUtils.serializeReferrerInfo(referrerInfo); var contentType = null, contentDisposition = null; try { var props = u.it.getImgCacheForDocument(doc).findEntryProperties(uri, doc); var cs = Ci.nsISupportsCString; try {contentType = props.get("type", cs).data;} catch {} try {contentDisposition = props.get("content-disposition", cs).data;} catch {} } catch {} this.sendAsyncMessage("", { url: (trg.currentRequestFinalURI || uri).spec, contentType, referrerInfo, cookieJarSettings, contentDisposition, sx, isPrivate: u.PrivateBrowsingUtils.isContentWindowPrivate(trg.ownerGlobal) }); } checkTextLinkyTool(doc) { if (doc.title || !doc.documentURI.startsWith("moz-extension:")) return; var lab = doc.querySelector("body > label#lblFrom:first-child")?.textContent; if (lab) doc.title = lab.slice(0, lab.lastIndexOf("(")); } } if (!ChromeUtils.domProcessChild.childID) { ChromeUtils.registerWindowActor("MouseImgSaver", { allFrames: true, parent: {moduleURI: __URI__}, messageManagerGroups: ["browsers"], child: {moduleURI: __URI__, events: {dblclick: {capture: true}, dragstart: {capture: true}}} }); var wref, data = Object.assign(Object.create(null), { "browser.download.dir": {type: "String", get set() { var dir = wref.get().Services.dirsvc.get("DfltDwnld", Ci.nsIFile); dir.append("_Images"); dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… var {path} = dir; // папка [Загрузки]/_Images Object.defineProperty(this, "set", {get() { var win = wref.get(); var title = win.gBrowser.selectedTab.label.slice(0, 100); return PathUtils.join(path, win.DownloadPaths.sanitize(title)); }}); return this.set; }}, "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true} }); var MouseImgSaverParent = class extends JSWindowActorParent { receiveMessage(msg) { var {url, contentType, contentDisposition, sx, isPrivate, referrerInfo, cookieJarSettings} = msg.data; var win = msg.target.browsingContext.topChromeWindow; if (sx && sx > win.mozInnerScreenX + win.innerWidth) return; wref = Cu.getWeakReference(win); var p = win.Services.prefs; 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 {win.internalSave( url, null, // document null, // file name contentDisposition, contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data u.E10SUtils.deserializeReferrerInfo(referrerInfo), u.E10SUtils.deserializeCookieJarSettings(cookieJarSettings), win.document, // initiating doc true, // skip prompt for where to save null, // cache key isPrivate, win.document.nodePrincipal );} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } } } }
если боковуха уже открыта , то при ЛКМ она сходу закрывается...Как бы избежать?
this.onclick = event => { if (event.button == 0) { var id = "viewHistorySidebar"; SidebarUI.isOpen && SidebarUI.currentID == id || SidebarUI.show(id); custombuttons.confirmBox(null, "Вниманиее ! Очистка Истории!", "Да", "Отмена") && PlacesUtils.history.clear(); SidebarUI.hide(); } ..... ..... ..... }
Отредактировано Dumby (18-05-2021 20:48:16)
Отсутствует
Этот код в 78 должен работать?
Думаю да. Добавил в 78 в custom_script_win.js — выглядит рабочим.
Только исключение тэгов для "bookmark-added" потерялось. Можно вписать.
/* for(var e of events) this.record(e.itemType, e.source, e.parentGuid); */ for(var e of events) e.isTagging || this.record(e.itemType, e.source, e.parentGuid);
Отсутствует
сохранение картинки … с двойным click'ом.
Спасибо, отличная работа!
Но есть вопрос по этому скрипту MouseImgSaver.jsm - как картинку сохранять по клику колёсиком? (вместо dblclick)
Я добавлял события mousedown, click, auxclick - все они не реагируют на клик средней кнопки мыши!
строка 100: child: {moduleURI: __URI__, events: {mousedown: {capture: true}…
Dumby Вторая просьба доработать кнопку переключения параметров Quick Toggle about:config.
Плюс этой кнопки в том, что по иконкам меню сразу видно значение и "безопасность" опций.
Нужно добавить подменю в Quick Toggle about:config, чтобы строки переключения опций можно было объединять по категориям в одном под-меню (т.к. меня этих опций более тридцати, многих из которых нет в настройках браузера).
Ещё в кнопке пункты меню без иконок, если не указаны userChoice или userAlt. Я добавил для таких строк иконку, но есть баг: строка "Закрывать меню этой кнопки" свою иконку меняет только после переключения опций!
код новой иконки: 367 строка. Нужно исправить баг: при первом открытии последняя строка меню не с родной иконкой.
// Quick Toggle Быстрое переключение параметров about:config для custom_script.js (async (name, id, func) => { // https://forum.mozilla-russia.org/viewtopic.php?pid=784165#p784165 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); // (this.constructor… {код кнопки}); BEGIN QuickToggle… })(this.constructor.name, "ToggleAboutConfig", () => { var description = `Quick Toggle Settings ПКМ Меню быстрых настроек …+Alt Отладка дополнений …Long ✍ about:config ЛКМ Боковая панель: Журнал …Long Антизапрет proxy ⬄ …+Shift ★ Библиотека закладок …+Alt Пипетка: захват цвета СКМ ± Zoom Текст/Страница …Long Консоль браузера — тире ⟳ Обновить ↯ Перезапуск`, // ЛКМ+Alt+⇧ этот hotkey свободен // 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 // Разделитель: Имя меню "—,⟳,↯" Опция, ⟳ обновить страницу, ↯ перезапуск браузера // стиль иконки: #ToggleAboutConfig .toolbarbutton-icon{ padding: 2px !important;} icon_vpn = "hue-rotate(270deg) brightness(95%)", menuactive = '#e8e8e8', // текст, подсвеченный курсором {prefs} = Services, db = prefs.getDefaultBranch(""), pv = parseInt(Services.appinfo.platformVersion), 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] : [name, name]; }); }, fontserif = font_pref(fonts), fontsans = [["PT Sans","PT Sans"], ...fontserif], secondary = [{ // pref … [apref, lab, akey, hint, js-code] pref: ["permissions.default.image", "Загрузка графики"], userChoice: 1, userAlt: 3, refresh: true, values: [[1, "Разрешена"], [3, "Только с сайта"], [2, "Отключить"]] },{ pref: ["browser.safebrowsing.downloads.remote.block_dangerous", "Опасные файлы, сайты"], 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: ["browser.display.use_document_fonts", "Загружать Web-шрифты"], userChoice: 1, refresh: true, values: [[1, "Да"], [0, "Нет"]] },{ pref: ["browser.sessionstore.restore_on_demand", "Загружать неактивные вкладки", , "При запуске загружаются все вкладки.\nМожет замедлить работу браузера."], userAlt: false, // userChoice: true, userAlt: false, values: [[false, "Да"], [true, "Нет"]] },{ pref: ["javascript.enabled", "Выполнять скрипты Java"], userChoice: true, refresh: true, values: [[true, "Да"], [false, "Нет"]] },null,{ pref: ["network.proxy.autoconfig_url", "Прокси (VPN) URL", "п"], userChoice: "127.0.0.1", userAlt: "https://antizapret.prostovpn.org/proxy.pac", refresh: true, values: [ ["127.0.0.1", "отключен…", "0", "", `prefs.setIntPref('network.proxy.type', 0); node.parentNode.parentNode.style.filter = '';`], ["https://antizapret.prostovpn.org/proxy.pac", "АнтиЗапрет", "1", "Надёжный доступ на заблокированные сайты\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"] ] },{ 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", "Все протоколы через прокси"], userChoice: true, refresh: true, values: [[true, "Да", "", "Прокси для всех протоколов при ручной настройке"], [false, "Нет"]] },{ pref: ["network.trr.mode", "DNS поверх HTTPS", , "Шифрование DNS-трафика для\nзащиты персональных данных"], userChoice: 1, userAlt: 2, refresh: true, values: [ [0, "по-умолчанию", "0"], [1, "автоматически", "1", "используется DNS или DoH, в зависимости от того, что быстрее"], [2, "DoH, затем DNS", "2"], [3, "только DoH", "3"], [4, "DNS и DoH", "4"], [5, "отключить DoH", "5"] ] },{ pref: ["network.trr.uri", "Провайдер DNS", , "↯ нужен перезапуск браузера"], userChoice: "https://mozilla.cloudflare-dns.com/dns-query", userAlt: "https://firefox.dns.nextdns.io/", restart: true, values: [ ["https://mozilla.cloudflare-dns.com/dns-query", "Cloudflare"], ["https://firefox.dns.nextdns.io/", "NextDNS"], ["https://doh.opendns.com/dns-query", "OpenDNS"], ["", "по-умолчанию"]] },null,{ pref: ["browser.zoom.full", "Масштабировать"], userChoice: false, userAlt: true, values: [[true, "всю страницу"], [false, "только текст"]] },{ pref: ["browser.display.document_color_use", "Использовать цвета сайтов"], userChoice: 0, userAlt: 1, values: [[0, "Авто", "0"], [1, "Всегда", "1"], [2, "Никогда", "2"]] },{ pref: ["font.name.sans-serif.x-cyrillic", "Шрифт без засечек "], userChoice: "Arial", userAlt: "PT Sans", values: fontsans },{ pref: ["font.name.serif.x-cyrillic", "Шрифт с засечками"], userChoice: "Cambria", userAlt: "Times", values: fontserif },{ pref: ["image.animation_mode", "Анимация изображений"], userChoice: "none", userAlt: "normal", refresh: true, values: [["none", "Выключена"], ["normal", "По циклу"], ["once", "Единожды"]] },{ pref: ["ui.prefersReducedMotion", "Анимация интерфейса", , "↯ перезапуск браузера"], userChoice: true, userAlt: 0, restart: true, values: [[1, "Отключена"], [0, "Включена"]] },null,{ pref: ["media.autoplay.default", "Авто-play аудио/видео"], userChoice: 5, userAlt: 2, refresh: true, values: [ [0, "Разрешить", "0"], [1, "Запретить", "1"], [2, "Спрашивать", "2"], [5, "Блокировать", "5"]] },{ pref: ["media.autoplay.blocking_policy", "Автозапуск (политика)"], userChoice: 1, userAlt: 2, refresh: true, values: [[1, "Временная", "1"], [2, "По действию", "2"], [0, "Постоянная", "0"]] },{ pref: ["plugin.state.flash", "Flash-plugin"], userChoice: 0, userAlt: 1, refresh: true, values: [ [2, "Всегда включать", "2"], [1, "Включать по запросу", "1"], [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отключите при разных проблемах с графикой"], userChoice: false, restart: true, values: [ [true, "Да", "", "", `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", false)`], [true, "Нет", "", "", `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", true)`] ] },null,{ pref: ["dom.disable_open_during_load", "Блокировать всплывающие окна"], userChoice: 2, userAlt: true, },{ pref: ["network.cookie.cookieBehavior", "Получать куки"], userChoice: 1, userAlt: 3, refresh: false, values: [ [1, "кроме сторонних"], [3, "кроме не посещённых"], [4, "кроме трекеров"], [2, "никогда"], [0, "со всех сайтов"] ] },{ pref: ["network.http.sendRefererHeader", "Referer: для чего"], userChoice: 2, userAlt: 1, values: [[0, "Ни для чего", "0"], [1, "Только ссылки", "1"], [2, "Ссылки, изобр.", "2"]] },{ pref: ["dom.storage.enabled", "Локальное хранилище", , "Сохранение персональных данных, по\nкоторым вас можно идентифицировать"], userChoice: false, userAlt: true, values: [[true, "Разрешить"], [false, "Запретить"]] },{ pref: ["privacy.resistFingerprinting", "Изоляция Firstparty-Fingerprint", ,"privacy.firstparty.isolate\nЗащита данных пользователя также\nзапрещает запоминать размер окна"], userChoice: true, 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", "Многопоточный режим вкладок"], userChoice: true },{ pref: ["dom.enable_performance", "Статус загрузки страницы",,"Передача данных разрешит определять\nфакт использования прокси-сервера"], userChoice: false },{ pref: ["browser.cache.disk.enable", "Дисковый кэш"], userChoice: true, values: [[true, "Включен"], [false, "Выключен", "", "Включается кэш в оперативной памяти", `prefs.setBoolPref("browser.cache.memory.enable", true)`]] },{ pref: ["browser.cache.memory.enable", "Кэш в оперативной памяти"], userChoice: true, values: [[true, "Да"], [false, "Запрет"]] },{ pref: ["general.useragent.override", "User Agent"], userChoice: null, userAlt: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.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 (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 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0", "Firefox 68 MacOSX"], ["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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36", "Chrome61 W10"], ["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"] ]} ]; return { label: "Quick Toggle Settings", id: "ToggleAboutConfig", tooltiptext: description, 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: lightblue !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; // = this.UserImg 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", "#804040", "important"); if (!alt) img = this.notUserChoiceImg; } if (!pref.img) img ? node.setAttribute("image", img) : /этой кнопки/.test(node.getAttribute("label")) ? node.setAttribute("image", "chrome://browser/skin/menu.svg") : node.setAttribute("image", this.UserImg); // : 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}`; } 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(); }, 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); }, auxclick(e) { // CKM if (e.button != 1 || !e.target.btn) return; var win = Services.wm.getMostRecentWindow("navigator:browser"); win.ZoomManager.toggleZoom(); }, command(e) { // нажатия левой кнопки мыши var trg = e.target, win = e.view; if (trg.btn) { // LMB if (e.shiftKey) e.altKey ? e.view.alert("Press Alt+Shift") // Alt+Shift : e.view.PlacesCommandHook.showPlacesOrganizer("BookmarksToolbar"); // Shift Библиотека Панель закладок else if (e.altKey) this.eyedropper(trg); // Alt Пипетка else { // LMB Click var bar = trg.ownerDocument.getElementById("add-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); }, 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) { // 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("about:debugging#/runtime/this-firefox", e); // ПКМ + Alt отладка дополнений } else if ("pref" in trg) { this.maybeClosePopup(e, trg); if (trg.pref.user) prefs.clearUserPref(trg.pref.pref), this.maybeRe(trg); } e.preventDefault(); }, click(e) { if (e.button) return; var trg = e.target, {pref} = trg; if (!pref) return; }, mousedown(e) { var reset = e => e.target.linkedObject = this; var id, lo = {command: reset, mousedown: reset}; 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); }, Notify(title, text, time = 2000){ Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService).showAlertNotification(null, title, text, false, '', null, time); }, switchToTab(url, e = this) { // открыть вкладку | закрыть, если открыта 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()}); }, Antizapret(trg) { if (prefs.getIntPref('network.proxy.type') == 2) { // выключить prefs.setIntPref('network.proxy.type', 0); prefs.setStringPref("network.proxy.autoconfig_url", "127.0.0.1"); trg.style.removeProperty("filter"); } else { prefs.setIntPref('network.proxy.type', 2); prefs.setStringPref("network.proxy.autoconfig_url", "https://antizapret.prostovpn.org/proxy.pac"); trg.style.setProperty("filter", icon_vpn, "important"); // this.Notify('Proxy', 'Работаем через VPN Антизапрет'); } }, londPress(e) { // удержание кнопки мыши. на второй долгий клик при отпускании сработает действие на обычный клик этой кнопки var trg = e.target, win = e.view; if (e.button == 0) this.Antizapret(e.target); if (e.button == 1) trg.ownerDocument.getElementById("key_browserConsole").doCommand(); // Консоль браузера if (e.button == 2) this.switchToTab("about:config", e); // RMB Long } }; }); // END ToggleAboutConfig
Отредактировано Dobrov (19-05-2021 08:17:48)
Отсутствует
Dumby
Опять не могу сделать. Окно по ПКМ выскакивает и другие коды сработают при отмене. Как бы запретить ?
if(event.button == 2 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ Sanitizer.showUI(window); CustomizableUI.setToolbarVisibility("PersonalToolbar", document.querySelector("#PersonalToolbar").closed); var s = "browser.zoom.full"; cbu.setPrefs(s, cbu.getPrefs(s) == true ? true : true); var s = "intl.accept_languages"; cbu.setPrefs(s, cbu.getPrefs(s) == "ru" ? "ru": "ru"); var s = "media.autoplay.default"; cbu.setPrefs(s, cbu.getPrefs(s) == 5 ? 5: 5); SidebarUI.hide(); var s = "extensions.long_left_click.timeContent"; cbu.setPrefs(s, cbu.getPrefs(s) == 350 ? 350: 350); document.querySelector( "#mainPopupSet > tooltip[onpopupshowing*=undoCloseTabsList]" )?.undoCloseTabsList.updUI(); gClipboard.clear(); var file = Services.dirsvc.get('ProfD', Ci.nsIFile); file.initWithPath(file.path + "\\memory\\start.vbs"); file.launch(); } };
Отсутствует
Я добавлял события mousedown, click, auxclick - все они не реагируют на клик средней кнопки мыши
Если заменил dblclick на auxclick в child.events,
тогда надо заменить dblclick на auxclick и в само́м class MouseImgSaverChild,
а так же, в handleEvent(), заменить if (e.button) на if (e.button > 1)
autoscroller? Ну, я уже упоминал, и ноль реакции, значит не проблема (выключен?).
Нужно исправить баг: при первом открытии последняя строка меню не с родной иконкой.
/* if (!pref.img) img ? node.setAttribute("image", img) : /этой кнопки/.test(node.getAttribute("label")) ? node.setAttribute("image", "chrome://browser/skin/menu.svg") : node.setAttribute("image", this.UserImg); // : node.removeAttribute("image"); */ node.nextSibling && node.setAttribute("image", img || this.UserImg);
просьба доработать кнопку переключения параметров Quick Toggle about:config.
Самоотвод.
Окно по ПКМ выскакивает и другие коды сработают при отмене. Как бы запретить ?
Вместо Sanitizer.showUI(window);
var cancel = true; Services.obs.addObserver(function wfp(win, topic) { Services.obs.removeObserver(wfp, topic); var sd = win.gSanitizePromptDialog, {sanitize} = sd; sd.sanitize = e => cancel = sanitize.call(sd, e); }, "widget-first-paint"); Sanitizer.showUI(window); if (cancel) return;
Отсутствует
Dumby - Спасибо, я доработал ClickPicSave.jsm-скрипт сохранения картинки.
Создал свой массив pics - опцию "ucf_save.dirs" = "_Web|0|_Images|1", где можно менять папку сохранения картинок.
Но код скрипта создаёт все данные для сохранения картинки только при запуске браузера!
Если изменить опции в about:config, то скрипт по-прежнему сохраняет в старую папку.
Dumby - помоги доработать код, чтобы при каждой записи файла путь брался из опции "ucf_save.dirs"
Если такой опции нет, берётся значение по-умолчанию. Мои изменения в коде: строка 100 и далее…
var EXPORTED_SYMBOLS = ["MouseImgSaverChild", "MouseImgSaverParent"]; var u = {get it() { delete this.it; return this.it = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools); }}; for(let name of ["E10SUtils", "PrivateBrowsingUtils"]) ChromeUtils.defineModuleGetter(u, name, `resource://gre/modules/${name}.jsm`); class MouseImgSaverChild extends JSWindowActorChild { handleEvent(e) { // клики мышью if (e.button > 1) return; // только ЛКМ, СКМ var trg = e.explicitOriginalTarget; trg.nodeType == Node.ELEMENT_NODE && trg instanceof Ci.nsIImageLoadingContent && this[e.type](trg, e); } handleDragEvent(e) { this[e.type](e); } dragstart(trg, e) { this.trg = trg; this.x = e.screenX; this.y = e.screenY; this.drag("add"); this.handleEvent = this.handleDragEvent; this.checkTextLinkyTool(trg.ownerDocument); } events = ["dragover", "drop", "dragend"]; drag(meth = (delete this.handleEvent, delete this.trg, "remove")) { meth += "EventListener"; var win = this.contentWindow; for(var type of this.events) win[meth](type, this, true); } drop() { this.drag(); } dragover(e) { var {x, y} = this, cx = e.screenX, cy = e.screenY, dx = cx - x, ax = Math.abs(dx), ay = Math.abs(cy - y); if (ax < 10 && ay < 10) return; if (dx < 0 || ax < ay) return this.drag(); this.x = cx; this.y = cy; } dragend(e) { var dt = e.dataTransfer, {trg} = this; this.drag(); dt.mozUserCancelled || this.send(trg, e.screenX); } auxclick(trg) { // клик СКМ this.dblclick(trg); } dblclick(trg) { // ЛКМ trg.matches(":any-link :scope") || this.send(trg); } send(trg, sx) { var uri = trg.currentURI; if (!uri) return; var doc = trg.ownerDocument; var cookieJarSettings = u.E10SUtils .serializeCookieJarSettings(doc.cookieJarSettings); var referrerInfo = Cc["@mozilla.org/referrer-info;1"] .createInstance(Ci.nsIReferrerInfo); referrerInfo.initWithElement(trg); referrerInfo = u.E10SUtils.serializeReferrerInfo(referrerInfo); var contentType = null, contentDisposition = null; try { var props = u.it.getImgCacheForDocument(doc).findEntryProperties(uri, doc); var cs = Ci.nsISupportsCString; try {contentType = props.get("type", cs).data;} catch {} try {contentDisposition = props.get("content-disposition", cs).data;} catch {} } catch {} this.sendAsyncMessage("", { url: (trg.currentRequestFinalURI || uri).spec, contentType, referrerInfo, cookieJarSettings, contentDisposition, sx, isPrivate: u.PrivateBrowsingUtils.isContentWindowPrivate(trg.ownerGlobal) }); } checkTextLinkyTool(doc) { if (doc.title || !doc.documentURI.startsWith("moz-extension:")) return; var lab = doc.querySelector("body > label#lblFrom:first-child")?.textContent; if (lab) doc.title = lab.slice(0, lab.lastIndexOf("(")); } } if (!ChromeUtils.domProcessChild.childID) { ChromeUtils.registerWindowActor("MouseImgSaver", { allFrames: true, parent: {moduleURI: __URI__}, messageManagerGroups: ["browsers"], child: {moduleURI: __URI__, events: {auxclick: {capture: true}, dblclick: {capture: true}, dragstart: {capture: true}}} }); var wref, data = Object.assign(Object.create(null), { "browser.download.dir": {type: "String", get set() { try {var dir = wref.get().Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = wref.get().Services.dirsvc.get("DfltDwnld", Ci.nsIFile);}; var pics = wref.get().Services.prefs.getStringPref("ucf_save.dirs", "_Web||_Images|1").split('|'); dir.append(pics[2]); dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… var {path} = dir; // папка Загрузки:/_Images/[title]/файл Object.defineProperty(this, "set", {get() { var win = wref.get(); var title = pics[3] ? win.gBrowser.selectedTab.label.slice(0, 100) : ''; // папка = имя вкладки return PathUtils.join(path, win.DownloadPaths.sanitize(title)); }}); return this.set; }}, "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true} }); var MouseImgSaverParent = class extends JSWindowActorParent { receiveMessage(msg) { var {url, contentType, contentDisposition, sx, isPrivate, referrerInfo, cookieJarSettings} = msg.data; var win = msg.target.browsingContext.topChromeWindow; if (sx && sx > win.mozInnerScreenX + win.innerWidth) return; wref = Cu.getWeakReference(win); var p = win.Services.prefs; 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 {win.internalSave( url, null, // document null, // file name contentDisposition, contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data u.E10SUtils.deserializeReferrerInfo(referrerInfo), u.E10SUtils.deserializeCookieJarSettings(cookieJarSettings), win.document, // initiating doc true, // skip prompt for where to save null, // cache key isPrivate, win.document.nodePrincipal );} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } } } }
Отсутствует
Думаю да. Добавил в 78 в custom_script_win.js — выглядит рабочим.
Только исключение тэгов для "bookmark-added" потерялось. Можно вписать.
Спасибо. Я его в custom_script.js пихал, вот он и не работал. Теперь нормально все.
Отсутствует
Если изменить опции в about:config, то скрипт по-прежнему сохраняет в старую папку.
Dumby - помоги доработать код, чтобы при каждой записи файла путь брался из опции "ucf_save.dirs"
Если такой опции нет, берётся значение по-умолчанию. Мои изменения в коде: строка 100 и далее…
Во навернул идею. Хорошо бы поподробнее. Может так
/* try {var dir = wref.get().Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = wref.get().Services.dirsvc.get("DfltDwnld", Ci.nsIFile);}; var pics = wref.get().Services.prefs.getStringPref("ucf_save.dirs", "_Web||_Images|1").split('|'); dir.append(pics[2]); dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… var {path} = dir; // папка Загрузки:/_Images/[title]/файл Object.defineProperty(this, "set", {get() { var win = wref.get(); var title = pics[3] ? win.gBrowser.selectedTab.label.slice(0, 100) : ''; // папка = имя вкладки return PathUtils.join(path, win.DownloadPaths.sanitize(title)); }}); return this.set; */ var win = wref.get(); var {DownloadPaths} = win, {prefs, dirsvc} = win.Services; var map = val => DownloadPaths.sanitize(val); Object.defineProperty(this, "set", {get() { try {var dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "||_Images|1").split('|').slice(2, 4); arr[0] ??= ""; // Hmm... arr[1] ??= wref.get().gBrowser.selectedTab.label.slice(0, 100); // имя вкладки arr.map(map).forEach(dir.append); dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… return dir.path; }}); return this.set;
Отредактировано Dumby (20-05-2021 22:38:05)
Отсутствует
Dumby - Спасибо! А у меня ещё актуальная хотелка по скрипту сохранения картинок перетаскиванием:
На некоторых картинках есть всплывающая подсказка-описание 1) Если tooltip картики есть, то нужно сохранять картинку с именем всплывающей подсказки.
2) на двойной клик мыши надо "повесить" другую полезную функцию на твоё усмотрение. Желательно поиск дубликата этой картинки в Яндекс. ну или перезагрузку картинки (то есть обновить её).
var EXPORTED_SYMBOLS = ["MouseImgSaverChild", "MouseImgSaverParent"]; // сохранить картинку — перетащив вправо; двойным кликом; колёсиком var u = {get it() { delete this.it; return this.it = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools); }}; for(let name of ["E10SUtils", "PrivateBrowsingUtils"]) ChromeUtils.defineModuleGetter(u, name, `resource://gre/modules/${name}.jsm`); class MouseImgSaverChild extends JSWindowActorChild { handleEvent(e) { // клики мышью if (e.button > 1) return; // только ЛКМ, СКМ var trg = e.explicitOriginalTarget; trg.nodeType == Node.ELEMENT_NODE && trg instanceof Ci.nsIImageLoadingContent && this[e.type](trg, e); } handleDragEvent(e) { this[e.type](e); } dragstart(trg, e) { this.trg = trg; this.x = e.screenX; this.y = e.screenY; this.drag("add"); this.handleEvent = this.handleDragEvent; this.checkTextLinkyTool(trg.ownerDocument); } events = ["dragover", "drop", "dragend"]; drag(meth = (delete this.handleEvent, delete this.trg, "remove")) { meth += "EventListener"; var win = this.contentWindow; for(var type of this.events) win[meth](type, this, true); } drop() { this.drag(); } dragover(e) { var {x, y} = this, cx = e.screenX, cy = e.screenY, dx = cx - x, ax = Math.abs(dx), ay = Math.abs(cy - y); if (ax < 10 && ay < 10) return; if (dx < 0 || ax < ay) return this.drag(); this.x = cx; this.y = cy; } dragend(e) { var dt = e.dataTransfer, {trg} = this; this.drag(); dt.mozUserCancelled || this.send(trg, e.screenX); } auxclick(trg) { // клик СКМ trg.matches(":any-link :scope") || this.send(trg); } dblclick(trg) { // ЛКМ trg.matches(":any-link :scope") || this.send(trg); } send(trg, sx) { var uri = trg.currentURI; if (!uri) return; var doc = trg.ownerDocument; var cookieJarSettings = u.E10SUtils .serializeCookieJarSettings(doc.cookieJarSettings); var referrerInfo = Cc["@mozilla.org/referrer-info;1"] .createInstance(Ci.nsIReferrerInfo); referrerInfo.initWithElement(trg); referrerInfo = u.E10SUtils.serializeReferrerInfo(referrerInfo); var contentType = null, contentDisposition = null; try { var props = u.it.getImgCacheForDocument(doc).findEntryProperties(uri, doc); var cs = Ci.nsISupportsCString; try {contentType = props.get("type", cs).data;} catch {} try {contentDisposition = props.get("content-disposition", cs).data;} catch {} } catch {} this.sendAsyncMessage("", { url: (trg.currentRequestFinalURI || uri).spec, contentType, referrerInfo, cookieJarSettings, contentDisposition, sx, isPrivate: u.PrivateBrowsingUtils.isContentWindowPrivate(trg.ownerGlobal) }); } checkTextLinkyTool(doc) { if (doc.title || !doc.documentURI.startsWith("moz-extension:")) return; var lab = doc.querySelector("body > label#lblFrom:first-child")?.textContent; if (lab) doc.title = lab.slice(0, lab.lastIndexOf("(")); } } if (!ChromeUtils.domProcessChild.childID) { ChromeUtils.registerWindowActor("MouseImgSaver", { allFrames: true, parent: {moduleURI: __URI__}, messageManagerGroups: ["browsers"], child: {moduleURI: __URI__, events: {auxclick: {capture: true}, dblclick: {capture: true}, dragstart: {capture: true}}} }); var wref, data = Object.assign(Object.create(null), { "browser.download.dir": {type: "String", get set() { var win = wref.get(); var {DownloadPaths} = win, {prefs, dirsvc} = win.Services; var map = val => DownloadPaths.sanitize(val); Object.defineProperty(this, "set", {get() { try {var dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(2, 4); // [Загрузки]/папки ucf_save/файл arr[1] = (arr[1]) ? wref.get().gBrowser.selectedTab.label.slice(0, 64).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim() : ""; // имя вкладки arr.map(map).forEach(dir.append); // ucf_save.dirs: путь для html|имя или домен|папка графики|имя вкладки dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… return dir.path; }}); return this.set; }}, "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true} }); var MouseImgSaverParent = class extends JSWindowActorParent { receiveMessage(msg) { var {url, contentType, contentDisposition, sx, isPrivate, referrerInfo, cookieJarSettings} = msg.data; var win = msg.target.browsingContext.topChromeWindow; if (sx && sx > win.mozInnerScreenX + win.innerWidth) return; wref = Cu.getWeakReference(win); var p = win.Services.prefs; 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 {win.internalSave( url, null, // document null, // file name contentDisposition, contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data u.E10SUtils.deserializeReferrerInfo(referrerInfo), u.E10SUtils.deserializeCookieJarSettings(cookieJarSettings), win.document, // initiating doc true, // skip prompt for where to save null, // cache key isPrivate, win.document.nodePrincipal );} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } } } }
…чтобы при каждой записи файла путь брался из опции "ucf_save.dirs"
Во навернул идею. Хорошо бы поподробнее.
Логика такая: мои скрипты берут из опций браузера пути сохранения страниц/картинок/(медиа).
Пользователь может указать в опциях кнопки Quick Toggle свои папки для сохранения файлов.
Например, имена картинок часто безсмысленные, поэтому лучше создавать папку с именем вкладки.
Синтаксис массива опции выбрал такой: папка|subdir: папка с именем вкладки или домена.
subdir [пусто|0 имя вкладки|1 домен т.е. dns.ru]. Если элемент массива пуст, папка не создаётся.
пример: "_Web|1|_Pics|0" для html запись в [Загрузки]/_Web/домен. Картинки в [Загрузки]/_Pics/имя вкладки.
var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(2, 4); // [Загрузки]/папки ucf_save/файл arr[1] = (arr[1]) ? wref.get().gBrowser.selectedTab.label.slice(0, 64).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim() : ""; // имя вкладки arr.map(map).forEach(dir.append); // ucf_save.dirs: путь для html|имя или домен|папка графики|имя вкладки return dir.path;
(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 Обзор папки [Загрузки] Ролик: Сохранить как файл .txt …Shift Сайт: графика Вкл/Выкл СКМ или Тащить рисунок вправо: …cохранить в [Загрузки]/_Images Alt⇧S нажать кнопку SingleSave` // нет SingleSave - выполнить save() pui.tooltipText = `ЛКМ: меню приложения ПКМ: ⇲ Свернуть окно …Alt Персонализация Ролик: Закрыть браузер` var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } }, 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); } 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("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 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); // [Загрузки]/папки ucf_save/файл arr[1] = (arr[1] == "0") ? Title(100) : (arr[1] == "1") ? Title(-1) : ""; // имя вкладки или домен arr.forEach(dir.append); // ucf_save.dirs: путь для html|имя или домен|папка графики|имя вкладки 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); 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) e.shiftKey // middle ? null : close() else if (e.button == 2) if (e.altKey) return else event.stopPropagation(), window.minimize(); }, // end Clicks keydown_win = e => { // нажатие клавиш if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return; var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID }, {prefs, dirsvc} = Services, tmax = btn.tooltipText.split("\n")[0].length, dw; btn.setAttribute("context", "event.stopPropagation()"); prefs.setBoolPref("browser.download.autohideButton", false); // не скрывать кнопку Загрузки 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}) => { 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
Dumby ты делал запуск js-кода в строках меню Quick Toggle. Так не пашет: this, node.parentNode.parentNode, …
Подскажи, как открыть вкладку с адресом? Я получаю ошибку: e.view is undefined
// строка 54 кнопки https://forum.mozilla-russia.org/viewtopic.php?pid=789824#p789824 [`_Web|1|_Images|0`, "ввести свои пути",,,`this.switchToTab("about:config", Services.wm.getMostRecentWindow("navigator:browser"))`]] … … … switchToTab(url, e = this) { // открыть вкладку | закрыть, если открыта 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()});
Отредактировано Dobrov (21-05-2021 16:35:33)
Отсутствует
Подскажите, почему я не могу обратиться к DOM-элементам страницы из кнопки или из Browser Console (CTRL+SHIFT+J)?
Пишет, что селектор null.
А из WEB Console (CTRL+SHIFT+K) команда прекрасно работает.
Вот, допустим, на этой же страницы ввести что-нибудь в "Быстрый ответ".
Как можно свободно обращаться к элементам DOM?
Отсутствует
Dumby – ещё хотелка - нужна Кнопка, которая отвечает за вид страницы, то есть переключает 1) режим чтения вкл/выкл 2) стиль страницы обычный/зелёный 3) масштаб с отображением процентов на кнопке 4) прочие функции, например переключить показ картинок, отключить стили страницы, гугл-перевод сайта/выделенного текста и т.п.
Режимы должны отображаться на иконке - 0) Обычный режим - родная иконка 1) Режим чтения - к иконке применён/отключен красный фильтр "filter: hue-rotate(90deg)" 2) если переключен стиль страницы, к иконке добавляется/отключается фон: background-image
Переключение вида иконки также должно происходить при переходе по вкладкам - то есть, если переходим на вкладку about:reader, то иконка кнопки должна смениться - к ней должен добавиться красный фильтр.
Эта моя кнопка из старого профиля для Basilisk, но адаптировать её сложно.
@-moz-document url-prefix("http"), url-prefix("https"), url-prefix("ftp"), url-prefix("file") { html *, html { background: #ccd1d1 !important; text-shadow: none !important; color: #000000 !important; -moz-border-top-colors: #8FBC8F !important; -moz-border-bottom-colors: #8FBC8F!important; -moz-border-left-colors: #8FBC8F !important; -moz-border-right-colors: #8FBC8F !important; } code, pre, input, samp, kbd, var, dfn,.postright { -moz-appearance: none !important; background-color: #BADBAD !important; } input, select, textarea, button { -moz-appearance: none !important; border: 1px solid #BADBAD !important; background-color: #BADBAD !important; } .codebox, BLOCKQUOTE, TEXTAREA, .spoiler { -moz-border-top-colors: #444 !important; -moz-border-bottom-colors: #444 !important; -moz-border-left-colors: #444 !important; -moz-border-right-colors: #444 !important; } a:link { color: #300090 !important; } a:visited { color: #489412 !important; } a:active { color: #d81e1e !important; } a:hover { color: #d81e1e !important; } }
const greenbg = "background-image: -moz-linear-gradient(#c0c8c0, #c0c8c0, #c0c8c0);"; function icon_color( icon, image, num, bg, setAttr) { bg = bg || ''; setAttr = setAttr || true; // запомнить настройки if (num == 1) { // зелёный + фильтр (если указан) icon.style.cssText = "background-image: none; filter: unset;" + bg; } else if (num == 2) { // красный icon.style.cssText = "filter: hue-rotate(90deg);" + bg; } else if (num == 3) { // серый icon.style.cssText = "filter: grayscale(100%) invert(40%) contrast(300%);"; } else if (num == 4) { // добавить фон icon.style.cssText = iconbutton.getAttribute('style').toString() +' '+ greenbg; } else if (num == 5) { // зелёный <> красный переключить цвет if ( /hue-rotate\(90deg\)/.test(icon.style.cssText) ) // красный icon_color( iconbutton, self.image, 1, iconbutton.getAttribute('bg').toString(), false) else icon_color( iconbutton, self.image, 2, iconbutton.getAttribute('bg').toString(), false); } else { self.image = this.image; // сброс icon_color( iconbutton, self.image, 1) // return; } if (!setAttr) return; // режим уже запомнен iconbutton.setAttribute('color', num); // запомнить режим iconbutton.setAttribute('style', icon.style.cssText); // запомнить режим iconbutton.setAttribute('bg', /linear-gradient/.test(icon.style.cssText)); // false: нет фона, true: есть };
try { CustomizableUI.createWidget({ tooltiptext: `ЛКМ: Reader`, type: "custom", id: "ucf_Reader", label: "Reader", localized: false, 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("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACTElEQVR4Ad1VIbCjMBBFIpHISCQSiUQiK5FIJBJZiaxEVpxAIpFI5JdfVpyoO1Ry76XZmcz8tP/uy2ZmmzD73tvNZpNG7zfquk4x1iRJjFJqwohf4YEZgT/IIffbAABOmIwYBPoX4p2PJffb7OM4vmN5gHwlid+hzKqqIvbmkpjJCWO9kWVZQwLKsxljYs4gmbIss0CADD5idwxiV3KdRngANPtlgbCCVc/wRVFUElzKBY3lWXkUtwg7hPQ/gxxwpUwqdGBSnjX64ZAyQasNORc68zwfmqbJ2rZN/1W467qUHHKDZcKB2fJI18hW0XYzfE/LRR87SDi+BjXD/UyLY1kzmxvqmwdqnsP3GeLQqPmldqlSurtMetx2PcyLzopSS9viRicoQUHjGmOjjxhiySGXGt5ZutPHJeHTQNB8GD3fjeE8fd61ynPtbunO2V/TR4zPoQa14H90o3RP1bQW+Ov3YcT43Y4XGyBk9BFzvT3wnPkNLUmqiXD6dqsdwXcJ8McasxrXTQIcKE9D4xpGHznAegGg0bmk0Il7hJ/tkc2IbPwAFmzOy+rX1D8z+r4G8HZNbZboxI+yPrlaWqCATXMepe6jBHBr6yNG8ORSozydbABq85DliTDDddaLd2CX/YNdYdwFLCWAWxv6iJFDJpca0PJfYWakBkx8Pk3d9boHqDmf/ZabA/8bswtCrOWQSw2X/eBf9RiEq9ch2rtoG15N/9mQXaT0hTjQmvq+j0P/By0if3CLmG+wAcGTF29QQgyx7H3wd2pEbzX+AiHuFSjoQ3KFAAAAAElFTkSuQmCC")', "important"); trbn.addEventListener("click", function(e) { var win = e.view, dirs; if (e.button == 0) { var green = ` @-moz-document url-prefix("http"), url-prefix("https"), url-prefix("ftp"), url-prefix("file") { html *, html { color: #800000 !important; }}`; var sss = this.sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var uri = this.uri = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI("data:text/css,"+ encodeURIComponent(green),null,null); function setStyleForPages( reason ) { var style = sss.sheetRegistered(uri, sss.AGENT_SHEET); style ? sss.unregisterSheet(uri, sss.AGENT_SHEET) : sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET); }; setStyleForPages(); return; } }, false); return trbn; }, }); } catch(e) {}
2) Как показать текст в строке статуса в течении 5 секунд ? (строка, которая появляется при наведении на ссылку)
Отредактировано Dobrov (22-05-2021 02:05:31)
Отсутствует
Переложите, пожалуйста, custom_buttons-0.0.7.0.0.17-fx-paxmod.xpi. Спасибо
Отсутствует
Dumby делаю GetSelectionText для loadFrameScript - функция получает выделенный текст для перевода в гугле, яндексе и т.п.
Но пока нужные команды обработки текста приходится вставлять в ту же функцию, которая получает текст.
1) как без использования add…Listener получить данные от FrameScript-функции, например так: GoogleTranslate(GetSelectionText())
2) из FrameScript не работает gBrowser - должна открыться вкладка Перевода выделенного текста
translate(browserMM, win, e, go) { // вариант browserMM.addMessageListener('getSelect', function listener(msg) { = команды обработки msg.data = browserMM.removeMessageListener('getSelect', listener, true); }); browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false); }, this.translate(gBrowser.selectedBrowser.messageManager, win, this, 1)
Отредактировано Dobrov (22-05-2021 16:52:33)
Отсутствует