Dumby
Вроде - гуд ! Только наоборот..
((id, g) => { addDestructor(r => r[5] == "e" && id in g && g[id].destroy()); if (g[id]) return; var topic = "quit-application-granted", {obs} = Services; obs.addObserver(g[id] = { // true - disable, false - enable states: { "addon_to@disable": true, "{6acd0f4d-ab79-4b79-9b28-8bde65ae355c}": false, "addon_to@enable": true, "@hoxx-vpn": true, "vkomforte-we@vkomforte": true, }, filter(addon) { var state = this.states[addon.id]; if ( state !== undefined && addon.userDisabled != state && addon.type.endsWith("extension") && addon.location.name != "app-builtin" ) { addon.active = addon.location.get(addon.id).enabled = !(addon.userDisabled = state); return true; } }, observe() { this.destroy(); if (g.XPIDatabase.getAddons().filter(this.filter, this).length) g.XPIDatabase.saveChanges(), g.XPIStates.save(); }, destroy() { delete g[id]; obs.removeObserver(this, topic); } }, topic, false); })( "CBQuitApplicationExtensionsSwitcher", Cu.import("resource://gre/modules/addons/XPIDatabase.jsm", {}) );
Отредактировано solombala (03-03-2020 13:30:47)
Отсутствует
Dumby
Снимаю шляпу, все как обычно, ничего лишнего.
Может пока посмотрел, глянешь, если время будет, возможно ли уменьшить эти 3 расстояния,
которые изобразил на картинке?
Добавлено 03-03-2020 17:35:16
что-то не редактируется сообщение или забыл уже как
вобщем через attributesInspector.js ничего найти не могу, где ужать, где уменьшить, где убрать
Отредактировано dezhnev (03-03-2020 17:35:16)
Отсутствует
ДА, а продолжить здесь можно? В смысле, еще какой аддон добавиться...
Конечно можно. Даже непонятно откуда могло взяться сомнение.
через attributesInspector.js ничего найти не могу, где ужать, где уменьшить, где убрать
Деревья. Вот такой, например, стиль вроде соответствует.
Сверху — предположительно твои один, два, три,
снизу — попытка симуляции того, что уже есть на картинке.
@-moz-document url(chrome://browser/content/places/bookmarksSidebar.xhtml) { treechildren { margin-left: -2px !important; } treechildren::-moz-tree-indentation { width: 2px !important; } treechildren::-moz-tree-image { margin-right: -1px !important; } /************************************************/ treechildren::-moz-tree-row { min-height: 18px !important; } treechildren::-moz-tree-twisty { width: 0 !important; padding: 0 !important; } }
Отсутствует
Есть код, который сохраняет выделенный текст в файл:
// Сохранить выделенный текст в один файл из контекстного меню ((contextMenu, el)=> { var menuitem = contextMenu.insertBefore(document.createElement("menuitem"), el); menuitem.id = "content-saveTextItem"; menuitem.setAttribute("label", "Сохранить выделенный текст в файл"); addDestructor(()=> menuitem.remove()); addEventListener('popupshowing', e=> menuitem.hidden = !gContextMenu.isTextSelected, false, contextMenu); menuitem.onclick =e=> e.button ? setPathToFile() : saveSelectionToFile(); function saveSelectionToFile() { try { var pathToFile = gPrefService.getComplexValue("CB.saveSelectionToFile", Ci.nsISupportsString).data } catch(e) { setPathToFile() }; var title = convertFromUnicode("UTF-8", getTabLabel()); var selection = gBrowser.contentDocument.defaultView.getSelection().toString(); var text = convertFromUnicode("UTF-8", selection) + "\n\n\n\n\n"; var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath(pathToFile); var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); file.exists() ? foStream.init(file, 0x02 | 0x10, 0664, 0) : foStream.init(file, 0x02|0x08|0x20, 0666, 0); foStream.write(text, text.length); foStream.close(); document.activeElement.blur(); setTimeout(()=> window.content.focus(), 300); }; function setPathToFile() { var fp = window.makeFilePicker(); fp.init(window, "Создайте текстовой файл для сохранения текста!", fp.modeSave); fp.appendFilters(fp.filterText); fp.defaultString = getTabLabel(); fp.open(result => result == fp.returnOK && cbu.setPrefs("CB.saveSelectionToFile", convertFromUnicode("UTF-8", fp.file.path) + ".txt")); }; function convertFromUnicode(charset, str) { var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); }; function getTabLabel() { var label = gBrowser.mCurrentTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); }; })(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open"));
Можно ли сделать так, что бы он вначале добавлял url той страницы из которой был сохранен?
Отредактировано _backup (04-03-2020 10:52:46)
Отсутствует
solombala
Тем более под аэро запросто подстраиваю . Последние коды - это нечто , столько проблем и сразу...Класс!
просто уже не терпится увидеть 74 в твоем исполнении, а релиз выйдет только 10 марта ...
Отредактировано ALEX_45_ORP (04-03-2020 13:15:54)
Win 10х64
Отсутствует
Можно ли сделать так, что бы он вначале добавлял url той страницы из которой был сохранен?
/*Initialization Code*/ // Сохранить выделенный текст в один файл из контекстного меню ((contextMenu, el)=> { var menuitem = contextMenu.insertBefore(document.createElement("menuitem"), el); menuitem.id = "content-saveTextItem"; menuitem.setAttribute("label", "Сохранить выделенный текст в файл"); addDestructor(()=> menuitem.remove()); addEventListener('popupshowing', e=> menuitem.hidden = !gContextMenu.isTextSelected, false, contextMenu); menuitem.onclick =e=> e.button ? setPathToFile() : saveSelectionToFile(); function saveSelectionToFile() { try { var pathToFile = gPrefService.getComplexValue("CB.saveSelectionToFile", Ci.nsISupportsString).data } catch(e) { setPathToFile() }; var title = convertFromUnicode("UTF-8", getTabLabel()); var selection = gBrowser.contentDocument.defaultView.getSelection().toString(); var url = gBrowser.currentURI.spec; var text = convertFromUnicode("UTF-8", url + "\n" + selection) + "\n\n\n\n\n"; var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath(pathToFile); var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); file.exists() ? foStream.init(file, 0x02 | 0x10, 0664, 0) : foStream.init(file, 0x02|0x08|0x20, 0666, 0); foStream.write(text, text.length); foStream.close(); document.activeElement.blur(); setTimeout(()=> window.content.focus(), 300); }; function setPathToFile() { var fp = window.makeFilePicker(); fp.init(window, "Создайте текстовой файл для сохранения текста!", fp.modeSave); fp.appendFilters(fp.filterText); fp.defaultString = getTabLabel(); fp.open(result => result == fp.returnOK && cbu.setPrefs("CB.saveSelectionToFile", convertFromUnicode("UTF-8", fp.file.path) + ".txt")); }; function convertFromUnicode(charset, str) { var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); }; function getTabLabel() { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); }; })(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open"));
«The Truth Is Out There»
Отсутствует
Dumby, №14402
Если я правильно понял, он при выходе вкл-откл заданные аддоны? А можно его совместить с этим кодом?
self.label="ToggleAddons[Fx]";self.image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABy0lEQVQ4jbWTz2sUMRiGn2Qmmewy47LLzir0D1BaQYUea/EwBQ9OFNuoFF2x0kHwoKgnLwYsXr0LHvQgKhbBivSk0n8sXjYlXdijuX3J+7xf3vyA/zCuAB+Brq7rM13XKe99HkIQieYysJFCfeAB8Bq4CvwdDAarRVE8Vkq9zbKsBWpgF3gGXAJupKZPgArAey+Vyv8sLdUXrbWV914Cz4EjYBiBLMtuee/zWN+NsLW2Kgp9OJlMLsxggC3gfRR776UxZtp1nYpzt0MIwlpbNU0z0FofFkVxNom4CXxImxhjdtIdbDvnek3TDKy1lRDiF3AuMbgGfIlw0zQDY8zO8RkopXbbtu0nmX8Ay4lBK4T4HmFrbZVl2fR4VSnVOed6SeZPwEpyYK3W+iDCM9291OD+3D3vA+dj5rIsN4tCHyQwJwyAbU6Ob8BKzFyW5ZbWej+BAaYpMG/wWWu9HDNXVXVdSvl1TjNdVNRCiKOyLO/EzHmerwM/E80IeJrGfgisAq+klC/H4/HqcDhcM8bsSSlfzBr8Bm4Cb4BHo9HoVPoONoA17710zvXatu0753qzDqeBPeAdsA4QQhDOuV76EgkhCO99vuD3LdT9A4TPkK2vNlObAAAAAElFTkSuQmCC"; this.onclick=e=> {if(e.button==0&&!e.ctrlKey)AddP(); //L //if(e.button==0&& e.ctrlKey)f(); //Ctrl+L //if(e.button==2&& e.ctrlKey){e.preventDefault();f();}; //Ctrl+R if(e.button==2&&!e.ctrlKey&&!e.shiftKey&&!e.altKey&&!e.metaKey){e.preventDefault();AddO();}}; //R this.tooltipText=self.label+"\nL: On/Off ProxyAddons\nR: On/Off OtherAddons"; //------------------------------------------------------------------------------------------ //forum.mozilla-russia.org/viewtopic.php?pid=777986#p777986 function AddP(){var args=[addon=>addon[addon.userDisabled?"enable":"disable"]({allowSystemAddons:true}),Cu.reportError]; for(var id of["....","...."])AddonManager.getAddonByID(id).then(...args);}; function AddO(){var args=[addon=>addon[addon.userDisabled?"enable":"disable"]({allowSystemAddons:true}),Cu.reportError]; for(var id of["bookmarksorganizer@agenedia.com","webscrapbook@danny0838.addons.mozilla.org","....","...."])AddonManager.getAddonByID(id).then(...args);};
Отсутствует
// Сохранить выделенный текст в один файл из контекстного меню
Так и должно быть, что после установки кнопки, контекстное меню на выделенном тексте стало в одну строчку из четырёх пунктов?
Отсутствует
Так и должно быть, что после установки кнопки, контекстное меню на выделенном тексте стало в одну строчку из четырёх пунктов?
Так быть не должно. И скорее всего эта кнопка не работает на последних версиях , мне не на чем проверить.
Отредактировано unter_officer (05-03-2020 01:52:46)
«The Truth Is Out There»
Отсутствует
Dumby вот добавил в твой код
// Добавить кнопки в диалог сохранения файла.......................................................................................... ((id, g) => { addDestructor(r => r[5] == "e" && id in g && g[id].destroy(true)); if (g[id]) return; var topics = ["widget-first-paint", "quit-application-granted"], {nsIFile} = Ci; var {obs, wm, dirsvc} = Services, uct = "unknownContentType", ends = `/${uct}.xhtml`; (g[id] = { init() { for(var topic of topics) obs.addObserver(g[id], topic, false); this.wins(); }, destroy(wins) { delete g[id]; for(var topic of topics) obs.removeObserver(this, topic); wins && this.wins("removeBtn"); }, btn(win, method = "addBtn") { win.location.href.endsWith(ends) && this[method](win.document); }, wins(method) { for(var win of wm.getEnumerator(null)) this.btn(win, method); }, observe(win, topic) { topic[0] == "q" ? this.destroy() : this.btn(win); }, get data() { var o = g.Object, d = key => dirsvc.get(key, nsIFile).path; delete this.data; return this.data = o.assign(o.create(null), { "Рабочий стол": d("Desk"), "chrome": d("UChrm"), "chrome\\CSS": d("UChrm") + "\\CSS", "C:": "C:\\", "E:": "E:\\", "F:": "F:\\", "G:": "G:\\", }); }, addBtn(doc) { var df = doc.createDocumentFragment(); var btn1 = doc.cbSaveToButton = df.appendChild(doc.createXULElement("button")); btn1.label = "Сохранить как"; btn1.className = "dialog-button"; btn1.setAttribute("oncommand", "handleCommand(event.target)"); btn1.handleCommand = this.cmdf; doc.getElementById(uct).getButton("extra1").before(df); var btn = doc.cbSaveToButton = df.appendChild(doc.createXULElement("button")); btn.label = "Сохранить в"; btn.className = "dialog-button"; var popup = btn.appendChild(doc.createXULElement("menupopup")); popup.setAttribute("oncommand", "handleCommand(event.target)"); popup.handleCommand = this.cmd; for(var lab in this.data) { var menuitem = popup.appendChild(doc.createXULElement("menuitem")); menuitem.label = lab; menuitem.dir = this.data[lab]; menuitem.className = "menuitem-iconic"; menuitem.image = "moz-icon:file:///" + menuitem.dir; } doc.getElementById(uct).getButton("cancel").before(df); btn.type = "menu"; }, removeBtn(doc) { if (doc.cbSaveToButton) doc.cbSaveToButton.remove(), delete doc.cbSaveToButton; }, cmdf(trg) { var win = trg.ownerGlobal; var file = (win.dialog.promptForSaveToFileAsync || win.dialog.promptForSaveToFile).call(win.dialog, win.dialog.mLauncher, window, win.dialog.mLauncher.suggestedFileName, "", true); if (file) { win.dialog.mLauncher.saveToDisk(file, 1); win.dialog.onCancel = function() {}; win.close(); } }, cmd(trg) { var file = h.Components.Constructor( "@mozilla.org/file/local;1", nsIFile, "initWithPath" )(trg.dir); var win = trg.ownerGlobal; file.append(win.document.getElementById("location").getAttribute("realname")); win.dialog.mLauncher.saveToDisk(file, 1); win.dialog.onCancel = function() {}; win.close(); } }).init(); })("CBUnknownContentTypeSaveToButtonizer", Cu.getGlobalForObject(Cu));
Отсутствует
На 73.0.1 вдруг заглючил профиль, на странице введения пароля почты Google/Youtube экран серый. Ну и так по мелочи. Решил переустановить, но нарисовалась проблемка. После добавления в новый профиль файла search.json.mozlz4 не показываются иконки у двух поисков и Яндекса. Это стандартные поиски, Google и Википедия (ru). Старый профиль показывал иконки.
Отсутствует
xrun1
https://www.upload.ee/files/11225480/______.rar.html
Отредактировано solombala (05-03-2020 16:09:20)
Отсутствует
Подскажите, как распотрошить search.json.mozlz4
Есть кнопка для СВ, то ли turbot делал, то ли yup, сейчас уже не вспомню. Но эта кнопка вроде выше 52-ой версии FF не работает.
Может кто переделает под последние версии FF?
/*CODE*/ // Mozilla's Lz4 files format Compressor/Decompresser. .......... var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); fp.displayDirectory = FileUtils.getDir("ProfD", []); fp.init(window, "Open File", Components.interfaces.nsIFilePicker.modeOpen); fp.appendFilter("Mozilla's Lz4 and json files format", "*.jsonlz4; *.mozlz4; *.json"); if (fp.show() == Components.interfaces.nsIFilePicker.returnOK) { var file = fp.file; if (file.exists() && file.isFile() && file.isReadable()) { Components.utils.import("resource://gre/modules/Task.jsm"); Components.utils.import("resource://gre/modules/osfile.jsm"); var oldFile = fp.file.path; if (oldFile.endsWith(".json")) { var newFile = oldFile.replace(/(\.json)$/, ".mozlz4"); function compress(oFilePath,nFilePath){ return Task.spawn(function* () { var jsonString = yield OS.File.read(oFilePath); yield OS.File.writeAtomic(nFilePath, jsonString, {compression: "lz4"}); LOG("Saved as: " + newFile); }) } compress(oldFile,newFile); } else { var newFile = (oldFile.replace(".mozlz4", ".json") || oldFile.replace(".jsonlz4", ".json")); function decompress(oFilePath,nFilePath){ return Task.spawn(function* () { var jsonString = yield OS.File.read(oFilePath, {encoding: "utf-8", compression: "lz4"}); yield OS.File.writeAtomic(nFilePath, JSON.stringify(JSON.parse(jsonString), null, ' '), {encoding: "utf-8"}); }) } decompress(oldFile,newFile); LOG("Saved as: " + newFile); custombuttons.alertSlide("Saved as: " + newFile); } } };
Отредактировано unter_officer (05-03-2020 18:33:54)
«The Truth Is Out There»
Отсутствует
unter_officer
Не актуально... Или здесь search-extensions лепишь любой поиск или через СВ , к примеру seasonvar
Services.search.addEngine("data:text/xml," + encodeURIComponent(` <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> <ShortName>Seasonvar.ru</ShortName> <Description>Сериалы ТУТ! Сериалы онлайн смотреть бесплатно. Смотреть онлайн.</Description> <InputEncoding>UTF-8</InputEncoding> <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADvklEQVRYhb1XTYgcRRR+JtNVr0ail0gUPLkehBwEVwgakMHNdr1XKwQ8RFQwF39uOXnxtkIwieAhetWLeoh7VVBE3IPgYY1gCIFA0OzOdL0aMYoH4y5xZsrDdjUzk91sz8BsQTFU09Pfz3uvXhXAjEax2FjoWP34MsCBWWHsDm7VKWGMwrh+7SiofScQnAlC+j9xeHvfwQvSbwnpO4FxIKTveKs+2TcXCsKF4EwMjINqOhODM1Fs9tRMwX9fgCPCGIX0oLvUjNV0ZhCciZ7wh5stwJkR6OTq1aR+hMBSs3LEW/3tzAh4q04OExj+DYwDYYxi8fWZgLcXG7kwbg6rT2S2y1H3hPRXMwEHABBnLgeH/cA46DozSLEvc+LrmQGn4UlfGY99cuD6cTg0U/B23nhOGO9OvtKB4PD7iT/qc/PsXu8I45vC2E3gaQ470HVmIKT/XgE4WAt4I89OF6S2PKnPA+ON3xbgyPg7geGhwPidMMauM4NU5+Oll1zwpLc6z4Cpp5zwlif9MwDAagsaweEXI6pz9YQn1R9Rm5Juh7ldBbp3JYf7axEorLoa2HwEALACcLCwahMA7gMA2DiBjw3bvRvoeAg84a3aIbg8D9ly2b9XW9DwrP8FAFi38Ig47EsqtaGNZjflVRISnq4FPj6uH4dDnvESAIA4c7FUFMO9Yj629QpjmAocAKCTq/eFtF0GODCJ9SkptxuQvjg1AWGMNxgeEMazeyneKfbBmbg+bQsubPakt7oLACCEa7XVjzlwswUPT6ee8LOCcAEAILCRWolXKq+2YWeitODw5ODz0PSkN9M6LDX/qhuC6gRUdsGC4dEp1OszwmatWrP5sxaBdPKx+K6w7gVnYnsxe3oKAihC+oO09ozFXvYPh6G92MiFUIQxetZvTwTeZj3nScci1y8MEVqrcuAeTlSll6uXOqReFMZYkFqZiMC2fRglz+bTs8KqT9PH99r3gzOxsOoUAIA4vO1J/zIZAdIfCmP0uV5Mzzp5dqzqfLspT1sv6UEnz44BAHjGS5701kQEpLTO8+jptTxY9HcsvSo/TN9b9U/6T5vUy9v3AfXKZC6w/rK81/306wl4sHTm4+FsHwF3JnaXTF8YY/t5mFttQWO5bGjCGAurrso8NKHsqjWd0Gc84x/pRBsc9kZuPCknqqOX7gVnup5xQxi3POGPJfFvSjEjeVVrXDsKqs16zlt1smOzN4TUO8J41hOe86wveNYXvFXnPalzBeF7aXqL54s8q1qwkLaFzV5Lbo6P/wEF7JeDr5SEggAAAABJRU5ErkJggg==</Image> <Url type="text/html" method="GET" template="http://seasonvar.ru/search"> <Param name="q" value="{searchTerms}"/> </Url> <SearchForm>http://seasonvar.ru/</SearchForm> </SearchPlugin> `), null, null);
Отсутствует
вот добавил в твой код
А g на h зачем заменил?
Вобщем, чуть переписал, вроде работает, на первый взгляд.
addBtn(doc) { var btns = doc.cbSaveButtons = doc.createXULElement("box"); var btn = btns.appendChild(doc.createXULElement("button")); btn.className = "dialog-button"; var btn1 = btn.cloneNode(false); btn1.label = "Сохранить как"; btn1.setAttribute("oncommand", "handleCommand(window)"); btn1.handleCommand = this.cmdf; btn.before(btn1); btn.label = "Сохранить в"; var popup = btn.appendChild(doc.createXULElement("menupopup")); popup.setAttribute("oncommand", "handleCommand(event.target)"); popup.handleCommand = this.cmd; for(var lab in this.data) { var menuitem = popup.appendChild(doc.createXULElement("menuitem")); menuitem.label = lab; menuitem.dir = this.data[lab]; menuitem.className = "menuitem-iconic"; menuitem.image = "moz-icon:file:///" + menuitem.dir; } doc.getElementById(uct).getButton("cancel").before(btns); btn.type = "menu"; }, removeBtn(doc) { if (doc.cbSaveButtons) doc.cbSaveButtons.remove(), delete doc.cbSaveButtons; }, close(win, dlg = win.dialog) { dlg.onCancel = dlg.onUnload; win.close(); }, cmdf(win) { var dlg = win.dialog, launcher = dlg.mLauncher; win.Object.defineProperty(dlg, "mLauncher", {configurable: true, set() { delete dlg.mLauncher; dlg.mLauncher = launcher; }}); var argLauncher = {source: launcher.source, saveDestinationAvailable(file) { if (file) launcher.saveDestinationAvailable(file), g[id].close(win, dlg); }}; dlg.promptForSaveToFileAsync(argLauncher, win.opener, launcher.suggestedFileName, "", true); }, cmd(trg) { var file = g.Components.Constructor( "@mozilla.org/file/local;1", nsIFile, "initWithPath" )(trg.dir); var win = trg.ownerGlobal; file.append(win.document.getElementById("location").getAttribute("realname")); win.dialog.mLauncher.saveToDisk(file, 1); g[id].close(win); }
как распотрошить search.json.mozlz4
Говорят, людям mozlz4-edit нравится.
Отсутствует
Dumby спасибо, сначала 2 кода делал и вместо g вставлял h и т.д., потом объединил и просто невнимательность, забыл заменить.
У меня есть такой код для загрузки CSS
/*Initialization Code*/ var idb=this.id; var button = document.getElementById(idb); (function(){ var editor = "C:\\Program Files\\AkelPad\\AkelPad.exe"; let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; if (!window.Services) Cu.import("resource://gre/modules/Services.jsm"); let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } window.UCL = { USE_UC: "UC" in window, AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, readCSS : {}, get disabled_list() { let obj = []; try { obj = this.prefs.getCharPref("disabled_list").split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader.") }, get styleSheetServices(){ delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile) aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath("CSS"); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, getFocusedWindow: function() { let win = document.commandDispatcher.focusedWindow; if (!win || win == window) win = content; return win; }, init: function() { const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const cbNS = "http://xsms.nm.ru/custombuttons/"; var menupopup = document.createElementNS(xulNS, "menupopup"); menupopup.onclick = function (event) { button.menuClick(event); } menupopup.addEventListener("popupshowing", function (event) { self.menuPopupShowing(event); }, false); button.appendChild(menupopup); button.type = "menu"; button.orient = "horizontal"; button.menuClick = function (event) { event.preventDefault(); event.stopPropagation(); button.open = false; } button.menuPopupShowing = function (event) { var nodeList = event.target.childNodes; for (var i = nodeList.length - 1; i >= 0; i--) if (nodeList[i].hasAttributeNS(cbNS, "flag")) nodeList[i].parentNode.removeChild(nodeList[i]); } let cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", }); menupopup.appendChild(cssmenu); let menupop = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupop); let menu = $C("menu", { label: "Инструменты", }); menupopup.appendChild(menu); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); mp.appendChild($C("menuitem", { label: "Обновить список файлов-стилей", accesskey: "R", acceltext: "Alt + R", oncommand: "UCL.rebuild();" })); mp.appendChild($C("menuseparator")); mp.appendChild($C("menuitem", { label: "Создать файл CSS", accesskey: "D", oncommand: "UCL.create();" })); mp.appendChild($C("menuitem", { label: "Открыть папку CSS", accesskey: "O", oncommand: "UCL.openFolder();" })); mp.appendChild($C("menuitem", { label: "Редактировать userChrome.css", hidden: false, oncommand: "UCL.editUserCSS(\'userChrome.css\');" })); mp.appendChild($C("menuitem", { label: "Редактировать userContent.css", hidden: false, oncommand: "UCL.editUserCSS(\'userContent.css\');" })); mp.appendChild($C("menuseparator")); mp.appendChild($C("menuitem", { label: "Тест стиля (Chrome)", id: "usercssloader-test-chrome", //hidden: true, accesskey: "C", oncommand: "UCL.styleTest(window);" })); mp.appendChild($C("menuitem", { label: "Тест стиля (Web)", id: "usercssloader-test-content", //hidden: true, accesskey: "W", oncommand: "UCL.styleTest();" })); mp.appendChild($C("menuitem", { label: "Поиск стиля на userstyles.org", accesskey: "S", oncommand: "UCL.searchStyle();" })); menu = $C("menu", { label: ".uc.css", accesskey: "U", hidden: !UCL.USE_UC }); mp = $C("menupopup", { id: "usercssloader-ucmenupopup" }); menu.appendChild(mp); mp.appendChild($C("menuitem", { label: "Importieren(.uc.js)", oncommand: "UCL.UCrebuild();" })); mp.appendChild($C("menuseparator", { id: "usercssloader-ucsepalator" })); $("mainKeyset").appendChild($C("key", { id: "usercssloader-rebuild-key", oncommand: "UCL.rebuild();", key: "R", modifiers: "alt", })); this.rebuild(); this.initialized = true; if (UCL.USE_UC) { setTimeout(function() { UCL.UCcreateMenuitem(); }, 1000); } window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", dis.join("|")); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); while (files.hasMoreElements()) { let file = files.getNext().QueryInterface(Ci.nsIFile); if (!ext.test(file.leafName) || not.test(file.leafName)) continue; let CSS = this.loadCSS(file); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Style importiert"; else XULBrowserWindow.statusTextField.label = "Styles importieren"; } }, loadCSS: function(aFile) { var CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { var CSS = this.readCSS[aLeafName]; var menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = document.createXULElement("menuitem"); menuitem.setAttribute("label", aLeafName); menuitem.setAttribute("id", "usercssloader-" + aLeafName); menuitem.setAttribute("class", "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : "USER_SHEET")); menuitem.setAttribute("type", "checkbox"); menuitem.setAttribute("autocheck", "false"); menuitem.setAttribute("oncommand", "UCL.toggle('"+ aLeafName +"');"); menuitem.setAttribute("onclick", "UCL.itemClick(event);"); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { var CSS = this.readCSS[aLeafName]; if (!CSS) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { if (event.button == 0) return; event.preventDefault(); event.stopPropagation(); let label = event.currentTarget.getAttribute("label"); if (event.button == 1) { this.toggle(label); } else if (event.button == 2) { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, styleTest: function(aWindow) { aWindow || (aWindow = this.getFocusedWindow()); new CSSTester(aWindow, function(tester){ if (tester.saved) UCL.rebuild(); }); }, searchStyle: function() { let word; try { word = gBrowser.currentURI.host; } catch { word = gBrowser.currentURI.spec; } var ctabpos = gBrowser.selectedTab._tPos +1; gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab("https://userstyles.org/styles/search/" + word), ctabpos); }, openFolder: function() { this.FOLDER.launch(); }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { try { var UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8"; var path = UI.ConvertFromUnicode(aFile.path); var app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); app.initWithPath(editor); var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); process.init(app); process.run(false, [path], 1); } catch (e) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Имя файла", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucsepalator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = document.createXULElement("menuitem"); m.setAttribute("label", aLeafName); m.setAttribute("tooltiptext", fileURL); m.setAttribute("id", "usercssloader-" + aLeafName); m.setAttribute("type", "checkbox"); m.setAttribute("autocheck", "false"); m.setAttribute("checked", "true"); m.setAttribute("oncommand", "this.setAttribute('checked', !(this.css.disabled = !this.css.disabled));"); m.setAttribute("onclick", "UCL.UCItemClick(event);"); m.css = css; popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button == 0) return; event.preventDefault(); event.stopPropagation(); if (event.button == 1) { event.target.doCommand(); } else if (event.button == 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; function CSSEntry(aFile) { this.path = aFile.path; this.leafName = aFile.leafName; this.lastModifiedTime = 1; this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ? Ci.nsIStyleSheetService.AGENT_SHEET: Ci.nsIStyleSheetService.USER_SHEET; } CSSEntry.prototype = { sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService), _enabled: false, get enabled() { return this._enabled; }, set enabled(isEnable) { var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile) aFile.initWithPath(this.path); var isExists = aFile.exists(); // Wenn die Datei existiert true var lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; var isForced = this.lastModifiedTime != lastModifiedTime; var fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile); var uri = Services.io.newURI(fileURL, null, null); if (this.sss.sheetRegistered(uri, this.SHEET)) { if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; function CSSTester(aWindow, aCallback) { this.win = aWindow || window; this.doc = this.win.document; this.callback = aCallback; this.init(); } CSSTester.prototype = { sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService), preview_code: "", saved: false, init: function() { var url = "data:text/html;charset=utf8,"+encodeURIComponent('<!DOCTYPE HTML><html lang="ja"><head><title>CSSTester</title></head><body></body></html>'); if (parseInt(Services.appinfo.platformVersion) >= 69 && Services.appinfo.browserTabsRemoteAutostart) { var chromeURL = `chrome://custombuttons/content/cbdialog${Date.now()}.xul`; Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup).registerChrome( Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)), [["override", chromeURL, url]] ); url = chromeURL; } this.dialog = openDialog(url, "", "width=550,height=400,dialog=no"); this.dialog.addEventListener("load", this, false); }, destroy: function() { this.preview_end(); this.dialog.removeEventListener("unload", this, false); this.previewButton.removeEventListener("click", this, false); this.saveButton.removeEventListener("click", this, false); this.closeButton.removeEventListener("click", this, false); }, handleEvent: function(event) { switch(event.type) { case "click": if (event.button != 0) return; if (this.previewButton == event.currentTarget) { this.preview(); } else if (this.saveButton == event.currentTarget) { this.save(); } else if (this.closeButton == event.currentTarget) { this.dialog.close(); } break; case "load": var doc = this.dialog.document; doc.body.innerHTML = '\ <style type="text/css">\ :not(input):not(select) { padding: 0px; margin: 0px; }\ table { border-spacing: 0px; }\ body, html, #main, #textarea { width: 100%; height: 100%; }\ #textarea { font-family: monospace; }\ </style>\ <table id="main">\ <tr height="100%">\ <td colspan="4"><textarea id="textarea"></textarea></td>\ </tr>\ <tr height="40">\ <td><input type="button" value="Vorschau" id="Vorschau"/></td>\ <td><input type="button" value="Speichern" id="Speichern"/></td>\ <td width="80%"><span class="log"></span></td>\ <td><input type="button" value="Schließen" id="Schliessen"/></td>\ </tr>\ </table>\ '; this.textbox = doc.querySelector("textarea"); this.previewButton = doc.querySelector('input[value="Vorschau"]'); this.saveButton = doc.querySelector('input[value="Speichern"]'); this.closeButton = doc.querySelector('input[value="Schließen"]'); this.logField = doc.querySelector('.log'); var code = "@namespace url(" + this.doc.documentElement.namespaceURI + ");\n"; code += this.win.location.protocol.indexOf("http") === 0? "@-moz-document domain(" + this.win.location.host + ") {\n\n\n\n}": "@-moz-document url(" + this.win.location.href + ") {\n\n\n\n}"; this.textbox.value = code; this.dialog.addEventListener("unload", this, false); this.previewButton.addEventListener("click", this, false); this.saveButton.addEventListener("click", this, false); this.closeButton.addEventListener("click", this, false); this.textbox.focus(); let p = this.textbox.value.length - 3; this.textbox.setSelectionRange(p, p); break; case "unload": this.destroy(); this.callback(this); break; } }, preview: function() { var code = this.textbox.value; if (!code || !/\:/.test(code)) return; code = "data:text/css;charset=utf-8," + encodeURIComponent(this.textbox.value); if (code == this.preview_code) return; this.preview_end(); var uri = Services.io.newURI(code, null, null); this.sss.loadAndRegisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET); this.preview_code = code; this.log("Preview"); }, preview_end: function() { if (this.preview_code) { let uri = Services.io.newURI(this.preview_code, null, null); this.sss.unregisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET); this.preview_code = ""; } }, save: function() { var data = this.textbox.value; if (!data) return; var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(window, "", Ci.nsIFilePicker.modeSave); fp.appendFilter("CSS Files","*.css"); fp.defaultExtension = "css"; if (window.UCL) fp.displayDirectory = UCL.FOLDER; var res = fp.show(); if (res != fp.returnOK && res != fp.returnReplace) return; var suConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); suConverter.charset = "UTF-8"; data = suConverter.ConvertFromUnicode(data); var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); foStream.init(fp.file, 0x02 | 0x08 | 0x20, 0o664, 0); foStream.write(data, data.length); foStream.close(); this.saved = true; }, log: function() { this.logField.textContent = dateFormat(new Date(), "%H:%M:%S") + ": " + $A(arguments); } }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { var el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDay()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log() { Application.console.log(Array.from(arguments)); } })();
Отсутствует
Тут в window.UCL я добавляю - AUTHOR_SHEET : Ci.nsIStyleSheetService.AUTHOR_SHEET
Теперь надо еще исправить строчку menuitem.setAttribute("class", "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : "USER_SHEET"));
Ну, например
//menuitem.setAttribute("class", "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : "USER_SHEET")); menuitem.setAttribute("class", "usercssloader-item " + ( CSS.SHEET == this.AGENT_SHEET ? "AGENT" : CSS.SHEET == this.AUTHOR_SHEET ? "AUTHOR" : "USER" ) + "_SHEET");
и строчку this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ? Ci.nsIStyleSheetService.AGENT_SHEET: Ci.nsIStyleSheetService.USER_SHEET;
А метку перед расширением для AUTHOR_SHEET
я что ли должен придумать вместо тебя?
Ладно, допустим blabla.au.css, тогда, опять же, например
//this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ? // Ci.nsIStyleSheetService.AGENT_SHEET: // Ci.nsIStyleSheetService.USER_SHEET; var prfx = /^xul-|\.a(s|u)\.css$/i.test(this.leafName) ? RegExp.$1 == "u" ? "AUTHOR" : "AGENT" : "USER"; this.SHEET = Ci.nsIStyleSheetService[prfx + "_SHEET"];
Отсутствует
Dumby cпасибо, а в этом же коде можешь посмотреть функцию CSSTester.prototype (необязательная можно и скрыть) - там выдает ошибки на кнопки при открытии окна.
да еще одна незначительная, не влияющая ни на что ошибка (TypeError: e.target.closest(...) is null), которая вылазит в консоли при нажатии на "Инструменты для всех дополнений" в этом коде
//Дополнительные пункты контекстного меню на странице about:addons для аддонов, плагинов, тем, CB..................................................................................... ((id, g, iconizer) => addDestructor(r => r[5] == "e" && id in g && g[id].destroy()) + addEventListener("shown", { //------------------------------------------------------------------ "Копировать имя_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVQ4jY2TTUhUURiGn5tD0Sp00iAwXM1iFu4kWkUZg/9MoZQhdoUCV7ooItq4atFORRGkuLMwoc0kNBGKDLSwFpEIQgspqGUUNsjI3HvPX4s7I3Nn7oW+1fn5vvd8z3vOsYiIgXuPneFMr21ZVmh9+m7GisoPxcTsM2d46on5c1gy9bHgvDVR+afqJzNzy870xIgNUJGGkqf4XVEAuJ4XeWCiNpibX3MGr/XYPd0pADxlOK0MQgf7Xw++sfJq0zRiJQAWcgWndHRkr28UWcrlAfCVwa8KrK4XOPxbYqz/MsnWcyfFi7lCIPD9x0/70YNRykKz+eELQkny74sIJbnQmqQ71UVhe+cES2hoP9uC63mBgO/7dF7s4NexZPRmBqlBaMPHnc+kL7UTh1VxqwKuGxjkaUP+zRZCSVqwKJeP2dvdj8SqGZuod9hXhr6hGwgNL5ZfEoc1PnaL2sFNAlvvthFKxmJJbfCUqXbghhHSyTOkJwcBmHr4vAnLVwKhJEPZbLgDXwh678yG7rfjfLIJS2qD0IEP9R6kiq8XrzS+sOz9p5+asKodXB0YCQkcNBbHYUXlxP6u67dnIj9PY8QJpIC2/6iX/wDxeTOAfNDrywAAAABJRU5ErkJggg==", "Копировать имя"(addon, hideOn) { if (hideOn) return false; gClipboard.write(addon.name); }, //------------------------------------------------------------------ "Копировать ID_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVQ4jY2TTUhUURiGn5tD0Sp00iAwXM1iFu4kWkUZg/9MoZQhdoUCV7ooItq4atFORRGkuLMwoc0kNBGKDLSwFpEIQgspqGUUNsjI3HvPX4s7I3Nn7oW+1fn5vvd8z3vOsYiIgXuPneFMr21ZVmh9+m7GisoPxcTsM2d46on5c1gy9bHgvDVR+afqJzNzy870xIgNUJGGkqf4XVEAuJ4XeWCiNpibX3MGr/XYPd0pADxlOK0MQgf7Xw++sfJq0zRiJQAWcgWndHRkr28UWcrlAfCVwa8KrK4XOPxbYqz/MsnWcyfFi7lCIPD9x0/70YNRykKz+eELQkny74sIJbnQmqQ71UVhe+cES2hoP9uC63mBgO/7dF7s4NexZPRmBqlBaMPHnc+kL7UTh1VxqwKuGxjkaUP+zRZCSVqwKJeP2dvdj8SqGZuod9hXhr6hGwgNL5ZfEoc1PnaL2sFNAlvvthFKxmJJbfCUqXbghhHSyTOkJwcBmHr4vAnLVwKhJEPZbLgDXwh678yG7rfjfLIJS2qD0IEP9R6kiq8XrzS+sOz9p5+asKodXB0YCQkcNBbHYUXlxP6u67dnIj9PY8QJpIC2/6iX/wDxeTOAfNDrywAAAABJRU5ErkJggg==", "Копировать ID"(addon, hideOn) { if (hideOn) return false; gClipboard.write(addon.id); }, //------------------------------------------------------------------ "Копировать версию_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVQ4jY2TTUhUURiGn5tD0Sp00iAwXM1iFu4kWkUZg/9MoZQhdoUCV7ooItq4atFORRGkuLMwoc0kNBGKDLSwFpEIQgspqGUUNsjI3HvPX4s7I3Nn7oW+1fn5vvd8z3vOsYiIgXuPneFMr21ZVmh9+m7GisoPxcTsM2d46on5c1gy9bHgvDVR+afqJzNzy870xIgNUJGGkqf4XVEAuJ4XeWCiNpibX3MGr/XYPd0pADxlOK0MQgf7Xw++sfJq0zRiJQAWcgWndHRkr28UWcrlAfCVwa8KrK4XOPxbYqz/MsnWcyfFi7lCIPD9x0/70YNRykKz+eELQkny74sIJbnQmqQ71UVhe+cES2hoP9uC63mBgO/7dF7s4NexZPRmBqlBaMPHnc+kL7UTh1VxqwKuGxjkaUP+zRZCSVqwKJeP2dvdj8SqGZuod9hXhr6hGwgNL5ZfEoc1PnaL2sFNAlvvthFKxmJJbfCUqXbghhHSyTOkJwcBmHr4vAnLVwKhJEPZbLgDXwh678yG7rfjfLIJS2qD0IEP9R6kiq8XrzS+sOz9p5+asKodXB0YCQkcNBbHYUXlxP6u67dnIj9PY8QJpIC2/6iX/wDxeTOAfNDrywAAAABJRU5ErkJggg==", "Копировать версию"(addon, hideOn) { if (hideOn) return ["custombuttons"]; gClipboard.write(addon.version); }, //------------------------------------------------------------------ "Копировать имя и версию_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVQ4jY2TTUhUURiGn5tD0Sp00iAwXM1iFu4kWkUZg/9MoZQhdoUCV7ooItq4atFORRGkuLMwoc0kNBGKDLSwFpEIQgspqGUUNsjI3HvPX4s7I3Nn7oW+1fn5vvd8z3vOsYiIgXuPneFMr21ZVmh9+m7GisoPxcTsM2d46on5c1gy9bHgvDVR+afqJzNzy870xIgNUJGGkqf4XVEAuJ4XeWCiNpibX3MGr/XYPd0pADxlOK0MQgf7Xw++sfJq0zRiJQAWcgWndHRkr28UWcrlAfCVwa8KrK4XOPxbYqz/MsnWcyfFi7lCIPD9x0/70YNRykKz+eELQkny74sIJbnQmqQ71UVhe+cES2hoP9uC63mBgO/7dF7s4NexZPRmBqlBaMPHnc+kL7UTh1VxqwKuGxjkaUP+zRZCSVqwKJeP2dvdj8SqGZuod9hXhr6hGwgNL5ZfEoc1PnaL2sFNAlvvthFKxmJJbfCUqXbghhHSyTOkJwcBmHr4vAnLVwKhJEPZbLgDXwh678yG7rfjfLIJS2qD0IEP9R6kiq8XrzS+sOz9p5+asKodXB0YCQkcNBbHYUXlxP6u67dnIj9PY8QJpIC2/6iX/wDxeTOAfNDrywAAAABJRU5ErkJggg==", "Копировать имя и версию"(addon, hideOn) { if (hideOn) return ["custombuttons"]; gClipboard.write(addon.name + " " + addon.version); }, //------------------------------------------------------------------ "Домашняя страница_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAC4jAAAuIwF4pT92AAAIIklEQVRYR61Xa1CU1xlGUNTpr/7rdNr+sCbt2DrRphPb0VZnWtsYhk5tNWnaaHHaVJsoWgWVNlRbMQoaE6poQATkLpdlWVAzLusqLgioi9xEdkGIIJdd9vLt5dvbd76n7/ncdaxigLbvzDNnYc6e5znP+55z3o2KeibmzZsXNX/+/KhYwvz/M/ja08VXCN8mvEx4KTz+r3gpjG8RvkqYGzVVzJkzJ5qGH+3Zs+diUVGxMTc393Zefr4xn6OgwFgQwfnzxvMRFBY+QWEERUXPfabv3S4vL29PTk7OI475xPW8gOjoaK5sTf3Fi8OgcHs88Pn98AcCCISCCIZCCEkSJMYUMFmGjJlFZN4VrbadOGKJ63kBpCqGhtVl5eV9gsvFHg4Ph0bHxtjY+Dgbn5hgExwWi4Jxi5VZrJPMOslhY1abnVlotNntzM7hcChwhDFpswVJPKuurm6Kms6BiooKs1cUwcktViuIBLSAAiKC2+VEUBTgdTng87rgF10I0N9ykBzzuuEUXHC53HC53XCH4RQECeSYuqbmJhcwpQNPBFRWmkWfD+O08wg57RJOp4OInTAPW1FmeIjTegu2fGpEwulOpNePotzwOR6M2UmIF16vlwR44PESKJUul0viaVCr1dMLqCQBPO/c8gi51+0EWY6shhEk5D7A91Nv4Y1jXViZ2oR1Gb1IrAghIWcMm7O6kasfgUC7Dvp9JECESG6SCxKvAXVt7fQCqqqqzIFgEBbKNbfcQ5YPjFjwx3MD2FLixHf3NmJlih7xaQZsy+7Gscs2nNCKyLwK7C624O3MXhxUj2PU5kIo6CcBPnLEowionakAXvGUf8Ztn7Tb8bdaO9K1AdR1BLEq1YC3jt/Ce9md2F/Sj8o7Iq71yShplXHsCrAzfxDb8kZx5JIAF6UiGAyAakoRoNFoZiCgutockriASRbwOlB0U1B2d80EpF+ZxC/T27DjbCfOUjpO1D9Ck0lEozmEXIOIQxoBf84fQWJeP94vFZGlHSHaEKXCqwioq6ubXkC1IkCC02FjD8YcSLssIbsxgB8evIlXknTYkN6KxNweHK8bwflGJ3pGQ3hoZ7jZ78fZay7sr/JgU5YJKSofXs/oocJ0QgoFZu7AYwEMotvGtD0iDtQz/PhQO6LerMJr+69h47E27Dz3WEChQUD/RAjEgfaHMloHgdIWCX/KNuEDtRcr03qQ2zBE1NIsHFCpzBKTSYCDFRh82K0KYFlKK6LfUmFZ0lWsP9qC93K6cLBiCFVtDrolZQxYGK7eZ8hrkpHZEMTRmkF8og3iB4f6sLvoPl0BjwXU19dPL0BVU2OmO4Oq38HO6EUkVYtIqZ7AkiQ9vrb1EtYdasbvM43kQi/OXHkEhxe4Nwpo7wF5zUBSuYCt2X1IuyhhyT4jtuaaZudADTnAb28uIEvnxbZiAUkVNuwoHsSXNqmxZJcW8YdbsDnzDv6Q1YF/XRrGZx0e5DSM4UONFbsKR/B+3hD+WQ/86vQj/J2OJFhw9g74vQL7VOckBwI4chnI0ss4XGfFig8asZyK8Q1yYsfZDqSW3sO+wm5syGjB6tRGbD7Vhb9SIXIB79K9UdDipRSEZi6ghgTwyZLfzWpvT2JrkYB/UCEe1IBOA+i8Syiho7k1pwO/PtaC19Oa8WqynpxpwJcT1PjFifuK4AN1DG/nWHG9L8CP4iwEqNWKAL/oZoNU3m9mDiG52otUjYQDGllZ/BS58c3EBkRtqMLCd9SUmloaCZvq8ErKHWXuPirefZUiHHQLhwI+SSZbwzUw9XMcEaAOC6BXjQEBfKQZovt+iFLhxF8qPUipkbCnwoVl+9uwaOcNfH37NXyD8PLuZryW2o6fHunDtiIndpT6ob4tkpWiLAjuEF+T1m6OmqkD9KSyQMAPwSPiNx934+cZJiSqRrBPY6FLRsDvzoxi/SdDiPvoAeIJG04+xJZzVtq1F9tLfDhU44DN7oBLcMo2m12iYOHXMPYL+4GIAx6Pm/GHhNG1PDLpwfqMdvzk4x7sqBhGRr0HJ3UBHP8sgLQ6Pz0+fqp2brkP72TbkVw6hs/paXYLDtlisWJ4eCRIAlBcXNxAHHO+OAW1tYoAasmYn1oyn8+viHC4fThM9bn+TB9WpfWR1YPYeHIMvz1jwcZTE4g7Pox4cildNQBT/yB6ujtlQ9NNNN64IZlMZrm1tdW6ePHiFZxrzlQWRATUPnHAQykIKO/5+PgE+vvN6Ll7CyWqS3j3wwtYlViOV7fXYMVODX62V41tR1UoU1/BndYbuFBeJtdqNDAYDKy3t5fdvXvXv3Tp0rgw+XPc/ykg7AB1NYoA7oIgCBgdHYXJ3I/7PV3oNrbgVvN13LiuQ1OjHrdbGpX/3evuQIPuqkxtHV+C8UZkYGAAa9asSQhzvIB9CgGecAqC1JyEqD9g1AlH4ulumNG7wdPEe0G73SHTrqHX66mXcEq0e8TFxe2aljw8QemKSYDpaQc4uIiIEA5eUFwQH7lI3njabDaZu3Tp8mWpq6tL5juPj49XyKfM+bNBc7gDq1UqVR+RSNRIBin/ks/nk4hEAYl5AhKkjCRU4ru1Wq2S2WwOGo1GdHZ2+teuXbuFrzvtziMRdmCNTqd7hP8iuCO8YNva2izLly9fF15zivP2ggj/NPvO3r178y9cuKCjM6stLS3VlZWVPQH9vHoONKeBn2/6qabNyclRLVq06Ht8vRiKaSinjNgw5s4CMU99VmJWO382YmNjoxcuXBizYMGCuYSYFyE859l588KpnHH8G9SEW7QrlTX7AAAAAElFTkSuQmCC", "Домашняя страница"(addon, hideOn) { if (hideOn) return !addon.homepageURL; var url = addon.homepageURL; if (!url) { if (addon.reviewURL) { url = addon.reviewURL.replace(/\/reviews\/.*$/, "/"); } } openURL(url); }, //------------------------------------------------------------------ "Поиск на АМО_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJGSURBVDjLjdJLSNRBHMDx78yqLZaKS75DPdgDDaFDbdJmde5QlhCJGxgpRJfqEEKnIsJLB7skQYQKZaSmdLaopPCgEvSCShCMzR5a7oq7/3l12RVtjfzBMA/4fWZ+MyOccwBM3g8HEbIdfCEhfAFnLVapOa28Uevpjrqz/WOsERJgsu9Uq5CZQzgqrJfo9BajNd5irEYn4p3OUiFExtCLmw2tawFi4l5zUMjMIau9u7K+qxeoAcoAA0wDb2OPwmfA16LiiaOHLj1edRLpkO3WmIis7+oBDgJbgQ2AH6gC6jY19N62RkcctKeVIJAhp9QgUA3kJXdONZVcq9JxPSgQoXRAyIDRth8oAXQyKdWnoCKrTD9CBv4GMqx1WGNZkeRWJKbG2hiD1Cb9FbTnzWFdY/LCdLKlgNQ84gyNKqHm0gDjqVHnxDHgA/B9RQkpaB6YklkZl62np9KBhOqwjpKFgeY2YAz4BESBWHI8Hhs6PVVSvc3v98ye4fP7T676B845nt040ip98qpWJmI9PWiU6bfWgXGN2YHcKwU7tsuc4kpUPMbU0+f8+vKt+Pitl7PLAMDI9cNBoB0hQwICzjqUp6MZvsy8yvp95BRuQUjJ75mPvH4wYo1NlJ64Mza7DPwrhi8cCOeXl/aUB4P4c/NJxKLMvpngycCrzxVFG2v/CwAMnguF80oLe8p27cQh+fnpPV/fTc95S6piXQDAw7a9YbWkezZXFbAwMx/xPFXb1D3+Y90AQF/L7kAsri9mZ4lrTd0TcYA/Kakr+x2JSPUAAAAASUVORK5CYII=", "Поиск на АМО"(addon, hideOn) { if (hideOn) return ["custombuttons","theme","plugin"]; var url = addon.homepageURL; if (!url) { url = "https://addons.mozilla.org/search/?q=" + encodeURIComponent(addon.name); } openURL(url); }, //------------------------------------------------------------------ "Папка установки_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABAklEQVR42mNkoBAwAjEXEAcCMTsW+U9AvB6I/+I0gJ2Noe3QJoZKASEgjwkq+h+C795lYPCKZMgC8mZg0fsfbICIIMOcF6cZkrGZ/v8fA0PndIa/7z8BXfAPqgVKv//A8GPeZoYERmE+hjmP1+AwAOgiTjOIP7HZLyjLMJNRmB/ogjMMyYzsUC8wIhQwsgCFWHAHoKAy0AARIYY5r69idwEhIKgBMgAYBq8vkGmALsyAU2QaYAwz4CiZBliADBAAGnCATANsYQbsJtMAJ5ABwGh8uZE8A4R9gAYwMzHkT8hl6Bfgxp5ecIH3Xxj+F05hyIdpUmXAnpnwge9AfJckW7EBAC/gSzisxsnmAAAAAElFTkSuQmCC", "Папка установки"(addon, hideOn) { if (hideOn) return ["custombuttons","theme","plugin"]; switch (addon.type) { case "plugin": var pathes = addon.pluginFullpath; for (var i = 0; i < pathes.length; i++) { this.revealPath(pathes[i]); } return; case "userchromejs": var file = addon._script.file; if (file.exists()) file.reveal(); 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(addon.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); } } }, //------------------------------------------------------------------ "Файл установки_i": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA51AAAOdQG5Y1EyAAAAhklEQVQ4y6WT0QnAIAxE78Bt2v1cod3PznP9kVLTRKUGBD+Sd5eQUBJWggCWCAkAJPGXOqlUPyVKkrSPQIoCQJGE6AF4HFyGuBmrR3cGQX8Wmp2cL8Cqv5JPD5Zm1D0nFZjTjHpQ7DuI1L3iBjBS9/pvhtjr21OukVkXiX/ug6SWj4mr53wDMz1vldHlLJkAAAAASUVORK5CYII=", "Файл установки"(addon, hideOn) { if (hideOn) return ["custombuttons","theme","plugin"]; 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(addon.id); if ( dir.exists() ) dir.launch(); var file = Components.classes['@mozilla.org/file/directory_service;1'] .getService(Components.interfaces.nsIProperties) .get('ProfD', Components.interfaces.nsIFile); file.append('extensions'); file.append( addon.id + '.xpi' ) if ( file.exists() ) file.launch(); return; }, //------------------------------------------------------------------ url: "chrome://mozapps/content/extensions/aboutaddons.html", handleEvent(e) { if (e.target.baseURI != this.url) return; var item = this.getItem(e.target.ownerDocument); var addon = item.addon = e.target.closest("addon-card").addon; for(var child of item.children) { var res = this[child.textContent](addon, true); child.hidden = Array.isArray(res) ? res.includes(addon.type) : res; } e.target.contains(item) || requestAnimationFrame( () => e.target.prepend(item) ); }, click(e) { e.stopPropagation(); iconizer.item.parentNode.hide(); this[e.target.textContent](iconizer.item.addon); }, getItem(doc) { if (iconizer.item) { if (iconizer.item.ownerDocument == doc) return iconizer.item; iconizer.handleEvent(); } var item = doc.createElement("div"); item.id = id; for(var lab of this.labels) item.appendChild( doc.createElement("panel-item") ).append(lab); item.onclick = this.click; doc.ownerGlobal.addEventListener("unload", iconizer); return iconizer.item = item; }, get labels() { delete this.labels; this.click = this.click.bind(this); if (id in g) return this.labels = (iconizer = g[id]).labs; g[id] = iconizer; var css = "", ind = 0, arr = []; var push = (ind, icon) => { var chromeImg = `chrome://custombuttons/content/${id + ind}`; arr.push(["override", chromeImg, icon]); return chromeImg; } var labs = iconizer.labs = Object.keys(this).filter(key => { var res = String(this[key]).startsWith('"'); if (!res) return false; ind++; var icon = this[key + "_i"]; if (icon) css += `\n\t#${ id } > panel-item:nth-child(${ind}) {\n\t\t--icon: url(${ push(ind, icon) }) !important;\n\t}`; return true; }); var ams = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup); var mUri = Services.io.getProtocolHandler("resource").getSubstitution("custombuttons-modules"); iconizer.iconHelper = ams.registerChrome(mUri, arr); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var md = "@-moz-document url(chrome://mozapps/content/extensions/aboutaddons.html) {"; var uri = Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(md + css + "\n}")); var args = [uri, sss.USER_SHEET]; sss.loadAndRegisterSheet(...args); iconizer.handleEvent = function() { if (!this.item) return; this.item.ownerGlobal.removeEventListener("unload", this); this.item.remove(); this.item = null; } iconizer.destroy = function() { delete g[id]; this.handleEvent(); sss.unregisterSheet(...args); this.iconHelper.destruct(); } return this.labels = labs; }, revealPath: function(path){ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); file.initWithPath(path); if(file.exists()) file.reveal(); } }, true, gBrowser.tabpanels || 1))("CBAddonsMenuExt", Cu.import("resource://gre/modules/Services.jsm", {}), {});
Отредактировано Andrey_Krropotkin (06-03-2020 00:29:33)
Отсутствует
можешь посмотреть функцию CSSTester.prototype (необязательная можно и скрыть) - там выдает ошибки на кнопки при открытии окна.
Объект же, а не функция.
Если имеется в виду установка doc.body.innerHTML в CSSTester.prototype.handleEvent()
то да, это не будет нормально работать для нас, так они решили, типа небезопасно.
Можно воспользоваться DOMParser'ом, тогда не будет ошибок при открытии окна,
но сам CSSTester от этого, разумеется, лучше не станет.
//doc.body.innerHTML = '\ doc.body.append(...new doc.ownerGlobal.DOMParser().parseFromSafeString('\ <style type="text/css">\ :not(input):not(select) { padding: 0px; margin: 0px; }\ table { border-spacing: 0px; }\ body, html, #main, #textarea { width: 100%; height: 100%; }\ #textarea { font-family: monospace; }\ </style>\ <table id="main">\ <tr height="100%">\ <td colspan="4"><textarea id="textarea"></textarea></td>\ </tr>\ <tr height="40">\ <td><input type="button" value="Vorschau" id="Vorschau"/></td>\ <td><input type="button" value="Speichern" id="Speichern"/></td>\ <td width="80%"><span class="log"></span></td>\ <td><input type="button" value="Schließen" id="Schliessen"/></td>\ </tr>\ </table>\ ', "text/html").querySelectorAll("style,table"));
одна незначительная, не влияющая ни на что ошибка (TypeError: e.target.closest(...) is null), которая вылазит в консоли при нажатии на "Инструменты для всех дополнений"
Да, шестерёнку втащили в aboutaddons.html и её менюшка
расположилась там на общих основаниях. Так, навскидку
handleEvent(e) { //if (e.target.baseURI != this.url) return; if (e.target.baseURI != this.url || e.target.parentNode.id) return;
Отредактировано Dumby (07-03-2020 11:18:57)
Отсутствует
Dumby спасибо. Чуть подпраил, вот что получилось
/*Initialization Code*/ var idb=this.id; var button = document.getElementById(idb); (function(){ var editor = "C:\\Program Files\\AkelPad\\AkelPad.exe"; let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; if (!window.Services) Cu.import("resource://gre/modules/Services.jsm"); let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } window.UCL = { USE_UC: "UC" in window, AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET : Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS : {}, get disabled_list() { let obj = []; try { obj = this.prefs.getCharPref("disabled_list").split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader.") }, get styleSheetServices(){ delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile) aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath("CSS"); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, getFocusedWindow: function() { let win = document.commandDispatcher.focusedWindow; if (!win || win == window) win = content; return win; }, init: function() { const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const cbNS = "http://xsms.nm.ru/custombuttons/"; var menupopup = document.createElementNS(xulNS, "menupopup"); menupopup.onclick = function (event) { button.menuClick(event); } menupopup.addEventListener("popupshowing", function (event) { self.menuPopupShowing(event); }, false); button.appendChild(menupopup); button.type = "menu"; button.orient = "horizontal"; button.menuClick = function (event) { event.preventDefault(); event.stopPropagation(); button.open = false; } button.menuPopupShowing = function (event) { var nodeList = event.target.childNodes; for (var i = nodeList.length - 1; i >= 0; i--) if (nodeList[i].hasAttributeNS(cbNS, "flag")) nodeList[i].parentNode.removeChild(nodeList[i]); } let cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", }); menupopup.appendChild(cssmenu); let menupop = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupop); let menu = $C("menu", { label: "Инструменты", }); menupopup.appendChild(menu); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); mp.appendChild($C("menuitem", { label: "Обновить список файлов-стилей", accesskey: "R", acceltext: "Alt + R", oncommand: "UCL.rebuild();" })); mp.appendChild($C("menuseparator")); mp.appendChild($C("menuitem", { label: "Создать файл CSS", accesskey: "D", oncommand: "UCL.create();" })); mp.appendChild($C("menuitem", { label: "Открыть папку CSS", accesskey: "O", oncommand: "UCL.openFolder();" })); mp.appendChild($C("menuitem", { label: "Редактировать userChrome.css", hidden: false, oncommand: "UCL.editUserCSS(\'userChrome.css\');" })); mp.appendChild($C("menuitem", { label: "Редактировать userContent.css", hidden: false, oncommand: "UCL.editUserCSS(\'userContent.css\');" })); mp.appendChild($C("menuseparator")); mp.appendChild($C("menuitem", { label: "Тест стиля", id: "usercssloader-test-chrome", accesskey: "C", oncommand: "UCL.styleTest(window);" })); mp.appendChild($C("menuitem", { label: "Поиск стиля на userstyles.org", accesskey: "S", oncommand: "UCL.searchStyle();" })); menu = $C("menu", { label: ".uc.css", accesskey: "U", hidden: !UCL.USE_UC }); mp = $C("menupopup", { id: "usercssloader-ucmenupopup" }); menu.appendChild(mp); mp.appendChild($C("menuitem", { label: "Importieren(.uc.js)", oncommand: "UCL.UCrebuild();" })); mp.appendChild($C("menuseparator", { id: "usercssloader-ucsepalator" })); $("mainKeyset").appendChild($C("key", { id: "usercssloader-rebuild-key", oncommand: "UCL.rebuild();", key: "R", modifiers: "alt", })); this.rebuild(); this.initialized = true; if (UCL.USE_UC) { setTimeout(function() { UCL.UCcreateMenuitem(); }, 1000); } window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", dis.join("|")); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); while (files.hasMoreElements()) { let file = files.getNext().QueryInterface(Ci.nsIFile); if (!ext.test(file.leafName) || not.test(file.leafName)) continue; let CSS = this.loadCSS(file); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Style importiert"; else XULBrowserWindow.statusTextField.label = "Styles importieren"; } }, loadCSS: function(aFile) { var CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { var CSS = this.readCSS[aLeafName]; var menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = document.createXULElement("menuitem"); menuitem.setAttribute("label", aLeafName); menuitem.setAttribute("id", "usercssloader-" + aLeafName); menuitem.setAttribute("class", "usercssloader-item " + ( CSS.SHEET == this.AGENT_SHEET ? "AGENT" : CSS.SHEET == this.AUTHOR_SHEET ? "AUTHOR" : "USER" ) + "_SHEET"); menuitem.setAttribute("type", "checkbox"); menuitem.setAttribute("autocheck", "false"); menuitem.setAttribute("oncommand", "UCL.toggle('"+ aLeafName +"');"); menuitem.setAttribute("onclick", "UCL.itemClick(event);"); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { var CSS = this.readCSS[aLeafName]; if (!CSS) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { if (event.button == 0) return; event.preventDefault(); event.stopPropagation(); let label = event.currentTarget.getAttribute("label"); if (event.button == 1) { this.toggle(label); } else if (event.button == 2) { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, styleTest: function(aWindow) { aWindow || (aWindow = this.getFocusedWindow()); new CSSTester(aWindow, function(tester){ if (tester.saved) UCL.rebuild(); }); }, searchStyle: function() { let word; try { word = gBrowser.currentURI.host; } catch { word = gBrowser.currentURI.spec; } var ctabpos = gBrowser.selectedTab._tPos +1; gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab("https://userstyles.org/styles/search/" + word), ctabpos); }, openFolder: function() { this.FOLDER.launch(); }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { try { var UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8"; var path = UI.ConvertFromUnicode(aFile.path); var app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); app.initWithPath(editor); var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); process.init(app); process.run(false, [path], 1); } catch (e) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Имя файла", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucsepalator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = document.createXULElement("menuitem"); m.setAttribute("label", aLeafName); m.setAttribute("tooltiptext", fileURL); m.setAttribute("id", "usercssloader-" + aLeafName); m.setAttribute("type", "checkbox"); m.setAttribute("autocheck", "false"); m.setAttribute("checked", "true"); m.setAttribute("oncommand", "this.setAttribute('checked', !(this.css.disabled = !this.css.disabled));"); m.setAttribute("onclick", "UCL.UCItemClick(event);"); m.css = css; popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button == 0) return; event.preventDefault(); event.stopPropagation(); if (event.button == 1) { event.target.doCommand(); } else if (event.button == 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; function CSSEntry(aFile) { this.path = aFile.path; this.leafName = aFile.leafName; this.lastModifiedTime = 1; var prfx = /^xul-|\.a(s|u)\.css$/i.test(this.leafName) ? RegExp.$1 == "u" ? "AUTHOR" : "AGENT" : "USER"; this.SHEET = Ci.nsIStyleSheetService[prfx + "_SHEET"]; } CSSEntry.prototype = { sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService), _enabled: false, get enabled() { return this._enabled; }, set enabled(isEnable) { var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile) aFile.initWithPath(this.path); var isExists = aFile.exists(); // Wenn die Datei existiert true var lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; var isForced = this.lastModifiedTime != lastModifiedTime; var fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile); var uri = Services.io.newURI(fileURL, null, null); if (this.sss.sheetRegistered(uri, this.SHEET)) { if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; function CSSTester(aWindow, aCallback) { this.win = aWindow || window; this.doc = this.win.document; this.callback = aCallback; this.init(); } CSSTester.prototype = { sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService), preview_code: "", saved: false, init: function() { var url = "data:text/html;charset=utf8,"+encodeURIComponent('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CSSTester</title></head><body></body></html>'); if (parseInt(Services.appinfo.platformVersion) >= 69 && Services.appinfo.browserTabsRemoteAutostart) { var chromeURL = `chrome://custombuttons/content/cbdialog${Date.now()}.xul`; Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup).registerChrome( Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)), [["override", chromeURL, url]] ); url = chromeURL; } this.dialog = openDialog(url, "", "width=850,height=600,dialog=no"); this.dialog.addEventListener("load", this, false); }, destroy: function() { this.preview_end(); this.dialog.removeEventListener("unload", this, false); this.previewButton.removeEventListener("click", this, false); this.saveButton.removeEventListener("click", this, false); this.closeButton.removeEventListener("click", this, false); }, handleEvent: function(event) { switch(event.type) { case "click": if (event.button != 0) return; if (this.previewButton == event.currentTarget) { this.preview(); } else if (this.saveButton == event.currentTarget) { this.save(); } else if (this.closeButton == event.currentTarget) { this.dialog.close(); } break; case "load": var doc = this.dialog.document; doc.body.append(...new doc.ownerGlobal.DOMParser().parseFromSafeString('\ <style>\ :not(input):not(select) { padding: 0px; margin: 0px; }\ table { border-spacing: 0px; }\ body, html, #main, #textarea { width: 100%; height: 100%; }\ #textarea { font-family: monospace; }\ </style>\ <table id="main">\ <tr height="100%">\ <td colspan="4"><textarea contentEditable="true" id="textarea"></textarea></td>\ </tr>\ <tr height="40">\ <td><input type="button" value="Просмотр" id="Vorschau"/></td>\ <td><input type="button" value="Сохранить" id="Speichern"/></td>\ <td width="80%"><span class="log"></span></td>\ <td><input type="button" value="Закрыть" id="Schliessen"/></td>\ </tr>\ </table>\ ', "text/html").querySelectorAll("style,table")); this.textbox = doc.querySelector("textarea"); this.previewButton = doc.querySelector('input[value="Просмотр"]'); this.saveButton = doc.querySelector('input[value="Сохранить"]'); this.closeButton = doc.querySelector('input[value="Закрыть"]'); this.logField = doc.querySelector('.log'); var eTLDsvc = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService); var eTLD; var uri = gBrowser.currentURI; try { eTLD = eTLDsvc.getBaseDomain(uri); } catch (e) { eTLD = uri.asciiHost; } var code = "@namespace url(" + this.doc.documentElement.namespaceURI + ");\n"; if (gBrowser.currentURI.spec.slice(0, 4) === "http") {code +="@-moz-document domain(" + eTLD + ") {\n\n\n\n}";} if (gBrowser.currentURI.spec.slice(0, 4) != "http") { code +="@-moz-document url(" + this.win.location.href + ") {\n\n\n\n}";} this.textbox.value = code; this.dialog.addEventListener("unload", this, false); this.previewButton.addEventListener("click", this, false); this.saveButton.addEventListener("click", this, false); this.closeButton.addEventListener("click", this, false); this.textbox.focus(); let p = this.textbox.value.length - 3; this.textbox.setSelectionRange(p, p); break; case "unload": this.destroy(); this.callback(this); break; } }, preview: function() { var code = this.textbox.value; if (!code || !/\:/.test(code)) return; code = "data:text/css;charset=utf-8," + encodeURIComponent(this.textbox.value); if (code == this.preview_code) return; this.preview_end(); var uri = Services.io.newURI(code, null, null); this.sss.loadAndRegisterSheet(uri, (Ci.nsIStyleSheetService.AGENT_SHEET || Ci.nsIStyleSheetService.USER_SHEET)); this.preview_code = code; this.log("Preview"); }, preview_end: function() { if (this.preview_code) { let uri = Services.io.newURI(this.preview_code, null, null); this.sss.unregisterSheet(uri, (Ci.nsIStyleSheetService.AGENT_SHEET || Ci.nsIStyleSheetService.USER_SHEET)); this.preview_code = ""; } }, save: function() { var data = this.textbox.value; if (!data) return; var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(window, "", Ci.nsIFilePicker.modeSave); fp.appendFilter("CSS Files","*.css"); fp.defaultExtension = "css"; if (window.UCL) fp.displayDirectory = UCL.FOLDER; var suConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); suConverter.charset = "UTF-8"; data = suConverter.ConvertFromUnicode(data); var nsIFilePicker = Components.interfaces.nsIFilePicker; fp.open(function (rv) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); foStream.init(fp.file, 0x02|0x20|0x08, 0666, 0); foStream.write(data, data.length); foStream.close(); } }); this.saved = true; }, log: function() { this.logField.textContent = dateFormat(new Date(), "%H:%M:%S") + ": " + $A(arguments); } }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.from(arr); } function $C(name, attr) { var el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDay()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log() { Application.console.log(Array.from(arguments)); } })();
getBrowserForContentWindow: function(aContentWindow) { return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow) .QueryInterface(Ci.nsIDOMChromeWindow); },
Отредактировано Andrey_Krropotkin (07-03-2020 17:55:21)
Отсутствует
добавить контестное меню в окно
Для этого нужны обеспечительные скрипты и стили.
Можно заменить CSSTester.prototype.init()
init() { var url = "data:application/xhtml+xml;charset=utf8," + encodeURIComponent( `<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin/menu.css" type="text/css"?> <?xml-stylesheet href="chrome://global/skin/popup.css" type="text/css"?> <html xmlns="${xhtmlns}"> <head> <title>CSSTester</title> <script src="chrome://global/content/globalOverlay.js"/> <script src="chrome://global/content/editMenuOverlay.js"/> <style>#textarea{width:calc(100% - 2px)!important;}</style> </head> <body></body> </html>` ); var proto = CSSTester.prototype; var uri = Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)); var chromeURL = `chrome://custombuttons/content/cbdialog${Date.now()}.xhtml`; var ams = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup); proto.CSSTesterHelper = ams.registerChrome(uri, [["override", chromeURL, url]]); addDestructor(proto.CSSTesterHelper.destruct); (proto.init = function() { (this.dialog = openDialog(chromeURL, "", "width=850,height=600,dialog=no")) .addEventListener("load", this, false); }).call(this); },
в preview: function() и в preview_end: function() добавил USER_SHEET и не уверен правильно или нет
Замысел непонятен, AGENT_SHEET имеет значение ноль,
таким образом запись (Ci.nsIStyleSheetService.AGENT_SHEET || Ci.nsIStyleSheetService.USER_SHEET)
эквивалентна просто Ci.nsIStyleSheetService.USER_SHEET
подскажи пожайлуста чем можно заменить
Хорошо бы посмотреть где и как это используется.
Вот, парочка вариантов, может подойдёт
getBrowserForContentWindow: aContentWindow => aContentWindow.docShell.rootTreeItem.domWindow, getBrowserForContentWindow: aContentWindow => aContentWindow.windowRoot.ownerGlobal,
Отсутствует
Замысел непонятен
Если тестирую браузер нужен AGENT_SHEET, если сайт - USER_SHEET (как то так, а с этим вроде бы все тестируется)
Хорошо бы посмотреть
Исправляю очень старый скрипт, пока на полпути
// ==UserScript== // @name SaveUserChromeJS.uc.js // @author ywzhaiqi // @description установка контекстного меню кнопок на github для скачивания скриптов // @include main // @charset UTF-8 // @version 0.4b // @homepageURL https://github.com/ywzhaiqi/userChromeJS/tree/master/SaveUserChromeJS // @reviewURL http://bbs.kafan.cn/thread-1590873-1-1.html // ==/UserScript== (function() { // Включены ли уведомления после сохранения? var notificationsAfterInstall = true; // Загружается ли скрипт после сохранения (запускать не нужно)? Поддерживается только .uc.js, некоторые скрипты проблематичны. var runWithoutRestart = false; let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; if (!window.Services) Cu.import("resource://gre/modules/Services.jsm"); if(typeof window.saveUserChromeJS != "undefined"){ window.saveUserChromeJS.uninit(); delete window.saveUserChromeJS; } const RE_USERCHROME_JS = /\.uc(?:-\d+)?\.(?:js|xul)$|userChrome\.js$/i; const RE_CONTENTTYPE = /text\/html/i; var ns = window.saveUserChromeJS = { init: function() { // добавить в contentAreaContextMenu if ( document.getElementById("uc-install-menu") ) return; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAICAAP//AICAgMDAwP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcj7VkAAABfdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8Ak5pfLAAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAFxJREFUKFNljgEOwCAIAwuF/395RWXMrDExHLQA3gKYpVXojwPo6SpewDSzAHGAXvWpkQYagNSWN2EyfGUM+G/RQWZFOnSt9AZMR3nGwggivqF1Q12xQVzavRHwALQIAv2bDRzYAAAAAElFTkSuQmCC"; var contextMenu = document.getElementById("contentAreaContextMenu"); var menuitem = document.createElementNS(xulns, "menuitem"); menuitem.setAttribute("id", "uc-install-menu"); menuitem.setAttribute("label", "Установить для userChromeJS"); menuitem.setAttribute("class", "menuitem-iconic"); menuitem.setAttribute("image", icon); menuitem.setAttribute("accessKey", "I"); menuitem.setAttribute("oncommand", "saveUserChromeJS.saveScript(gContextMenu.linkURL)"); contextMenu.insertBefore(menuitem, contextMenu.firstChild); contextMenu.addEventListener("popupshowing", this, false); this._menuitem = menuitem; }, handleEvent: function(event){ switch(event.type){ case "popupshowing": if (event.target != event.currentTarget) return; if(gContextMenu.onLink){ this._menuitem.hidden = !RE_USERCHROME_JS.test(gContextMenu.linkURL); }else{ this._menuitem.hidden = true; } break; } }, observe: function(aSubject, aTopic, aData) { switch (aTopic) { case "content-document-global-created": let safeWin = aSubject; let chromeWin = this.getBrowserForContentWindow(safeWin).wrappedJSObject; if (!chromeWin) return; let gBrowser = chromeWin.gBrowser; if (!gBrowser) return; let lhref = safeWin.location.href; if(lhref.startsWith("view-source")) return; // Показать баннер установки scriptish, если пользователь переходит к .user.js // файл в top-level tab. if (safeWin === safeWin.top && RE_USERCHROME_JS.test(lhref) && !RE_CONTENTTYPE.test(safeWin.document.contentType)) { safeWin.setTimeout(function(){ ns.showInstallBanner(gBrowser.getBrowserForDocument(safeWin.document)); }, 500); } if(safeWin.location.hostname == 'github.com'){ safeWin.addEventListener("DOMContentLoaded", function(){ ns.github_addButton(safeWin.document); // github с history.pushstate, нужно добавить кнопку еще раз после загрузки страницы // 2014-7-15:firefox 33(nightly)если цитируется unsafeWindow.$ это потерпит крах if (Services.appinfo.version < 33) { ns.github_addListener(safeWin); } var sWBrowser = gBrowser.getBrowserForContentWindow(safeWin); if (!sWBrowser.ProgListener) { sWBrowser.ProgListener = { QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]), onLocationChange: function() { safeWin.setTimeout(function() { ns.github_addButton(safeWin.document); }, 0); } }; }; try { sWBrowser.addProgressListener(sWBrowser.ProgListener, Ci.nsIWebProgress.NOTIFY_LOCATION); safeWin.addEventListener('beforeunload', function() { sWBrowser.removeProgressListener(sWBrowser.ProgListener); }); } catch(e) { }; }, false); } break; } }, showInstallBanner: function(browser) { var notificationBox = gBrowser.getNotificationBox(browser); var greeting = "Das ist ein userChrome Script. Klicken Sie auf Installieren, um es zu verwenden. Nach dem Speichern im Chrome Ordner bitte einen Neustart durchführen."; var btnLabel = "Installieren"; // Удалить существующие уведомления. Уведомления удаляются // автоматически по клику и по странице навигации, но нам нужно удалить // их самим в случае перезагрузки, или они складываются. for (var i = 0, child; child = notificationBox.childNodes[i]; i++) if (child.getAttribute("value") == "install-userChromeJS") notificationBox.removeNotification(child); var notification = notificationBox.appendNotification( greeting, "install-userChromeJS", null, notificationBox.PRIORITY_WARNING_MEDIUM, [{ label: btnLabel, accessKey: "I", popup: null, callback: this.saveCurrentScript } ]); }, github_addButton: function(doc){ if(doc.getElementById("uc-install-button")) return; var rawBtn = doc.getElementById("raw-url"); if(!rawBtn) return; var downURL = rawBtn.href; if(!RE_USERCHROME_JS.test(downURL)) return; var installBtn = doc.createXULElement("a"); installBtn.setAttribute("id", "uc-install-button"); installBtn.setAttribute("class", "btn btn-sm"); installBtn.setAttribute("href", downURL); installBtn.innerHTML = "Installieren"; installBtn.addEventListener("click", function(event){ event.preventDefault(); ns.saveScript(downURL); }, false); rawBtn.parentNode.insertBefore(installBtn, rawBtn); }, github_addListener: function(win){ var script = '\ (function(){\ var $ = unsafeWindow.jQuery;\ if(!$) return;\ $(document).on("pjax:success", function(){\ github_addButton(document);\ });\ })();\ '; let sandbox = new Cu.Sandbox(win, {sandboxPrototype: win}); sandbox.unsafeWindow = win.wrappedJSObject; sandbox.document = win.document; sandbox.window = win; sandbox.github_addButton = ns.github_addButton; Cu.evalInSandbox(script, sandbox); }, saveCurrentScript: function(event){ ns.saveScript(); }, saveScript: function(url) { var win = ns.getFocusedWindow(); var doc, name, fileName, fileExt, charset; if(!url){ url = win.location.href; doc = win.document; name = doc.body.textContent.match(/\/\/\s*@name\s+(.*)/i); charset = doc.body.textContent.match(/\/\/\s*@charset\s+(.*)/i); } name = name && name[1] ? name[1] : decodeURIComponent(url.split("/").pop()); fileName = name.replace(/\.uc\.(js|xul)$|$/i, ".uc.$1").replace(/\s/g, '_'); if (fileName.match(/\.uc\.$/i)) { // Исправить имя var m = url.match(/\.(js|xul)$/); if (m) fileName += m[1]; } fileExt = name.match(/\.uc\.(js|xul)$/i); fileExt = fileExt && fileExt[1] ? fileExt[1] : "js"; charset = charset && charset[1] ? charset[1] : "UTF-8"; // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Open_and_Save_Dialogs var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); var err = false; try { fp.init(window, "", Ci.nsIFilePicker.modeSave); } catch(e) { fp.init(ns.getMostRecentWindow(), "", Ci.nsIFilePicker.modeSave); err = true; Application.console.log('SaveUserChromeJS.uc.js - error catched (A)'); }; var SCRIPTS_FOLDER = Services.dirsvc.get("UChrm", Ci.nsIFile); fp.appendFilter("*." + fileExt, "*.uc.js;*.uc.xul"); fp.appendFilters(Ci.nsIFilePicker.filterAll); fp.displayDirectory = SCRIPTS_FOLDER; fp.defaultExtension = fileExt; fp.defaultString = fileName; var nsIFilePicker = Components.interfaces.nsIFilePicker; fp.open(function (rv) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist); persist.persistFlags = persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; var url2 = url.replace("github", "raw.githubusercontent").replace("\/blob", " "); var obj_URI; if(doc && fileExt != 'xul'){ obj_URI = doc.documentURIObject; }else{ obj_URI = Services.io.newURI(url2, null, null); } if(notificationsAfterInstall){ persist.progressListener = { onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { if(aCurSelfProgress == aMaxSelfProgress){ var win = err ? ns.getMostRecentWindow() : window; win.setTimeout(function(){ ns.showInstallMessage({ fileExt: fileExt, fileName: fileName, file: fp.file, charset: charset }); }, 100); } }, onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { } }; } persist.saveURI(obj_URI, document.nodePrincipal, null, null, null, null, fp.file, null); } }); }, showInstallMessage: function(info){ var isRun = (info.fileExt == "js"); var mainAction, secondActions; if(runWithoutRestart && isRun){ mainAction = { label: "Выполнить немедленно (без перезапуска).", accessKey: "a", callback: function(){ ns.runScript(info.file, info.charset); } }; secondActions = [{ label: "Перезагрузите сейчас", accessKey: "s", callback: ns.restartApp }]; }else{ mainAction = { label: "Перезагрузите сейчас", accessKey: "s", callback: ns.restartApp }; secondActions = null; } var showedMsg = ns.popupNotification({ id: "userchromejs-install-popup-notification", message: "'" + info.fileName + "' Установка завершена.", mainAction: mainAction, secondActions: secondActions, options: { removeOnDismissal: true, persistWhileVisible: true } }); }, popupNotification: function(details){ var win = ns.getMostRecentWindow(); if (win && win.PopupNotifications) { win.PopupNotifications.show( win.gBrowser.selectedBrowser, details.id, details.message, "", details.mainAction, details.secondActions, details.options); return true; } return false; }, // Только поддержка us.js runScript: function(file, charset){ window.userChrome_js.getScripts(); if(window.userChromeManager){ window.userChromeManager.rebuildScripts(); } var dir = file.parent.leafName; if(dir.toLowerCase() == 'chrome' || (dir in window.userChrome_js.arrSubdir)){ let context = {}; Services.scriptloader.loadSubScript( "file:" + file.path, context, charset || "UTF-8"); } }, flushCache: function (file) { if (file) Services.obs.notifyObservers(file, "flush-cache-entry", ""); else Services.obs.notifyObservers(null, "startupcache-invalidate", ""); }, getFocusedWindow: function() { var win = document.commandDispatcher.focusedWindow; try { return (!win || win == window) ? content : win; } catch(e) { Application.console.log('SaveUserChromeJS.uc.js - error catched (B)'); return (!win || win == window) ? null : win; }; }, getMostRecentWindow: function(){ return Services.wm.getMostRecentWindow("navigator:browser") }, getBrowserForContentWindow: function(aContentWindow) { return aContentWindow.docShell.rootTreeItem.domWindow; }, restartApp: function() { const appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup); // Уведомить все окна о том, что приложение было запрошено. var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].createInstance(Components.interfaces.nsISupportsPRBool); os.notifyObservers(cancelQuit, "quit-application-requested", null); // Что-то прервало процесс выхода. if (cancelQuit.data) return; // Уведомить все окна о том, что приложение завершено. os.notifyObservers(null, "quit-application-granted", null); // Перечислить все окна и обработчики вызовов var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator); var windows = wm.getEnumerator(null); var win; while (windows.hasMoreElements()) { win = windows.getNext(); if (("tryToClose" in win) && !win.tryToClose()) return; } let XRE = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime); if (typeof XRE.invalidateCachesOnRestart == "function") XRE.invalidateCachesOnRestart(); appStartup.quit(appStartup.eRestart | appStartup.eAttemptQuit); } }; function log(arg){ Application.console.log("[SaveUserChromeJS]" + arg);} function checkDoc(doc) { if (!(doc instanceof HTMLDocument)) return false; if (!window.mimeTypeIsTextBased(doc.contentType)) return false; if (!doc.body || !doc.body.hasChildNodes()) return false; if (doc.body instanceof HTMLFrameSetElement) return false; return true; } })(); window.saveUserChromeJS.init();
Отредактировано Andrey_Krropotkin (09-03-2020 01:33:21)
Отсутствует