Dumby
При исп. скрипта миниатюр вкладок в профиле появляется TabHoverSnapshotsStorage.json. Так и должно быть? Или это кто-то попросил ? Можно избавиться?
Сделал по наитию ,но вря дли это кошерно... var key = "TabHoverSnapshotsStorage"; , на var key = "";
Отредактировано ВВП (16-08-2021 20:45:09)
Отсутствует
это кто-то попросил ? Можно избавиться?
Ну да, Stkvsky попросил:
«А можно ли сделать чтобы эти миниатюры куда нибудь сохранялись …».
Если хочешь, могу вырезать
(async query => { var width = 300; var timeout = 400; var tid, once = {once: true}; var nh = tab => !tab.matches(":hover"); await delayedStartupPromise; var slot = gBrowser.selectedTab.flattenedTreeParentNode; var lst = e => { var tab = e.target; if ( tab.nodeName == "tab" //&& !tab.selected && tab.linkedPanel ) tid && clearTimeout(tid), tid = setTimeout(onTab, timeout, tab); } var args = ["mouseenter", lst, true], cb; if (addEventListener != window.addEventListener) cb = true, addEventListener(...args, slot); else slot.addEventListener(...args), addEventListener("unload", () => slot.removeEventListener(...args) , once); var onTab = tab => { tid = 0; if (nh(tab)) return; var cwg = tab.linkedBrowser .browsingContext?.currentWindowGlobal; cwg && openPopup(tab, cwg); } var openPopup = (...args) => { var popup = (cb ? this : mainPopupSet) .appendChild(document.createXULElement("menupopup")); popup.setAttribute("ignorekeys", true); popup.setAttribute("rolluponmousewheel", true); popup.setAttribute("consumeoutsideclicks", "never"); popup.shadowRoot.querySelector("style").append(` :host { padding: 0 !important; margin-top: 1px !important; -moz-appearance: none !important; } arrowscrollbox::part(scrollbutton-up), arrowscrollbox::part(scrollbutton-down) { display: none !important; } `); var hide = () => popup.hidePopup(); var canvas = popup.appendChild(document.createElement("canvas")); canvas.width = width; var context = canvas.getContext("2d", {alpha: false}); if (parseInt(Services.appinfo.platformVersion) >= 81) { var wp = "width", hp = "height"; query += "Info"; } else { var wp = 0, hp = 1; query += "Size"; } (openPopup = async (tab, cwg) => { var res = await cwg.getActor("Thumbnails").sendQuery(query); if (nh(tab)) return; var w = res[wp]; if (w < width) return; var h = res[hp], k = width / w; try {var bitmap = await cwg.drawSnapshot( new DOMRect(0, 0, w, h), k, "white" );} catch {} if (nh(tab) || !bitmap) return; canvas.height = k * h; context.drawImage(bitmap, 0, 0); bitmap.close(); popup.openPopup(tab, "after_start"); tab.addEventListener("mouseleave", hide, once); })(...args); } })("Browser:Thumbnail:Content");
Отсутствует
Dumby
Вы бы не могли пожалуйста добавить в этот код еще одну функцию?
Чтобы при открытии со строки поиска вкладки с результатами поиска, автоматически открывалась еще пустая вкладка(about:blank)
(async (sel, self) => ({ icon: "circle", colors: [ "#FF9800", "#03A9F4", "#FFC107", "#00BCD4", "#FFEB3B", "#009688", "#CDDC39", "#4CAF50", "#8BC34A", "#D32F2F", "#4949ff", "#C2185B", "#607D8B", "#7B1FA2", "#9E9E9E", "#673AB7", "#795548", "#3F51B5", "#FF5722", "#2196F3", ], 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.maybeRemove); }, maybeRemove() { var ids = Array.from(self.closed); self.closed.clear(); for(var id of ids) self.maybeRemoveById(id); }, maybeRemoveById(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.resolveOnNewTabCreated = br => gBrowser.moveTabTo( gBrowser.getTabForBrowser(br), Infinity ), 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, triggerNode} = this.parentNode; var node = triggerNode._placesView && triggerNode._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) => { var {bookmarkGuid: guid, title} = node; if (guid && title) title = win.PlacesUtils.bookmarks.getLocalizedTitle({guid, title}); this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node), title); guid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls, title) { var userContextId = this.newUsercontext(title); 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" );
Отсутствует
автоматически открывалась еще пустая вкладка(about:blank)
В этом же контейнере?
/* if (where != "current") params.resolveOnNewTabCreated = br => gBrowser.moveTabTo( gBrowser.getTabForBrowser(br), Infinity ), */ if (where != "current") params.resolveOnNewTabCreated = br => { var tab = gBrowser.getTabForBrowser(br); gBrowser.moveTabTo(tab, Infinity); gBrowser.addTrustedTab("about:blank", { index: tab._tPos + 1, userContextId: tab.userContextId }); },
Отсутствует
Dumby
Спасибо большое, супер, да, в этом же контейнере
Забыл уточнить, извиняюсь, если можно добавить, чтобы пустая вкладка открывалась перед вкладкой с поиском
(но фокус оставался на вкладке с поиском)
Отредактировано Stkvsky (14-08-2021 12:35:47)
Отсутствует
Dumby, здравствуйте.
В кнопке "Управление закладками", автор bunda1,
https://forum.mozilla-russia.org/viewto … pid=724500
есть пункт: "Левый длинный клик добавляет текущую вкладку в закладки под нажатой закладкой, в боковой панели закладок".
Пожалуйста адаптируйте этот кусок кода для Firefox 91.
// Управление закладками, от 25.10.2014. (function func() { // страницы где левый длинный клик открывает закладку в текущей странице var current = ["about:newtab", "about:blank", "chrome://browser/content/bookmarks/bookmarksPanel.xul"]; const background = false; // открывать закладку в фоновой вкладке const nextToCurrent = true; // открывать закладку рядом с текущей вкладкой const menuAutoClose = true; // автоматически закрыть меню закладок при уходе курсора function handleClick(e) { var target = e.originalTarget; var sidebar = target.ownerDocument.defaultView.top !== content && target.id == 'bookmarks-view-children'; if ( !sidebar && !target._placesNode ) return; // стоп, если не закладка, папка, разделитель // получить закладку, адрес, папку и id закладки, другие переменные if ( sidebar ) { var tree = target.parentNode; var box = tree.treeBoxObject; var row = box.getRowAt(e.clientX, e.clientY); var node = tree.view.nodeForTreeIndex(row); } var node = sidebar ? node : target._placesNode, id = node.itemId, uri = node.uri, button = e.button, type = e.type, isFolder = PlacesUtils.nodeIsContainer(node), isURI = PlacesUtils.nodeIsURI(node); // двойной клик добавляет закладку или удаляет закладку, разделитель if ( button !== 1 && type == 'mouseup' ) { if ( button == 0 && func.flag == true && isFolder ) { addBookmark(node, false); sidebar && tree.view.toggleOpenState(row); } if ( button == 2 && func.flag == true && !isFolder ) { setTimeout(function() { target.ownerDocument.getElementById("placesContext").hidePopup() try { PlacesUtils.bookmarks.removeItem(id) } catch(e) {}; }, 0); } func.flag = true; setTimeout(function() func.flag = false, 400 ); } if ( isFolder ) return; // стоп, если папка закладок if ( button == 0 ) window.clearTimeout( func.timer ); // сбросить таймер длинного клика // блокировать действие по умолчанию для клика и отжатия if ( button !== 2 && /click|mouseup/.test(type) ) { e.preventDefault(); e.stopPropagation(); } // левый длинный клик добавляет текущую вкладку в закладки под нажатой закладкой if ( button == 0 && type == 'mousedown' ) { func.loadBook = true; func.timer = setTimeout(function() { func.loadBook = false; addBookmark(node.parent, id); }, 400 ); } // левый клик открывает закладку в новой или текущей вкладке if ( button == 0 && type == 'mouseup' && func.loadBook && isURI ) { ( uri.startsWith("javascript") || current.indexOf(content.location.href) !== -1 || e.ctrlKey ) ? gBrowser.loadURI( uri ) : gBrowser.loadOneTab( uri, {relatedToCurrent: nextToCurrent, inBackground: background, referrerURI: null } ); } // средний клик открывает закладку в текущей вкладке if ( button == 1 && type == 'click' && isURI ) { gBrowser.loadOneTab( uri, {relatedToCurrent: nextToCurrent, inBackground: true, referrerURI: null } ); } // автоматически закрыть все меню закладок при уходе курсора var menu = target.parentNode; if ( !menuAutoClose || !menu || menu.localName !== 'menupopup' || type !== 'click' || button == 2 ) return; menu.onmouseover = function() menu.f = true; menu.onmouseleave = function() { menu.f = false; setTimeout(function() { if ( menu.f ) return; for ( var node = menu; node; node = node.parentNode ) node.nodeName == 'menupopup' && node.hidePopup(); menu.onmouseleave = null; }, 500); }; }; ["click", "dragstart", "mouseup", "mousedown"] .forEach(function(type) addEventListener(type, handleClick, true) ); // добавить страницу в закладки в указанной папке function addBookmark(folder, id) { var title = gBrowser.mCurrentTab.label; var folderId = PlacesUtils.getConcreteItemId(folder); var index = id ? PlacesUtils.bookmarks.getItemIndex(id) + 1 : 0; var readOnlyFolder = PlacesUtils.nodeIsQuery(folder) || PlacesUtils.annotations.itemHasAnnotation(folderId, PlacesUtils.LMANNO_FEEDURI); if ( !readOnlyFolder ) PlacesUtils.bookmarks.insertBookmark(folderId, gBrowser.currentURI, index, title); // всплывающая подсказка if ( id ) return; var al = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); if ( readOnlyFolder ) { al.showAlertNotification("chrome://global/skin/icons/error-16.png", folder.title, "Не поддерживается"); return; } var icon = gBrowser.mCurrentTab.image || "chrome://global/skin/icons/information-16.png"; al.showAlertNotification(icon, "Добавил в папку " + (folder.title || "(без заголовка)") + ":", title.slice(0, 100)); }; })();
Отсутствует
Dumby
Можно вас еще попросить сделать чтобы внешние ссылки открывались в том же контейнере что и активная вкладка?(в конце списка вкладок)
И открытие новой вкладки (кнопка + на панели вкладок(ctrl+t)) так же было в активном контейнере
Отредактировано Stkvsky (16-08-2021 13:41:22)
Отсутствует
Dumby
Возможно ли что-то придумать, что бы при закреплении вкладки она оставалась на своей позиции, а не перемещалась влево?
«The Truth Is Out There»
Отсутствует
Dumby - приветствую!
var EXPORTED_SYMBOLS = ["MouseImgSaverChild", "MouseImgSaverParent"]; // открыть картинку, перетащив вправо; сохранить колёсиком var u = {get it() { delete this.it; return this.it = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools); }}; for(let name of ["E10SUtils", "PrivateBrowsingUtils"]) ChromeUtils.defineModuleGetter(u, name, `resource://gre/modules/${name}.jsm`); class MouseImgSaverChild extends JSWindowActorChild { handleEvent(e) { // клики мышью if (e.button > 1) return; // только ЛКМ, СКМ var trg = e.explicitOriginalTarget; trg.nodeType == Node.ELEMENT_NODE && trg instanceof Ci.nsIImageLoadingContent && this[e.type](trg, e); } handleDragEvent(e) { this[e.type](e); } dragstart(trg, e) { this.trg = trg; this.x = e.screenX; this.y = e.screenY; this.drag("add"); this.handleEvent = this.handleDragEvent; this.checkTextLinkyTool(trg.ownerDocument); } events = ["dragover", "drop", "dragend"]; drag(meth = (delete this.handleEvent, delete this.trg, "remove")) { meth += "EventListener"; var win = this.contentWindow; for(var type of this.events) win[meth](type, this, true); } drop() { this.drag(); } dragover(e) { var {x, y} = this, cx = e.screenX, cy = e.screenY, dx = cx - x, ax = Math.abs(dx), ay = Math.abs(cy - y); if (ax < 10 && ay < 10) return; if (dx < 0 || ax < ay) return this.drag(); this.x = cx; this.y = cy; } dragend(e) { // перетаскивание рисунка var dt = e.dataTransfer, {trg} = this; this.drag(); // dt.mozUserCancelled || this.send(trg, e.screenX); dt.mozUserCancelled || this.sendAsyncMessage("dragend", (trg.currentRequestFinalURI || uri).spec); } auxclick(trg) { // клик СКМ trg.matches(":any-link :scope") || this.send(trg); } dblclick(trg) { // ЛКМ trg.matches(":any-link :scope") || this.sendAsyncMessage("dblclick", (trg.currentRequestFinalURI || uri).spec); } send(trg, sx) { var uri = trg.currentURI; if (!uri) return; var doc = trg.ownerDocument; var cookieJarSettings = u.E10SUtils .serializeCookieJarSettings(doc.cookieJarSettings); var referrerInfo = Cc["@mozilla.org/referrer-info;1"] .createInstance(Ci.nsIReferrerInfo); referrerInfo.initWithElement(trg); referrerInfo = u.E10SUtils.serializeReferrerInfo(referrerInfo); var contentType = null, contentDisposition = null; try { var props = u.it.getImgCacheForDocument(doc).findEntryProperties(uri, doc); var cs = Ci.nsISupportsCString; try {contentType = props.get("type", cs).data;} catch {} try {contentDisposition = props.get("content-disposition", cs).data;} catch {} } catch {} this.sendAsyncMessage("", { title: trg.closest("[title]")?.title, url: (trg.currentRequestFinalURI || uri).spec, contentType, referrerInfo, cookieJarSettings, contentDisposition, sx, isPrivate: u.PrivateBrowsingUtils.isContentWindowPrivate(trg.ownerGlobal) }); } checkTextLinkyTool(doc) { if (doc.title || !doc.documentURI.startsWith("moz-extension:")) return; var lab = doc.querySelector("body > label#lblFrom:first-child")?.textContent; if (lab) doc.title = lab.slice(0, lab.lastIndexOf("(")); } } if (!ChromeUtils.domProcessChild.childID) { ChromeUtils.registerWindowActor("MouseImgSaver", { allFrames: true, parent: {moduleURI: __URI__}, messageManagerGroups: ["browsers"], child: {moduleURI: __URI__, events: {auxclick: {capture: true}, dblclick: {capture: true}, dragstart: {capture: true}}} }); var wref, titles = Object.create(null); var data = Object.assign(Object.create(null), { "browser.download.dir": {type: "String", get set() { var win = wref.get(), {prefs, dirsvc} = win.Services var {DownloadPaths, FileUtils} = win; var map = val => DownloadPaths.sanitize(val); win.Downloads.getList(win.Downloads.ALL).then(list => list.addView({ onDownloadChanged(download) { if (!download.stopped) return; var {url} = download.source, title = titles[url]; if (!title) return; delete titles[url]; if (!download.succeeded) return; var file = FileUtils.File(download.target.path), {leafName} = file; var ext = leafName.slice(leafName.lastIndexOf(".")); var newName = map(title) + ext, {parent} = file; var newFile = parent.clone(); newFile.append(newName); try { newFile.createUnique(file.NORMAL_FILE_TYPE, file.permissions); file.renameTo(parent, newFile.leafName); download.target.path = newFile.path; download.refresh(); } catch {} } })); Object.defineProperty(this, "set", {get() { try {var dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(2, 4); // [Загрузки]/папки ucf_save/файл arr[1] = (arr[1]) ? wref.get().gBrowser.selectedTab.label.slice(0, 64).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim() : ""; // имя вкладки arr.map(map).forEach(dir.append); // ucf_save.dirs: путь для html|имя или домен|папка графики|имя вкладки dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… return dir.path; }}); return this.set; }}, "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true} }); var MouseImgSaverParent = class extends JSWindowActorParent { receiveMessage(msg) { var win = msg.target.browsingContext.topChromeWindow, {name} = msg; if (name) return this[name](win, msg.data); var {url, contentType, contentDisposition, sx, title, isPrivate, referrerInfo, cookieJarSettings} = msg.data; if (sx && sx > win.mozInnerScreenX + win.innerWidth) return; if (title) titles[url] = title; wref = Cu.getWeakReference(win); var p = win.Services.prefs; for(var pref in data) { var obj = data[pref], meth = `et${obj.type}Pref`; obj.val = p.prefHasUserValue(pref) ? p["g" + meth](pref) : null; p["s" + meth](pref, obj.set); } try {win.internalSave( url, null, // document null, // file name contentDisposition, contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data u.E10SUtils.deserializeReferrerInfo(referrerInfo), u.E10SUtils.deserializeCookieJarSettings(cookieJarSettings), win.document, // initiating doc true, // skip prompt for where to save null, // cache key isPrivate, win.document.nodePrincipal );} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } } dblclick(win, imgURL) { var gb = win.gBrowser, index = gb.selectedTab._tPos + 1; gb.selectedTab = gb.addTrustedTab('https://yandex.ru/images/search?rpt=imageview&url=' + imgURL, {index}); } dragend(win, imgURL) { var gb = win.gBrowser, index = gb.selectedTab._tPos + 1; gb.selectedTab = gb.addTrustedTab(imgURL, {index}); } } }
Отредактировано Dobrov (17-08-2021 11:17:43)
Отсутствует
"Левый длинный клик добавляет текущую вкладку в закладки под нажатой закладкой, в боковой панели закладок"
Скорее «длинное нажатие», чем «длинный клик».
(sb => { var delay = 500; var tid, once = {once: true, capture: true}; var erre = /^about:(?:neterror|certerror|blocked)/; var click = e => { window.removeEventListener("dragstart", dragstart, once); tid ? clearTimeout(tid) : e.stopPropagation(); } var dragstart = e => { tid && clearTimeout(tid); window.removeEventListener("click", click, once); } var bookmark = async (index, parentGuid, tree, row) => { tid = null; var br = gBrowser.selectedBrowser; var url = new URL(br.currentURI.spec); var charset, info = {url}; try { if (br.documentURI && erre.test(br.documentURI.spec)) { var entry = await PlacesUtils.history.fetch(br.currentURI); if (entry) info.title = entry.title; } else info.title = br.contentTitle; charset = br.characterSet; } catch {} await PlacesTransactions.NewBookmark({index, parentGuid, ...info}).transact(); charset && PlacesUIUtils.setCharsetForPage(url, charset, window).catch(Boolean); tree.ensureRowIsVisible(row + 1); } var pointerdown = function(e) { if (e.button) return; var tree = this.parentNode; if (tree.view._rootNode.query.searchTerms) return; var {row} = tree.getCellAt(e.x, e.y); if (row == -1) return; var node = tree.view.nodeForTreeIndex(row); if (node?.bookmarkGuid && ( node.type == node.RESULT_TYPE_URI || node.type == node.RESULT_TYPE_SEPARATOR )) { var pid = node.parent.targetFolderGuid; if (!pid) return; window.addEventListener("click", click, once); window.addEventListener("dragstart", dragstart, once); var ind = node.bookmarkIndex + 1; tid = setTimeout(bookmark, delay, ind, pid, tree, row); } } var gtc = e => (e.target || e)?.getElementById?.("bookmarks-view")?.body; var unload = e => { var tc = gtc(e); if (tc) tc.removeEventListener("pointerdown", pointerdown, true), tc.ownerGlobal.removeEventListener("unload", unload); } addDestructor(() => unload(sb.contentDocument)); var pageshow = e => { var tc = gtc(e); if (tc) tc.addEventListener("pointerdown", pointerdown, true), tc.ownerGlobal.addEventListener("unload", unload); } addEventListener("pageshow", pageshow, true, sb || 1); pageshow(sb.contentDocument); })(document.getElementById("sidebar"));
Можно вас еще попросить сделать чтобы внешние ссылки открывались в том же контейнере что и активная вкладка?
И открытие новой вкладки (кнопка + на панели вкладок(ctrl+t)) так же было в активном контейнере
Больше вмешательств — больше вероятность негативных последствий.
Ну попробуй дописать после «this.quit = false;» ещё строк. Вот так:
....... this.quit = false; var tuc = "gBrowser.selectedTab.userContextId"; win.BrowserOpenTab = win.eval(`(${win.BrowserOpenTab})`.replace( "resolve,", `$&\n userContextId: ${tuc},` )); var bdw = win.browserDOMWindow.wrappedJSObject; win.Object.assign(bdw, win.eval( `({${bdw.getContentWindowOrOpenURI}})` .replace("userContextId,", `isExternal ? ${tuc} : $&`) .replace( /null,\s+null,\s+null,\s+aTriggeringPrincipal/, `isExternal ? ${tuc} : $&` ) ));
Возможно ли что-то придумать, что бы при закреплении вкладки она оставалась на своей позиции, а не перемещалась влево?
Если переопределить метод gBrowser.pinTab() так,
чтобы в нём не исполнялось выражение this.moveTabTo(aTab, this._numPinnedTabs);
то, при закреплении вкладки, она останется на своей позиции, влево не переместится.
А если серьёзно, то задача подавления специфического позиционирования
закреплённых вкладок кажется довольно сложной. И, если бы не юзерагент
из поста с вопросом, то можно было бы попробовать повозиться, но без особой надежды.
Зачем мне такие ссылки, если у меня скрипты не разрешены.
Не исключено, что поможет, если для таких документов
зарегистрировать стиль типа img {pointer-events: auto !important;}
Проверь.
Отсутствует
И, если бы не юзерагент из поста с вопросом, то можно было бы попробовать повозиться, но без особой надежды.
Dumby, извиняюсь. Мне надо было сразу указать, что мой вопрос для крайней версии .
«The Truth Is Out There»
Отсутствует
Dobrov
/* https://2gis.ru/ - доступность картинок */ @-moz-document url-prefix("https://2gis.ru/") { img { pointer-events: auto !important; } }
Отредактировано _zt (17-08-2021 21:59:44)
Отсутствует
Dumby
Можно вас попросить добавить еще открытие закладки в контейнере?
Чтобы ЛКМ по закладке отрывал ее в контейнере (название для контейнера бралось с названия папки в которой находится закладка)
(async (sel, self) => ({ icon: "circle", colors: [ "#FF9800", "#03A9F4", "#FFC107", "#00BCD4", "#FFEB3B", "#009688", "#CDDC39", "#4CAF50", "#8BC34A", "#D32F2F", "#4949ff", "#C2185B", "#607D8B", "#7B1FA2", "#9E9E9E", "#673AB7", "#795548", "#3F51B5", "#FF5722", "#2196F3", ], 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; var tuc = "gBrowser.selectedTab.userContextId"; win.BrowserOpenTab = win.eval(`(${win.BrowserOpenTab})`.replace( "resolve,", `$&\n userContextId: ${tuc},` )); var bdw = win.browserDOMWindow.wrappedJSObject; win.Object.assign(bdw, win.eval( `({${bdw.getContentWindowOrOpenURI}})` .replace("userContextId,", `isExternal ? ${tuc} : $&`) .replace( /null,\s+null,\s+null,\s+aTriggeringPrincipal/, `isExternal ? ${tuc} : $&` ) )); }, 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.maybeRemove); }, maybeRemove() { var ids = Array.from(self.closed); self.closed.clear(); for(var id of ids) self.maybeRemoveById(id); }, maybeRemoveById(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.resolveOnNewTabCreated = br => { var tab = gBrowser.getTabForBrowser(br); gBrowser.moveTabTo(tab, Infinity); gBrowser.addTrustedTab("about:blank", { index: tab._tPos, userContextId: tab.userContextId }); }, 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, triggerNode} = this.parentNode; var node = triggerNode._placesView && triggerNode._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) => { var {bookmarkGuid: guid, title} = node; if (guid && title) title = win.PlacesUtils.bookmarks.getLocalizedTitle({guid, title}); this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node), title); guid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls, title) { var userContextId = this.newUsercontext(title); 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 (21-08-2021 13:26:05)
Отсутствует
У меня Waterfox 2020.10 не работает ни одна из версий расширения, ни кто не подскажет в моём браузере это расширение вообщt работает?
У меня в Waterfox 2021.07 работает Custom Buttons 0.0.5.8.9.6 - https://forum.mozilla-russia.org/viewto … 43#p744943
Отредактировано unter_officer (22-08-2021 20:35:19)
«The Truth Is Out There»
Отсутствует
Rin66 пишетУ меня Waterfox 2020.10 не работает ни одна из версий расширения, ни кто не подскажет в моём браузере это расширение вообщt работает?У меня в Waterfox 2021.07 работает Custom Buttons 0.0.5.8.9.6 - https://forum.mozilla-russia.org/viewto … 43#p744943
Отредактировано unter_officer (Сегодня 20:35:19)
Ставил эти версии, после установки внизу браузера постоянно висит надпись "xmlns-http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">"
Отсутствует
Доброго времени .
Отвалилась кнопка Custom Buttons при переходе на версию ESR 91.0.1 .
Есть какое решение?
Distance Subordinatio!
Отсутствует
Dumby
Где эта настройка ? Все облазил и не могу найти. "переключаться на вкладку..."
Да,еще, а нельзя при запуске браузера исполнить бантик ? Наверное только через ключ ? Пробую от tete009/,а там Default Browser Agent залетает в реестр.
При выходе убирается ,вот бы при запуске вообще не появлялся ,может скриптом ?
Батник и vbs - есть,но как после запуска чтоб он сработал ? А,черт с ним . Просто вставил в ini
var file = Services.dirsvc.get('ProfD', Ci.nsIFile); file.initWithPath(file.path + "\\memory\\Delк.vbs"); file.launch();
Отредактировано ВВП (23-08-2021 23:06:07)
Отсутствует