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 ),
Отсутствует
Stkvsky пишетПодскажите как поставить Custom Buttons на 781) В папку, куда установлен Firefox, скопируй одноимённую папку из данного архива. (Костыли для FF)2) ставь обычным способом расширение custom_buttons-0.0.7.0.0.17-fx-bootstrap.xpi
На 78.10.1 ESR portable не ставится.
Отредактировано foxboy (13-05-2021 12:37:24)
Отсутствует
На 78.10.1 ESR portable не ставится.
Win7
Отсутствует
Вопрос: как получить текст первого конкретного html-тэга текущей страницы? Так не работает: doc.getElementsByTagName("label")[0];
В коде, вместо статического path, определить геттер.
Расширение Text Linky Tool открывает страницу moz-extension://…/imglist.html, хочу доработать Сохранение картинки перетаскиванием,
чтобы создаваемое имя папки было осмысленным, а не moz-extension.
То есть, в код, где получаю Заголовок текущей вкладки, хочу добавить проверку, что это страница moz-extension:// и тогда брать заголовок из label-тэга текущей страницы.
<body> <label id="lblFrom">Custom Buttons | Форум Mozilla Россия(https://forum.mozilla-russia.org/viewtopic.php?id=9591&p=623/page/2)</label> <label>Images Viewer</label><span id="spnCount"> - 65 pics</span>
Да я понял уже, что вам такой вариант решения неинтересен, надоедать больше не буду.
Не в интересе дело, а в том, что расширение Image Picka не подгружает картинки, по которым не кликали, то есть оно бесполезно!
Отредактировано Dobrov (14-05-2021 02:51:24)
Отсутствует
Dumby
Посмотрите, пожалуйста, кнопкуSave, от 07.03.2017. .............
Идет неправильное сохранение через пункт "Сохранить всю страницу или выбранное как HTML"
Не сохраняются изображения и стили. При просмотре сохраненной страницы в автономном режиме(без инета) получается ерунда,
например здесь.
Отсутствует
voqabuhe
Кнопка с твоей ссылки точно также не сохраняет изображения и стили. При просмотре сохраненной страницы в автономном режиме(без инета) получается ерунда.
Твой код применяю для UCF.
Отсутствует
Кнопка с твоей ссылки точно также не сохраняет изображения и стили. При просмотре сохраненной страницы в автономном режиме(без инета) получается ерунда.
Твой код применяю для UCF.
вот кнопка SaveHTML от Dumby, с моими доработками. Данная ссылка с рецептами без интернета открывается нормально.
(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"; 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 = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.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 FatMs = (str) => {return str.replace(/[:\\\/<>?*|"'`]+/g,'').replace(/\s+/g,' ').replace(/ /g,' ');} var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", FatMs(Title(-1))); // каталог Загрузки + домен var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(savedir); if ( !file.exists() || !file.isDirectory() ) file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); // создать папку, если не существует… var path = PathUtils.join(savedir, FatMs(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
Отсутствует
Dumby - есть два кода, показывающих при наведении на Звёздочку адрес закладки или последнюю папку, куда добавлялась закладка.
Первый работает в custom_script_win.js , а Второй почему-то только в кнопке CustomButton.
Нужно устранить три недостатка либо первого либо второго скрипта (ещё второй не работает в custom_script_win.js):
1) Оба скрипта зачем-то удаляют стандартную подсказку Звёздочки: у меня это «Добавить страницу в Закладки (⌘D)».
2) Нет строки "Недавняя папка\n:" перед текстом последней папки, куда добавлялась закладка [как в этом же коде "Адрес закладки:\n"]. Я не смог найти строку кода, где нужно добавить этот текст!
3) нет обработки кликов Звёздочки, я их добавил в более старый вариант, но у него нет "Недавней папки":
try {((bu, bm, {star} = bu) => { // показать расположение закладки в Избранном. Клики на Звёздочке: var listener = { // СКМ: Вернуть вкладку, СКМ+Alt страница about:newtab, СКМ+Shift google.ru async handleEvent() { var result = []; await this.fetch(); for(var guid of this.guids) { var arr = []; while(true) { if (!this.hover) return; var res = await bm.fetch(guid); if ((guid = res.parentGuid) == bm.rootGuid) { arr.unshift(bm.getLocalizedTitle(res)); break; } arr.unshift(res.title || "[Безымянная папка]"); } result.push(arr.join("\\")); } this.hover && this.setTooltip(result); }, get fetch() { var set = this.guids = new Set(); var args = [b => set.add(b.parentGuid), {concurrent: true}]; delete this.fetch; return this.fetch = () => set.clear() || bm.fetch({url: gBrowser.currentURI.spec}, ...args); }, setTooltip(arr) { var m = arr.length > 1; var help = '\nРолик: Вернуть вкладку \n…+Alt Быстрый доступ\n…+Shift поиск в Google', text = `Адрес${m ? "а" : ""} заклад${m ? "ок" : "ки"}:\n${arr.join("\n")}\n`+ help; if (bu._itemGuids.size) star.tooltipText = "\u3164" else text = star.tooltipText + help; if (/Ролик/.test(star.tooltipText)) return; document.tooltipNode == star ? this.tt.label = text : star.tooltipText = text; }, get tt() { var list = InspectorUtils.getChildrenForNode(document.documentElement, true); delete this.tt; return this.tt = list.item(list.length - 1); }, get hover() {return star.matches(":hover");} }, loadURI_ex = (url, newtab) => { newtab = newtab || false; // параметры по-умолчанию if (newtab) switchToTabHavingURI(url, true, {relatedToCurrent: true, triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}) else gBrowser.loadURI(url, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}); }, clicks = e => { if (e.button != 1) return; // CKM Click if (e.shiftKey) loadURI_ex('https://www.google.ru', true) else if (e.altKey) loadURI_ex('about:newtab') else document.defaultView.undoCloseTab(); }; star.addEventListener("mouseenter", listener); star.addEventListener("click", clicks); addEventListener("unload", () => { star.removeEventListener("mouseenter", listener); star.removeEventListener("click", clicks) } , {once: true}); })(BookmarkingUI, PlacesUtils.bookmarks);} catch(ex) {Cu.reportError(ex);}
Отсутствует
вот кнопка SaveHTML от Dumby, с моими доработками
Что-то у меня ничего не получилось с этим кодом. Создал файл SaveHTML.js, прописал его в загрузчик custom_script_win.js.
Никаких кнопок, меню ни где не появилось, в коде написано дополнительные клики на downloads-button для custom_script_win.js. А что это такое downloads-button ? у меня вроде нигде нет такого.
Отсутствует
rubel это стандартная кнопка «Загрузки», всё и так ясно по названию downloads-button.
Alt+Shift+S для сохранения страницы или жми на «Загрузки» правой кнопкой мыши, включив постоянный показ:
Персонализация > Правый клик на кнопке «Загрузки» > Снять флажок: Автоматически скрывать на панели инструментов.
Отсутствует
Dobrov
ОК. Спасибо, все работает и сохраняет как надо ! Но вот путь сохранения для меня не удобен, да еще и по домену.
У меня все сохраняется в "D:\Downloads" вот нужно и прописать в ваш скрипт этот путь. Как правильно прописать ?
И еще бы сделать при сохранение открытие диалогового окна, чтобы корректировать имя файла.
Отредактировано rubel (16-05-2021 07:32:26)
Отсутствует