阅读:2344回复:2
Firefox 115ESR可移动的按钮菜单脚本求修复
更新到Firefox 115ESR后脚本失效,求万能的坛友修复
// ==UserScript== // @name AnotherButton // @description 可移动的按钮菜单 // @author feiruo // @charset UTF-8 // @include main // @id [A26C02CA] // @inspect window.anoBtn // @startup window.anoBtn.init(); // @shutdown window.anoBtn.onDestroy(); // @config window.anoBtn.EditFile(anoBtn.File); // @reviewURL http://bbs.kafan.cn/thread-1657589-1-1.html // @homepageURL https://github.com/feiruo/userChromeJS/tree/master/anoBtn // @downloadURL https://github.com/feiruo/userChromeJS/raw/master/anoBtn/anoBtn.uc.js // @note 支持菜单和脚本设置重载 // @note 需要 _anoBtn.js 配置文件 // @version 1.4.1 2016.11.07 14:30 Fix For E10s。 // ==/UserScript== (function(CSS) { let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; if (!window.Services) Cu.import("resource://gre/modules/Services.jsm"); if (window.anoBtn) { window.anoBtn.onDestroy(); delete window.anoBtn; } var useScraptchpad = true; // 如果不存在编辑器,则使用代码片段速记器,否则设置编辑器路径 var anoBtn = { get File() { let aFile; aFile = FileUtils.getFile("UChrm", ["local", "_anoBtn.js"], false); if (!aFile.exists()) { saveFile(aFile, ''); alert('_anoBtn.js配置为空,该文件在local目录下'); } delete this.file; return this.file = aFile; }, get FocusedWindow() { var title = gBrowser.selectedTab.label || gBrowser.selectedBrowser.contentTitle; var url = gBrowser.currentURI.spec || gBrowser.selectedBrowser.currentURI.spec; var cont; if (gMultiProcessBrowser) { function listener(message) { cont = message.objects.cont; return cont; } window.messageManager.addMessageListener("AnotherButton:AnotherButton-e10s-content-" + this.E10SMSG, listener); window.messageManager.removeMessageListener("AnotherButton:AnotherButton-e10s-content-" + this.E10SMSG, listener); } else { return window.content || gBrowser.selectedBrowser._contentWindow; } // return window.content || gBrowser.selectedBrowser._contentWindow; }, init: function() { var ins = $("menu_ToolsPopup").firstChild; ins.parentNode.insertBefore($C("menuitem", { id: "anoBtn_set", label: "自定义按钮", tooltiptext: "左键:重载配置\n右键:编辑配置", class: "menuitem-iconic", onclick: "anoBtn.BtnClick(event);", }), ins); if (!this.E10SMSG) this.E10SMSG = Math.floor(Math.random() * 900000 + 99999); if (gMultiProcessBrowser) { if (!this.IsMultiProcessScript) { var script = "data:application/javascript," + encodeURIComponent('sendAsyncMessage("AnotherButton:AnotherButton-e10s-content-' + this.E10SMSG + '", {}, {cont: content,})'); window.messageManager.loadFrameScript(script, true); this.IsMultiProcessScript = true; } } this.ToRegExp(); this.Rebuild(); //setTimeout(function() { // anoBtn.Rebuild(); //}, 1000); //again for webDeveloperMenu this.style = addStyle(CSS); window.addEventListener("unload", function() { anoBtn.onDestroy(); }, false); }, ToRegExp: function() { let he = "(?:_HTML(?:IFIED)?|_ENCODE)?"; let rTITLE = "%TITLE" + he + "%|%t\\b"; let rTITLES = "%TITLES" + he + "%|%t\\b"; let rURL = "%(?:R?LINK_OR_)?URL" + he + "%|%u\\b"; let rHOST = "%HOST" + he + "%|%h\\b"; let rIP = "%IP" + he + "%"; let rBASEDOMAIN = "%BASEDOMAIN" + he + "%"; let rSEL = "%SEL" + he + "%|%s\\b"; let rLINK = "%R?LINK(?:_TEXT|_HOST)?" + he + "%|%l\\b"; let rIMAGE = "%IMAGE(?:_URL|_ALT|_TITLE)" + he + "%|%i\\b"; let rIMAGE_BASE64 = "%IMAGE_BASE64" + he + "%|%i\\b"; let rMEDIA = "%MEDIA_URL" + he + "%|%m\\b"; let rCLIPBOARD = "%CLIPBOARD" + he + "%|%p\\b"; let rFAVICON = "%FAVICON" + he + "%"; let rEMAIL = "%EMAIL" + he + "%"; let rExt = "%EOL" + he + "%"; let rFAVICON_BASE64 = "%FAVICON_BASE64" + he + "%"; let rRLT_OR_UT = "%RLT_OR_UT" + he + "%"; // 链接文本或网页标题 this.rTITLE = new RegExp(rTITLE, "i"); this.rTITLES = new RegExp(rTITLES, "i"); this.rURL = new RegExp(rURL, "i"); this.rIP = new RegExp(rIP, "i"); this.rHOST = new RegExp(rHOST, "i"); this.rBASEDOMAIN = new RegExp(rBASEDOMAIN, "i"); this.rSEL = new RegExp(rSEL, "i"); this.rLINK = new RegExp(rLINK, "i"); this.rIMAGE = new RegExp(rIMAGE, "i"); this.rMEDIA = new RegExp(rMEDIA, "i"); this.rCLIPBOARD = new RegExp(rCLIPBOARD, "i"); this.rFAVICON = new RegExp(rFAVICON, "i"); this.rEMAIL = new RegExp(rEMAIL, "i"); this.rExt = new RegExp(rExt, "i"); this.rFAVICON_BASE64 = new RegExp(rFAVICON_BASE64, "i"); this.rIMAGE_BASE64 = new RegExp(rIMAGE_BASE64, "i"); this.rRLT_OR_UT = new RegExp(rRLT_OR_UT, "i"); this.regexp = new RegExp([rTITLE, rTITLES, rURL, rHOST, rBASEDOMAIN, rIP, rSEL, rLINK, rIMAGE, rIMAGE_BASE64, rMEDIA, rCLIPBOARD, rFAVICON, rFAVICON_BASE64, rEMAIL, rExt, rRLT_OR_UT].join("|"), "ig"); }, onDestroy: function() { this.RebuildBtn(); this.RebuildPopup(); if ($("anoBtn_set")) $("anoBtn_set").parentNode.removeChild($("anoBtn_set")); Services.obs.notifyObservers(null, "startupcache-invalidate", ""); }, BtnClick: function(event) { if (event.target != event.currentTarget) return; event.stopPropagation(); event.preventDefault(); switch (event.target.id) { case 'anoBtn_set': switch (event.button) { case 0: anoBtn.Rebuild(true); break; case 1: break; case 2: anoBtn.EditFile(anoBtn.file); break; } break; case 'anoBtn_Icon': //$("anoBtn_Popup").openPopup(event.target); //$("anoBtn_Popup").showPopup(); $('anoBtn_Popup').addEventListener('popupshowing', this, false); break; } return; }, Rebuild: function(isAlert) { var MenuDate = this.LoadFile(this.File); !!this.BuildPopup && this.BuildPopup.Remove(); if (!MenuDate) return; this.anomenu = MenuDate.anomenu; this.anobtnset = MenuDate.anobtnset; this.RebuildBtn(true); this.RebuildPopup(true); if (isAlert) alert('配置已经重新载入'); }, /*****************************************************************************************/ RebuildBtn: function(isAlert) { var icon = $("anoBtn_Icon"); if (icon) icon.parentNode.removeChild(icon); delete icon; if (!isAlert) return; var iconInTag = this.anobtnset.intags ? this.anobtnset.intags : "tabbrowser-tabs"; var iconImage = this.anobtnset.image ? this.anobtnset.image : "chrome://branding/content/icon16.png"; var intags = $(iconInTag); var orientation = this.anobtnset.orientation ? this.anobtnset.orientation : 'before'; if ($('anoBtn_set')) $('anoBtn_set').setAttribute('image', iconImage); var IconType = this.IconSstatusBarPanel ? 'statusbarpanel' : 'image'; this.icon = $C('toolbarbutton', { id: 'anoBtn_Icon', tooltiptext: '快速打开指定选项', class: 'toolbarbutton-1 chromeclass-toolbar-additional', popup: 'anoBtn_Popup', context: 'anoBtn_Popup', type: 'menu', removable: true, image: iconImage, src: iconImage, onclick: "anoBtn.BtnClick(event);", }); if (this.anobtnset.Icon_Pos === 0) { ToolbarManager.addWidget(window, this.icon, true); } else if (this.anobtnset.Icon_Pos === 1) { $('urlbar-icons').appendChild(this.icon); } else if (this.anobtnset.Icon_Pos === 2) { if (orientation == 'before') intags.parentNode.insertBefore(this.icon, intags); else if (orientation == 'after') { var parentEl = intags.parentNode; if (parentEl.lastChild == intags) { parentEl.appendChild(this.icon); } else { parentEl.insertBefore(this.icon, intags.nextSibling); } } } if (this.anobtnset.IconSstatusBarPanel) this.icon.classList.add('class', 'statusbarpanel-iconic'); return true; }, RebuildPopup: function(isAlert) { if (!this.anomenu) return; var Popup = $("anoBtn_Popup"); if (Popup) Popup.parentNode.removeChild(Popup); this.Popup = null; !!this.BuildPopup && this.BuildPopup.Remove(); delete this.BuildPopup; delete Popup; if (!isAlert) return; if (!this.BuildPopup) { this.BuildPopup = new AnoBtn_BuildPopup('anoBtn', $C("menupopup", { id: "anoBtn_Popup", position: this.anobtnset.position, // onpopupshowing: "anoBtn.PopupShowing(event);" })); } this.BuildPopup.Build(this.anomenu); this.icon.appendChild(this.BuildPopup.Popup); }, onCommand: function(event) { if (event.target != event.currentTarget) return; var menuitem = event.target; var text = menuitem.getAttribute("text") || ""; var keyword = menuitem.getAttribute("keyword") || ""; var url = menuitem.getAttribute("url") || ""; var where = menuitem.getAttribute("where") || ""; var exec = menuitem.getAttribute("exec") || ""; var Post = menuitem.getAttribute("Post") || ""; var Action = menuitem.getAttribute("Action") || ""; if (Post) return this.PostData(this.ConvertText(url), this.ConvertText(Post)); if (keyword) { let param = (text ? (text = this.ConvertText(text)) : ""); let engine = Services.search.getEngineByAlias(keyword); if (engine) { let submission = engine.getSubmission(param); this.OpenCommand(event, submission.uri.spec, where); } else { PlacesUtils.keywords.fetch(keyword || '').then(entry => { if (!entry) return; let newurl = entry.url.href.replace('%s', encodeURIComponent(param)); this.OpenCommand(event, newurl, where); }); } } else if (url) this.OpenCommand(event, this.ConvertText(url), where || "tab"); else if (exec) this.Exec(exec, this.ConvertText(text)); else if (text) this.Copy(this.ConvertText(text)); else if (Action) this.OpenAction(Action); }, OpenAction: function(url, fId, val, bId, bClass) { var wrap = { try: function(js) { return "try{" + js + "}catch(e){}"; }, delay: function(js) { return wrap.try("content.window.setTimeout(function(){" + wrap.try(js) + "},100);"); }, doOnLoad: function(js) { return wrap.try("let onLoad = function(){" + "removeEventListener('load',onLoad,true);" + wrap.try(js) + "};" + "addEventListener('load',onLoad,true);"); }, quotes: function(str) { return "\"" + str + "\""; }, getElement: function(id) { const selector = "form #" + id; return "content.window.document.querySelector(" + wrap.quotes(selector) + ")"; }, getElementC: function(id) { const selector = "form ." + id; return "content.window.document.querySelector(" + wrap.quotes(selector) + ")"; } }; function openURL(url) { var browser = window.getBrowser(); try { window.TreeStyleTabService.readyToOpenChildTab(browser.selectedTab); } catch (e) {} var newTab = browser.addTab(url, { ownerTab: browser.selectedTab, relatedToCurrent: true }); browser.selectedTab = newTab; return browser.getBrowserForTab(newTab); } var contentScript = wrap.getElement(fId) + ".value = " + wrap.quotes(this.ConvertText(val)) + ";"; if (bId) contentScript += wrap.delay(wrap.getElement(bId) + ".click();") else if (bClass) contentScript += wrap.delay(wrap.getElementC(bClass) + ".click();") contentScript = "data:text/javascript," + encodeURIComponent(wrap.doOnLoad(contentScript)); var targetBrowser = openURL(url); targetBrowser.messageManager.loadFrameScript(contentScript, false); }, OpenCommand: function(event, url, where, postData) { var uri; try { uri = Services.io.newURI(url, null, null); } catch (e) { return console.log("URL 不正确: " + url); } if (uri.scheme === "javascript") loadURI(url); else if (where) openTrustedLinkIn(uri.spec, where, false, postData || null); else if (event.button == 1) openNewTabWith(uri.spec); else openUILink(uri.spec, event); }, Exec: function(path, arg) { var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); try { var a; if (typeof arg == 'string' || arg instanceof String) { a = arg.split(/\s+/) } else if (Array.isArray(arg)) { a = arg; } else { a = [arg]; } file.initWithPath(path); if (!file.exists()) { Cu.reportError('File Not Found: ' + path); return; } if (file.isExecutable()) { process.init(file); process.runw(false, a, a.length); } else { file.launch(); } } catch (e) { console.log(e); } }, PostData: function(aURI, aPostData) { var stringStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); if ("data" in stringStream) stringStream.data = aPostData; else stringStream.setData(aPostData, aPostData.length); var PostData = Cc["@mozilla.org/network/mime-input-stream;1"].createInstance(Ci.nsIMIMEInputStream); PostData.addHeader("Content-Type", "application/x-www-form-urlencoded"); PostData.addContentLength = true; PostData.setData(stringStream); gBrowser.loadOneTab(aURI, null, null, PostData, false); }, ConvertText: function(text) { var that = this; var tab = document.popupNode && document.popupNode.localName == "tab" ? document.popupNode : null; var win = tab ? tab.linkedBrowser.contentWindow : this.FocusedWindow; var title = gBrowser.selectedTab.label || gBrowser.selectedBrowser.contentTitle; var url = gBrowser.currentURI.spec || gBrowser.selectedBrowser.currentURI.spec; var host; try{ var host = gBrowser.currentURI.asciiHostPort || gBrowser.currentURI.HostPort || gBrowser.currentURI.hostPort || gBrowser.currentURI.host; }catch(e){ host = url; } function convert(str) { switch (str) { case "%T": case "%TITLE%": return title; case "%TITLES%": return title.replace(/\s-\s.*/i, "").replace(/_[^\[\]【】]+$/, ""); case "%U": case "%URL%": return url; case "%H": case "%HOST%": return host; case "%S": case "%SEL%": return that.getSelection(win) || ""; case "%P": case "%CLIPBOARD%": return readFromClipboard() || ""; case "%FAVICON%": return gBrowser.getIcon(tab ? tab : null) || ""; case "%FAVICON_BASE64%": return img2base64(gBrowser.getIcon(tab ? tab : null)); case "%EMAIL%": return getEmailAddress() || ""; case "%IP%": return FeiRuoNet && FeiRuoNet.Caches.DNS[gBrowser.selectedBrowser.currentURI.host]; case "%BASEDOMAIN%": var eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService); return eTLDService.getBaseDomain(makeURI(gBrowser.selectedBrowser.currentURI.spec)); case "%EOL%": return "\r\n"; } return str; } function htmlEscape(s) { return (s + "").replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/\"/g, """).replace(/\'/g, "'"); }; function getEmailAddress() { var url = context.linkURL; if (!url || !/^mailto:([^?]+).*/i.test(url)) return ""; var addresses = RegExp.$1; try { var characterSet = context.target.ownerDocument.characterSet; const textToSubURI = Cc['@mozilla.org/intl/texttosuburi;1'].getService(Ci.nsITextToSubURI); addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses); } catch (ex) {} return addresses; } function img2base64(imgsrc) { if (typeof imgsrc == 'undefined') return ""; const NSURI = "http://www.w3.org/1999/xhtml"; var img = new Image(); var that = this; var canvas, isCompleted = false; img.onload = function() { var width = this.naturalWidth, height = this.naturalHeight; canvas = document.createElementNS(NSURI, "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); ctx.drawImage(this, 0, 0); isCompleted = true; }; img.onerror = function() { Components.utils.reportError("Count not load: " + imgsrc); isCompleted = true; }; img.src = imgsrc; var thread = Cc['@mozilla.org/thread-manager;1'].getService().mainThread; while (!isCompleted) { thread.processNextEvent(true); } var data = canvas ? canvas.toDataURL("image/png") : ""; canvas = null; return data; } return text.replace(this.regexp, function(str) { str = str.toUpperCase().replace("%LINK", "%RLINK"); if (str.indexOf("_HTMLIFIED") >= 0) return htmlEscape(convert(str.replace("_HTMLIFIED", ""))); if (str.indexOf("_HTML") >= 0) return htmlEscape(convert(str.replace("_HTML", ""))); if (str.indexOf("_ENCODE") >= 0) return encodeURIComponent(convert(str.replace("_ENCODE", ""))); return convert(str); }); }, handleRelativePath: function(path) { if (path) { //path = path.replace(/\//g, '\\').toLocaleLowerCase(); path = path.replace(/\//g, '\\'); var profD = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile); if (/^(\\)/.test(path)) { if (path.startsWith('\\..\\')) { return profD.parent.path + path.replace('\\..', ''); } return profD.path + path; } else { return path; } } }, getSelection: function(win) { win || (win = this.FocusedWindow); var selection = this.getRangeAll(win).join(" "); if (!selection) { let element = document.commandDispatcher.focusedElement; let isOnTextInput = function(elem) { return elem instanceof HTMLTextAreaElement || (elem instanceof HTMLInputElement && elem.mozIsTextField(true)); }; if (isOnTextInput(element)) { selection = element.QueryInterface(Ci.nsIDOMNSEditableElement) .editor.selection.toString(); } } if (selection) { selection = selection.replace(/^\s+/, "") .replace(/\s+$/, "") .replace(/\s+/g, " "); } return selection; }, getRangeAll: function(win) { win || (win = this.FocusedWindow); var sel = win.getSelection(); var res = []; for (var i = 0; i < sel.rangeCount; i++) { res.push(sel.getRangeAt(i)); }; return res; }, /*****************************************************************************************/ EditFile: function (aFile, aLineNumber) { if (!aFile || !aFile.exists() || !aFile.isFile()) return; var editor; try { editor = Services.prefs.getComplexValue("view_source.editor.path", Ci.nsIFile); } catch (e) { } if (!editor || !editor.exists()) { if (useScraptchpad) { this.openScriptInScratchpad(window, aFile); return; } else { alert("请先设置编辑器的路径!!!"); var fp = Cc['@mozilla.org/filepicker;1'].createInstance(Ci.nsIFilePicker); fp.init(window, "设置全局脚本编辑器", fp.modeOpen); fp.appendFilter("执行文件", "*.exe"); if (fp.show() == fp.returnCancel || !fp.file) return; else { editor = fp.file; Services.prefs.setCharPref("view_source.editor.path", editor.path); } } } // 调用自带的 if(typeof(userChrome) == 'undefined') { this.openScriptInScratchpad(window, aFile); return; } else { var aURL = userChrome.getURLSpecFromFile(aFile); var aDocument = null; var aCallBack = null; var aPageDescriptor = null; gViewSourceUtils.openInExternalEditor({ URL: aURL, lineNumber: aLineNumber }, aPageDescriptor, aDocument, aLineNumber, aCallBack); } }, openScriptInScratchpad: function (parentWindow, file) { let spWin = window.openDialog("chrome://devtools/content/scratchpad/index.xul", "Toolkit:Scratchpad", "chrome,resizable=yes,centerscreen,dependent"); spWin.addEventListener("load", function spWinLoaded() { spWin.removeEventListener("load", spWinLoaded, false); let Scratchpad = spWin.Scratchpad; Scratchpad.setFilename(file.path); Scratchpad.addObserver({ onReady: function () { Scratchpad.removeObserver(this); Scratchpad.importFromFile.call(Scratchpad, file); } }); }, false); }, Copy: function(str) { if (!str) str = this.icon.tooltipText; Cc['@mozilla.org/widget/clipboardhelper;1'].createInstance(Ci.nsIClipboardHelper).copyString(str); StatusPanel._label = "已复制: " + str; }, OpenScriptInScratchpad: function(parentWindow, file) { let spWin = (parentWindow.Scratchpad || Services.wm.getMostRecentWindow("navigator:browser").Scratchpad).openScratchpad(); spWin.addEventListener("load", function spWinLoaded() { spWin.removeEventListener("load", spWinLoaded, false); let Scratchpad = spWin.Scratchpad; Scratchpad.setFilename(file.path); Scratchpad.addObserver({ onReady: function() { Scratchpad.removeObserver(this); Scratchpad.importFromFile.call(Scratchpad, file); } }); }, false); }, LoadFile: function(aFile, isAlert) { if (!aFile || !aFile.exists() || !aFile.isFile()) return null; var fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); var sstream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream); fstream.init(aFile, -1, 0, 0); sstream.init(fstream); var data = sstream.read(sstream.available()); try { data = decodeURIComponent(escape(data)); } catch (e) {} sstream.close(); fstream.close(); if (!data) { var errmsg = "Rebuild Error:【" + aFile.leafName + "】文件不存在"; console.log(errmsg); if (isAlert) alert(errmsg); return null; } var sandbox = new Cu.Sandbox(new XPCNativeWrapper(window)); sandbox.Components = Components; sandbox.Cc = Cc; sandbox.Ci = Ci; sandbox.Cr = Cr; sandbox.Cu = Cu; sandbox.Services = Services; sandbox.locale = Services.prefs.getCharPref("general.useragent.locale","zh-CN"); try { var lineFinder = new Error(); Cu.evalInSandbox(data, sandbox, "1.8"); } catch (e) { let line = e.lineNumber - lineFinder.lineNumber - 1; var errmsg = 'Error: ' + e + "\n请重新检查【" + aFile.leafName + "】文件第 " + line + " 行"; console.log(errmsg); if (isAlert) alert(errmsg); } return sandbox || null; }, }; function AnoBtn_BuildPopup(ID, Popup) { this.ID = ID; if (typeof Popup == 'string') Popup = document.getElementById(Popup); Popup = Popup || document.getElementById(ID) || document.getElementById(ID + '_Popup'); if (!Popup || !Popup.tagName || Popup.tagName != "menupopup") { Popup = document.createXULElement("menupopup"); Popup.setAttribute('id', thins.ID + '_Popup') } this.Popup = Popup; this.Remove(); } AnoBtn_BuildPopup.prototype = { ID: null, Popup: null, isReady: false, Remove: function() { Array.prototype.slice.call((this.Popup || document).querySelectorAll("." + this.ID + "_MenuNote")).forEach(item => { $("main-menubar").appendChild(item); item.classList.remove(this.ID + '_CustomMenu'); }); Array.prototype.slice.call((this.Popup).querySelectorAll("." + this.ID + "_CustomMenu")).forEach(item => { item.parentNode.removeChild(item); }); }, Build: function(Menus) { if (!Menus) return this.Remove(); for (let obj of Menus) { if (!obj) continue; //this.Popup.appendChild(this.CreateMenuitem(obj)); const menuitem = this.CreateMenuitem(obj); this.Popup.appendChild(menuitem); if(menuitem.render){ for(const child of menuitem.childNodes){ if(child.localName !== 'menupopup') child.remove(); } menuitem.renderedOnce = false; menuitem.render(); } } this.isReady = true; return this.Popup; }, CreateMenuitem: function(obj, i) { if (obj.MapFolder) return this.CreateMenu(this.EnumerateFolder(obj)); let menuitem; if (obj.id && (menuitem = $(obj.id))) { let dupMenuitem; let isDupMenu = (obj.clone != false); if (isDupMenu) dupMenuitem = menuitem.cloneNode(true); else dupMenuitem = menuitem; for (let key in obj) { let val = obj[key]; if (typeof val == "function") obj[key] = val = "(" + val.toString() + ").call(this, event);"; dupMenuitem.setAttribute(key, val); } let type = dupMenuitem.nodeName, cls = dupMenuitem.classList; if ((type == 'menuitem' || type == 'menu') && !cls.contains(type + '-iconic')) cls.add(type + '-iconic'); if (!cls.contains(this.ID + '_CustomMenu')) cls.add(this.ID + '_CustomMenu'); if (!isDupMenu && !cls.contains(this.ID + '_MenuNote')) cls.add(this.ID + '_MenuNote'); return dupMenuitem; } if (obj.child) return this.CreateMenu(obj); if (obj.label === "separator" || (!obj.label && !obj.image && !obj.text && !obj.keyword && !obj.url && !obj.oncommand && !obj.command)) { menuitem = document.createXULElement("menuseparator"); } else if (obj.oncommand || obj.command) { let org = obj.command ? document.getElementById(obj.command) : null; if (org && org.localName === "menuseparator") { menuitem = document.createXULElement("menuseparator"); } else { menuitem = document.createXULElement("menuitem"); if (obj.command) menuitem.setAttribute("command", obj.command); if (!obj.label) obj.label = obj.command || obj.oncommand; } } else { menuitem = document.createXULElement("menuitem"); if (!obj.label) obj.label = obj.exec || obj.keyword || obj.url || obj.text || "NoName"; if (obj.keyword && !obj.text) { let index = obj.keyword.search(/\s+/); if (index > 0) { obj.text = obj.keyword.substr(index).trim(); obj.keyword = obj.keyword.substr(0, index); } } if (obj.where && /\b(tab|tabshifted|window|current)\b/i.test(obj.where)) obj.where = RegExp.$1.toLowerCase(); if (obj.where && !("acceltext" in obj)) obj.acceltext = obj.where; if (obj.exec) obj.exec = this.handleRelativePath(obj.exec); } for (let key in obj) { let val = obj[key]; if (key === "command" || key === "MapFolder" || key === "Filter" || key === "Sort" || key === "ExcludeDir") continue; if (typeof val == "function") obj[key] = val = "(" + val.toString() + ").call(this, event);"; menuitem.setAttribute(key, val); } var cls = menuitem.classList; cls.add(this.ID + "_CustomMenu"); let type = menuitem.nodeName; if ((type == 'menuitem' || type == 'menu') && (!cls.contains(type + '-iconic'))) cls.add(type + '-iconic'); if (menuitem.localName == "menuseparator") return menuitem; if (!obj.onclick) menuitem.setAttribute("onclick", "checkForMiddleClick(this, event)"); if (obj.oncommand || obj.command) return menuitem; menuitem.setAttribute("oncommand", "anoBtn.onCommand(event);"); this.SetMenusIcon(menuitem, obj); return menuitem; }, CreateMenu: function(menuObj, i) { var menu = document.createXULElement("menu"); var Popup = menu.appendChild(document.createXULElement("menupopup")); if (menuObj.MapFolder) menuObj = this.EnumerateFolder(menuObj); for (let key in menuObj) { let val = menuObj[key]; if (key === "child" || key === "MapFolder" || key === "Sort" || key === "Filter" || key === "Exclude" || key === "Directories" || key === "FilterDirs" || key === "ExcludeDirs") continue; if (key === 'onshowing') { this.customShowings.push({ item: menu, fnSource: menuObj.onshowing.toString() }); delete menuObj.onshowing; continue; } if (typeof val == "function") menuObj[key] = val = "(" + val.toString() + ").call(this, event);" menu.setAttribute(key, val); } let cls = menu.classList; cls.add(this.ID + "_CustomMenu"); cls.add("menu-iconic"); menuObj.child && menuObj.child.forEach(function(obj) { Popup.appendChild(this.CreateMenuitem(obj)); }, this); if (!menu.hasAttribute('label')) { let firstItem = menu.querySelector('menuitem'); if (firstItem) { let command = firstItem.getAttribute('command'); if (command) firstItem = document.getElementById(command) || firstItem; ['label', 'accesskey', 'image', 'icon'].forEach(function(n) { if (!menu.hasAttribute(n) && firstItem.hasAttribute(n)) menu.setAttribute(n, firstItem.getAttribute(n)); }, this); menu.setAttribute('onclick', "if (event.target != event.currentTarget) return;var firstItem = event.currentTarget.querySelector('menuitem');if (!firstItem) return;if (event.button === 1) {checkForMiddleClick(firstItem, event);} else {firstItem.doCommand();closeMenus(event.currentTarget);}"); } } return menu; }, EnumerateFolder: function(obj) { obj || (obj = {}); var path = this.handleRelativePath(obj.MapFolder); var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); dir.initWithPath(path); if (!dir.exists() || !dir.isDirectory()) return obj; var Entries = dir.directoryEntries; var ExcludeDirs = obj.ExcludeDirs ? ((typeof obj.ExcludeDirs == "string") ? (new RegExp(obj.ExcludeDirs)) : obj.ExcludeDirs) : null; var FilterDirs = obj.FilterDirs ? ((typeof obj.FilterDirs == "string") ? (new RegExp(obj.FilterDirs)) : obj.FilterDirs) : null; obj.child || (obj.child = []); if (obj.child.length > 0 && obj.child[obj.child.length - 1].label != "separator") { obj.child.push({ label: 'separator', }); } while (Entries.hasMoreElements()) { var Entry = Entries.getNext(); Entry.QueryInterface(Components.interfaces.nsIFile); if (Entry.isDirectory() && (typeof obj.Directories === 'number') && (obj.Directories > 0)) { if (ExcludeDirs && ExcludeDirs.test(Entry.leafName)) continue; if (FilterDirs && !FilterDirs.test(Entry.leafName)) continue; obj.child.push(this.EnumerateFolder({ label: Entry.leafName, MapFolder: Entry.path, exec: Entry.path, Directories: obj.Directories - 1, Filter: obj.Filter, Exclude: obj.Exclude, ExeText: obj.ExeText, FilterDirs: obj.FilterDirs, ExcludeDirs: obj.ExcludeDirs, onclick: "anoBtn.onCommand(event);", Sort: 0, image: "moz-icon://" + Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(Entry) + "?size=16", })) continue; } if (!Entry.isFile()) continue; var Exclude = obj.Exclude ? ((typeof obj.Exclude == "string") ? (new RegExp(obj.Exclude)) : obj.Exclude) : null; var Filter = obj.Filter ? ((typeof obj.Filter == "string") ? (new RegExp(obj.Filter)) : obj.Filter) : null; if (Exclude && Exclude.test(Entry.leafName)) continue; if (Filter && !Filter.test(Entry.leafName)) continue; var child = { label: Entry.leafName.substr(0, Entry.leafName.lastIndexOf(".")), exec: Entry.path, Sort: 1, tooltiptext: Entry.path, }; var text; if (typeof obj.ExeText == 'object') { var Program = obj.ExeText.Program ? ((typeof obj.ExeText.Program == "string") ? (new RegExp(obj.ExeText.Program)) : obj.ExeText.Program) : null; if (Program.test(Entry.leafName)) { text = obj.ExeText.text.replace(/%DIR%/i, dir.leafName).replace(/%EXE%/i, obj.label) } } if (!!text) child.text = text; obj.child.push(child); } if (obj && obj.child && obj.child[obj.child.length - 1] && obj.child[obj.child.length - 1].label == "separator") delete obj.child[obj.child.length - 1]; obj.MapFolder = false; obj.child.sort(function(a, b) { return a.Sort - b.Sort; }); return obj; }, handleRelativePath: function(path) { if (path) { //path = path.replace(/\//g, '\\').toLocaleLowerCase(); path = path.replace(/\//g, '\\'); var profD = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile); if (/^(\\)/.test(path)) { if (path.startsWith('\\..\\')) { return profD.parent.path + path.replace('\\..', ''); } return profD.path + path; } else { return path; } } }, SetMenusIcon: function(menu, obj) { if (menu.hasAttribute("src") || menu.hasAttribute("image") || menu.hasAttribute("icon")) return; if (obj.exec) { var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); try { aFile.initWithPath(obj.exec); } catch (e) { return; } if (!aFile.exists()) { menu.setAttribute("disabled", "true"); } else { let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile); menu.setAttribute("image", "moz-icon://" + fileURL + "?size=16"); } return; } if (obj.keyword) { let engine = Services.search.getEngineByAlias(obj.keyword); if (engine && engine.iconURI) { menu.setAttribute("image", engine.iconURI.spec); return; } } var setIconCallback = function(url) { let uri, iconURI; try { uri = Services.io.newURI(url, null, null); } catch (e) {} if (!uri) return; menu.setAttribute("scheme", uri.scheme); PlacesUtils && PlacesUtils.favicons && PlacesUtils.favicons.getFaviconDataForPage(uri, { onComplete: function(aURI, aDataLen, aData, aMimeType) { try { // javascript: URI の host にアクセスするとエラー menu.setAttribute("image", aURI && aURI.spec ? "moz-anno:favicon:" + aURI.spec : "moz-anno:favicon:" + uri.scheme + "://" + uri.host + "/favicon.ico"); } catch (e) {} } }); } PlacesUtils && PlacesUtils.keywords && PlacesUtils.keywords.fetch(obj.keyword || '').then(entry => { let url; if (entry) { url = entry.url.href; } else { url = (obj.url + '').replace(/%TITLE(?:_HTML(?:IFIED)?|_ENCODE)?%|%t\b|%TITLES(?:_HTML(?:IFIED)?|_ENCODE)?%|%t\b|%(?:R?LINK_OR_)?URL(?:_HTML(?:IFIED)?|_ENCODE)?%|%u\b|%HOST(?:_HTML(?:IFIED)?|_ENCODE)?%|%h\b|%BASEDOMAIN(?:_HTML(?:IFIED)?|_ENCODE)?%|%h\b|%IP(?:_HTML(?:IFIED)?|_ENCODE)?%|%h\b|%SEL(?:_HTML(?:IFIED)?|_ENCODE)?%|%s\b|%R?LINK(?:_TEXT|_HOST)?(?:_HTML(?:IFIED)?|_ENCODE)?%|%l\b|%IMAGE(?:_URL|_ALT|_TITLE)(?:_HTML(?:IFIED)?|_ENCODE)?%|%i\b|%IMAGE_BASE64(?:_HTML(?:IFIED)?|_ENCODE)?%|%i\b|%MEDIA_URL(?:_HTML(?:IFIED)?|_ENCODE)?%|%m\b|%CLIPBOARD(?:_HTML(?:IFIED)?|_ENCODE)?%|%p\b|%FAVICON(?:_HTML(?:IFIED)?|_ENCODE)?%|%FAVICON_BASE64(?:_HTML(?:IFIED)?|_ENCODE)?%|%EMAIL(?:_HTML(?:IFIED)?|_ENCODE)?%|%EOL(?:_HTML(?:IFIED)?|_ENCODE)?%|%RLT_OR_UT(?:_HTML(?:IFIED)?|_ENCODE)?%/gi, ""); } setIconCallback(url); }, e => { console.log(e) }).catch(e => {}); } }; window.AnoBtn_BuildPopup = AnoBtn_BuildPopup; // 来自 User Agent Overrider 扩展 const ToolbarManager = (function() { /** * Remember the button position. * This function Modity from addon-sdk file lib/sdk/widget.js, and * function BrowserWindow.prototype._insertNodeInToolbar */ let layoutWidget = function(document, button, isFirstRun) { // Add to the customization palette let toolbox = document.getElementById('navigator-toolbox'); toolbox.palette.appendChild(button); // Search for widget toolbar by reading toolbar's currentset attribute let container = null; let toolbars = document.getElementsByTagName('toolbar'); let id = button.getAttribute('id'); for (let i = 0; i < toolbars.length; i += 1) { let toolbar = toolbars[i]; if (toolbar.getAttribute('currentset').indexOf(id) !== -1) { container = toolbar; } } // if widget isn't in any toolbar, default add it next to searchbar if (!container) { if (isFirstRun) { container = document.getElementById('nav-bar'); } else { return; } } // Now retrieve a reference to the next toolbar item // by reading currentset attribute on the toolbar let nextNode = null; let currentSet = container.getAttribute('currentset'); let ids = (currentSet === '__empty') ? [] : currentSet.split(','); let idx = ids.indexOf(id); if (idx !== -1) { for (let i = idx; i < ids.length; i += 1) { nextNode = document.getElementById(ids[i]); if (nextNode) { break; } } } // Finally insert our widget in the right toolbar and in the right position container.insertItem(id, nextNode, null, false); // Update DOM in order to save position // in this toolbar. But only do this the first time we add it to the toolbar if (ids.indexOf(id) === -1) { container.setAttribute('currentset', container.currentSet); document.persist(container.id, 'currentset'); } }; let addWidget = function(window, widget, isFirstRun) { try { layoutWidget(window.document, widget, isFirstRun); } catch (error) { console.log(error); } }; let removeWidget = function(window, widgetId) { try { let widget = window.document.getElementById(widgetId); widget.parentNode.removeChild(widget); } catch (error) { console.log(error); } }; let exports = { addWidget: addWidget, removeWidget: removeWidget, }; return exports; })(); function log(str) { console.log("[Another Button Debug] ", arguments); } function alert(aString, aTitle) { Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService).showAlertNotification("", aTitle || "Another Button", aString, false, "", null); } function $(id) { return document.getElementById(id); } function $C(name, attr) { var el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) {return el.setAttribute(n, attr[n])}); return el; } function addStyle(css) { var pi = document.createProcessingInstruction( 'xml-stylesheet', 'type="text/css" href="data:text/css;utf-8,' + encodeURIComponent(css) + '"' ); return document.insertBefore(pi, document.documentElement); } anoBtn.init(); window.anoBtn = anoBtn; })('\ #anoBtn_Icon dropmarker {\ display: none;\ }\ '.replace(/\n|\t/g, '')); |
|
1楼#
发布于:2023-07-06 22:18
太长了吧,看得头晕
|
|
|
2楼#
发布于:2023-07-19 19:15
我在116b2这个能用,但要注意配置文件_anoBtn.js,我发现目录枚举会导致出图标点不动。
https://blog.iplayloli.com/anotherbuttonucjs.html |
|
|