Ki_rrrilll пишет
Может подскажете еще одну вещь.
Не, в контентских делах я не помощник.
И «некоторые» сайты, видимо, настолько забористые,
что их адреса даже нельзя называть, а то, может,
у других заинтересованных ответить было бы больше шансов.
Нет, сайты не забористые, просто я не хотел обвинений в рекламе. Вот один из этих сайтов: https://www.yaplakal.com/
Там из всех элементов при наведении курсора только ссылки имеют псевдокласс :hover, остальные элементы нет.
Почему? Может кто ответит?
И хотел попросить у вас, Dumby, код чтобы при закрытии вкладки, открытой из СВ, возвращаться на последнюю активную вкладку. Сейчас если я закрываю вкладку созданную из СВ, перехожу на крайнюю правую.
Отредактировано Ki_rrrilll (27-01-2022 16:53:56)
Отсутствует
я ничего из вашего ответа не понял
Думаю наоборот, это я без понятия что есть
«принудительное использование однооконного режима браузера».
Казалось бы, не нравятся окна — не открывай, но, похоже,
не всё так просто, видимо, вебу дано право их открывать (см. п. 3).
Вот и поставил упомянутое расширение, чтоб посмотреть.
Нужен bootstapLoader. Есть у xiao, или, может, парафраз,
смысл которого только в простоте копипасты в config.js
Накрутил кнопку
Уж поверь наслово, я, обычно, не склонен
критиковать чужой код, если не попросят, но это ...
выкинь немедленно, чтоб такого говнокода
в браузере даже духу никогда не было.
Наверно и рад бы был помочь исправить, но, нужно
объяснение замысла, которое, разумеется, взять будет негде.
Там из всех элементов при наведении курсора только ссылки имеют псевдокласс :hover, остальные элементы нет.
Ух ты! Я вижу это.
Дело, каким-то ..., в кривом <!DOCTYPE>
Например, воспроизводится по адресу
data:text/html;charset=utf-8,<center><h1>TEST</h1></center>
и не воспроизводится по адресу
data:text/html;charset=utf-8,<!DOCTYPE html><center><h1>TEST</h1></center>
при закрытии вкладки, открытой из СВ
Уволь.
Отсутствует
Думаю наоборот, это я без понятия что есть
«принудительное использование однооконного режима браузера».
Я же выше два раза написал, что под этим имеется ввиду.
Хорошо. Сформулирую иначе.
Мне надо, чтобы при попытке открыть новое окно FF, вместо нового окна открывалась новая вкладка в текущем окне.
Такое можно реализовать в FF 91 ESR?
Если нет, то нет. Переживу.
А ставить расширения, от которых я всеми силами стараюсь избавится заменяя функции этих расширений кнопками СВ и UCF, я не хочу.
«The Truth Is Out There»
Отсутствует
Dumby
Помните скрипт "сохранить сессию" А как бы туда втулить " Удалить все сессии" ? А то кнопу новую делать ,плюс батник...
Да и восстановить сессию тоже желательно в новой вкладке...
Отредактировано ВВП (27-01-2022 22:06:01)
Отсутствует
при закрытии вкладки, открытой из СВ
Уволь.
Очень жаль.
Отсутствует
Есть старый код, подобный расширению locationbar - позволяет при клике на часть url перейти к нему. Например, есть некий url с адресом site.domen/forum/loremipsum, и при клике на слово "forum" в нём, браузер переходил на адрес site.domen/forum.
Как переделать этот код для работы с UCF (такое расширение не нашёл)
(function () { if (location != "chrome://browser/content/browser.xul") return; var URLBarInput = gURLBar.mInputField; var locationBar = URLBarInput.parentNode.appendChild(document.createElement("hbox")); locationBar.style.display = "none"; URLBarInput.parentNode.addEventListener("click", function () { if (URLBarInput.style.display === "none") { URLBarInput.style.display = ""; locationBar.style.display = "none"; gURLBar.select(); } }, false); URLBarInput.parentNode.addEventListener("mouseout", function () { if (document.activeElement !== gURLBar.inputField) { locationBar.style.display = "none"; URLBarInput.style.display = ""; gURLBar._urlTooltip && gURLBar._hideURLTooltip(); } }, false); URLBarInput.addEventListener("mouseover", function (event) { if (event.ctrlKey || document.activeElement === gURLBar.inputField) { return; } locationBar.parentNode.removeChild(locationBar); locationBar = URLBarInput.parentNode.appendChild(document.createElement("hbox")); locationBar.style.overflow = "hidden"; locationBar.style.width = URLBarInput.clientWidth + "px"; gURLBar.value.split("?")[0].split("/").map(function (value, index, arr) { return index + 1 === arr.length ? (gURLBar.value.split("?")[1] ? (value + "?" + gURLBar.value.split("?")[1]) : value) : value; }).map(function (value, index, arr) { var sec = locationBar.appendChild(document.createElement("label")); //sec.style.margin = "5px"; sec.style.margin = "5px 0 0 0"; sec.value = value; if (index < arr.length - 1) sec.value = value.replace(/[^\/]$/, "$&/"); index === 0 && (sec.style.marginLeft = "1px"); if (index === 0 && /:\/$/.test(sec.value)) { sec.value += "/"; } else { sec.onmouseover = function () { this.style.textDecoration = "underline"; this.style.color = "blue"; this.style.fontWeight = "bold"; this.style.cursor = "pointer"; //this.setAttribute("style", "font-weight: bold;"); } sec.onmouseout = function () { this.style.textDecoration = ""; } sec.onclick = function (event) { if (event.button === 0) { var vert=URLBarInput.value.split(this.value)[0] + this.value; getBrowser (). loadURI(vert, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() }); //loadURI(URLBarInput.value.split(this.value)[0] + this.value); while (this.nextSibling) { this.nextSibling.parentNode.removeChild(this.nextSibling); } event.stopPropagation(); } } URLBarInput.style.display = "none"; locationBar.style.display = ""; } }) }, false); })();
Отсутствует
(такое расширение не нашёл)
Scroll Up Folder https://addons.mozilla.org/ru/firefox/a … -up-folder
Отсутствует
unter_officer
Есть вариант просто тупо закрывать окна, что уже нехорошо.
Вот так, например, перекрывает основной попс — окна,
создаваемые с участием parent (docShell).
Но без него — нет, для таких окон непонятно где взять адрес,
который пойдёт загружаться, а когда пойдёт загружаться,
то закрывать поздновато — браузерные коды уже на него рассчитывают.
Увы, для WebExtensions, браузер создаёт окна именно так.
Вписал некое вмешательство в создание, но закомментировал.
Можно раскомментировать, посмотреть что ещё может сломаться.
Вобщем, частично и грубо.
(br => ({ async init() { lockPref("browser.link.open_newwindow", 3); lockPref("browser.link.open_newwindow.restriction", 0); lockPref("browser.link.open_newwindow.override.external", 3); lockPref("browser.link.open_newwindow.disabled_in_fullscreen", true); var self = this; var topic = "webNavigation-createdNavigationTarget-from-js"; var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); obs.addObserver(this, topic); obs.addObserver(function quit(s, t) { obs.removeObserver(quit, t); obs.removeObserver(self, topic); }, "quit-application-granted"); delete this.init; this.imp = Cu.getGlobalForObject(Cu).ChromeUtils.import; /* var url = "resource://gre/modules/ExtensionParent.jsm"; var mgr = this.imp(url).ExtensionParent.apiManager; await new Promise(resolve => mgr.once("ready", resolve)); var g = mgr.global; g.Object.defineProperty(g, "windows", { configurable: true, enumerable: true, set(val) { var proto = val.prototype; g.Object.assign(proto, g.eval(`({${proto.getAPI}})`.replace( /\n\n[^\n]+?Services.ww/, "\n\n var res = redirectBWCArgs(args, features, windowManager);" + "\n if (res) return res;$&" ))); delete this.windows; this.windows = val; } }); g.redirectBWCArgs = (arr, features, wm) => { var pr = features.at(-1); var win = this.getWin(null, pr.startsWith("p")); if (!win) { if (features.length > 3) features.join = () => "dialog=no,all," + pr; return; } var args = []; for(var ind = 0, len = arr.length; ind < len; ind++) { var item = arr.GetElementAt(ind); if (item) { if (ind == 5) item = item.QueryInterface(Ci.nsISupportsPRUint32).data; else if (ind > 5 && ind < 9) item = item.QueryInterface(Ci.nsIPrincipal); else if (ind == 9) item = false; } args.push(item); } this.onArgs(win, args); return g.Promise.resolve(wm.getWrapper(win).convert({populate: true})); } */ }, getWin(win, p) { var url = "resource:///modules/BrowserWindowTracker.jsm"; var bwt = this.imp(url).BrowserWindowTracker; return (this.getWin = (win, p) => bwt.getTopWindow({ private: win ? win.browsingContext.usePrivateBrowsing : p }))(win, p); }, observe(subj) { var bag = subj.QueryInterface(Ci.nsIPropertyBag2); if (bag.get("url") != br) return; var w = bag.get("createdTabDocShell").domWindow; if (w) { var win = this.getWin(w); if (win) w.close(), w.arguments ? this.onArgs(win, w.arguments): this.tab(win); } }, onArgs(win, args) { var [arg] = args; if (arg) { if (win.XULElement.isInstance(arg)) return win.gBrowser.duplicateTab(arg, true, {inBackground: false}); if (arg instanceof Ci.nsIArray) arg = Array.from(arg.enumerate(Ci.nsISupportsString), ss => ss.data); else if (arg instanceof Ci.nsISupportsString) arg = arg.data; } else arg = args[0] = "about:blank"; win.arguments = args; win.gBrowserInit.uriToLoadPromise = arg; this.tab(win, args[5]); win.gBrowserInit._handleURIToLoad(); }, tab(win, id) { var index = win.gBrowser.selectedTab._tPos + 1; win.gBrowser.selectedTab = win.gBrowser .addTrustedTab("about:blank", {index, userContextId: id}); win.focus(); } }).init())("chrome://browser/content/browser.xhtml");
Помните скрипт "сохранить сессию" А как бы туда втулить " Удалить все сессии" ?
Да, что-то припоминаю. Хорошо, попробую добавить.
Да и восстановить сессию тоже желательно в новой вкладке...
Это что значит? Если как при клике по пункту «Восстановить»
с зажатым Ctrl или средней кнопкой мыши, когда (тогда)
вкладки первого окна сессии добавляются в окно к уже имеющимся,
то можно инвертировать: найти
//return this[cmd](arg, !e.button && !e.ctrlKey && e.view);
и расскомментировать, а строку перед ней закомментировать или удалить.
(async (pid, mp) => CustomizableUI.createWidget(({ id: "797321", label: "Simple Session Manager", tooltiptext: "Simple Session Manager", localized: false, init() { this.handleEvent = e => this[e.type](e); this.onTimeout = () => this.saveSession() || this.save(); Services.obs.addObserver(this, "quit-application"); var {openMenu} = this; this.render = function() { this.openMenu = openMenu; this.constructor.prototype.render.call(this); } delete this.init; return this; }, onCreated(btn) { btn.type = "menu"; btn.phTimestamp = 0; btn.render = this.render; btn._handleClick = this.click; btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC"); var popup = btn.ownerDocument.createXULElement("menupopup"); popup.filler = this; popup.id = pid; popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)"); btn.prepend(popup); btn.addEventListener("mousedown", this); popup.addEventListener("command", this); btn.ownerGlobal.addEventListener("unload", () => { btn.removeEventListener("mousedown", this); popup.removeEventListener("command", this); if (popup.filler != this) popup.removeEventListener("dragstart", this), popup.removeEventListener("popuphidden", this); }, {once: true}); }, openMenu(arg) { var pos; if (this.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = this.ownerGlobal, {width, height, top, bottom, left, right} = this.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; this.firstChild.setAttribute("position", pos); delete this.openMenu; this.openMenu(arg); }, mousedown(e) { if (e.button) return; var trg = e.target; if (trg.nodeName.startsWith("t")) { trg.mdTimestamp = Cu.now(); trg.tid = e.view.setTimeout(this.onTimeout, 500); return e.preventDefault(); } e.detail == 2 && trg.nodeName == "menu" && this.boot(trg); }, boot(trg) { var popup = trg.parentNode; var old = popup.querySelector("[boot]"); if (old != trg) old?.removeAttribute("boot"); trg.toggleAttribute("boot"); popup.dblMD = true; }, click() { var win = this.ownerGlobal; if (win.event.target != this) return; win.clearTimeout(this.tid); if (this.mdTimestamp - this.phTimestamp > 50) this.open = true; }, command(e) { var arg, trg = e.target, cmd = trg.value; if (cmd.startsWith("r")) { arg = trg.parentNode.parentNode.label; if (cmd.startsWith("res")) return this[cmd](arg, (e.button == 1 || e.ctrlKey) && e.view); //return this[cmd](arg, !e.button && !e.ctrlKey && e.view); } this[cmd](arg) || this.save(); }, dragstart(e) { var trg = e.target; if (trg.nodeName != "menu") return; var popup = trg.parentNode; this.dragData = {trg, mouse: true}; trg.menupopup.hidePopup(); var win = trg.ownerGlobal; win.setCursor("grabbing"); var {width} = trg.getBoundingClientRect(); trg.setAttribute("maxwidth", width); win.addEventListener("mouseup", this); popup.addEventListener("mousemove", this); }, mousemove(e) { var trg = e.target, dtrg = this.dragData.trg; if (trg == dtrg || trg.nodeName != "menu") return; e.movementY > 0 ? trg.nextSibling != dtrg && trg.after(dtrg) : trg.previousSibling != dtrg && trg.before(dtrg); }, mouseup(arg) { if (arg.constructor.isInstance?.(arg)) { arg.preventDefault(); var {trg} = this.dragData; this.dragData.mouse = false; } else var trg = arg; trg.removeAttribute("maxwidth"); trg.ownerGlobal.setCursor("auto"); trg.ownerGlobal.removeEventListener("mouseup", this); trg.parentNode.removeEventListener("mousemove", this); }, popuphidden(e) { if (!e.target.id) return; e.view.removeEventListener("keydown", this, true); var popup = e.target; popup.parentNode.phTimestamp = Cu.now(); if (!this.dragData && !popup.dblMD) return; var save; if (this.dragData) { var {trg, mouse} = this.dragData; mouse && this.mouseup(trg); delete this.dragData; var order = Array.from(popup.getElementsByTagName("menu"), m => m.label); if (order.toString() != this.meta.order.toString()) { var hasBoot = this.meta.boot != null; if (hasBoot) var bootName = this.meta.order[this.meta.boot]; this.meta.order = order; if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName); save = true; } } if (popup.dblMD) { delete popup.dblMD; var {boot} = this.meta; var bootNode = e.target.querySelector("[boot]"); var ind = bootNode && this.meta.order.indexOf(bootNode.label); if (ind != boot) this.meta.boot = ind, save = true; } save && this.save(e.view); }, sku: `#${pid} > menu[maxwidth]`, skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`, keydown(e) { if (e.repeat && e.key == "Shift" || !e.shiftKey) return; var func = this.keyHandlers[e.key]; if (!func) return; var menu = e.view.windowRoot .ownerGlobal.document.querySelector(this.skd); if (menu) e.stopImmediatePropagation(), func.call(this, menu); }, keyup(e) { if (e.key != "Shift") return; var win = e.view.windowRoot.ownerGlobal; win.removeEventListener("keyup", this, true); win.document.querySelector(this.skd)?.removeAttribute("maxwidth"); }, keyHandlers: { Enter(menu) { this.boot(menu); }, ArrowDown(menu) { var ns = menu.nextSibling; if (ns) ns.after(menu), this.arrow(menu); }, ArrowUp(menu) { var ps = menu.previousSibling; if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu); } }, arrow(menu) { if (menu.hasAttribute("maxwidth")) return; menu.setAttribute("maxwidth", menu.getBoundingClientRect().width); menu.ownerGlobal.addEventListener("keyup", this, true); this.dragData = {trg: menu}; }, fill(e) { var mxe = e.view.MozXULElement; var initFrag = mxe.parseXULToFragment(` <menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/> <menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/> <menuseparator/> `); this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup> <menuitem label="Восстановить" class="menuitem-iconic" value="restoreSession"/> <menuitem label="Переименовать" class="menuitem-iconic" value="renameSession"/> <menuitem label="Удалить" class="menuitem-iconic" value="removeSession"/> </menupopup></menu>`); this.regStyle(); var filler = {fill: e => e.target.id ? e.view.addEventListener("keydown", this, true) || e.target.fillFlag || this.fillSessions(e.target) : this.dragData?.mouse && e.preventDefault() }; (this.fill = e => { var trg = e.target; trg.setAttribute("context", ""); trg.append(trg.ownerDocument.importNode(initFrag, true)); (trg.filler = filler).fill(e); trg.addEventListener("dragstart", this); trg.addEventListener("popuphidden", this); })(e); }, fillSessions(popup) { while(popup.lastChild.nodeName == "menu") popup.lastChild.remove(); var ind = 0, {boot} = this.meta; for(var name of this.meta.order) { var df = popup.ownerDocument.importNode(this.menuFrag, true); df.firstChild.setAttribute("label", name); if (ind++ == boot) df.firstChild.toggleAttribute("boot"); popup.append(df); } popup.fillFlag = true; }, regStyle() { delete this.regStyle; var subst = "ucf-ssm-style-resurl"; Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution( subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(` @-moz-document url-prefix(chrome://browser/content/browser.xhtml) { #${pid} > menu { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC"); } #${pid} > [value=saveSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC"); } #${pid} [value=restoreSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII="); } #${pid} [value=renameSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII="); } #${pid} :is([value=removeSession], [value=deleteAllSessions]) { list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg=="); } #${pid} > menuseparator:last-child, #${pid} > menu[maxwidth] > .menu-right, #${pid} > [value=deleteAllSessions]:nth-last-child(2) { display: none; } #${pid} > menu[boot] { color: red; font-weight: bold; } #${pid} > menu[maxwidth] { color: blue; font-weight: bold; outline-offset: -2px; outline: 2px solid orangered; } } `.replace(/;$/gm, " !important;")))); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET); }, get gs() { delete this.gs; return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}); }, getState() { return JSON.parse(this.gs.SessionStore.getBrowserState()); }, splice(name, newName) { var ind = this.meta.order.indexOf(name); if (ind == -1) return; var args = [ind, 1]; if (1 in arguments) args.push(newName); else { if (ind == this.meta.boot) this.meta.boot = null; else if (ind < this.meta.boot) this.meta.boot--; } this.meta.order.splice(...args); }, get meta() { var file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.append("simple_session_manager.json"); this.path = file.path; try { this.data = JSON.parse(Cu.readUTF8File(file)); } catch { this.pp = file.parent.path; this.data = Object.create(null); } var meta = this.data[mp]; if (!meta) { var order = Object.keys(this.data); meta = this.data[mp] = {order, boot: null}; } delete this.meta; return this.meta = meta; }, async save(excWin) { var io = Cu.getGlobalForObject(Cu).IOUtils; if (this.pp) await io.makeDirectory(this.pp), delete this.pp; (this.save = excWin => { this.meta.order.length ? io.writeJSON(this.path, this.data) : io.remove(this.path, {ignoreAbsent: true}); for(var win of CustomizableUI.windows) { if (win == excWin) continue; var popup = win.document.getElementById(pid); if (popup) popup.fillFlag = false; } })(excWin); }, get prompter() { var {prompt} = Services; var p = {}, args = [null, null, "UCF Simple Session Manager"]; p.alert = prompt.alert.bind(...args); p.confirm = prompt.confirm.bind(...args); var pr = prompt.prompt.bind(...args); p.prompt = (msg, value) => { var res = {value}; return pr(msg, res, null, {}) ? res.value : null; } delete this.prompter; return this.prompter = p; }, observe(s, t, data) { Services.obs.removeObserver(this, "quit-application"); if (data.includes("restart")) return; var {boot} = this.meta; if (boot == null) return; var state = this.data[this.meta.order[boot]]; //this.gs.SessionStoreInternal.getCurrentState = () => state; var ssi = this.gs.SessionStoreInternal; ssi.getCurrentState = () => state; Services.obs.removeObserver(ssi, "browser:purge-session-history"); Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); }, get bwt() { delete this.bwt; var url = "resource:///modules/BrowserWindowTracker.jsm"; return this.bwt = ChromeUtils.import(url).BrowserWindowTracker; }, getName(state) { var wl = state.windows.length, tl = 0; for(var w of state.windows) tl += w.tabs.length; return `${ this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70) } ${wl}/${tl} [${ new Date().toLocaleString("mn").replace(" ", "-") }]`; }, exists(name) { this.meta; return (this.exists = name => name in this.data && !this.prompter.alert("Сессия с тем же именем уже существует!"))(name); }, saveSession(state = this.getState(), name = this.getName(state)) { var name = this.prompter.prompt("Сохранить:", name); if (name == null) return true; if (this.exists(name)) return this.saveSession(state, name); this.data[name] = state; this.meta.order.push(name); //this.meta.order.unshift(name); //if (this.meta.boot != null) this.meta.boot++; }, restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, renameSession(name, newName = name) { var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName); if (newName == null || newName == name) return true; if (this.exists(newName)) return this.renameSession(name, newName); var {data} = this; this.splice(name, newName); data[newName] = data[name]; delete data[name]; }, removeSession(name) { if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`)) return true; delete this.data[name]; this.splice(name); }, deleteAllSessions() { if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`)) return true; delete this.dragData; delete this.bwt.getTopWindow().document.getElementById(pid).dblMD; this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null}; } }).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");
Как переделать этот код
В смысле как? Всякий древний стафф зачистить, типа
mInputField - inputField, createElement - createXULElement, getBrowser () - gBrowser, ...
Никогда что ли не делал такое.
для работы с UCF
В custom_script_win.js проверка location не требуется.
Подключать из «по событию "load"».
такое расширение не нашёл
Вроде заявлен какой-то AdvancedLocationbar².
Ещё есть скрипт dav_LinkifiesLocationBar.uc.js,
(там проверка адреса идёт интервалом, долбёжка 20 раз в секунду).
Отсутствует
Dumby
Теперь класс ! resource://usercontext-content/cart.svg - это обратно подставил. return this[cmd](arg, !e.button && !e.ctrlKey && e.view); -это тоже.
Хорошая фишка получилась. Жаль сессия в фоне открывается , как бы последняя вкладка активной была ?
Отредактировано ВВП (03-02-2022 18:03:41)
Отсутствует
Хорошая фишка получилась
в 93 или новее затачиваешь?
Win 10х64
Отсутствует
unter_officer
скрытый текстПытался размышлять над однооконным режимом, и понял,
что ничего хорошего у меня придумать не получится.Есть вариант просто тупо закрывать окна, что уже нехорошо.
Вот так, например, перекрывает основной попс — окна,
создаваемые с участием parent (docShell).Но без него — нет, для таких окон непонятно где взять адрес,
который пойдёт загружаться, а когда пойдёт загружаться,
то закрывать поздновато — браузерные коды уже на него рассчитывают.Увы, для WebExtensions, браузер создаёт окна именно так.
Вписал некое вмешательство в создание, но закомментировал.
Можно раскомментировать, посмотреть что ещё может сломаться.Вобщем, частично и грубо.
Выделить кодКод:
(br => ({ async init() { lockPref("browser.link.open_newwindow", 3); lockPref("browser.link.open_newwindow.restriction", 0); lockPref("browser.link.open_newwindow.override.external", 3); lockPref("browser.link.open_newwindow.disabled_in_fullscreen", true); var self = this; var topic = "webNavigation-createdNavigationTarget-from-js"; var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); obs.addObserver(this, topic); obs.addObserver(function quit(s, t) { obs.removeObserver(quit, t); obs.removeObserver(self, topic); }, "quit-application-granted"); delete this.init; this.imp = Cu.getGlobalForObject(Cu).ChromeUtils.import; /* var url = "resource://gre/modules/ExtensionParent.jsm"; var mgr = this.imp(url).ExtensionParent.apiManager; await new Promise(resolve => mgr.once("ready", resolve)); var g = mgr.global; g.Object.defineProperty(g, "windows", { configurable: true, enumerable: true, set(val) { var proto = val.prototype; g.Object.assign(proto, g.eval(`({${proto.getAPI}})`.replace( /\n\n[^\n]+?Services.ww/, "\n\n var res = redirectBWCArgs(args, features, windowManager);" + "\n if (res) return res;$&" ))); delete this.windows; this.windows = val; } }); g.redirectBWCArgs = (arr, features, wm) => { var pr = features.at(-1); var win = this.getWin(null, pr.startsWith("p")); if (!win) { if (features.length > 3) features.join = () => "dialog=no,all," + pr; return; } var args = []; for(var ind = 0, len = arr.length; ind < len; ind++) { var item = arr.GetElementAt(ind); if (item) { if (ind == 5) item = item.QueryInterface(Ci.nsISupportsPRUint32).data; else if (ind > 5 && ind < 9) item = item.QueryInterface(Ci.nsIPrincipal); else if (ind == 9) item = false; } args.push(item); } this.onArgs(win, args); return g.Promise.resolve(wm.getWrapper(win).convert({populate: true})); } */ }, getWin(win, p) { var url = "resource:///modules/BrowserWindowTracker.jsm"; var bwt = this.imp(url).BrowserWindowTracker; return (this.getWin = (win, p) => bwt.getTopWindow({ private: win ? win.browsingContext.usePrivateBrowsing : p }))(win, p); }, observe(subj) { var bag = subj.QueryInterface(Ci.nsIPropertyBag2); if (bag.get("url") != br) return; var w = bag.get("createdTabDocShell").domWindow; if (w) { var win = this.getWin(w); if (win) w.close(), w.arguments ? this.onArgs(win, w.arguments): this.tab(win); } }, onArgs(win, args) { var [arg] = args; if (arg) { if (win.XULElement.isInstance(arg)) return win.gBrowser.duplicateTab(arg, true, {inBackground: false}); if (arg instanceof Ci.nsIArray) arg = Array.from(arg.enumerate(Ci.nsISupportsString), ss => ss.data); else if (arg instanceof Ci.nsISupportsString) arg = arg.data; } else arg = args[0] = "about:blank"; win.arguments = args; win.gBrowserInit.uriToLoadPromise = arg; this.tab(win, args[5]); win.gBrowserInit._handleURIToLoad(); }, tab(win, id) { var index = win.gBrowser.selectedTab._tPos + 1; win.gBrowser.selectedTab = win.gBrowser .addTrustedTab("about:blank", {index, userContextId: id}); win.focus(); } }).init())("chrome://browser/content/browser.xhtml");
Попробовал оба варианта - с закомментированным участком кода и с раскомментированным.
На первый взгляд оба варианта работают нормально.
Понаблюдаю в работе и если что-то пойдёт не так, то обязательно отпишусь.
Ну, а пока всё нормально. Большое спасибо за код.
«The Truth Is Out There»
Отсутствует
как бы последняя вкладка активной была ?
В смысле которая была активной в сессии?
Если да, то можно такую правку попробовать
/* restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, */ restoreSession(name, win) { var ss = this.gs.SessionStore; var state = this.data[name]; if (!win) return ss.setBrowserState(JSON.stringify(state)); var [w] = state.windows; var tab = w.tabs[w.selected - 1]; var ext = tab.extData; (ext || (tab.extData = {}))[mp] = "1"; win.addEventListener("SSWindowRestored", this.winRetored, {once: true}); ss.setWindowState(win, JSON.stringify(state)); ext ? delete tab.extData[mp] : delete tab.extData; }, winRetored(e) { var {gBrowser, SessionStore} = e.target; for(var tab of gBrowser.visibleTabs) if (SessionStore.getCustomTabValue(tab, mp) == "1") { gBrowser.selectedTab = tab; SessionStore.deleteCustomTabValue(tab, mp); break; } },
Отсутствует
Dumby
Если да, то можно такую правку попробовать
От теперь класс ! . Как бы еще автосубтиры на ютубе загасит ? Приходиться аж две кнопки лепить. т. е. стилем гасить...
А, как на "Отмена" можно код всунуть ? Не важно какой , ну, чтоб окно закрылось , и чтоб код нужный сработал ?
if (Services.prompt.confirm(null, "ВНИМАНИЕ !", "Открытые вкладки не восстановятся !" + "\nПерезапустить с зачисткой профиля ?", "Да", "Отмена"))
ТИПА, else Services.prefs.setIntPref а дальше не знаю...
Отредактировано ВВП (04-02-2022 23:20:01)
Отсутствует
Dumby
Вы когда-то давно написали вот этот код:
/*Initialization Code*/ // Закрытие вкладки = переход на предыдущую посещенную .......... // https://forum.mozilla-russia.org/viewtopic.php?pid=759770#p759770 ..... ((blurTab, dummy, s, lastSelect) => { (s = () => lastSelect = Date.now())(); addEventListener("TabSelect", s, false, gBrowser.tabContainer || 1); gBrowser._blurTab = tab => { if (!tab.selected) return; var tabToSelect = dummy; for(var t of gBrowser.tabs) if ( !t.hidden && !t.closed && t.lastAccessed > tabToSelect.lastAccessed && t.lastAccessed < lastSelect ) tabToSelect = t; if (tabToSelect == dummy) blurTab.call(gBrowser, tab); else gBrowser.selectedTab = tabToSelect; } addDestructor(() => gBrowser._blurTab = blurTab); })(gBrowser._blurTab, {lastAccessed: 0});
У меня две просьбы.
1. Подправить, чтобы код срабатывал нормально.
2. Переделать этот код для UCF.
«The Truth Is Out There»
Отсутствует
А, как на "Отмена" можно код всунуть ? Не важно какой , ну, чтоб окно закрылось , и чтоб код нужный сработал ?
ТИПА, else
Как-то так, наверно. Если код синхронный.
то переходит на предыдущую посещенную вкладку, то вдруг переходит на какую ему вздумается вкладку
Ну, раз так, можно попробовать свой трекер запилить.
Допустим, под «предыдущей посещенной вкладкой»,
подразумевается предыдущая (по времени)
активировавшаяся вкладка, не скрытая и не закрытая.
Следует понимать, что такой может не быть,
тогда переход пойдёт туда, куда перейдёт сам браузер.
(async ucf => { await delayedStartupPromise; var set = new Set([gBrowser.selectedTab]); var bt = gBrowser._blurTab; gBrowser._blurTab = tab => { if (!tab.selected) return; set.delete(tab); var res; for(var t of set) t.hidden || (res = t); res ? gBrowser.selectedTab = res : bt.call(gBrowser, tab); } var arr = [ ["TabClose", e => set.delete(e.target)], ["TabSelect", e => set.add(e.target, set.delete(e.target))] ]; var id, tc = gBrowser.tabContainer; for(var args of arr) tc.addEventListener(...args); ucf.unloadlisteners.push(id = Symbol()); ucf[id] = {destructor() { set.clear(); for(var args of arr) tc.removeEventListener(...args); }}; })(ucf_custom_script_win);
Отсутствует
Ну, раз так, можно попробовать свой трекер запилить.
Как я понял, это для custom_script_win.js и куда его там надо разместить? А то у меня не срабатывает.
Спасибо. Отлично работает.
Отредактировано voqabuhe (06-02-2022 11:37:14)
Отсутствует
Dumby
Как-то так, наверно. Если код синхронный.
Не догоняю, как использовать с этим ?
if(event.button == 1 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ if (custombuttons.confirmBox(null, "Сброс Кукситов !", "Да", "Отмена") ) { SiteDataManager.removeSiteData(); alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); alertsService.showAlertNotification("chrome://global/skin/icons/cpd_OK.png", "Кукситы", "Куки Сброшены" ); setTimeout(()=> alertsService.closeAlert(), 1600); } }
/*CODE*/ if (Services.prompt.confirm(null, "ВНИМАНИЕ !", "Открытые вкладки не восстановятся !" + "\nПерезапустить с зачисткой профиля ?", "Да", "Отмена")){ var file = Services.dirsvc.get('ProfD', Ci.nsIFile); file.initWithPath(file.path + "\\memory\\del.vbs"); file.launch(); }
Отредактировано ВВП (06-02-2022 12:23:27)
Отсутствует
Не догоняю, как использовать с этим ?
Добавляешь в код после закрывающей скобки «}» от if с confirm'ом.
В приведённых кодах эта скобка:
в первом — предпоследняя, во втором — последняя.
Отсутствует
Dumby
Куда ? Ни фига не врубаюсь .
else if (WindowIsClosing()) { CustomizableUI.setToolbarVisibility("PersonalToolbar", document.querySelector("#PersonalToolbar").closed); window.close(); }
Разобрался window.close(); - убрать
Отредактировано ВВП (06-02-2022 15:06:19)
Отсутствует
Ну, раз так, можно попробовать свой трекер запилить.
Допустим, под «предыдущей посещенной вкладкой»,
подразумевается предыдущая (по времени)
активировавшаяся вкладка, не скрытая и не закрытая.
Следует понимать, что такой может не быть,
тогда переход пойдёт туда, куда перейдёт сам браузер.скрытый текстВыделить кодКод:
(async ucf => { await delayedStartupPromise; var set = new Set([gBrowser.selectedTab]); var bt = gBrowser._blurTab; gBrowser._blurTab = tab => { if (!tab.selected) return; set.delete(tab); var res; for(var t of set) t.hidden || (res = t); res ? gBrowser.selectedTab = res : bt.call(gBrowser, tab); } var arr = [ ["TabClose", e => set.delete(e.target)], ["TabSelect", e => set.add(e.target, set.delete(e.target))] ]; var id, tc = gBrowser.tabContainer; for(var args of arr) tc.addEventListener(...args); ucf.unloadlisteners.push(id = Symbol()); ucf[id] = {destructor() { set.clear(); for(var args of arr) tc.removeEventListener(...args); }}; })(ucf_custom_script_win);
Dumby, спасибо большое.
«The Truth Is Out There»
Отсутствует
Dumby
Я для себя переделывал одну кнопочку из СВ в UCF.
В принципе кнопка получилась рабочей, но что-то мне подсказывает, что код получился "кривой".
Посмотрите пожалуйста своим профессиональным взглядом. Хотелось бы услышать ваше мнение.
И ещё. В моём коде мне не нравится использование eval(), но как избавится от eval что-то не соображу. Может подскажете?
try { CustomizableUI.createWidget({ id: "ucf_exportsBookmarksToHTMLFile", label: "Экспорт закладок в HTML-файл", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII=", // defaultArea: CustomizableUI.AREA_NAVBAR, localized: false, onCreated(btn) { btn.setAttribute("type", "menu"); btn.setAttribute("image", this.image); btn.onmouseover =()=> { var path = getPathToBookmarksFolder(); btn.setAttribute("tooltiptext", "ЛКМ: Открыть меню кнопки\n\nПапка для экспорта закладок:\n" + path); } var doc = btn.ownerDocument; var win = doc.defaultView; var popup = doc.createXULElement("menupopup"); var alertsImage = this.image; var array = [ ["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", "exportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="], ["separator"], ["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", "setPathAndExportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="], ["separator"], ["ucf_AllBookmarks", "Показать все закладки", "win.PlacesCommandHook.showPlacesOrganizer('AllBookmarks');", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="], ["separator"], ["ucf_TotalNumberOfBookmarks", "Общее количество закладок", "totalNumberOfBookmarks();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="], ]; array.forEach(m => { if (m[0] == "separator") { popup.append(doc.createXULElement("menuseparator")); return; }; var menuitem = popup.appendChild(doc.createXULElement("menuitem")); menuitem.setAttribute("id", m[0]); menuitem.setAttribute("label", m[1]); menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", m[3]); menuitem.addEventListener("command", ()=> eval(m[2])); }); btn.prepend(popup); function exportsBookmarksToHTMLFile() { var filePath = getPathToBookmarksFolder(); YMD = new Date().toLocaleString("af").slice(0, 10).replace(/-/g, "_"); HMS = new Date().toLocaleTimeString('de', '%H_%M_%S').replace(/:/g, "_"); myDate = (YMD + '\u00F7' + HMS); var path = filePath + "\\bookmarks_(" + myDate + ").html"; Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm"); BookmarkHTMLUtils.exportToFile(path).then(null, Cu.reportError); var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) alertsService.showAlertNotification(alertsImage, "Экспорт закладок в HTML-файл", "Файл сохранен в " + filePath); // стиль всплывающей подсказки var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var uri = win.makeURI('data:text/css,'+ encodeURIComponent('\ #alertBox { border: 1px solid threedshadow !important; border-radius: 3px !important; background-color: -moz-Dialog !important; width: 360px !important; height: 80px !important; }\ #alertImage { height: 20px !important; width: 20px !important; object-fit: contain !important; margin: 3px 0 20px 20px !important; }\ #alertNotification:hover { cursor: pointer !important; }\ .alertTitle { color: #003366 !important; text-align: center !important; font-family: Segoe UI !important; font-size: 120% !important; }\ #alertTextLabel { color: #2B552B !important; text-align: center !important; text-decoration: underline !important; font-weight: bold !important; }\ ')); sss.loadAndRegisterSheet(uri, 0); // удалить стиль и подсказку через указанное время setTimeout(()=> { sss.unregisterSheet(uri, 0); alertsService.closeAlert(); }, 3500); } function openBookmarksFolder() { var folder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); folder.initWithPath(getPathToBookmarksFolder()); folder.launch(); } function setPathAndExportsBookmarksToHTMLFile() { var fp = win.makeFilePicker(); fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder); fp.open(re=> { if ( re != fp.returnOK ) return; Services.prefs.setCharPref("CB.exportsBookmarksToHTMLFile.path", convertFromUnicode("UTF-8", fp.file.path)); exportsBookmarksToHTMLFile(); }) } function getPathToBookmarksFolder() { try { return Services.prefs.getComplexValue("CB.exportsBookmarksToHTMLFile.path", Ci.nsIPrefLocalizedString).data } catch(e) { return "C:" }; } function convertFromUnicode(charset, str) { var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); } function totalNumberOfBookmarks() { var statement = PlacesUtils.history.DBConnection .createStatement("SELECT count(fk) FROM moz_bookmarks"); statement.executeStep(); var bkmcnt = statement.getInt32(0); statement.finalize(); var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService); prompts.alert(null, "Общее количество закладок", "Общее количество закладок = " + bkmcnt); } }, }); } catch(ex) { Cu.reportError(ex); }
«The Truth Is Out There»
Отсутствует
Как , кодом, стилем , настройкой можно вкл/выкл превью вкладок ?
Есть код, добавляет в контекстное меню CB-кнопок
чекбокс-пункт «[✔] Включить инициализацию».
Если «превью вкладок» оформлено отдельной кнопкой, то можно использовать.
не нравится использование eval()
А что, вроде бочку катят только на оконный eval(),
а на от сандбокса и глобального объекта JSM'ок нет.
Но можно и без eval. И ["separator"]'ы можно убрать,
если таков замысел, что они всегда присутствуют между menuitem'ами.
/* var array = [ ["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", "exportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="], ["separator"], ["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", "setPathAndExportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="], ["separator"], ["ucf_AllBookmarks", "Показать все закладки", "win.PlacesCommandHook.showPlacesOrganizer('AllBookmarks');", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="], ["separator"], ["ucf_TotalNumberOfBookmarks", "Общее количество закладок", "totalNumberOfBookmarks();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="], ]; array.forEach(m => { if (m[0] == "separator") { popup.append(doc.createXULElement("menuseparator")); return; }; var menuitem = popup.appendChild(doc.createXULElement("menuitem")); menuitem.setAttribute("id", m[0]); menuitem.setAttribute("label", m[1]); menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", m[3]); menuitem.addEventListener("command", ()=> eval(m[2])); }); */ [ ["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", exportsBookmarksToHTMLFile, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="], ["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", setPathAndExportsBookmarksToHTMLFile, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="], ["ucf_AllBookmarks", "Показать все закладки", win.PlacesCommandHook.showPlacesOrganizer.bind(null, "AllBookmarks"), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="], ["ucf_TotalNumberOfBookmarks", "Общее количество закладок", totalNumberOfBookmarks, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="], ] .forEach((m, ind) => { ind && popup.append(doc.createXULElement("menuseparator")); var menuitem = popup.appendChild(doc.createXULElement("menuitem")); menuitem.id = m[0]; menuitem.setAttribute("label", m[1]); menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", m[3]); menuitem.addEventListener("command", m[2]); });
/* YMD = new Date().toLocaleString("af").slice(0, 10).replace(/-/g, "_"); HMS = new Date().toLocaleTimeString('de', '%H_%M_%S').replace(/:/g, "_"); myDate = (YMD + '\u00F7' + HMS); */ var myDate = new Date().toLocaleString("mn") .replace(/(?:(\.|:))/g, "_").replace(" ", "\u00F7");
Но это не строго, теоретически, может случиться ошибка,
тогда алерт будет вроде как некстати, то есть, лучше бы сделать
exportsBookmarksToHTMLFile как async function,
а await ….exportToFile() завернуть в try {...} catch(ex) {Cu.reportError(ex); return;}
или алерт и дальнейшее записать как функцию вместо null, где ….then(null, …
но с чего бы, мы же, наверно, разумные люди, и назначать папку
для экспорта такую, куда браузер не сможет записать, не будем.
/* Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm"); BookmarkHTMLUtils.exportToFile(path).then(null, Cu.reportError); */ ChromeUtils.import("resource://gre/modules/BookmarkHTMLUtils.jsm") .BookmarkHTMLUtils.exportToFile(path).catch(Cu.reportError);
/* function setPathAndExportsBookmarksToHTMLFile() { var fp = win.makeFilePicker(); fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder); fp.open(re=> { if ( re != fp.returnOK ) return; Services.prefs.setCharPref("CB.exportsBookmarksToHTMLFile.path", convertFromUnicode("UTF-8", fp.file.path)); exportsBookmarksToHTMLFile(); }) } function getPathToBookmarksFolder() { try { return Services.prefs.getComplexValue("CB.exportsBookmarksToHTMLFile.path", Ci.nsIPrefLocalizedString).data } catch(e) { return "C:" }; } function convertFromUnicode(charset, str) { var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); } */ var pref = "CB.exportsBookmarksToHTMLFile.path"; // CB -> UCF ? function setPathAndExportsBookmarksToHTMLFile() { var fp = win.makeFilePicker(); fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder); fp.open(re => { if (re != fp.returnOK) return; Services.prefs.setStringPref(pref, fp.file.path); exportsBookmarksToHTMLFile(); }); } function getPathToBookmarksFolder() { return Services.prefs.getStringPref(pref, "C:"); }
Отсутствует
Dumby
Если «превью вкладок» оформлено отдельной кнопкой
В том то и дело, что скриптом... Стилем можно, но не то ...Tab:hover {display: initial !important; }
Ладно итак сойдет.
Отредактировано ВВП (10-02-2022 11:42:15)
Отсутствует