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)
Отсутствует
Dumby - ещё просьба для кода Сохранения картинки жестом: перетаскивание заменить кликом средней кнопки мыши на картинке.
в Firefox 87 ошибка Uncaught (in promise) TypeError: ref is undefined на этих строках:
this[e.type](e);
url && this.save(url, name);
if (ref.spec.startsWith("http"))
})(url, name);
Я же без понятия что имеется в виду под «папка Загрузки», тем более на Мак.
Но ведь в коде видно, что это папка Загрузки по-умолчанию, указанная в Настройках.
Ещё по значку браузера видно, что я проверял скрипт не на Маке, а на Линуксе.
Отредактировано Dobrov (11-05-2021 15:55:05)
Отсутствует
Подскажите, почему не получается сделать запись в локальное хранилище?
Выдаёт сообщение, типа недоступно.
Ну и вопрос. Это так важно «почему»? Нет и всё.
Попробовал чуток порыться, и, если я правильно понял,
то для SystemPrincipal окон localStorage не создаётся вообще.
Но мысль интересная — хранить своё добро в localStorage окна браузера (browser.xhtml).
Увы, затейникам отказано.
как получить originAttributes кук
Куки (nsICookie) уже имеют свойство originAttributes, код-то запускал?
Как-то особо получать не требуется, достаточно просто обратиться к этому свойству.
А если имеется в виду «активной вкладки» и не понравилось gBrowser.contentPrincipal.originAttributes
то, возможно, подойдёт gBrowser.selectedBrowser.browsingContext.originAttributes
Хотя, видимо, это не совсем одно и то же. В первом случае там заполняется firstPartyDomain
если включено privacy.firstparty.isolate, так что, наверно, лучше взять вообще все куки (Services.cookies.cookies),
и фильтровать, в зависимости от представления что есть «куки вкладки».
в Firefox 87 ошибка Uncaught (in promise) TypeError: ref is undefined
Хм, действительно, browsingContext.currentURI добавили только в Firefox 88.
Можно заменить var ref = bc.currentURI; на
var ref = bc.currentWindowGlobal?.documentURI || {spec: ""};
Но ведь в коде видно, что это папка Загрузки по-умолчанию, указанная в Настройках.
Ещё по значку браузера видно, что я проверял скрипт не на Маке, а на Линуксе.
По значку браузера да, видно, проявил невнимательность.
А вот по коду — ничего не видно. В Настройках папка Загрузки — это что угодно,
но только не "browser.download.lastDir". По-умолчанию? А что у тебя возвращает
Services.dirsvc.get("DfltDwnld", Ci.nsIFile).path
перетаскивание заменить кликом
Заменить?! Затрудняюсь даже прокомментировать это.
Отсутствует
Заменить?! Затрудняюсь даже прокомментировать это.
А что у тебя возвращает Services.dirsvc.get("DfltDwnld", Ci.nsIFile).path
Это чтобы картинка сохранялась не Перетаскиванием, а по клику Колёсиком мыши на изображении (так быстрее).
Services.dirsvc… возвращает путь к папке Загрузки, указанной в настройках.
Сделал сохранение в путь: [Загрузки]/_Images/Имя вкладки, но вместо имени вкладки получаю "Mozilla Firefox" или "Новая вкладка". :-(
Dumby, почини код, чтобы файл сохранялся в указанный путь!
(async id => { // Firefox 85+ сохранить изображение жестом var Title = function (type) { // получить заголовок (type >0 обрезка) var title = (gBrowser.selectedTab.label || window.document.title); return title.substr(0, type).trim(); // ограничить длину заголовка } var path = OS.Path.join(Services.dirsvc.get("DfltDwnld", Ci.nsIFile).path, "_Images", Title(100)); // папка [Загрузки]/_Images/Имя вкладки var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(path); if ( !file.exists() || !file.isDirectory() ) file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); // создать папку, если не существует… // … далее код не менял, только исправил var ref = bc.currentURI;
Просьбами Вы, конечно, только достали лично меня
Какими просьбами? Ведь вы мне не помогали, ваши посты неинформативны - а у меня всё работает… Спасибо, получилось. так значительно лучше! Спасибо, всё отлично!
Вы интересный человек, Вам нужен мак. А кому он здесь нужен?
У меня Хакинтош и на 2020 год ваш скепсис опровергнут более четверти пользователей компьютеров:
статистика Операционных систем в США | Мире: Windows — 65,95|76,58% OS X — 27,77|18,93 Linux — 1,7%|1,62%.
Отредактировано Dobrov (12-05-2021 04:34:17)
Отсутствует
kazarin - у меня на обложке-ссылке фильма Гости из прошлого не появляется кнопка загрузки, только курсор в виде руки.
настройка Show a download button on hover создаёт над изображением кнопку, с которой можно сохранять без запроса.
Эту опцию надо включить, она не выставлена по умолчанию.
Отсутствует
Эту опцию надо включить, она не выставлена по умолчанию.
Извините, я всегда проверяю настройки и думал, вы поймёте, что эта опция у меня конечно же включена. Результат тот же.
Кроме того, ведь здесь вообще-то тема по обсуждению скриптов / кнопок, а не расширений. ;-)
Отредактировано Dobrov (12-05-2021 04:35:15)
Отсутствует
Stkvsky пишетЕсли закрыть браузер и запустить заново удаляется
А, наверно имеется ввиду не закрыть браузер как приложение (Выход, Ctrl+Shift+Q),
а когда последнее/единственное браузерное окно закрывается.
Хорошо, попробую.скрытый текстВыделить кодКод:
(async (sel, self) => ({ icon: "circle", colors: [ "mediumseagreen", "silver", "crimson", "blue", "peru", ], initColors() { var colorName = "ucf-gen"; var css = "@-moz-document url(about:preferences#containers)," + " url-prefix(chrome://browser/content/browser.x) {\n"; this.colors.forEach((color, ind) => { var [ic, tc] = color.split(/\s*\|\s*/); css += `\t.identity-color-${colorName}${ind} {\n` + `\t\t--identity-tab-color: ${tc || ic};\n` + `\t\t--identity-icon-color: ${ic};\n\t}\n` }); var url = "data:text/css;charset=utf-8," + encodeURIComponent(css + "}"); var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET); var len = this.colors.length; var pref = "ucf.openInGeneratedContainer.lastColor"; var ind = Math.min(Services.prefs.getIntPref(pref, -1), len - 1); this.nextColor = () => { var next = ind + 1; Services.prefs.setIntPref(pref, ind = next == len ? 0 : next); return colorName + ind; } }, quit: false, init(topic) { Services.obs.addObserver(self = this, topic); var lt = "browser-lastwindow-close-granted"; var lw = () => this.quit = true; Services.obs.addObserver(lw, lt); Services.obs.addObserver(function quit(s, t) { self.quit = true; Services.obs.removeObserver(self, topic); Services.obs.removeObserver(lw, lt); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); this.initColors(); this.newUsercontext = name => { var id = this.cis.create( name || `[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.nextColor() ).userContextId; this.saveGens(this.gens.add(id)); return id; } var cpref = "ucf.openInGeneratedContainer.containers"; var arr = Services.prefs.getStringPref(cpref, "").split(",").map(Number).filter(Boolean); if (arr.length) { var ids = this.cis.getPublicIdentities().map(i => i.userContextId); arr = arr.filter(id => ids.includes(id)); } this.gens = new Set(arr); (this.saveGens = () => Services.prefs.setStringPref(cpref, Array.from(this.gens).join(",")))(); }, observe(doc) { var list = doc.querySelectorAll(sel); if (!list.length) return; var menuitem = doc.createXULElement("menuitem"); for(var args of Object.entries({ selectiontype: "single", oncommand: "cmd(window)", nodetype: "folder|query", selection: "folder|query", label: "Открыть всё в контейнере", id: "placesContext_openContainer:tabs:newUsercontext" })) menuitem.setAttribute(...args); menuitem.cmd = this.cmd; menuitem.rnd = menuitem.constructor.prototype.render; menuitem.render = this.render; var [m1, m2] = menuitem.list = Array.from(list); (m2 || m1).after(menuitem); if (doc.documentElement.getAttribute("windowtype") != "navigator:browser") return; for(var btn of [ doc.getElementById("tabs-newtab-button"), doc.getElementById("new-tab-button") || doc.ownerGlobal.gNavToolbox.palette.querySelector("#new-tab-button") ]) if (btn) btn.checkForMiddleClick = this.click; var win = doc.ownerGlobal; this.redefDoSearch(win, win.customElements.get("searchbar").prototype); win.gBrowser.tabContainer.addEventListener("TabClose", this.tabClose); win.addEventListener("unload", this.winUnload, {once: true}); this.quit = false; }, winUnload(e) { var win = e.target.ownerGlobal; win.removeEventListener("TabClose", self.tabClose); if (self.quit) return; var gb = win.gBrowser; if (gb) for(var tab of gb.tabs) self.tabClose(null, tab); }, closed: new Set(), cis: ChromeUtils.import("resource://gre/modules/ContextualIdentityService.jsm") .ContextualIdentityService, tabClose(e, tab = e.target) { var id = +tab.getAttribute("usercontextid"); id && self.gens.has(id) && self.closed.add(id); self.closed.size == 1 && ChromeUtils.idleDispatch(self.meaybeRemove); }, meaybeRemove() { var ids = Array.from(self.closed); self.closed.clear(); for(var id of ids) self.meaybeRemoveById(id); }, meaybeRemoveById(id) { for(var win of CustomizableUI.windows) if (win.document.querySelector(`tab.tabbrowser-tab[usercontextid="${id}"]`)) return; this.saveGens(this.gens.delete(id)); this.cis.remove(id); }, redefDoSearch(win, proto) { var code = `(openTrustedLinkIn => [ {${proto.doSearch}}, openTrustedLinkIn ])( function otl(url, where, params) { if (where != "current") params.userContextId = otl.newUsercontext( document.getElementById("searchbar").value ); openTrustedLinkIn(url, where, params); } );`; (this.redefDoSearch = (win, proto) => { var [obj, func] = win.eval(code); Object.assign(proto, obj); func.newUsercontext = this.newUsercontext; })(win, proto); }, click(btn, e) { if (!(e.button != 2 || e.ctrlKey || e.shiftKey)) { var txt = e.view.readFromClipboard(); if (txt) { var urls = txt.split("\n").map(self.map).filter(Boolean); if (urls.length) return e.preventDefault(), self.openFromClipboard(e.view, urls); } } e.view.checkForMiddleClick(btn, e); }, eo: Object.create(null), map(str) { str = str.trim(); try { var scheme = Services.io.extractScheme(str); var ph = Services.io.getProtocolHandler(scheme); if (ph.scheme == scheme) return Services.io.newURI(str) && {uri: str}; } catch {} }, openFromClipboard(win, urls) { if (win.OpenInTabsUtils.confirmOpenInTabs(urls.length, win)) urls.load = true, this.open(win, this.eo, urls); }, async render() { this.rnd(); await new Promise(this.ownerGlobal.requestAnimationFrame); this.hidden || (this.hidden = this.list.every(self.every)); }, every: node => node.disabled || node.hidden, cmd(win) { var view = this.parentNode._view; var node = win.document.popupNode; node = node._placesView && node._placesView.result.root; self.open(win, node || view.selectedNode || view.result.root); }, open(win, node, list) { var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow; var w = gbw(win); this.pu = w.PlacesUIUtils; this.fs = w.PlacesUtils.favicons; this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; (this.open = (win, node, list) => { this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node)); node.bookmarkGuid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls) { var userContextId = this.newUsercontext(); var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win); var {load} = urls, gb = win.gBrowser, pos = gb.selectedTab._tPos; for(var {uri, title, isBookmark} of urls) try { if (mark) isBookmark ? this.pu.markPageAsFollowedBookmark(uri) : this.pu.markPageAsTyped(uri); if (load) { gb.addTrustedTab(uri, {index: ++pos, userContextId}); continue; } var state = {userContextId, entries: [{ url: uri, title: title || uri, triggeringPrincipal_base64: this.sysp }]}; var [,, data, mime] = await new Promise( resolve => this.fs.getFaviconDataForPage( Services.io.newURI(uri), (...args) => resolve(args), 16 ) ); if (data.length) state.image = `data:${ mime || "image/x-icon" };base64,${ btoa(String.fromCharCode(...data)) }`; var tab = gb.addTrustedTab(null, {index: ++pos, userContextId}); win.SessionStore.setTabState(tab, state); } catch {}; } }).init("chrome-document-loaded"))( "#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs" );
Просто супер, спасибо огромное, работает как часы
Можно вас еще попросить добавить чтобы со строки поиска результат поиска открывался в конце списка вкладок?
Отредактировано Stkvsky (12-05-2021 06:07:22)
Отсутствует
Это чтобы картинка сохранялась не Перетаскиванием, а по клику Колёсиком мыши на изображении
Это я понял (только тогда не понял почему ничего
не сказано что делать с autoscroller'ом и картинками-ссылками).
Я к тому, что это не называется «для кода заменить», это называется
сделать новый, совсем другой, ну кроме, собственно, сохранялки.
Сделал сохранение в путь: [Загрузки]/_Images/Имя вкладки, но вместо имени вкладки получаю "Mozilla Firefox" или "Новая вкладка". :-(
Нет, не сделал. Просто прицепил к path [Загрузки]/_Images
имя вкладки, такое, какое было на момент исполнения кода,
то есть при старте окна браузера (ничего удивительного в имени нет).
1. Это удалить
… var path = OS.Path.join(Services.dirsvc.get("DfltDwnld", Ci.nsIFile).path, "_Images", Title(100)); // папка [Загрузки]/_Images/Имя вкладки var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(path); if ( !file.exists() || !file.isDirectory() ) file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); // создать папку, если не существует…
/* "browser.download.dir": {type: "String", set: path} */ "browser.download.dir": {type: "String", get set() { var dir = Services.dirsvc.get("DfltDwnld", Ci.nsIFile); dir.append("_Images"); var {path} = dir; // папка [Загрузки]/_Images Object.defineProperty(this, "set", {get() { dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… return PathUtils.join(path, DownloadPaths.sanitize(Title(100))); }}); return this.set; }}
чтобы со строки поиска результат поиска открывался в конце списка вкладок
/* if (where != "current") */ if (where != "current") params.resolveOnNewTabCreated = br => gBrowser.moveTabTo( gBrowser.getTabForBrowser(br), Infinity ),
Отсутствует