okkamas_knife и bunda1 спасибо за помощь, а то я немного запутался.
Вот фрагмент работоспособного кода, может кому то пригодиться
var IncDecPage = 1; //Только целое число!!! var delay = 600; // Задержка для Long Right this.onmousedown = function(event) {this._mouseDownTime = Date.now();}; //.................... //Вверх по странице this.rightclick = function(event) { if ((Date.now() - this._mouseDownTime) > delay) { gShowPopup(this); return; } var scroller = this.scroller; if(!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) { event.preventDefault(); event.stopPropagation(); content.scrollByPages(-IncDecPage); } }; //.................... this.setAttribute('onclick', 'custombuttons.gQuot.mHandler(event, this)'); this.setAttribute('ondblclick', 'custombuttons.gQuot.mHandler(event, this)');
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует
Вопрос знающим людям
Как отсортировать массив объектов placesList по свойству uri так что бы объекты с одинаковыми доменами uri.split(/\/+/g)[1] были по группам в массиве, а эти группы были отсортированы по свойству title в алфавитном порядке placesList.sort(function(a, b) a.title.localeCompare(b.title, {sensitivity: "base"}));Мучаюсь с этим уже который час и не могу придумать решение
Я, конечно, человек не знающий, но что если:
1. Отсортировать исходный массив по свойству uri в алфавитном порядке.
2. Отсортированный массив распихать по группам с одинаковыми доменами.
(Просто при прохождении массива текущий домен сравнивать с предыдущим.
Если равны - переписывать в ту же группу, если нет - создавать новую и записывать туда)
3. Каждую такую группу отсортировать по свойству title в алфавитном порядке.
Отредактировано difabor (10-06-2014 18:55:49)
Хорошо, когда у человека есть выбор, но плохо, когда он перед ним стоит ©
Отсутствует
Сегодня обновил браузер до 30. Перестала работать "//Добавление в меню расширений дополнительных пунктов". Поправьте, пожалуйста.
//Добавление в меню расширений дополнительных пунктов (function(){ var iconURL = null; let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/XPIProvider.jsm"); const usoRegx = /^https?:\/\/userscripts.org\/scripts\/source\/\d+.\w+.js$/; window.AMD_Helper = { init: function(){ document.addEventListener("DOMContentLoaded", this, false); this.addHomePageForScriptish(); }, handleEvent: function(event){ switch(event.type){ case "DOMContentLoaded": var doc = event.target; var win = doc.defaultView; if (["about:addons","chrome://mozapps/content/extensions/extensions.xul"].indexOf(doc.URL) == -1) return; this.addPopupMenu(doc); win.AMD_Helper = AMD_Helper; this.win = win; var observer = new MutationObserver(function(e) { e = e[e.length-1]; if(e.attributeName == "loading") { var doc = e.target.ownerDocument; } }); observer.observe(doc.getElementById("detail-view"), {attributes: true}); break; case "popupshowing": this.getAddon(this.win.document.popupNode.value, this.setItemsAttributes, event); break; } }, addHomePageForScriptish: function(){ if(!window.Scriptish_config) return; Scriptish_config.scripts.forEach(function(script){ if(!script.homepageURL && script.updateURL){ if(usoRegx.test(script.updateURL)){ script.homepageURL = script.updateURL.replace(/source/, "show").replace(/.\w+.js$/, ""); } } }); }, //Создаем меню addPopupMenu: function(doc){ var mainicon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAB3RJTUUH1wcREBAg9OD7NAAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAARnQU1BAACxjwv8YQUAAAH6SURBVHjaxVNBaxNBFP4mGRNp06bSaGu9qXhRLOSQX6Dg0d48SMWC4Mmbv8AfYA7Sgp6UgteCF29CKahBsKKWglgam4rRxGxiks3u7Mz6zZIlSVHRk7N8vLcz7/vemzczwP8eorSCgtLJJeXpUGtMBQHgK5RptxbuYJUx5o8CL5bx+OzCkyuZ2cLIwtPihbVW9a1GiCyFQyusFD4S2zfv4x5DtI2TAphOZk8zbXFE4NKt5ctInDmY8OLd6zNrtI+IlhURG0Xs55dezZXXF9Gq7CA9NQvNbAH19W/wo+6gWXeaN1aQkybEXLv2Bb36Z+SvfUAynYLgB9Y+GLEv6Sl4HTdcvX0yy4kZqdkit1nFWC4Pme4ydvMXxNiOwwTfIVP5OCBlK0Cv8Y4C5xnXYM+bB0ixTwjWHwpUdzbh+ijZSWlYQefrcxwrLJJcIZxRAWM33qP1KTCOwJ9ErbyLno8trvqRgOrsITV5ik6pT2IXvbZdINmjVr8CmYMx09h7/8wKMBtUtIWgu4/DE8e5lxob4pLsDkhhvxJrjYfE2Am065/Et1ZUQRAJTBxJIDQJZrgKZDiRwYA03AlxCF1Ho92oYGM7ElCS5/qmVjXzLx+cg71tMex5D/8Pw+ng4etd2GYpER0ucJRI26v9l2/Ivg82CI2YIP+BPCyifwI91AzKs/qQkQAAAABJRU5ErkJggg=="; var mainicon1="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABVUlEQVQ4y2P4//8/AyWYoALpQsb9ftPM/4tnM+4nywCQ5s5jRf8d+7T+k2VAxHzH/TUHkv57TDMgzgWyJYz74xZ6/E9Y4vU/ZaXv/9Jd0f/LDkb+j13v8N9xmtp/oy6J/xqN/P+5Ihj2YzUApHnxtb7/My83/e8+W/C/9nj8//yD/v+T99j/D99u8N9nk/J/h9Vi/+Vq2P5jNQBkMz7NTuvE/1ut5v0vV8+M3QCQs3Fptlsh+l93Ktd/pTaW/wKpjAgDYFEFCjCQn3HZDNLME8tYANLDEcrgADcAFlWg0AYFGC5nK3ew/McaC6BEAopnUFSBQhubZpMVbP81JrFgdwEyBkUVup9BNoM0681hBdMYYYCMQfGMzc8gGqQZ5BIQxhkLoEQCimeQs0E2IcuB+CDNxkvZ/ktX4jAAlMJAiQRkA8iZML+CaBAfJA7SDOTvJyovEMIAruB4gKjNkYMAAAAASUVORK5CYII="; var mainicon2="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAwAAAP8AAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAD/AAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAA/wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAP8AAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAD/AAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAA8wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAPAAAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAAAAAAAHsAAAD/AAAAkAAAAAAAAADwAAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAIQAAAD/AAAAjQAAAAAAAAB1AAAA/wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAIoAAAD/AAAAigAAAAAAAABpAAAAAAAAAAAAAAB7AAAA/wAAAIcAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAigAAAAAAAAB7AAAA8AAAAAAAAACEAAAA/wAAAIcAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAhwAAAAAAAACBAAAA/wAAAPAAAACKAAAA/wAAAIcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAAA/wAAAP8AAAD/AAAA/wAAAIcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAIQAAAAAAAAAAAAAAAAAAAAAAB8AAAAfAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAxAAAAIgAAAAWAAAAJEAAAEDAAD+BwAA+A8AAA=="; var ins = doc.getElementById("menuitem_uninstallItem"); if(!ins) return; ins = ins.nextSibling; var popup = ins.parentNode; var menuitem = $C("menuseparator", { id: "AMD-separator-1" }); popup.insertBefore(menuitem, ins); menuitem = $C("menuitem", { id: "AMD-browse-dir", class: "menu-iconic", image: mainicon, label: "Место установки", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.browseDir);" }); popup.insertBefore(menuitem, ins); menuitem = $C("menuitem", { id: "AMD-browse-Folder", class: "menu-iconic", image: mainicon1, label: "Папка установки", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.Folder);" }); popup.insertBefore(menuitem, ins); menuitem = $C("menuitem", { id: "AMD-browse-goHome", label: "Домашняя страница", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.goHome);" }); popup.insertBefore(menuitem, ins); menuitem = $C("menuitem", { id: "AMD-browse-goAMO", label: "Страница на AMO", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.goAMO);" }); popup.insertBefore(menuitem, ins); menuitem = $C("menuitem", { id: "AMD-browse-support", label: "Страница поддержки", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.support);" }); popup.insertBefore(menuitem, ins); var menu = $C("menu", { id: "AMD-menu", class: "menu-iconic", image: mainicon2, label: "Копировать", }); popup.insertBefore(menu, ins); var menuPopup = $C("menupopup", { id: "AMD-menupopup", }); menu.appendChild(menuPopup); menuitem = $C("menuitem", { id: "AMD-copy-name", label: "Копировать имя", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyName);" }); menuPopup.appendChild(menuitem); menuitem = $C("menuitem", { id: "AMD-copy-version", label: "Копировать версию", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyVersion);" }); menuPopup.appendChild(menuitem); menuitem = $C("menuitem", { id: "AMD-copy-NameVersion", label: "Копировать имя и версию", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyNameVersion);" }); menuPopup.appendChild(menuitem); menuitem = $C("menuitem", { id: "AMD-copy-id", label: "Копировать id", oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyID);" }); menuPopup.appendChild(menuitem); menuitem = $C("menuitem", { id: "AMD-go-uso", class: "greasemonkey", hidden: true, label: "Страница на Userscripts.org", oncommand: "openURL(this.tooltipText);" }); popup.appendChild(menuitem); menuitem = $C("menuitem", { id: "AMD-find-uso", class: "greasemonkey", hidden: true, label: "Поиск по Userscripts.org", oncommand: "openURL(this.getAttribute('find-on-uso'));" }); popup.appendChild(menuitem); popup.addEventListener("popupshowing", this, true); }, //Указываем где и когда показывать элементы меню setItemsAttributes: function(aAddon, event){ var popup = event.target; var doc = popup.ownerDocument; var isExtension = (aAddon.type == "extension"); var isTheme = (aAddon.type == "theme"); var isPlugin = (aAddon.type == "plugin"); var isUserStyle = (aAddon.type == "userstyle"); var isScriptish = (aAddon.type == "userscript"); var isUserScript = (aAddon.type == "user-script") || // Greasemonkey (aAddon.type == "userscript") || // Scriptish (aAddon.type == "greasemonkey-user-script"); // Greasemonkey 1.7+ var isCustomButton = (aAddon.type == "custombuttons"); var isService = (aAddon.type == "service"); var browseDirItem = doc.getElementById("AMD-browse-dir"); browseDirItem.hidden = isUserStyle || isUserScript || isCustomButton || isService; var browseFolderItem = doc.getElementById("AMD-browse-Folder"); browseFolderItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService; var copyNameItem = doc.getElementById("AMD-copy-name"); copyNameItem.tooltipText = aAddon.name; copyNameItem.className = isUserScript ? isScriptish ? "" : "greasemonkey" : ""; var copyNameVersionItem = doc.getElementById("AMD-copy-NameVersion"); copyNameVersionItem.hidden = isUserStyle || isCustomButton || isService; copyNameVersionItem.tooltipText = aAddon.name + " " + aAddon.version; copyNameVersionItem.className = isUserScript ? isScriptish ? "" : "greasemonkey" : ""; var copyIDItem = doc.getElementById("AMD-copy-id"); copyIDItem.tooltipText = "ID: " + aAddon.id; copyIDItem.className = isUserScript ? isScriptish ? "" : "greasemonkey" : ""; var copyVersionItem = doc.getElementById("AMD-copy-version"); copyVersionItem.tooltipText = aAddon.version; copyVersionItem.hidden = isUserStyle || isCustomButton || isService; copyVersionItem.className = isUserScript ? isScriptish ? "" : "greasemonkey" : ""; var opengoAMOItem = doc.getElementById("AMD-browse-goAMO"); opengoAMOItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService; var amoURL = aAddon.reviewURL ? aAddon.reviewURL.replace(/\/reviews\//, "/") : null; opengoAMOItem.tooltipText = amoURL; opengoAMOItem.hidden = !amoURL || /addons.mozilla.org/.test(aAddon.homepageURL); var opengoHomeItem = doc.getElementById("AMD-browse-goHome"); opengoHomeItem.hidden = isUserScript || isCustomButton || isPlugin; if (aAddon.homepageURL) { opengoHomeItem.tooltipText = aAddon.homepageURL; } else if (aAddon.reviewURL) { opengoHomeItem.tooltipText = amoURL; } opengoHomeItem.hidden = !(aAddon.homepageURL || aAddon.reviewURL); var opensupportItem = doc.getElementById("AMD-browse-support"); opensupportItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService; opensupportItem.tooltipText = aAddon.supportURL; opensupportItem.hidden = !aAddon.supportURL; if(isUserScript && !isScriptish){ var usoURL = ""; if (aAddon._script) { var usDownloadURL = aAddon._script._downloadURL; var usUpdateURL = aAddon._script._updateURL; if (usoRegx.test(usDownloadURL)) { usoURL = usDownloadURL; } else if (usoRegx.test(usUpdateURL)) { usoURL = usUpdateURL; } } var usoItem = doc.getElementById("AMD-go-uso"); usoItem.disabled = !usoRegx.test(usoURL); usoItem.className = isUserScript ? usoItem.disabled ? "" : "greasemonkey" : ""; usoItem.tooltipText = usoURL.replace(/source/, "show") .replace(/.\w+.js$/, ""); var fusoItem = doc.getElementById("AMD-find-uso"); fusoItem.disabled = usoRegx.test(usoURL); fusoItem.className = isUserScript ? fusoItem.disabled ? "" : "greasemonkey" : ""; fusoItem.setAttribute("find-on-uso", "http://userscripts.org/scripts/search?q=" + encodeURIComponent(aAddon.name)); } }, getPopupNode: function (aNode) { var doc = aNode.ownerDocument; return "triggerNode" in aNode.parentNode ? aNode.parentNode.triggerNode : doc.popupNode; }, getAddon: function (aId, aCallback, aEvent) { var self = this; if (this.win.gDetailView._addon) { aCallback.apply(this, [this.win.gDetailView._addon, aEvent]); return; } AddonManager.getAllAddons(function(aAddons) { for (var i = 0; i < aAddons.length; i++) { if (aAddons[i].id == aId) { aCallback.apply(self, [aAddons[i], aEvent]); return; } } }); }, //Домашняя страница goHome: function (aAddon) { var url = aAddon.homepageURL; if (!url) { if (aAddon.reviewURL) { url = aAddon.reviewURL.replace(/\/reviews\/.*$/, "/"); } else { url = "https://addons.mozilla.org/search/?q=" + encodeURIComponent(aAddon.name); } } openURL(url); }, //Страница на АМО goAMO: function (aAddon) { var sourceTracker = "/?src=external-Add-ons_Manager_Context_Menu-extension"; if (aAddon.reviewURL) { var amoURL = aAddon.reviewURL.replace(/\/reviews\//, "/") .replace(/\/(firefox|seamonkey|thunderbird|android)/, "") .replace(/\/\?src\=api/, sourceTracker); } if (/personas.mozilla.org$/.test(aAddon.id)) { amoURL = "https://addons.mozilla.org/addon/" + aAddon.id.match(/\d+/) + sourceTracker; } openURL(amoURL); }, //Страница поддержки support: function (aAddon) { openURL(aAddon.supportURL); }, //Открыть место установки browseDir: function (aAddon) { switch(aAddon.type){ case "plugin": var pathes = aAddon.pluginFullpath; for (var i = 0; i < pathes.length; i++) { this.revealPath(pathes[i]); } return; } var gecko = parseInt(Services.appinfo.platformVersion); var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile", "initWithPath"); var dir = Services.dirsvc.get("ProfD", Ci.nsIFile); dir.append("extensions"); dir.append(aAddon.id); var fileOrDir = dir.path + (dir.exists() ? "" : ".xpi"); try { (new nsLocalFile(fileOrDir)).reveal(); } catch (ex) { var addonDir = /.xpi$/.test(fileOrDir) ? dir.parent : dir; try { if (addonDir.exists()) { addonDir.launch(); } } catch (ex) { var uri = Services.io.newFileURI(addonDir); var protSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]. getService(Ci.nsIExternalProtocolService); protSvc.loadUrl(uri); } } }, //Открыть папку установки Folder: function (aAddon) { var gecko = parseInt(Services.appinfo.platformVersion); var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile", "initWithPath"); var dir = Services.dirsvc.get("ProfD", Ci.nsIFile); dir.append('extensions'); dir.append(aAddon.id); if ( dir.exists() ) dir.launch(); var file = Components.classes['@mozilla.org/file/directory_service;1'] .getService(Components.interfaces.nsIProperties) .get('ProfD', Components.interfaces.nsILocalFile); file.append('extensions'); file.append( aAddon.id + '.xpi' ) if ( file.exists() ) file.launch(); return; }, //Копировать имя copyName: function (aAddon) { this.copyToClipboard(aAddon.name); }, //Копировать ID copyID: function (aAddon) { this.copyToClipboard("ID: " + aAddon.id); }, //Копировать версию copyVersion: function (aAddon) { this.copyToClipboard(aAddon.version); }, //Копировать имя и версию copyNameVersion: function (aAddon) { this.copyToClipboard(aAddon.name + " " + aAddon.version); }, //Вспомогательные функции revealPath: function(path){ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); file.initWithPath(path); if(file.exists()) file.reveal(); }, copyToClipboard: function (aString) { Cc["@mozilla.org/widget/clipboardhelper;1"]. getService(Ci.nsIClipboardHelper).copyString(aString); } }; AMD_Helper.init(); function $C(name, attr) { var el = document.createElement(name); if (attr) Object.keys(attr).forEach(function(n) el.setAttribute(n, attr[n])); return el; } })();
Отредактировано Mishania (10-06-2014 10:19:15)
Отсутствует
Cu.import("resource://gre/modules/XPIProvider.jsm");
https://blog.mozilla.org/addons/2014/05 … irefox-30/
Move some addon-private JSM’s to a subdirectory. A large number of number of JS modules used in the Add-ons Manager were moved to a different path. They include AddonRepository.jsm, LightweightThemeImageOptimizer.jsm, XPIProvider.jsm, AddonUpdateChecker.jsm, AddonLogging.jsm, PluginProvider.jsm, AddonRepository_SQLiteMigrator.jsm, XPIProviderUtils.js and SpellCheckDictionaryBootstrap.js. The new path is resource://gre/modules/addons/MODULE.jsm.
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Mishania
Как минимум, надо заменить
на
Или (чтобы универсально) на
try { Cu.import("resource://gre/modules/XPIProvider.jsm"); } catch(e) { Cu.import("resource://gre/modules/addons/XPIProvider.jsm"); }
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Отсутствует
Хотя если перегрузить браузер, какое-то время отображается правильно, но потом опять меню разрастается.
Можно попробовать заменить
на
и
на
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Mishania
Это лучше к автору, чтобы не было кучи дублей.
Я так понимаю, вот это оригинал: https://forum.mozilla-russia.org/viewto … 33#p632733
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
1. Отсортировать исходный массив по свойству uri в алфавитном порядке.
2. Отсортированный массив распихать по группам с одинаковыми доменами.
(Просто при прохождении массива текущий домен сравнивать с предыдущим.
Если равны - переписывать в ту же группу, если нет - создавать новую и записывать туда)
3. Каждую такую группу отсортировать по свойству title в алфавитном порядке.
Спасибо за отзывчивость.
Отсутствует
Infocatcher Вопрос к тебе, т.к. кнопка твоя - Custom_Buttons/Bookmarks_Folder at master · Infocatcher/Custom_Buttons · GitHub
Правда после модификаций она стала немного иной, но все они, модификации, даны тобой
/*CODE*/ if(!event.target && !this.disabled) // Button's hotkey pressed this.open = true;
и
/*Initialization Code*/ // http://infocatcher.ucoz.net/js/cb/bookmarksFolder.js // https://github.com/Infocatcher/Custom_Buttons/tree/master/Bookmarks_Folder // Bookmarks Folder button for Custom Buttons // (code for "initialization" section) // (c) Infocatcher 2011-2013 // version 0.1.0 - 2013-01-26 // Compatibility: Firefox 4.0+, SeaMonkey 2.1+ // Icon by FatCow Web Hosting: http://www.iconfinder.com/icondetails/36059/16/ // Hidden feature: you can manually set extensions.custombuttons.button<N>.bookmarkFolder // preference to any place: URI https://developer.mozilla.org/en-US/docs/Places_query_URIs // (and press OK in button editor or reopen window or restart browser) /* //Описание иконок для подпапок menu.bookmark-item[label="Форум Mozilla Россия"] { list-style-image: url("https://forum.mozilla-russia.org/style/img/Moz-infinity/pun_icon_unactive.png") !important; -moz-image-region: auto !important; } */ setTimeout(function() { //--------------------------- // ----- Массив описания подпапок с иконками -------- var icons = { "Форум Mozilla Россия": "data:image/png;base64,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", "Мозилла код": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFv0lEQVR4XuXVfYxcVRnH8e9z7p33nZntbrfb2u221bZSaukLtbSBUEvVEJAitURMDBAEo2hCo2TVSIjBkGiIEBs1vhRrpJi6kgiGWG1CDMTwIgWKKbZq0a7SNe1u2dnZ7szOy3kem5tNMxNn1t3wh3/4SX6ZP25+55577s0z/N8TZkbyB0cvB15h7jDjCuAlZhAmvn+UduKTEx+pGXdNpfO/oVZ9FKgyS9nxkWurqcznK5kL3XptHzBFC2ElnqJRujC6VISbQW7FbK15D+p3Al8GOyjG48AfaSFVPNcnIjcDt6F+HVHXrsf4khMGzdvjwKs0CMUbqcJZQeR6kE8CNxnEwTDvMa9QV1DfDwwYMgD2DLAf4yDgM+Mj15kLPgHsNixJ1FVMFbwH7/sUvkAUnsV4FLNfAeNhauzsLuDrmF0KRhMz8AbRQspFwg7E7cDsK+mJsSJqW0FpotNd75u7sG06p4H7QvO6DriUFswrhAp+Ok6iXyZrYAKZcA0YmIEaAGYGgHqFhrSwGNgc4v3btKPR8QEGNQ/nypAIWLsoQ9I5jo6WKL1VABRwYAqdKTKZGOY9NKSNt0NUhXbUUAecOQ/1Onve38ut6xewoT8LwMkzJZ46luP14SKX9eVQE7713CnOjpXJpAPQGU8gElqbi84JVTXqfxtjw6rF/PCGVWx6TyeNVvSm+WLvCsADLsq2JTm2fOdFpkLDBQr6XzaAKk0MJHSUpmrwjwKf3XEJ37t9PQgtFSfOX3zvmZhwxcoeVs1L8Zdjp/HrlgIG6md5AgYucJQLZcJyjcc+s5VbrlrOTEQENcOJRN9mOqjwxO0beeDJOE/8tQijBvkYdMRbnoRDlYsxpVKqsiQVsvfGNXhT3hguYMyOCEyWK6xdluMXe67myD1buG9bH30OGJ4g4rUpIXXlIgHnoDBZ4bev/JOdW5fR0xFHmD3nHIVimQDj8lU9UQY+uJQ7B48z+KcR6EyCNb4C1aZH0HKN1d0ZrnrfQi5b3kl3OsZcORHqapSnpkglk2RzCe7evpTBl09DNg7W9iMUUGV+KqAyPsXh14ZZuShPPuQd64kFuHiAVuvgpGEDXmkkgfDC0Bid3tj1gZUUS1XyqQTvlMeQugfvwKT9HBAhumk5EM6dKXIyF2dJd5Y2msZvLpcCHL5SYbxcb3xQvn34TXyxDPk4qM0wBzDoiPHacIF6scyDm5ZQ9UY8EFpRVTpSMWLxNH8eGmViosKG9/bQ1ZkG4MiJEZ58eZgDr/8LulNQ8zMPIgHUlFOlKvMc7Dt0gq/dtoV4KqCVZCIGKnz1R8/z0OHj1MxY09/F1asXUNGQH//+NBTL0N8JsQC8p5GEn3psD/AIDQSJFuLvozz0uW3c+7ENtGaAcNfDz7DvJy/B+sXRTSiUYaIEyQz0L4IYUFdaeDDEa8tlAxF8V4pfPz/EHdespmtekv8kjE9Msv8Pp+CSBYSBgCrkE7hsiI+n8BhU6oDQSjQHWhGDIJfgdyfOsvGep9l/92a2b+mnGbxw4bofm4TeHOYVhIhXxeoKgYIaYLQSnUArBrgpj70ry1CxzjX3H+bGK5fx6Q+tZOuaXublkwC8cXIUxsvIwhxNa6mCU/B+5j8jvNKOmcJUDfJZSAtPvTgUZf78DMsXZsllYpwaHsH15aFWB2ssN8x8U9oJTWfegHktU62nUIOFHaDGaKnG6PEzUPMQr+CycfCK0SDqaom6pjGdywkY057F9KcEdgjVzXh/B56dCJBwkEiBGK6iUKmBBI3d5zA9QKBPY7oR7++EqOtohshHvzsAfHO6PCQig8BB4FWaocncCsx2Y3wcWA8g1QlQD+LeEpGfT3ePtOi+G7ObgFswNgEgPCyyc+8DwIdBHsHJL4EqsxHv2I4xQOV8N6bfIHCHgDKzYPHsdkzvBY6J3LB3F0IS+BlzlchdJ5XzXcAB5kgTmWsxksLu/fwv/RsPi9kR85vfAgAAAABJRU5ErkJggg==" }; var rules = []; for(var label in icons) if(icons.hasOwnProperty(label)) { rules.push('\ %button% menu.bookmark-item[label="' + label + '"] {\n\ list-style-image: url("' + icons[label] + '") !important;\n\ -moz-image-region: auto !important;\n\ }' ); } var cssStr = ('\ @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");\n\ @-moz-document url("' + document.documentURI + '") {\n' + rules.join("\n") + '\n\ }') .replace(/%button%/g, "#" + self.id); //--------------------------- var cssURI = Services.io.newURI("data:text/css," + encodeURIComponent(cssStr), null, null); var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); if(!sss.sheetRegistered(cssURI, sss.USER_SHEET)) sss.loadAndRegisterSheet(cssURI, sss.USER_SHEET); addDestructor(function(reason) { if(reason == "update" || reason == "delete") { if(sss.sheetRegistered(cssURI, sss.USER_SHEET)) sss.unregisterSheet(cssURI, sss.USER_SHEET); } }); }, 50); var hideDropMarker = true; function _localize(s, key) { var strings = { "Select folder": { ru: "Выберите папку" }, "Root folder": { ru: "Корневая папка" } }; var locale = (cbu.getPrefs("general.useragent.locale") || "en").match(/^[a-z]*/)[0]; _localize = !locale || locale == "en" ? function(s) { return s; } : function(s) { return strings[s] && strings[s][locale] || s; }; return _localize.apply(this, arguments); } this.onclick = function(e) { if(e.target != this) return; //if(e.button == 2 && !e.ctrlKey &&!e.shiftKey && !e.altKey && !e.metaKey) { // Действие при клике ПКМ без модификаторов //this.bookmarks.changeFolder(); //event.preventDefault(); //event.stopPropagation(); // } if(e.button != 2 && !this.bookmarks.initialized) this.bookmarks.init(); else if(e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey)) this.bookmarks.changeFolder(); }; this.onmousedown = function(e) { if(e.target == this && e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey)) e.preventDefault(); }; this.onmouseover = function(e) { if(e.target != this) return; Array.some( this.parentNode.getElementsByTagName("*"), function(node) { if( node != this && node.namespaceURI == xulns && node.boxObject && node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && node.open ) { node.open = false; this.open = true; return true; } return false; }, this ); }; this.bookmarks = { button: this, get pref() { delete this.pref; return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder"; }, get folder() { return cbu.getPrefs(this.pref) || ""; }, set folder(val) { cbu.setPrefs(this.pref, String(val)); }, get wm() { delete this.wm; return this.wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); }, initialized: false, init: function() { var folder = this.folder; if(!folder) { folder = this.selectFolder(); if(!folder) return; this.folder = folder; } var btn = this.button; btn.setAttribute("ondragenter", "PlacesMenuDNDHandler.onDragEnter(event);"); btn.setAttribute("ondragover", "PlacesMenuDNDHandler.onDragOver(event);"); btn.setAttribute("ondragexit", "PlacesMenuDNDHandler.onDragExit(event);"); //btn.setAttribute("ondrop", "PlacesMenuDNDHandler.onDrop(event);"); btn.setAttribute("ondrop", "this.bookmarks.onDrop(event);"); var mp = btn.getElementsByTagName("menupopup"); mp.length && mp[0].parentNode.removeChild(mp[0]); mp = document.createElement("menupopup"); mp.setAttribute("context", "placesContext"); mp.setAttribute("placespopup", "true"); var placeURI = folder.substr(0, 6) == "place:" ? folder : "place:folder=" + folder + "&excludeItems=0&expandQueries=0"; placeURI = placeURI .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """); mp.setAttribute( "onpopupshowing", 'this.parentNode.bookmarks.initMenu(event, "' + placeURI + '");' ); mp.setAttribute("oncommand", "BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"); mp.setAttribute("onclick", "BookmarksEventHandler.onClick(event, this.parentNode._placesView);"); mp.setAttribute("tooltip", "bhTooltip"); mp.setAttribute("popupsinherittooltip", "true"); btn.appendChild(mp); this.initialized = true; }, initMenu: function(event, placeURI) { var btn = this.button; if("_placesView" in btn) return; btn._placesMenu = new PlacesMenu(event, placeURI); // Add "Open All in Tabs" menuitem PlacesViewBase.prototype._mayAddCommandsItems(btn.firstChild); }, destroy: function() { var btn = this.button; if(!("_placesMenu" in btn)) return; try { btn._placesMenu.uninit(); } catch(e) { Components.utils.reportError(e); } delete btn._placesView; delete btn._placesMenu; }, initWithFolder: function(folder) { this.destroy(); this.folder = folder; var mp = this.button.firstChild; mp.setAttribute( "onpopupshowing", mp.getAttribute("onpopupshowing") .replace(/(place:folder=)\w+/, "$1" + folder) ); }, selectFolder: function() { var winType = this.button.id + ":dialog"; var win = this.wm.getMostRecentWindow(winType); if(win) { win.focus(); return null; } // https://developer.mozilla.org/en/Displaying_Places_information_using_views var rootFolder = PlacesUIUtils.allBookmarksFolderId; var placesOverlay = Application.name == "SeaMonkey" ? '\n\ <?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks.css"?>\n\ <?xml-stylesheet href="chrome://communicator/content/places/places.css"?>\n\ <?xul-overlay href="chrome://communicator/content/bookmarks/placesOverlay.xul"?>' : '\n\ <?xml-stylesheet href="chrome://browser/content/places/places.css"?>\n\ <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>\n\ <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>'; // Note: <property name="view"> from chrome://communicator/content/places/tree.xml#places-tree // are null sometimes. // We are trying to re-apply binding as a workaround. var winSrc = '\ <?xml version="1.0"?>\n\ <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>' + placesOverlay + '\n\ <dialog xmlns="' + xulns + '"\n\ id="' + this.button.id + "-dialog" + '"\n\ windowtype="' + winType + '"\n\ title="' + _localize("Select folder") + '"\n\ buttons="accept,cancel"\n\ onload="init();"\n\ ondialogaccept="return dialogCallback();"\n\ width="400"\n\ height="350">\n\ <keyset>\n\ <key id="key-accept" keycode="VK_RETURN" modifiers="control"\n\ oncommand="document.documentElement.acceptDialog();" />\n\ </keyset>\n\ <tree id="tree" type="places"\n\ place="place:excludeItems=1&excludeQueries=1&folder=' + rootFolder + '"\n\ hidecolumnpicker="true" seltype="single" flex="1"\n\ onselect="onSelect();">\n\ <treecols>\n\ <treecol id="title" flex="1" primary="true" hideheader="true" />\n\ </treecols>\n\ <treechildren />\n\ </tree>\n\ <checkbox id="root" label="' + _localize("Root folder") + '" oncommand="onSelect();" />\n\ <script type="application/javascript"><![CDATA[\n\ var [folderId, rootFolder, callback, context] = window.arguments;\n\ var tree = document.getElementById("tree");\n\ var root = document.getElementById("root");\n\ function init() {\n\ if(!ensurePlacesBinding(init, this, arguments))\n\ return;\n\ if(folderId == rootFolder)\n\ root.checked = true;\n\ else if(folderId != undefined) {\n\ tree.selectItems([folderId]);\n\ var i = tree.view.selection.currentIndex;\n\ if(i != -1) {\n\ setTimeout(function() {\n\ tree.treeBoxObject.ensureRowIsVisible(i);\n\ }, 0);\n\ }\n\ }\n\ onSelect();\n\ }\n\ function onSelect(dis) {\n\ if(!ensurePlacesBinding(onSelect, this, arguments))\n\ return;\n\ if(!arguments.length)\n\ dis = !root.checked && !tree.view.selection.getRangeCount();\n\ document.documentElement.getButton("accept").disabled = dis;\n\ disableTree(root.checked);\n\ }\n\ function ensurePlacesBinding(func, context, args) {\n\ if(tree.view && tree.selectItems)\n\ return true;\n\ \// Try re-apply binding, hack for SeaMonkey\n\ tree.removeAttribute("type");\n\ setTimeout(function() {\n\ tree.setAttribute("type", "places");\n\ setTimeout(function() {\n\ func.apply(context, args);\n\ }, 0);\n\ }, 0);\n\ return false;\n\ }\n\ function disableTree(dis) {\n\ var treechildren = tree.getElementsByTagName("treechildren")[0];\n\ if(dis) {\n\ treechildren.style.opacity = "0.6";\n\ tree.setAttribute("disabled", "true");\n\ }\n\ else {\n\ treechildren.style.opacity = "";\n\ tree.removeAttribute("disabled");\n\ }\n\ }\n\ function dialogCallback() {\n\ if(root.checked)\n\ var id = rootFolder;\n\ else {\n\ var view = tree.view;\n\ var i = view.selection.currentIndex;\n\ if(i == -1)\n\ return false;\n\ var item = view.nodeForTreeIndex(i);\n\ if(item) {\n\ var id = /place:folder=(\\w+)/.test(item.uri)\n\ ? RegExp.$1\n\ : item.itemId;\n\ }\n\ }\n\ callback.call(context, id);\n\ return true;\n\ }\n\ onSelect(false);\n\ ]]></script>\n\ </dialog>'; var folder; var callback = function(folderId) { folder = folderId; }; var folderId = this.getFolderId(this.folder); window.openDialog( "data:application/vnd.mozilla.xul+xml," + encodeURIComponent(winSrc.replace(/^\s+/, "")), "_blank", "chrome,all,resizable,centerscreen,modal", folderId, rootFolder, callback, this ); return folder; }, changeFolder: function() { if(!this.initialized) { this.init(); return; } var folder = this.selectFolder(); if(!folder) return; this.initWithFolder(folder); var ws = this.wm.getEnumerator("navigator:browser"); while(ws.hasMoreElements()) { let w = ws.getNext(); if(w == window) continue; let btn = w.document.getElementById(this.button.id); btn && btn.bookmarks.initWithFolder(folder); } }, getFolderId: function(folder) { if(/^\d+$/.test(folder)) return Number(folder); var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"] .getService(Components.interfaces.nsINavBookmarksService); switch(folder) { case "BOOKMARKS_MENU": return bmsvc.bookmarksMenuFolder; case "TOOLBAR": return bmsvc.toolbarFolder; case "UNFILED_BOOKMARKS": return bmsvc.unfiledBookmarksFolder; } return undefined; }, placesDrop: function(event, folder) { // Based on PlacesMenuDNDHandler.onDrop(event) function try { var ip = new InsertionPoint(folder, PlacesUtils.bookmarks.DEFAULT_INDEX, Ci.nsITreeView.DROP_ON); PlacesControllerDragHelper.onDrop(ip, event.dataTransfer); event.stopPropagation(); } catch(e) { Components.utils.reportError(e); } }, onDrop: function(e) { var folder = this.folder; if(e.target != this.button || !folder) { PlacesMenuDNDHandler.onDrop(e); return; } var folderId = this.getFolderId(folder); if(folderId) this.placesDrop(e, folderId); else PlacesMenuDNDHandler.onDrop(e); } }; this.type = "menu"; this.orient = "horizontal"; if(hideDropMarker) { let btn = this; let doc = btn.ownerDocument; let stopTime = Date.now() + 500; setTimeout(function hideDropMarker() { // Wait for menu XBL binding var dm = doc.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-menu-dropmarker"); if(dm) { dm.hidden = true; let icon = doc.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-icon"); if(icon) { let s = doc.defaultView.getComputedStyle(icon, null); if(s.paddingRight != s.paddingLeft) // Hack for Firefox 19 and large icons icon.style.paddingLeft = icon.style.paddingRight = s.paddingLeft; } } else if(Date.now() < stopTime) setTimeout(hideDropMarker, 10); }, 0); } setTimeout(function(_this) { // Don't show modal "Select folder" dialog during initialization _this.bookmarks.init(); }, 0, this); this.onDestroy = function() { this.bookmarks.destroy(); }; /* this. onmouseover = function (event) { this. open = true; }; [/spoiler] this. onmouseout = function (event) { setTimeout(function() {this. open = true;},1250); this. open = false; }; */ //code_snippets/autoOpenCloseMenu.js // https://github.com/Infocatcher/Custom_Buttons/blob/master/code_snippets/autoOpenCloseMenu.js // Automatically open menu on mouse over (and hide it on mouse out) // (code for "initialization" section) // Dummy menu this.type = "menu"; this.orient = "horisontal"; this.appendChild(parseXULFromString( '<menupopup xmlns="' + xulns + '" oncommand="alert(event.target.getAttribute(\'label\'));">\ <menuitem label="Item 1" />\ <menuitem label="Item 2" />\ <menuitem label="Item 3" />\ </menupopup>' )); function parseXULFromString(xul) { xul = xul.replace(/>\s+</g, "><"); return new DOMParser().parseFromString(xul, "application/xml").documentElement; } // Autoopen/close feature var openDelay = 200; var closeDelay = 350; var _openTimer = 0; var _closeTimer = 0; this.onmouseover = function(e) { clearTimeout(_closeTimer); if(e.target == this && closeOtherMenus()) { this.open = true; return; } _openTimer = setTimeout(function() { self.open = true; }, openDelay); }; this.onmouseout = function(e) { clearTimeout(_openTimer); _closeTimer = setTimeout(function() { if(!isContextOpened()) self.open = false; }, closeDelay); }; function closeOtherMenus() { return Array.some( self.parentNode.getElementsByTagName("*"), function(node) { if( node != self && node.namespaceURI == xulns && node.boxObject && node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && node.open ) { node.open = false; return true; } return false; } ); } function isContextOpened() { return inBtn(document.popupNode); } function inBtn(node) { for(; node; node = node.parentNode) if(node == self) return true; return false; }
Просто я иногда сохраняю кнопки в HTML-файле и иногда нужно что то восстановить, но вот твоя кнопка ведёт себя немного прикольно, то выдаёт запрос, то ссылается на пустую папку, а то и на другую произвольную — мне надо от этого избавится... ну просто неудобно каждый раз прописывать каждой кнопке соответствующую ей папку.
P.S. Надеюсь, я всё верно изложил.
Отредактировано Indomito (11-06-2014 09:17:42)
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует
Теперь Вопрос: Как отключить автозапрос папки при создании новой кнопки?
Данный вопрос сводится к Вопросу — Как в каждой кнопке "намертво" прописать имя папки с которой она работает?Просто я иногда сохраняю кнопки в HTML-файле и иногда нужно что то восстановить, но вот твоя кнопка ведёт себя немного прикольно, то выдаёт запрос, то ссылается на пустую папку, а то и на другую произвольную — мне надо от этого избавится... ну просто неудобно каждый раз прописывать каждой кнопке соответствующую ей папку.
Во-первых, кнопку можно обновить.
Во-вторых, от «// Dummy menu» и до «// Autoopen/close feature» пример меню, он нужен только для полноценной демонстрации и тут не лишний.
Идентификатор папки сохраняется в about:config:
get pref() { delete this.pref; return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder"; }, get folder() { return Application.prefs.getValue(this.pref, ""); }, set folder(val) { Application.prefs.setValue(this.pref, String(val)); },
Можно убрать номер кнопки из имени настройки, но нужно будет для каждой кнопки вручную задавать что-то уникальное, например,
get pref() { delete this.pref; return this.pref = "extensions.custombuttons.buttonMisc.bookmarkFolder"; },
И можно вписать идентификатор прямо в код:
get folder() { return "12345"; // Идентификатор папки }, set folder(val) { // Сохранение больше не будет работать },
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Установил кнопу на чистом профиле, истыкал её вдоль и поперёк (согласно подсказок), но так и не увидел полезных свойств. Работают только Left Long, Right и Right Long. В консоли соотвественно реакция
TypeError: pt is null
на неработающие клики и ссылается на 52 строку
var pt_hideAttr = pt.getAttribute("type") == "menubar" ? "autohide" : "collapsed";
Отредактировано >ORG@niZM< (11-06-2014 13:45:33)
Отсутствует
Infocatcher Значит в фрагменте
this.bookmarks = { button: this, get pref() { delete this.pref; return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder"; }, get folder() { return cbu.getPrefs(this.pref) || ""; }, set folder(val) { cbu.setPrefs(this.pref, String(val)); },
this.bookmarks = { button: this, get folder() { return "12345"; // Идентификатор папки }, set folder(val) { // Сохранение больше не будет работать }, /* get pref() { delete this.pref; return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder"; }, get folder() { return cbu.getPrefs(this.pref) || ""; }, set folder(val) { cbu.setPrefs(this.pref, String(val)); }, */
Добавлено 11-06-2014 15:52:20
Установил кнопу на чистом профиле, истыкал её вдоль и поперёк (согласно подсказок), но так и не увидел полезных свойств. Работают только Left Long, Right и Right Long. В консоли соотвественно реакция
TypeError: pt is null
на неработающие клики и ссылается на 52 строку
var pt_hideAttr = pt.getAttribute("type") == "menubar" ? "autohide" : "collapsed";
проблема ID панели - HideShowPanel(тут написан ID панели как строковая или можно переменную задать);
У всех много разных панелей и отловить все это надо сканировать prefs.js текущего профиля, но нет гарантии что все будут найдены.
Проще взять кнопку Attributes_Inspector и прописать нужный для тебя ID панели на конкретное действие мыши.
P.S. Я учту твои замечания и создам блок в коде с описанием ID-панелей, что бы избежать путаницы.
Отредактировано Indomito (11-06-2014 16:04:03)
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует
Infocatcher после замены фрагмента исходного на твой... пришлось править таблицу кнопок в ручную, т.к. при наведении на модифицированную кнопку происходит глобальное зависание мозиллы
Про правку я написал в посте №8755 - может что то ещё надо сделать, а?
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует
Indomito
Идентификаторы папок при втором варианте, когда все в коде, надо получать вручную.
Или смотреть, что сохраняет оригинальная версия кнопки в about:config.
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Indomito
Идентификаторы папок при втором варианте, когда все в коде, надо получать вручную.
Или смотреть, что сохраняет оригинальная версия кнопки в about:config.
плиз поясни
1. "Надо получать вручную" - что ты под этим имел, т.е. что писать то?
2. "Оригинальная версия" - тоже проблематично, т.к. не понятно по какому признаку искать.
Если можно немного подробнее напиши.
Отредактировано Indomito (13-06-2014 20:44:05)
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует
плиз поясни
1. "Надо получать вручную" - что ты под этим имел, т.е. что писать то?
2. "Оригинальная версия" - тоже проблематично, т.к. не понятно по какому признаку искать.
Что писать – зависит от выбора папки, у каждой свой уникальный идентификатор.
Оригинальная кнопка записывает этот идентификатор в about:config, в настройку "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder", this.button.id.match(/\d*$/)[0] – номер из идентификатора кнопки.
Можно заменить вот так:
Работать будет не совсем корректно, но после выбора папки ее идентификатор выведет alert'ом. Его нужно скопировать и заменить «null» на «"идентификатор"», кавычки обязательны.
Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела
Отсутствует
Infocatcher Я верно понял:
get folder() { return null; //заменяем на //return "идентификатор"; }, set folder(val) { alert("Folder id: " + val); },
Так?
Что то ещё в коде менять нужно?
Просто не хочется чистить в ручную, из-за подвисаний FireFox, файл buttonsoverlay.xul
"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах
Отсутствует