не работает функция перезапуска
Да, BrowserUtils изрядно покромсали.
Ещё, смотрю, на 89, так сделанный alert/confirm
уходит в ихний новомодный внутриоконный вариант,
что не очень хорошо сочетается с незакрывающимся меню.
Вобщем, такая правка
/* maybeRestart(node, conf) { var msgRest = "Перезапустить браузер?", msgAbort = "Запрос на выход отменен."; if (pv >= 77) { var title = node.closest("toolbarbutton").label; var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({ domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW }); var confirm = win => pp(win).confirm(title, msgRest); var alert = win => pp(win).alert(title, msgAbort); } else { var confirm = win => win.confirm(msgRest); var alert = win => win.alert(msgAbort); } return (this.mayBeRestart = (node, conf) => { var win = node.ownerGlobal; if (conf && !confirm(win)) return; if (win.BrowserUtils.restartApplication() === false) alert(win); else return true; })(node, conf); }, */ 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); },
Отсутствует
Dumby просьба «косметически» доработать кнопку Quick Toggle about:config
я добавил скобки [] для строк меню, преф которых не существует (по-умолчанию).
Есть строки, требующие перезапуск браузера или обновление страницы. «Название меню» и «Значение» разделены тире —.
Нужно вместо тире — для строк, требующих refresh, подставлять например символ «⩫»; а для restart символ «↯»
чтобы строка, запрашивающая например перезапуск (restart), выглядела так: Провайдер DNS ↯ Cloudflare
// строка 400 кнопки https://forum.mozilla-russia.org/viewtopic.php?pid=789824#p789824 lab += ` — "${sfx}"`; // тире - обычный параметр, ⩫ требуется обновить страницу, ↯ нужен перезапуск браузера
Отсутствует
я добавил скобки [] для строк меню, преф которых не существует
Так и это, вроде как, не сложнее
Отсутствует
Deriax пишет14f477a2ce81.png
Фу, в переводе это выглядит ещё более непонятно, чем в оригинале.
На самом деле, cookieStoreId — это всего лишь id'шник контейнера,
то есть, всего лишь уточняющий параметр для cookies.get() (и компании), не более того.Типа — кука, именуемая так-то, с урлом каким-то эдаким, ограниченная контейнером (cookieStoreId) таким-то.
Еще раз: никакого «Хранилища файлов cookie вкладки» (так, как это звучит!) не существует.
Пожалуйста, подскажите как получить id контейнера, вообще как это выглядит? Нашёл такое расширение,
https://chrome.google.com/webstore/detail/cookie-tab-viewer/fdlghnedhhdgjjfgdpgpaaiddipafhgk
функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (
Отредактировано Deriax (07-05-2021 12:52:42)
Отсутствует
вообще как это выглядит?
В реальности — это атрибут "usercontextid" <tab>'а и <browser>'а.
Выглядит как число.
А в WebExtensions представлении — ну, смотри сам.
Допустим, например:
Открываем какое-то количество вкладок, в разных контейнерах и не в контейнере.
Берём аддон с нужными permissions и переходим на любой его moz-extension://… адрес.
Открываем там веб-консоль (Ctrl+Shift+K), запускаем код типа такого и смотрим результат.
(await browser.tabs.query({})) .map(tab => tab.cookieStoreId.padEnd(30) + tab.title.slice(0, 100)) .join("\n");
функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (
Может официальный пример немного прояснит.
Отсутствует
Deriax пишетвообще как это выглядит?
В реальности — это атрибут "usercontextid" <tab>'а и <browser>'а.
Выглядит как число.А в WebExtensions представлении — ну, смотри сам.
Допустим, например:
Открываем какое-то количество вкладок, в разных контейнерах и не в контейнере.
Берём аддон с нужными permissions и переходим на любой его moz-extension://… адрес.
Открываем там веб-консоль (Ctrl+Shift+K), запускаем код типа такого и смотрим результат.
[spoiler]Выделить кодКод:
(await browser.tabs.query({})) .map(tab => tab.cookieStoreId.padEnd(30) + tab.title.slice(0, 100)) .join("\n");
функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (
Может официальный пример немного прояснит.
[/spoiler]
На будущее может пригодиться.
Отредактировано Deriax (11-05-2021 19:11:23)
Отсутствует
Dumby - спасибо, кнопку переключения настроек обновил.
Почините скрипт Save HTML, он не работает в Firefox 78 ESR, ошибка консоли: IOUtils is not defined
(async (id, func) => { // дополнительные клики на downloads-button для custom_script_win.js await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"); if (!btn) return; btn.setAttribute("context", "event.stopPropagation()"); // откл контекстное меню btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +` ПКМ: Сохранить единый .html …Shift Обзор папки «Загрузки» Ролик: Сохранить как файл .txt всё | выделенный текст …Shift Сайт: графика Вкл/Выкл Alt⇧S нажать SingleSave`; // если такой кнопки нет, то выполнить save() var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } } var 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 var save = async () => { // автор: Лекс, правка: Dumby, Dobrov var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); }; var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен var path = PathUtils.join(savedir, fileName); await IOUtils[write](path, fileContent); var d = await Downloads.createDownload({ source: "about:blank", target: FileUtils.File(path)}); (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 var listener = e => { // Clicks var trg = e.target, {prefs} = Services; 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 } } var 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 } btn.addEventListener("click", listener); 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); 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 {} }; var getSelWin = function (w) { if (w.getSelection().toString()) return w; for (var i = 0, f, r; f = w.frames[i]; i++) { try { if (r = getSelWin(f)) return r; } catch(e) {} } }; var 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; }; var 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'; } }; var 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); var meta = doc.createElement('meta'); meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); var title = doc.getElementsByTagName('title')[0]; if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (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); }; var sheets = doc.styleSheets; 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().toLocaleString("ru").replace(", ","-").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
Отсутствует
куки нужной активной вкладки, как это реализовать через xpcom или модуль Services?
Без понятия что значит «куки вкладки», вообще кук не держу.
Возможно что-то типа такого
var {host, originAttributes} = gBrowser.contentPrincipal; var cookies = Services.cookies.getCookiesFromHost(host, originAttributes); var resultAsJSON = JSON.stringify(cookies, null, "\t"); gBrowser.selectedTab = gBrowser.addTrustedTab( "data:text/plain;charset=utf-8," + encodeURIComponent(resultAsJSON) );
Почините скрипт Save HTML, он не работает в Firefox 78 ESR
Что значит «почините»?
Он и не должен работать «в Firefox 78».
Можно попробовать добавить перед строкой с ошибкой
… if (typeof IOUtils != "object") { 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))}; }
Отсутствует
Deriax пишеткуки нужной активной вкладки, как это реализовать через xpcom или модуль Services?
Без понятия что значит «куки вкладки», вообще кук не держу.
Возможно что-то типа такогоскрытый текстВыделить кодКод:
var {host, originAttributes} = gBrowser.contentPrincipal; var cookies = Services.cookies.getCookiesFromHost(host, originAttributes); var resultAsJSON = JSON.stringify(cookies, null, "\t"); gBrowser.selectedTab = gBrowser.addTrustedTab( "data:text/plain;charset=utf-8," + encodeURIComponent(resultAsJSON) );Dobrov пишетПочините скрипт Save HTML, он не работает в Firefox 78 ESR
Что значит «почините»?
Он и не должен работать «в Firefox 78».
Можно попробовать добавить перед строкой с ошибкойскрытый текстВыделить кодКод:
… if (typeof IOUtils != "object") { 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))}; }
Как исправить эту ошибку?
gBrowser.addTrustedTab is not a function
Отсутствует
Dumby - ваш код IOUtils как всегда идеален!
А есть варианты, как Сохранить картинку без запроса для user_chrome_files?
Лучше жестом или двойным кликом мыши или из контекстного меню (но это дольше).
Не работают: user-скрипт MouseGestures2_e10s.uc.js и CB Сохранить изображение без запроса…
Отсутствует
Как исправить эту ошибку?
gBrowser.addTrustedTab is not a function
Не может быть такой ошибки.
Ну, если только использовать Firefox древнее чем 63,
что было бы более чем странно. (в смысле не написать об этом).
Не работают: ... и CB Сохранить изображение без запроса…
На 90.0a1 работает.
Только, обычная (теперь уже), проблема с сепараторами, и настройку включить надо.
Для ucf? Например, вариант
(async sel => { var path = "E:\\Download"; var menuitem = document.createXULElement("menuitem"); document.querySelector(sel).before(menuitem); var {render} = menuitem.constructor.prototype; menuitem.render = () => { menuitem.className = "menuitem-iconic"; menuitem.setAttribute("oncommand", "saveImg()"); menuitem.setAttribute("label", "Сохранить изображение в папку: " + path); menuitem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABAnAAAQJwAAAAAAAAAAAAAAAAEGAQECKAABATsAAAAoAAAAFAAAAAkAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjRRXUVtk8U+Y4TGKUBYrRgmNpcOFR91BQgMWAECBD8AAQEqAAAAGAAAAAwAAAAGAAAAAQAAAAAAAAAAAAAAAEVrp7Nws9//fcr6/3W+9f5wten5ZKHQ7lWGsedDaI7QL0hjtR4sQKERGSaBBgkOXgAAACoAAAAEAAAAAAAAAABKdrK+aqjY/4XO7P+AyfL/fcXy/4HL+/97xPT/eMHy/3e+8f9trt77YpvI8Ux0m98TGymTAAAAJQAAAAAAAAAAVIS7yGWh0/8yTVv/UniH/0htff+L0e//WIab/0x2i/9XiKL/RGp+/zNRYv9dkrP+S26S2QQGClwAAAAGAAAAAGeYxtFxrtr/IDA7/01mbf8sPkP/SWZw/zlSWv88Vl//LkRL/3Wsv/83UVr/XYqe/3+51PQaJDCWAAAAGwAAAAB5qtHajMXk/yY1Pf9fa23/GB8g/2yGjP8mMDL/Sl9k/0RYXP9wmKL/dZ+r/4i6y/+n4PD+TmV5yQECA0UAAAACh7bX46zh8/9tjZj/gpen/4GMk//G4Oj/kJ6f/52clf+svbz/f5id/3yXnv+gx9L/wez1/5u0xuwPExt+AAAAEJTA3ey/7vr/ve35/7Hf8v+w0ub/ubvE/8a4uf/NwLv/083I/9Pl6//T7ff/0O32/9fw9v/a6vL8P0ZYtAAAAC+iy+P2zvX8/831/P/K6e3/y7Kg/+GNZf/vlWr/6Zx3/9qegv/Ino7/t8TQ/7HM4/+itc3yu8ja52BtirQAAAEkqs/l9dv8/f/b/P3/1dzU/9qXcf/slmb/+aFr//+td//+rXb/+aRu/9+1k/+/2uL/RldrtiIrPU0ZITEoAAAAA46017zX8Pf85/7+/+X8+//g7+3+yryw+O6odPz/wYj/9bJ7/+KpgP/nqn3/0tPJ/kRTY6QAAQEYAAAAAAAAAAA6V3Yuboyqj6C81My50ubgo7zR1I92bLbzt3/3/tGZ/8aTZttfY2+PbX2Sn3GFm7EiLDtNAAAABQAAAAAAAAAAAgMEAAUHCgYYJDETIS4+LjMwNU+3e029/NGZ/vHHlPRrSSx/BQUFEAMFBwcEBQcJAQECAgAAAAAAAAAAAAAAAAAAAAAAAAAAEQgAA1wvElSsaz3B9LZ8+fC7gu6WZ0COFg0GGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcTAQrWbS+y7pdZ8eOVWMqUWy91IRIJFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AACf/wAAgH8AAIAfAACADwAAgA8AAIAHAACABwAAgA8AAIAPAADOHwAA/v8AAP//AAD//wAA//8AAA=="); menuitem.saveImg = () => { var p = Services.prefs; var data = Object.assign(Object.create(null), { "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true}, "browser.download.dir": {type: "String", set: path} }); var save = eval(`(function ${gContextMenu.saveMedia})`.replace( "\n false, // don't", "\n true, //" )); (menuitem.saveImg = () => { for(var pref in data) { var obj = data[pref], meth = `et${obj.type}Pref`; obj.val = p.prefHasUserValue(pref) ? p["g" + meth](pref) : null; p["s" + meth](pref, obj.set); } try {save.call(gContextMenu);} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } })(); } (menuitem.render = async () => { render.call(menuitem); var {context, browser} = nsContextMenu.contentData || {}; menuitem.hidden = !context?.onImage || browser.classList.contains("webextension-popup-browser"); })(); } })("#context-viewimageinfo, #context-viewimagedesc");
Отсутствует
Только, обычная (теперь уже), проблема с сепараторами, и настройку включить надо
Какую настройку? Скрипт подключил в custom_script_win.js, работает нормально, но папку загрузок пришлось получать вот таким неправильным кодом:
// var path = Services.downloads.userDownloadsDirectory.path; // ошибка получения пути «Загрузки», так не работает var {prefs} = Services; var path = prefs.getStringPref("browser.download.lastDir", Services.dirsvc.get("Desk", Ci.nsIFile).path); // так не работает, если папка Загрузки не выбрана
Сохранить изображение без запроса…
клики и жесты, ну ты же понимаешь, что изображение в другом процессе?
В два действия из контекстного меню слишком долго! Кроме того, на картинках-ссылках появляется второй сепаратор.
А есть код: Сохранить картинку без запроса перетаскиванием вправо или двойным кликом? Желательно в папку <Загрузки>/_Images
Второй вопрос: сделал код Автоскрытие панели вкладок, панель переключается нормально, когда код в кнопке CustomButtons.
Но ничего не происходит при подключении этого кода в custom_script_win.js или custom_script.js (напрямую или через loadscript).
(url => { // автоскрытие панели вкладок. aris-t2/customcssforfx > TABS BELOW TITLEBAR (Fx56-like) var IdHeight = function (id_name, height) { document.getElementById(id_name).style.cssText = `min-height: ${height}px !important; max-height: ${height}px !important;`; } var TabCollapsed = function (tabs, nav_h, tab_h) { // пока только для панели вкладок в один ряд if (tabs == 1) bar.collapsed = true, IdHeight("navigator-toolbox", nav_h - tab_h); if (tabs == 2) bar.collapsed = false, IdHeight("navigator-toolbox", nav_h); } var num = gBrowser.tabs.length, bar = document.getElementById("TabsToolbar"), nav = document.getElementById("navigator-toolbox"); this.hasAttribute("nav_h") ? null : this.setAttribute("nav_h", nav.clientHeight); this.hasAttribute("tab_h") ? null : this.setAttribute("tab_h", bar.clientHeight); var nav_h = this.getAttribute("nav_h"), tab_h = this.getAttribute("tab_h"); addEventListener("TabOpen", () => { TabCollapsed(++num, nav_h, tab_h); }, false, gBrowser.tabContainer); addEventListener("TabClose", () => { TabCollapsed(--num, nav_h, tab_h); }, false, gBrowser.tabContainer); var type = windowUtils.USER_SHEET; windowUtils.loadSheetUsingURIString(url, type); TabCollapsed(num, nav_h, tab_h); addDestructor(() => { windowUtils.removeSheetUsingURIString(url, type); TabCollapsed(2, nav_h, tab_h); }); })("data:text/css;charset=utf-8,%23TabsToolbar[collapsed]:not([customizing]){visibility:collapse!important;}");
Отредактировано Dobrov (10-05-2021 11:40:26)
Отсутствует
А есть код: Сохранить картинку без запроса перетаскиванием вправо или двойным кликом? Желательно в папку <Загрузки>/_Images
Извиняюсь, что лезу, но Вам принципиально, чтоб это было реализовано скриптом? А то в аддоне Image Picka, на который я раньше давал ссылку, настройка Show a download button on hover создаёт над изображением кнопку, с которой можно сохранять без запроса.
Отсутствует
kazarin
расширения бесполезны на страницах moz-extension://… Если сайт скрывает картинки под div, сохранить их можно так:
Клик по кнопке Text Linky Tool покажет всю, даже скрытую графику, а расширение Pick Images таких картинок не найдёт.
Думаю, код user-chrome_files Сохранить картинку без запроса перетаскиванием или двойным кликом будет работать на странице найденных картинок moz-extension://…, открытой расширением Text Linky Tool.
Ведь скрипт Save HTML без проблем сохраняет страницы из режима просмотра about:reader, где расширение SingleFile и подобные не работают!
Отсутствует
Dobrov
Я бы на этой странице сделал так:
https://www.upload.ee/files/13132535/Video_2021-05-11_064226.wmv.html
Если правильно понимаю, это сайт из той же группы, что и предыдущий, дораматв? Там через Image Picka можно получить список урлов.
https://www.upload.ee/files/13132548/Video_2021-05-11_065220.wmv.html
Ну и расширение DownThemAll от xiaoxiaoflood на этой странице работает.
Если будет ещё и скрипт, хорошо, но, кмк, и одного расширения достаточно для этой работы
Отсутствует
Какую настройку?
Которая возвращает в строй пункт «Информация об изображении».
browser.menu.showViewImageInfo (Firefox 89+).
на картинках-ссылках появляется второй сепаратор
Не вижу такого. Хотелось бы думать,
что это из-за какого-то другого добавленного пункта.
А есть код: Сохранить картинку без запроса перетаскиванием вправо
Ну, вообще-то, dataTransfer в родительском процессе есть.
И focused (content) browsingContext (Firefox 85+).
Можно попробовать прицепиться, но не уверен.
(async id => { var path = "E:\\Download"; await delayedStartupPromise; var listener = { handleEvent(e) { this[e.type](e); }, dragstart(e) { if ( e.dataTransfer.mozItemCount && gBrowser.selectedBrowser.matches(":hover") && e.dataTransfer.getData("text/x-moz-url-data") ) this.x = e.screenX, this.y = e.screenY, this.drag("add"); }, events: ["dragover", "drop", "dragend"], drag(meth = "remove") { meth += "EventListener"; for(var type of this.events) window[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; this.drag(); if (dt.mozUserCancelled || e.screenX > mozInnerScreenX + innerWidth) return; var url, name = null; if (dt.types.contains("application/x-moz-nativeimage")) url = dt.getData("application/x-moz-file-promise-url"), name = dt.getData("application/x-moz-file-promise-dest-filename"); else { var html = dt.getData("text/html"); if (html) url = new DOMParser().parseFromString( `<template>${html}</template>`, "text/html" ).querySelector("template").content.querySelector("img")?.src; } url && this.save(url, name); }, save(url, name) { var p = Services.prefs; var data = Object.assign(Object.create(null), { "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true}, "browser.download.dir": {type: "String", set: path} }); var refp = "network.http.sendRefererHeader"; var ReferrerInfo = Components.Constructor( "@mozilla.org/referrer-info;1", "nsIReferrerInfo", "init" ); var {fetch} = Cu.getGlobalForObject(Cu); (this.save = async (url, name) => { var bc = Services.focus.focusedContentBrowsingContext; var http = url.startsWith("http"); var referrerInfo = null; if (bc && http && Services.prefs.getIntPref(refp) != 0) { var ref = bc.currentURI; if (ref.spec.startsWith("http")) referrerInfo = new ReferrerInfo(Ci.nsIReferrerInfo.EMPTY, true, ref); } var contentType = this.getContentType(name && http ? "http://example.com/" + name : url); if (!contentType) {try { var arr = new Uint8Array(await (await fetch(url)).arrayBuffer()); contentType = Cc["@mozilla.org/image/loader;1"] .createInstance(Ci.nsIContentSniffer) .getMIMETypeFromContent(null, arr, arr.length); } catch {}} 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 {internalSave( url, null, // document name, // file name null, // contentDisposition contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data referrerInfo, bc?.currentWindowGlobal?.cookieJarSettings, document, // initiating doc true, // skip prompt for where to save null, // cache key bc?.usePrivateBrowsing, 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); } })(url, name); }, getContentType(url) { var re = /^data:(image\/[^;,]+)/; var ms = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); return (this.getContentType = url => { if (re.test(url)) return RegExp.$1; try {return ms.getTypeFromURI(Services.io.newURI(url));} catch {} return null; })(url); } }; gBrowser.tabpanels.addEventListener("dragstart", listener, true); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor: () => gBrowser.tabpanels.removeEventListener("dragstart", listener, true)}; ucf.unloadlisteners.push(id); })("drag-image-saver");
Отсутствует
Dumby - да, жестом картинка сохраняется, но не в папку Загрузки, а в корневую папку профиля.
А как сохранять в другую папку? Код изменения пути Загрузок не помог:
var {prefs} = Services; var path = prefs.getStringPref("browser.download.lastDir", Services.dirsvc.get("Desk", Ci.nsIFile).path); path = PathUtils.join(path, "_Images");
Отсутствует
Dobrov
Я же без понятия что имеется в виду под «папка Загрузки», тем более на Мак.
Вариант: открой вкладку с адресом resource://gre/modules/DownloadIntegration.jsm
и поищи там getPreferredDownloadsDirectory и getSystemDownloadsDirectory
может найдётся подсказка к тому, что требуется.
Отсутствует
Подскажите, почему не получается сделать запись в локальное хранилище?
Выдаёт сообщение, типа недоступно.
Exception { name: "NS_ERROR_NOT_AVAILABLE", message: "", result: 2147746065, filename: "chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button21@code line 1 > Function", lineNumber: 3, columnNumber: 0, data: null, stack: "anonymous@chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button21@code line 1 > Function:3:1\n@chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button21@code:1:34\nbuttonCbExecuteCode@chrome://custombuttons/content/cbbutton.js:311:24\nbuttonCommand@chrome://custombuttons/content/cbbutton.js:338:10\ncommand@chrome://custombuttons/content/toolbarbutton/toolbarbutton.js:19:34\n", location: XPCWrappedNative_NoHelper }
Отредактировано Cytrus (11-05-2021 13:00:21)
Отсутствует