Страницы: 1
Открыть всё из папки закладок в новых вкладках не загружая страниц ( Firefox 24+ )
Автор: bunda1, Dumby
Версия: от 07.04.2014.
Описание: Код даёт возможность открыть всё из папки закладок или папки истории в новых вкладках не загружая страниц, если нажать средней кнопкой мыши на папку или нажать в контекстном меню папки пункт Открыть всё во вкладках или открыть не загружая страниц выделенные закладки если нажать в контекстном меню этих закладок пункт Открыть всё во вкладках.
Код по умолчанию открывает только закладки с http(s) адресом, и не открывает закладки которые имеют протоколы «about:», «chrome:», «view-source:», «file:» и тп., это можно отключить в начале кода: var httpItem = true;
Если закладок для открывания очень много код что бы избежать зависания браузера будет их открывать по частям, максимальное количество одновременно открываемых закладок 30, это можно изменить в начале кода: var maxBook = 30;
Код покажет в всплывающей подсказке количество открытых закладок если закладки открывались по частям, это можно отключить в начале кода: var showAlert = true;
// Открыть всё из папки закладок в новых вкладках не загружая страниц, от 07.04.2014. ................................ (function () { var httpItem = true; // открывать закладки только с http(s) адресом var maxOpenBook = 30; // максимальное количество одновременно открываемых закладок var showAlert = true; // показать в сообщение количество открытых закладок если закладки открывались по частям const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); // Изменить внутренние функции Firefox которые открывает всё во вкладках .... const nodesInTabs = PlacesUIUtils.openURINodesInTabs; PlacesUIUtils.openURINodesInTabs = function(node) { openNodes(node) }; const nodeInTabs = PlacesUIUtils.openContainerNodeInTabs; PlacesUIUtils.openContainerNodeInTabs = function(node) { openNodes(node) }; addDestructor(function() { PlacesUIUtils.openURINodesInTabs = nodesInTabs; PlacesUIUtils.openContainerNodeInTabs = nodeInTabs }); // Открывать всё во вкладках не загружая страниц .... function openNodes( node ) { node.containerOpen = true; // если это папка из библиотеки if ( node.type && node.type > 5 ) node = PlacesUtils.getContainerNodeWithOptions( node, false, true ); // получить массив с закладками из папки закладок или с выделенными закладками var array = PlacesUtils.nodeIsContainer(node) ? [] : node; for ( i = 0; i < node.childCount; ++i ) { var item = node.getChild(i); if ( httpItem ? !item.uri.startsWith("http") : !PlacesUtils.nodeIsURI(item) ) continue; array.push( node.getChild(i) ); } // открыть в текущей если пустая вкладка var blank = isBlankPageURL( content.location.href ); if ( blank ) gBrowser.loadURI( array.shift().uri ); // открыть массив с закладками с паузами если закладок очень много function f() { for ( var i = 0; i < array.length; ++i ) { var item = array[i]; // добавить вкладку с указанными данными не загружая страницы var {uri, title, icon} = item; if ( !title ) title = uri; var tab = gBrowser.addTab(); ss.setTabState(tab, JSON.stringify({entries: [{ url: uri, title: title}], lastAccessed: 0, index: 1, hidden: false, attributes: {} })); icon && tab.setAttribute("image", icon ); // пауза в цикле через установленное количество циклов if ( i && i % maxOpenBook == 0 ) { setTimeout(function() gen.next(), 150 ); yield 0; } // всплывающая подсказка .... if ( showAlert && array.length == i+1 && i > maxOpenBook ) { var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) alertsService.showAlertNotification("chrome://custombuttons/skin/button.png", "Открыть всё во вкладках", "открыл " + array.length + " закладок"); } } yield 0; } var gen = f(); gen.next(); node.containerOpen = false; } })();
Отредактировано bunda1 (07-04-2014 14:05:57)
Отсутствует
Спасибо за отзывчивость okkamas_knife
небольшой совет по улучшению юзабельности
когда вкладок много непонятно закончилось открытие ии нет, добавь в код (отключаемый в настройках) alertslide показывающий после открытия очередной пачки "Открыто Х вкладок из У"
Может у меня комп слабый но даже при том что закладки открываются по частям браузер притормаживает если открываешь сотни закладок и по этому alertslide будет медленно появляться и рывками а это некрасиво, и так видно что закладки открываются по частям по появлению новые групп вкладок и наверно лучше всего сделать alertslide после того как откроются все закладки. Да так и сделаю.
тогда в массиве можно будет задавать не только протоколы но и домены например
Добавыть возможность делать дополнительные исключения для открывания закладок. Разумно. Может добавлю позже.
Отсутствует
bunda1
Прошу прощения, действительно работает. Как оказалось случайно убрал галку в настройках Не загружать вкладки без запроса.
Отсутствует
bunda1 не могли бы Вы подредактировать под 66?
Отсутствует
bunda1 не могли бы Вы подредактировать под 66?
Нужен портативный Firefox66 + Сustom Buttons.
Отсутствует
bunda1
Варианты сборок
1. http://effect8.ru/soft/browsers/mozilla … e-rus.html, но там пока beta, хотя сборки одни из лучших
2. https://sourceforge.net/projects/portab … tion 66.0/
3. Сustom Buttons - пост Dumby - https://forum.mozilla-russia.org/viewto … 60#p767960 c config.js, config-prefs.js прежний
pref("general.config.obscure_value", 0); pref("general.config.filename", "config.js"); pref("general.config.sandbox_enabled", false);
// Открыть всё из папки закладок в новых вкладках не загружая страниц, от 15.02.2014. ................................ (function () { var ss = "nsISessionStore" in Components.interfaces ? ( Components.classes["@mozilla.org/browser/sessionstore;1"] || Components.classes["@mozilla.org/suite/sessionstore;1"] ).getService(Components.interfaces.nsISessionStore) : SessionStore; // изменить внутреннюю функцию Firefox которая открывает всё во вкладках const openInTabs = PlacesUIUtils.openContainerNodeInTabs; eval("PlacesUIUtils.openContainerNodeInTabs = " + openInTabs.toString().replace(' {', '{\n openTabWithoutLoading(aNode);\n if (aNode.itemId !== -1) return;\n')); addDestructor(function() {PlacesUIUtils.openContainerNodeInTabs = openInTabs} ); // открыть всё из папки закладок function openTabWithoutLoading( aNode ) { aNode.containerOpen = true; for ( var i = 0; i < aNode.childCount; ++i ) { var item = aNode.getChild(i); if ( !PlacesUtils.nodeIsURI( item ) ) continue; // добавить вкладку с указанными данными не загружая страницы var tab = gBrowser.addTab(null, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() }); ss.setTabState( tab, JSON.stringify({ entries: [ { url: item.uri, title: item.title } ], lastAccessed: 0, index: 1, hidden: false, attributes: {}, image: item.icon.replace("moz-anno:favicon:", "") })); } // если текущая пустая вкладка закрыть и переключится на соседнюю вкладку var blank = isBlankPageURL(content.location.href); if ( !blank ) return; gBrowser.removeCurrentTab(); gBrowser.mTabContainer.advanceSelectedTab(1); }; })();
У меня портабельной нет, ну если что, в принципе можно собрать.
Отсутствует
под 66
Давай попробую что-нибудь набросать тебе для правки.
((g, id) => { addDestructor(r => r[5] == "e" && id in g && (g.PlacesUIUtils[id] = g[id]) && delete g[id]); if (id in g) return; g[id] = g.PlacesUIUtils[id]; var func = g => PlacesUIUtils.openMultipleLinksInTabs = async function(nodeOrNodes, event, view) { var where, win = getBrowserWindow(view.ownerWindow); var newWin = !win || (where = win.whereToOpenLink(event, false, true)) == "window"; var items = PlacesUtils.nodeIsContainer(nodeOrNodes) ? PlacesUtils.getURLsForContainerNode(nodeOrNodes) : Array.from(nodeOrNodes).filter(PlacesUtils.nodeIsURI); if (newWin) { var args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray); args.appendElement(PlacesUtils.toISupportsString(items.shift().uri)); win = Services.ww.openWindow( win || null, AppConstants.BROWSER_CHROME_URL, null, "chrome,dialog=no,all", args ); if (!items.length) return; await new Promise(resolve => win.addEventListener("load", resolve, {once: true})); } var loadInBackground = where == "tabshifted"; var insertAfterCurrent = !newWin && Services.prefs.getBoolPref("browser.tabs.insertAfterCurrent"); var triggeringPrincipal_base64 = g.Utils.SERIALIZED_SYSTEMPRINCIPAL || g.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; var multi = items.length > 1; var params = { skipAnimation: multi || newWin, bulkOrderedOpen: multi, createLazyBrowser: true }; if (insertAfterCurrent) params.index = win.gBrowser.selectedTab._tPos; var first = true; for(var {uri, title} of items) { if (insertAfterCurrent) params.index += 1; var tab = win.gBrowser.addTrustedTab(null, params); var state = { index: 1, hidden: false, attributes: {}, lastAccessed: 0, entries: [{url: uri, title, triggeringPrincipal_base64}] }; var image = await new Promise(resolve => PlacesUtils.favicons.getFaviconDataForPage( Services.io.newURI(uri), (uri, len, data, type) => { if (!len) return resolve(); var reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(new Blob([new Uint8Array(data)], {type})); }, 16 )); if (image) state.image = image; g.SessionStore.setTabState(tab, JSON.stringify(state)); if (first) { first = false; if (newWin) continue; if (multi && insertAfterCurrent) params.index = tab._tPos; if (!loadInBackground) win.gBrowser.selectedTab = tab; } } } Services.scriptloader.loadSubScript("data:," + encodeURIComponent( `(${func})(Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}))` ), g); })(Cu.import("resource:///modules/PlacesUIUtils.jsm", {}), "openMultipleLinksInTabs");
Отсутствует
Dumby Вы как всегда на высоте. Посмотрите пожалуйста, если вас не затруднит мой пост первый пункт, я не знаю куда копать, вроде изменений в 66 после 65 для этого нет
Отсутствует
Andrey_Krropotkin
Не, с findbar'ом я давно решил не связываться, слишком сложно для меня.
Ну, так, поверхностно, подкрутил кое-что немного
((bar, button = true, insertAtTop = false, ctrlFcloseFinbar = false) => ({ init(parent) { var has = bar = parent.querySelector("#appcontent > findbar"); has || this.initFinbar(parent); var lo = bar.linkedObject; lo.listenCtrlF = ctrlFcloseFinbar ? listen => listen ? addEventListener("keydown", lo, true) : removeEventListener("keydown", lo, true) : () => {}; has && !bar.hidden && lo.listenCtrlF(true); if (button) self._handleClick = () => bar.hidden ? bar.startFind(bar.FIND_NORMAL) : bar.collapsed || bar.close(); addDestructor(lo.destroy, lo); }, destructors: [], destroy(reason) { if (reason[5] != "e") return; bar.close(); bar._browser = {}; bar.remove(); this.setProgressListener(false); for(var destructor of this.destructors) destructor(); Services.ppmm.removeDelayedProcessScript(this.url); Services.ppmm.loadProcessScript("data:," + encodeURIComponent(`(xrt => xrt.processType != xrt.PROCESS_TYPE_DEFAULT && xrt.processType != xrt.PROCESS_TYPE_CONTENT || (nsvo => { var proto = nsvo.Finder.prototype; if ("_requestMatchesCount" in proto) { proto.requestMatchesCount = proto._requestMatchesCount; delete proto._requestMatchesCount; } })(Cu.import("resource://gre/modules/Finder.jsm", {})))( Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) );` ), false); }, initFinbar(parent) { for(var tab of gBrowser.tabs) { if (!tab._findBar) continue; tab._findBar.browser = null; tab._findBar._browser = {}; tab._findBar.remove(); delete tab._findBar; } bar = document.createElement("findbar"); var p = new Proxy({}, {get: () => () => {}}); bar._browser = {finder: p, messageManager: p}; parent.insertBefore(bar, insertAtTop ? parent.firstChild : null); bar.linkedObject = this; if (parseInt(Services.appinfo.platformVersion) < 66) { var winProps = ["gFindBar", "gFindBarInitialized"]; var winVals = winProps.map(key => Object.getOwnPropertyDescriptor(window, key)); winProps.forEach((key, ind) => { delete window[key]; window[key] = ind ? true : bar; }); this.destructors.push(() => winProps.forEach( (key, ind) => Object.defineProperty(window, key, winVals[ind]) )); } else { var initVal = gBrowser.isFindBarInitialized; gBrowser.isFindBarInitialized = () => true; this.destructors.push(() => gBrowser.isFindBarInitialized = initVal); } var barKey = "getCachedFindBar" in gBrowser ? "getCachedFindBar" : "getFindBar"; var barVal = gBrowser[barKey]; gBrowser[barKey] = () => bar; this.destructors.push(() => gBrowser[barKey] = barVal); //========================================================================================== var createBtn = (before, attrs) => { var btn = document.createElement("toolbarbutton"); for(var args of Object.entries(attrs)) btn.setAttribute(...args); gFindBar.getElement(before).before(btn); return btn; } createBtn("highlight", { type: "button", class: "toolbarbutton-1", id: "clearFindbar-button", tooltiptext: "ЛКМ - вставить из буфера. \nПКМ - очистить поиск", style: "margin-right: 6px !important; margin-left: 6px !important;", image: "data:image/x-icon;base64,AAABAAEADhAAAAEAIADoAwAAFgAAACgAAAAOAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXn/eXl5/3l5ef95eXn/eXl5/3l5ef95eXn/eXl5/ylTda0pU3X/KVN1/ylTdf8pU3X/HTpS/4WFhf/w8PL/8fHz//Hx8//x8fP/8fHz//Hx8/+FhYX/KVN1/yRJaP8jSGf/I0dl/yNHZP8YMEX/j4+P//Hx8//x8vP/8fLz//Hy8//x8vP/8fLz/4+Pj/8pU3X/JUxr/yVLav8kSmn/JElo/xkyR/+cnJz/8vLz//Ly9P/y8vT/8vL0//Ly9P/y8vT/nJyc/ylTdf8nTm3/Jk1t/yVMa/8lSmn/GjNJ/6urq//y8vT/8/P1//Pz9f/z8/X/8/P1//Pz9f+rq6v/KVN1/ydPb/8nTm7/Jk1t/yZMa/8aNEr/srKy//X19v/19vf/9fb3//X29//19vf/9fb3/7Kysv8pU3X/J1Bx/ydQb/8nTm//Jk1t/xs2S/+8vLz/+fr6//r7+//6+/v/ubm5/7e3t/+3t7f/ubm5/ylTdf8oUXP/KFBx/ydQcf8nT2//GzZN/76+vv/6+/v/+/v8//v7/P/ExMT/9vb2/7e3t/na2tpfKVN1/ylTdP8pUXP/KFBy/yhPcP8bN03/v7+///v7/P/7/Pz/+/z8/8rKyv+3t7f/4OLgaQAAAAApU3X/KVN1/yhSdP8oUnT/KFJy/xw4UP+/v7//v7+//7+/v/+/v7//uru7/2OBmf8AAAAAAAAAAClTdf8pU3X/KVN1/ylSdP8pUnT/JEpn/yRIZv8kSGX/I0dk/yNGY/8jRWL/KVN1/wAAAAAAAAAAKVN1/ylTdf8lS2n/IztO/yM7Tv8jO07/IztO/yM7Tv8jO07/JUtp/ydOb/8lS2n/AAAAAAAAAAApU3X/K2GQ/yhahv91dXX/XV1d/11dXf9dXV3/XV1d/4B/f/8oWob/Kmad/ylTdf8AAAAAAAAAAClTda0pU3X/KVN1/7O0tP/h4eD/3t7f/97f3//g4OD/s7S0/ylTdf8pU3X/KVN1rQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1yds1dXFv1XVxb9Wxxdc8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUwFASZMCwAlTAsAI00LIys1CxcXFsEYFxbCJS01DAAlTQsAJk0LASZNCwAlTQUAAAAAAAAAAPwArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAASsQQAMrEEADKxBAAysQQAMrEEADKxB8PysQQAMrEE=" }).onclick = e => { if (!e.button) { // поиск из буфера обмена var ed = gFindBar._findField.editor.QueryInterface(Ci.nsIPlaintextEditor); ed.selectAll(); ed.insertText(gClipboard.read().trim()); //Highlight("hits", "greenLight"); } else if (e.button == 2) { if (!gFindBar._findField.value) return gFindBar.close(); // очистить поле текстового ввода gFindBar._findField.value = ""; gFindBar.onFindAgainCommand(false); } } createBtn("findbar-textbox", { oncommand: "close();", id: "closeFindbar-button", tooltiptext: "Закрыть панель поиска", class: "findbar-closebutton close-icon" }); gFindBar.getElement("find-closebutton").setAttribute("style", "display: none !important;"); // FindBar, поиск колесиком мыши gFindBar.onwheel = e => { gFindBar.onFindAgainCommand(e.deltaY < 0);// updateHits("flash"); } //========================================================================================== [ "close", "startFind", "onMatchesCountResult", "_updateMatchesCount", "_onBrowserKeypress", "receiveMessage" ].forEach((key, ind) => { var func = bar[key].bind(bar); bar[key] = ind ? (...args) => this[key](...args) || func(...args) : (...args) => func(...args) || this[key](...args); }); this.url = "data:," + encodeURIComponent(`(xrt => xrt.processType != xrt.PROCESS_TYPE_DEFAULT && xrt.processType != xrt.PROCESS_TYPE_CONTENT || (nsvo => { var proto = nsvo.Finder.prototype; if ("_requestMatchesCount" in proto) return; proto._requestMatchesCount = proto.requestMatchesCount; proto.requestMatchesCount = ${ this.newRequestMatchesCount } })(Cu.import("resource://gre/modules/Finder.jsm", {})))( Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) );` ); delete this.newRequestMatchesCount; Services.ppmm.loadProcessScript(this.url, true); }, newRequestMatchesCount: async function requestMatchesCount(aWord, aLinksOnly) { if (typeof aLinksOnly != "boolean") { var {linksOnly, data} = aLinksOnly; aLinksOnly = linksOnly; this.entireWord = data.entireWord; this.caseSensitive = data.caseSensitive; this.onModalHighlightChange(data.useModalHighlight); this.onHighlightAllChange(data.highlightAll); data.highlightAll && await this.highlighter.highlight(true, aWord, linksOnly); this._iterator && this._iterator.reset(); var obj; Object.defineProperty(this, "_currentMatchesCountResult", { configurable: true, enumerable: true, get: (val = obj) => { if (val) { if (!val.total) val.total = new Number(0); val.currentFound = val._currentFound; } return obj = val; }, set: val => { if (val) return obj = val; delete this._currentMatchesCountResult; return obj = this._currentMatchesCountResult = val; } }); var lfr = this._lastFindResult; lfr !== null && lfr != Ci.nsITypeAheadFind.FIND_NOTFOUND || Object.defineProperty(this, "_lastFindResult", { configurable: true, enumerable: true, get: () => null, set: val => { if (val == Ci.nsITypeAheadFind.FIND_WRAPPED) val = Ci.nsITypeAheadFind.FIND_FOUND; delete this._lastFindResult; return this._lastFindResult = val; } }); } this._requestMatchesCount(aWord, aLinksOnly); }, close() { bar.collaped = false; this.setProgressListener(false); this.setBrowser(null, null); }, startFind() { if (this.maybeCollapse(gBrowser.selectedBrowser)) return true; if (bar.hidden) this.setBrowser(300), this.setProgressListener(true); else if (!ctrlFcloseFinbar) setTimeout(() => this.updateMatchesCount(), 100); }, onMatchesCountResult(res) { if (!("currentFound" in res) || res.total == -1 || res.currentFound) return; bar._foundMatches.value = `${+res.total || "Нет"} совпадени${ bar.pluralForm.get(res.total, "е;я;й") }.`; bar._foundMatches.hidden = false; return true; }, _updateMatchesCount() { return true; }, _onBrowserKeypress(e) { if (!bar.hidden) return; if (!e.charCode) return true; this.setBrowser(300); this.setProgressListener(true); }, receiveMessage(msg) { msg.target = bar._browser; }, progressListenerAdded: false, setProgressListener(add) { if (add) { if (this.progressListenerAdded) return; this.progressListenerAdded = true; gBrowser.addProgressListener(this); this.listenCtrlF(true); } else { if (!this.progressListenerAdded) return; this.progressListenerAdded = false; gBrowser.removeProgressListener(this); this.listenCtrlF(false); } }, handleEvent(e) { if ( e.ctrlKey && e.code == "KeyF" && !e.shiftKey && !e.altKey && !bar.collapsed ) e.preventDefault(), e.stopPropagation(), bar.close(); }, updateMatchesCount() { var str = bar._findField.value; if (!str) return; var data = { entireWord: bar._entireWord, caseSensitive: bar._typeAheadCaseSensitive, highlightAll: bar._highlightAll, useModalHighlight: bar._useModalHighlight }; bar.browser.finder.requestMatchesCount( bar._findField.value, {linksOnly: bar._findMode == bar.FIND_LINKS, data} ); }, maybeCollapse(br) { return br.isSyntheticDocument || br.documentContentType == "application/vnd.mozilla.xul+xml"; }, setBrowser(updateDelay, br = gBrowser.selectedBrowser) { if (bar._browser != br) { var b = bar._browser; if (b) { b.messageManager.removeMessageListener("Findbar:Mouseup", bar); b.finder.removeResultListener(bar); bar._highlightAll && b.finder.highlight(false); } if (br) { br.messageManager.addMessageListener("Findbar:Mouseup", bar); bar._updateBrowserWithState(); } bar._browser = br; } if (!br) return; bar._updateStatusUI(); bar._foundMatches.value = ""; br.finder.addResultListener(bar); if ( !(bar.collapsed = this.maybeCollapse(br)) && br.currentURI.spec != "about:blank" && updateDelay !== null ) updateDelay ? setTimeout(this.updateMatchesCount, updateDelay) : this.updateMatchesCount(); }, onStateChange(wpr, req, state) { state & Ci.nsIWebProgressListener.STATE_STOP && this.setBrowser(); }, onLocationChange(wpr, req) { req || Components.stack.formattedStack.includes("SessionStore.jsm") || this.setBrowser(); } }).init(document.getElementById("appcontent")))();
Отсутствует
Dumby большое спасибо
Отсутствует
Страницы: 1