Добрый день . Есть необходимость в кнопке или на худой конец код для CSS FG_userChrome "Запрета любого масштабирования на определённом сайте" если есть в закромах, буду весьма признателен.
Отредактировано Duche (28-12-2024 15:20:07)
Отсутствует
новой CB не предвидеться ? для 128 к примеру. и скрипты отвалились к тому же...
Отсутствует
Еще что-то надо ?
При закрытом Firefox, удалить папку startupCache из Локального каталога профиля.
Но у вас 136 . Видимо надо откатится на версию поменьше.
Отсутствует
vending_machine
Но у вас 136
не это user agent / а так 128 и startupCache удалял...бесполезно
Так понимаю выше 115 об СВ можно забыть ?
Отредактировано green25 (15-01-2025 13:50:22)
Отсутствует
У кого может есть ссылка на paxmod?
Не знаю какая именно версия CB нужна для ФФ 115
Отсутствует
Не знаю какая именно версия CB нужна для ФФ 115
Win7
Отсутствует
kokoss
Большое спасибо!
Отсутствует
Приветствую!
Вопрос: как отображать цифру на любой кнопке ? и каждый час обновлять ?
Например, на своей кнопке или unified-extensions-button выводить справа сверху цифру аналогично AdBlock, но на синем фоне ?
Dumby - сделал подсчёт дней от смены пароля, через nsILoginManager не получилось...
(async ()=>{ // код выполнять в окне var AlLogins = await Services.logins.getAllLogins(); var PassInfo = urluser => AlLogins.filter(function(item){ if(item.origin +' '+ item.username == urluser) return item; })[0]; try {var dayPass = PassInfo("https://accounts.google.com USER@gmail.com").timePasswordChanged; } catch {dayPass = new Date()} var diffDays = Math.ceil(Math.abs(new Date().getTime() - new Date(dayPass).getTime())/86400000); console.log(diffDays); //прошло дней от смены пароля })();
Отредактировано Dobrov (01-02-2025 04:44:29)
Отсутствует
Вопрос: как отображать цифру на любой кнопке ? и каждый час обновлять ?
Например, на своей кнопке или unified-extensions-button выводить справа сверху цифру аналогично AdBlock, но на синем фоне ?
(id => { var btn = document.getElementById(id); btn.setAttribute("badged", true); btn.setAttribute("badgeStyle", "color: white; background-color: blue"); btn.textContent = ""; btn.render(); var tick = num => { btn.setAttribute("badge", String(num).padStart(3, "0")); ++num > 100 || setTimeout(tick, 250, num); } tick(0); })("unified-extensions-button");
А на любой (чужой) — надо смотреть, нет ли в ней
чего-то полезного, типа <menupopup>, и если есть,
тогда удалять только добро, добавленное кустомэлементщиной.
сделал подсчёт дней от смены пароля, через nsILoginManager не получилось...
А через что же тогда?
Ну-ка запусти alert(Services.logins); Что видно?
Подсчётом дней от смены пароля он не занимается,
но сами логины ты взял именно у него.
А ceil — вроде как-то немного непонятно,
может лучше floor или, в крайнем случае, round
Да и сам подсчёт у тебя какой-то слишком странный. Вот, прогон всех
(async () => { var logins = await Services.logins.getAllLogins(); var formatter = new Intl.RelativeTimeFormat("ru", {style: "long"}); var now = Date.now(); var day = 24 * 60 * 60 * 1000; var result = logins.map(login => { var info = login.username + " " + login.origin + "\n"; var changed = login.timePasswordChanged; var changedDate = new Date(changed).toLocaleDateString("ru"); var diff = Math.floor((now - changed) / day); return info + changedDate + " \u2014 " + formatter.format(-diff, "day"); }); console.log("\n" + result.join("\n\n") + "\n "); })();
Отсутствует
Dumby - спасибо! (исчо другой вопрос в теме UCF задал)
На кнопке не получается показать 4 символа, видно первые три. Это ограничение Firefox ?
Делаю показ дней от смены/обновления пароля выбранной учётки или до смены пароля (если указан срок жизни пароля при регулярной замене)
Отсутствует
Отсутствует
Dumby, здравствуете.
В связи с прилётом Bug 1881888 - Remove support for JSMs, пытаюсь поднять bootstrap расширения, но столкнулся с необходимостью перезагрузки всего . Подскажите пожалуйста, может есть какое решение для перезагрузки/выгрузки ESModule`й в
ЗЫ: В случае с DTA, выкидывает ошибку:
can't access dead object
Жизнь иногда такое выкидывает, что хочется подобрать...
На форуме
может есть какое решение для перезагрузки/выгрузки ESModule`й в
Нет, они не выгружаются.
Чтобы не быть голословным, вот
Bug 1836480 - Convert toolkit/mozapps/extensions/internal/XPI* to ES modules
Там прямо сходу сказано: «ES modules cannot be unloaded».
Поэтому, запилили какой-то жуткий wrapper XPIExports,
где новые экземпляры модулей обретаются посредством импорта
с добавлением к урлу модуля суффикса «?…».
А вообще, кстати да, я как-то связязан только с не restartless расширениями,
поэтому даже не задумывался, а ведь для настоящих bootstrap расширений
это, действительно, может быть проблемой.
Отредактировано Dumby (05-02-2025 22:02:58)
Отсутствует
ведь для настоящих bootstrap расширений
это, действительно, может быть проблемой.
Спасибо за ответ, Вы для меня были последней инстанцией, конечно я запилил рестарт если моодуль загружен или отказ от обслуживания...
ЗЫ: и да я проштудировал что смог найти и там нет выгрузки перезагрузки и etc... Спасибо за подтверждение.
PPS: А ещё вопрос Вы будете поддерживать DOMi или мне пора разбираться с Browser Toolbox?...
Ну я всё-таки начинал с Netscape Navigator, хотя если удаться отконсолить и поймать ошибки, но пока это для меня сложно.
Жизнь иногда такое выкидывает, что хочется подобрать...
На форуме
ещё вопрос Вы будете поддерживать DOMi или мне пора разбираться с Browser Toolbox?...
Не готов согласться с этим вот «или», поскольку DOMi
Browser Toolbox'у даже близко вообще ни разу не замена.
Встроенная машинерия — это мощь, шок и трепет.
Навык обращения с ней представляет безотносительную ценность.
А DOMi — это так, просто выцветший отголосок-отражения чего-то былого.
Впрочем, иногда, сугубо для простецких задач, вполне себе ностальгически-симпатичен.
Вобщем, собственно ответ, можно сформулировать как «если смогу».
У меня сейчас такой.
Firefox 136 + 0.0.7.0.0.35
this.Click = function(event) {alert(event.button);}
Больше не выводит "1"
Ага, Firefox 28.0 0.0.5.8.2
this.Click = function(event) {alert(event.button);}
тоже не выводит "1"
Отсутствует
Dumby
Раскрыл 136b2. Перестали рабтать кнопки:
1. Экспорт в HTML файл в контекстном меню закладок
//-------------------- Экспорт в HTML файл в контекстном меню закладок (popup => addEventListener("popupshowing", { handleEvent() { if (this.shouldHide()) return; var before = document.getElementById("placesContext_openSeparator"); var menuitem = popup.insertBefore(document.createXULElement("menuitem"), before); menuitem.setAttribute("label", "Экспорт папки в HTML"); menuitem.setAttribute("oncommand", "exportFolder();"); menuitem.exportFolder = this.pick.bind(this); addDestructor(() => menuitem.remove()); (this.handleEvent = () => menuitem.hidden = menuitem.disabled = this.shouldHide())(); }, shouldHide() { var node = popup.triggerNode._placesNode; var hide = !node || node.type != node.RESULT_TYPE_FOLDER; if (!hide) this.guid = node.bookmarkGuid, this.title = node.title; return hide; }, pick() { var fp = makeFilePicker(); fp.init(window.browsingContext, PlacesUIUtils.promptLocalization.formatValueSync("places-bookmarks-export"), fp.modeSave); fp.defaultString = (this.title ? DownloadPaths.sanitize(this.title) : "untitled") + ".html"; fp.open(res => res == fp.returnCancel || this.export(fp.file.path)); }, async export(path) { var tree = await PlacesUtils.promiseBookmarksTree( this.guid, {includeItemIds: true} ); var bookmarks = {children: [ {root: "toolbarFolder"}, {root: "unfiledBookmarksFolder"}, {root: "bookmarksMenuFolder", children: [tree], guid: PlacesUtils.bookmarks.menuGuid} ]}; new this.nsvo.BookmarkExporter(bookmarks).exportToFile(path); }, get nsvo() { delete this.nsvo; return this.nsvo = Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm", {}); } }, false, popup))(document.getElementById("placesContext") || 1);
2.Дополнительные пункты в контекстном меню кнопки
/*Initialization Code*/ ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Создание меню /////////////////////////////// ///////////////////////////////////////////////////////////////////////////// function $(aId) { return document.getElementById(aId); }; function addMenuItem(aNewIDs, aNodeIDs, aLabel, aIcon, aCommand) { for (var i = 0; i < aNewIDs.length; i++) { if ($(aNewIDs[i])) $(aNewIDs[i]).parentNode.removeChild($(aNewIDs[i])); var mi = document.createXULElement("menuitem"); mi.setAttribute("id", aNewIDs[i]); mi.setAttribute("class", "menuitem-iconic"); mi.setAttribute("image", aIcon); mi.setAttribute("label", aLabel); mi.setAttribute("oncommand", aCommand); if (i == 0) mi.setAttribute("observes", "custombuttons-contextbroadcaster-primary"); if ($(aNodeIDs[i])) { if ($(aNodeIDs[i]).nextSibling) { $(aNodeIDs[i]).parentNode.insertBefore(mi, $(aNodeIDs[i]).nextSibling); } else { $(aNodeIDs[i]).parentNode.appendChild(mi); } } } }; var saveImg1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnUlEQVQ4jc3RPQ4BURTF8Z+PgrAPtUJnIxZgBZagkolVqDWWIliARCFR6GSq0Twyw2SemcpJTnPzzv/edy//ohOymj7mARl6NRoOQ6YAiGmNFAm6TQBpePdAJwYYYIF+rpaE8CoGaGEbarsw7qfaVYCl4rY3mOOGaQwwU326O8Zhyi/AJPwxdv8rRmWAyw/hl89lgCZ+69AgvPcXegKfOWlGgoA/rgAAAABJRU5ErkJggg=="; var saveImg2 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAADbAAADpcAAA//AAANVwAAD/8AAAKsAAAD/AAAP//AAAP8AAAD/AAAD/8AAAwDAAAP/wAAA/wAAAP8AAA"; var saveImg3 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQf//rEH4j6xB8IesQeHDrEHD4axBh/CsQYf4rEGH8KxBw+GsQeHDrEHwh6xB+I+sQf//rEH//6xB//+sQQ=="; var saveImg4 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAA/wAAAP8AAA"; var saveImg5 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU1FQr1FRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wU1FQrwAAAAAAAAAAAAAAAHd0cpz//////////////////////////////////////////////////////////3d0cpwAAAAAAAAAAAAAAAB4d3Sc/////+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg//////94d3ScAAAAAAAAAAAAAAAAenh3nP/////i4uL/4uLi/5yiz/9HYcT/PWrR/1qQ3P+nuNr/4uLi/+Li4v//////enh3nAAAAAAAAAAAAAAAAH18eJz/////5OTk/2FluP8IJ6r/D1TU/wli4v8FZeb/D3He/4y+5f/k5OT/+/v7/318eJwAAAAAAAAAAAAAAACBfXyc/////5Wc0v8JKq//E2Pd/yFTrv9EKTn/LjVZ/xaF2/8OdNP/zNnm//z8/P+BfXycAAAAAAAAAAAAAAAAhIGBnP////89Xc7/Dk7N/wpQ0/8zVp//TGCK/4U2Cf9DW2b/Eqj7/5C+5//8/Pz/hIGBnAAAAAAAAAAAAAAAAIaEgZz/////Kmnf/wlFzf8gPZ7/uXcl/8OAK/+UTBL/b1Az/zfG9f9srdX/+fn5/4aEgZwAAAAAAAAAAAAAAACJhoac/////0iN6P8HQtH/EVzd/2mCqf/dqkz/0pY6/6FnKv9Nvt7/kMfs//X19f+JhoacAAAAAAAAAAAAAAAAiomJnP////+Mr+r/FFnU/xVRyv+LorL/8Oqh//nXbP+5omH/Urvf/8bj7v/s7Oz/iomJnAAAAAAAAAAAAAAAAI6Kipz/////2+n3/5aSm/+hcEn/4uXC////2P/25KD/rqSD/7HR5//o6Oj/4eHh/46KipwAAAAAAAAAAAAAAACPjo6c//////j4+P/4+Pj/3s/F/9i/n//p27n/5NG0/+7r6f/r6+v/3t7e/9LS0v+Pjo6cAAAAAAAAAAAAAAAAk4+PnP/////6+vr/+vr6//r6+v/6+vr/+vr6//j4+P/19fX/r66t/62sq/ObmprrkI2NpgAAAAAAAAAAAAAAAJOTk5z//////Pz8//z8/P/8/Pz/+/v7//r6+v/4+Pj/9fX1/66trfHs7Ozrp6emp4aGhhMAAAAAAAAAAAAAAACWlpOc/////////////////v7+//39/f/6+vr/9/f3//Pz8/+bmprrp6enp3NzcxYAAAAAAAAAAAAAAAAAAAAAmJiWnJiYlpyYmJacmJiWnJeTk52SkZGemJiWnJeTk52SkZGej4+LpIaGhhMAAAAAAAAAAAAAAAAAAAAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACABwAAgA8AAA=="; var saveImg6 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKklEQVR42mNkQAMNDAxCQMoTiB2BWAEq/ACI9wPxdqD8O2T1jGiao4HUEgb8IAaobimGAUDBGiDVzEAcqAWqb4EbQKTNWF3CCPXzW5ho/f//YDqHkZFhCpQNA7lAMV4gzY4QEmZEtx1mgCtQ8W4o2xLIPg5lJwDZUghDYkAGzAEyktENMAQqPA9l6wDZEkB6D6Yhc0EG7AGynfEZYAxkawHpxVC+A5CvC6RFGBj2Em2AIZCeg8Q3BtLSUAMIegGkwQBIz8U0YC7OQEQ2wAjIPoekGRQTUC/E4IxGkMKzaNEI8jso4chDbGdgA0UjekJ6A8S3gRikFWQyKOF/higGR50UFLPBEhLM9AZoUv4F1cAA1QTi/2SAJFkQnxdCoyZlJEPIz0xIhpCUnQFx83abgfUZOQAAAABJRU5ErkJggg=="; var saveImg7 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASUlEQVR42mNkoBAw0s6ABob/aHxGkg1I8zEGM2dtOTskDED3MxCgGIBpASOGATANhACyi6hrAGVeoDgQB6UB2PxMvAFEAooNAAC7izYR2pQ0nAAAAABJRU5ErkJggg=="; var saveImg8 = "data:application/file;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///8A////AESqAABHpgAASKAAAEukAQxMpQMYR6MAAEepAQ9MpgOLRKgACUenAABHpgAARKoAAP///wD///8A////AP///wBEqgAARaIAAFS2FVBj0jS3Y9AzyVG0EUROrwt8TKcDs0ikAANInwAAR6YAAESqAAD///8A////AP///wD///8ARKQAAVvJKJtj0jX/SaAJ/0abCv9UtSH/U7QX8lW5IMddwyfQW8Iii0mqBQ1DqQAA////AP///wD///8A////AEWlAAFYwB6YXsYc5F7GFt9bwA+vVbgWvU6rAKBRrgf0RZgA/02oDP9ezCzJR6UBA////wD///8A////AP///wBFrAAASKIAADiGNQAeYIIpF1iJHVa4GKEve0tFLHl1Pla7J51exRnUWL8VjEetAAP///8A////AP///wD///8AC0WuAAk/tAAANdpIAFD6/wA+7f8gd6jqBlPX+QBE9PIGS8uDLnZLADqNJwAzjDMA////AP///wD///8A////AAAw0QAALc0AAEPdegBI4f8AK8P/ADHX/wAwzf8AL8b/AEno/gAz2zYALtEQAC3VAP///wD///8A////AP///wAAMssAADjSMwBA2pIATen/ADG9/wBe1v8ATcz/ADHK/wBN5/4ASeH/AEvl6wA10DP///8A////AP///wD///8AADnTSQBO5/8ANc7/ADnR/xC+9/8C0f//AMj//wCP8P8ALcX/ACrC/wBE3f8ASeOf////AP///wD///8A////AABI4Z4ARN3/ACvG/wJAxP8Z5v//AMT//wDE//8Axv7/AETM/wA51P8AUervADjSPP///wD///8A////AP///wAAOdRiAFry+QBS6/QATOP/H+P8/xDe//8J1///E9H4/wFE2f8AReC6ADTOEwAyywD///8A////AP///wD///8AADDNAAAyzCcARN7WACvG/wVfzf8d0vf/HM30/whf0/8AI7n/ADzV+AA40kUAMswA////AP///wD///8A////AAAwywAAPNdTAEfg/wAsw/8AOdb/ADLP/wAswv8AReP/AC7H/wA40f8AR+GfADDKAP///wD///8A////AP///wAAMswAADfRQgBY8f8AT+j/AE7o7AA+1/8AK8T/AE7o/wBN5f8AVe7/AD/ZbAAwywD///8A////AP///wD///8AADPMAAAyywAANM4vADjSUQA0zikAU+z3AEff/wBJ4sMAN9EtADjROQAyywAAM8wA////AP///wD///8A////AAAzzAAAM8wAADHLAAAwywAAMcsAAD/YXQBK4pYAN9AxAC/KAAAwygAAM8wAADPMAP///wD///8A+R8AAPAfAADABwAAwAMAAPgDAADwHwAA8AcAAOADAADAAwAAwAMAAMAHAADgBwAA4AcAAOAHAADwDwAA/j8AAA=="; var saveImg9 = "data:application/file;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAFwAAAGkAAABzAAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAADkAAAAP////AQAAAIdgZmj/YWlt/2FobP9haGz/YGhr/2Boa/9fZ2v/X2dr/15mav9dZWn/XGRo/0ZNUP8AAACdAAAAFf///wEAAACr2tzc/9ve4P/a3t//1dnZ/7S2tf+foJz/m5ya/6apqP/O0tP/09fZ/9DV1v+hqq//AAAAuQAAABX///8BAAAAq+3u7//e4eL/ub29/2hnXv9oVUX/U0As/zgxGf83Lx3/YWBX/7a5uv/S1tj/o6yx/wAAALkAAAAV////AQAAAKv29/f/19na/1dUQf9jXDv/dmtJ/4FoSP9VQiL/V0Ek/008Iv9HQTP/yc3P/6Wus/8AAAC5AAAAFf///wEAAACr+Pj4/5uamP9tY0L/g31b/6GLa/+McVH/eFY5/4xwUv9yXkD/RTki/4uMiv+nsLT/AAAAuQAAABX///8BAAAAq/n6+v+FfXL/waSM/8qznf/DrZP/ooFi/7WfhP+qh2//blk9/1A+Iv9aWlH/pK2x/wAAALkAAAAV////AQAAAKv6+/v/d3Rr/9zCsP/RxbH/z8Wu/9fJt//Qvab/qItv/5iOb/9tYUH/VVJK/6Wtsf8AAAC5AAAAFf///wEAAACr+/z8/4mHff+3pI//3NK//+HXxf/m3Mz/5trJ/9rMuf+bgWT/d14//2hnYP+osbX/AAAAuQAAABX///8BAAAAq/z9/f/FxL7/j4l+//Xw5f/29ez/8/Dl/+DMuv/VuaP/poZn/2dFKv+srav/oamt/wAAALkAAAAV////AQAAAKv+/v7/+/z8/5iZjf+5uqr/6+PW/+3i1P/kzL3/vZR+/4NhSf+Qh3z/z9HS/4qQkv8AAAC1AAAAFf///wEAAACr/v7+//7+/v/u7u3/tbiv/5WSgP+DfGj/e25Z/29gTv+sppz/vr6+/5aYmP90eHr/AAAApwAAABP///8BAAAAq/////////////////7+/v/9/f3//f39//v8/P/5+fn/1dXV/2pqav9TU1P/QUFB/wEBAYkAAAAJ////AQAAAKv7+/v//////////////////v7+//7+/v/+/v7/+vr6/9fY2P/V1tb/7Ozs/4KCgv8EBAQrAAAAA////wEAAACFlJSU/6ioqP+qqqr/qqqq/6qqqv+qqqr/qKio/6anp/2kpaX9o6Oj/4qKitUZGRk9////Af///wH///8BAAAAFQAAAFUAAABVAAAAVQAAAFUAAABVAAAAVQAAAFUAAABTBAQEUx8fH1dfX18z////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w=="; var loadImg = "data:image/x-icon;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////AQAAAB+yg2l71ZRt+daTa//Wk2v/1pNr/9aTa//Wk2v/v4NlywYEAycAAAAX////Af///wH///8B////Af///wHdo4M53Zx3/+Sgef/innb/4p52/+Kedv/lo3r/5aR6/+mqgfvPj27N////Af///wH///8B////Af///wH///8B4KSD8+mmff/opH3/56N6/+Whef/no3r/66qB/8KBXf/Fg1//0Y5s78+Pbqn///8B////Af///wH///8B////AeGlg//trIX/7ayE/+6thP/urIX/9bWL/8eFYf/GhF//yYZh/9SPa/nkn3j/////Af///wH///8B////Af///wHkn3j/76+G/+6uh//vrob/76+G//W3jP/GhF//y4di/9ONZ//XkWr/5J94/////wH///8B////Af///wH///8B5J94/++wif/wsIj/8LGJ//CxiP/0toz/y4di/8+KZf/vroP/766D/+SfeP////8B////Af///wH///8B////AeSfeP/xs4v/8bOL//Cziv/ws4v/87WL/9CNa+3QjWvt3p96/96fev/en3r/////Af///wH///8B////Af///wHkn3j/8rWN//K2jf/ytY3/8rWN//O2jvfdo4Lj0I5sJdCObCXQjmwl0I5sJf///wH///8B////Af///wH///8B5J94//O3j//zuI//87iP//O4j//zuZDx3aOD7////wH///8B////Af///wHdo4M/5J94/+SfeP/kn3j/5J94/++2j//zupH/9LqR//O6kv/0upL/87qR/+SfeP/kn3j/5J94/+SfeP////8B////Af///wHkoXr/9cCY//W8k//0vJT/9L2T//S8lP/0vZT/9LyU//S8lP/1vJT/9cCY/+Shev////8B////Af///wH///8B9b+WC+SjfP/2yqP/9b+W//a/lf/2v5X/9b6V//W+lv/1vpX/9sqj/+SjfP////8B////Af///wH///8B////Af///wH2wZgX5aZ+//fTrP/2wJj/9sCY//bAmP/2wZj/99Os/+Smf/////8B////Af///wH///8B////Af///wH///8B////Af///wHkqYH/99ax//fCmv/3wpn/99aw/+Sogf////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AeWrhP/317L/99ey/+WrhP////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B5a2F/+Wthf////8B////Af///wH///8B////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w=="; var moveToMenu = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKElEQVR42o3TMUvDQBQH8P+7tLlEwaW4ugl+iU6CCA4i0tbdqavgZ/ErCE79DsVBkYpKLR2kuApOatG297zLJWkqXnIPwrsk937cveQIJXHZBZt8cgFyzaEqYGuTvl7feM2FVAIHR8Bj341UAu1T4PPdjXgBJgzyPKDFy4SDIkJZo1yRASZ+FDB5Itzfct7YBGjuBBBh6oT6ed2OazGjsV3wQ2Cu64bXUKM7FgZJgPaufinTSVFhrDPFheVIe01nwLgfq9HNVCRAaw8Q6USWS4B05mgVIH2/qG+ABh+46im7heP9EELOLRDZpVqAQev8ZwUS/DBLivMtlDWxc7Ycs6yBhyov9vqMGcBBDB5/rxT7/Qfntjn/FXsDrmIvoHUonMVegMllx/kXlvSRMQ0GPE4AAAAASUVORK5CYII="; var removeFromToolbar = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACMElEQVR42p3Sz2/SUBwA8G9pgQJd6QYZQQkOjUFdXMCLMn9B4l3myRgXhydPZgcTY2KyLfGiF/wT9GTmhfIXjMQ4NP5YD5qZTGdVdEx+9FVKSwttrTV4QD3AN3mH9837fr7v+/Kww1e4ic2HiSYMRGxufcHjxs87nQ5GN0zodnXQNLVomvCAL6ZR/xxmAS9VsX1umz1pJ/dfKGeD4+58OERNYQQO7Y4BWs8E3XCAqvRAEkWkdpTcNptm+4DpMVUOtboZl4tY2reXWmTGvbDTVKFnALicTrvYsFqbpgEOBw6tpgiigOb4Yoa1gTMzY1B+XUexKM1gLid8a3QgQHtBklQQBJm3RuAxDBiPl0z4aMq+eu1rFYmiFLOBowd8QJEEiLIBlbpV7PdArdZCApJX3j9O3e/Pe/Di0zTpJgvB8CSjSG1o7O7mbCA04QIHjoGsGuAfI6FRk0D8ISe3VlPc4OPGL61nab+/QDE0VD9/+T1CKOCCtqoDQRBAe0n4yH/nZUVLVtjTCP4R8cvPN8LRSKL6qVKygUjIC0rXAAMw6+EI6GkmoGaDM0DP8KuzfyHx+WfLe6KRpdpOlbMB+E9oWof78OhEcjB/5OqLbHAyUEB1oYTBCDFz7VWaYZg11BTYkYBj17lFyu3Lo5aYGwk4fuNNHgd8QVHk2EjA7K3NDVM3iuV708tDA2dXtqb0rr5mrWT57jQaGjh1+13eKio+uXOo9Gs/NJC6+TZhdf7zQ38Ceg0HgF1MCP0AAAAASUVORK5CYII="; var iconADD = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACDUlEQVR42nWT30sUURTHz91Zd9FkVBRrX0oScTMI8weSIYSU/QMFbb5oGAn+AQo9B/UH9BAF+lIr+OLrSETQQ4GhEVRrUFkP/SLRNcvUnXv8nrmz7XVcB86cy7nn+5kz556ryHrueKxIYcFkPMmbxXHgzA6NDyguatQewBzHkKMMQDnWPgDsIwYh8/hATP8HQCRJEFIc5iA1DpljZIGogJU/9WXp39DR1pj99QBwe45dZb6UhCXE2Hx6m4xtQZQ/8SDni+DdSNopVYtysUiFpVbDqp4vPL4uCWc6zt+H+wvbAOBrCBCRFgh0AtIA6BboBVADc6eeZLMCGOq/kkF8Hcs8AO8tgDwav5M0AI/bw87Xw9dml+bvSUamtfsGYmuIrQDwKgIoQirkF3pR9uCbz28vx+tTMWo6VRdsL79eLax80yePtc3MTlwYKwMIT8HTvYufFkc+bq4NOjWN9Kf6cIVsHNr4sePnf9LxytqH06Od1w6oICGA9uZGOnvEpb7tgkrefLl8UXZvdTV5CYe3vv9Wzy6dVnfL9KAKfkcALeihaSKT+yj3Imji1XRPBvFyTTSn4LHMi5Y5SCnrGFc3c5MCqKtMD5c5RnsOisfILlmD1NxA5yThwy96GhkkRtlxrP3oIO0d5ZKXfSSbUYaJ1/tGef9lovAyUeQyAaKCO4nLpPRBABWJlwCWt6vYBccZ9A793wmLAAAAAElFTkSuQmCC"; var customBtn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjVJREFUeNqcUkuIUmEUPl4fML6bBsFRacRF2EaCcRO48bFLEIJcBIJLxb2b2UWLkIEgQQjauVFaKmgYuclUTMUHKoaKE4GPxnxh5r3ezh0QHJFmmA/OPZfDfx7fdw7AfojQ7qGx4QawdgMymeyRyWR6IZVKucFg8N10Ov0Ot4VGozmNRCLx5XL5F/HHbrefYZh7m1yWWq0+TafTn2kEdqXr9TrtcDje3JR4xRHH1QYCgXOz2Wzs9/sQj8dBIpEATtGrVqu9yWSywmdLNGq3AAeNsFgsz202mxk7QzKZBK1WCzqdjtHjKUmSx41Go4L+slQqpYvF4keKoibXpnA6nWfY+VehUKBSqRTJ0Oh2u3Qul6MHgwE9Ho9pLMD4H16v95zD4RxuU6BbrdYlPh5g8tfFYvET9XiIiRylUsnQgPl8DtgVhsOheL1eS6LRaGy1Wg02FAA5VmKxWB1/yUQioWOxWHKXy2XEYsDQEggEgKJCJpOBcrnMbOliW4MNSOaDCbVKpVISCoVGHBnQQygUgnK1AkeH9z+Ew+HX2xoQezZDjUaj3ygDiMViaLfbV8kK+TGw2WysJzzafry3QK1W+9Lr9RpIDbLZLEhE4vedTsdvMBieuN3ulwRBPLh2B7uYzWYXzWZzjBoc5PP5MJ70K1xfEsVc4cpNeDcnuLFvzM3978gILpcrRy/w+XybGE+v1z/z+/2frFarG9d5AHeBSqUyeDyetwqF4jHcFXw+/4TH44n+CTAA3Ccog288LRAAAAAASUVORK5CYII="; var saveAll = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACOElEQVR42mNkwAJ+7xf7//3tKwZeIUELRqf3JxnwAEZkzrtlwnv/MzE6/WfkWCwS/iTu7RLO/wzMPAwc/z4Lc0f/eIfTgP/7BM0PXDY5ofB9N8M/EB8k+BcoyQw1mEWd4SurLIO97lkUFzX9b/oPNmBznc7/////MbAzfIdoBoI/P77Abfnzn4XhH9A0kOLA7icQV88HKn0EdcH6Ss3/yM76/f0jg2vTXYZ/f39j9fdUgQkMdTp1DNFXoiEGrCzFNMCj6SrD/79/MDQzsbAzCEfyMTBwADkbGBjBBiwrRDXgF9AAz6ZLWF1QIlHCsFRnKdj2pYxLIQYsytPAMMC75SLYBVMkpzDkPM+By0lFSTEwCDAwvJ79eouoqKgv2IB5WWgGfPvI4N95kUEyQQwcJVXbq8CGeEp6MlzUuQi2fcKbCQgDZqWhG/CJIaDrLIPMf0kGBjeggAoDw5YNWxh8rHwYGMQZGB5PfszAysq6RUJCAmLAtCR1DAMCu08zzJSZxtDm0cbA8AQoyAxJGyDbWx+2MrCwsGyRkZGBGDApDpsBx8FhME95HkObfhtYM4MqA8OdnjtgNSAXyMvLQwzoi8JmwGF4NGoc12Bg6IHYXnuzFm6AsrIyxIAJ+UHXfj27oomIhc9AA/ajpAOdPToMV1yuwPnMzMxbNDU14QaEAqnGH28fqYGywt/fP5i8q5czYUtIMABygY6ODsSAJUuWOKMrUFHT2PPvzy90YZhX/79//36dt7d3KACPfPJHOU7GxAAAAABJRU5ErkJggg=="; let cIDs = ["custombuttons-contextpopup-exportXML", "custombuttons-contextpopup-exportXML-sub"]; let bIDs = ["custombuttons-contextpopup-bookmarkButton", "custombuttons-contextpopup-bookmarkButton-sub"]; addMenuItem(cIDs, bIDs, "Сохранить код кнопки в XML файл", saveImg9, "document.getElementById('" + this.id + "').saveXML(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode.URI " + ": document.popupNode.URI);", "X"); let xIDs = ["custombuttons-contextpopup-importnewbutton", "custombuttons-contextpopup-importnewbutton-sub"]; let aIDs = ["custombuttons-contextpopup-addnewbutton", "custombuttons-contextpopup-addnewbutton-sub"]; addMenuItem(xIDs, aIDs, "Добавить кнопку из XML файла\u2026", loadImg, "document.getElementById('" + this.id + "').loadXML();"); let fIDs = ["custombuttons-contextpopup-copyImageURI", "custombuttons-contextpopup-copyImageURI-sub"]; let b2IDs = ["custombuttons-contextpopup-copyURI", "custombuttons-contextpopup-copyURI-sub"]; addMenuItem(fIDs, b2IDs, "Копировать изображение кнопки в формате base64", saveImg1, "document.getElementById('" + this.id + "').copyImageURI(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "6"); let f1IDs = ["custombuttons-contextpopup-saveButtonImage", "custombuttons-contextpopup-saveButtonImage-sub"]; addMenuItem(f1IDs, cIDs, "Сохранить изображение кнопки", saveImg8, "document.getElementById('" + this.id + "').saveImageURI(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "I"); let f2IDs = ["custombuttons-contextpopup-copyButtonsCodeText", "custombuttons-contextpopup-copyButtonsCodeText-sub"]; addMenuItem(f2IDs, b2IDs, "Копировать код кнопки как текст", saveImg2, "document.getElementById('" + this.id + "').copyButtonsCodeText(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "T"); let f3IDs = ["custombuttons-contextpopup-copyAsHTML", "custombuttons-contextpopup-copyAsHTML-sub"]; addMenuItem(f3IDs, b2IDs, "Копировать код кнопки как HTML ссылку", saveImg3, "document.getElementById('" + this.id + "').copyToHTMLCode(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "M"); let f4Ds = ["custombuttons-contextpopup-copyToBBCode", "custombuttons-contextpopup-copyToBBCode-sub"]; addMenuItem(f4Ds, b2IDs, "Копировать код кнопки как BBcode сылку", saveImg4, "document.getElementById('" + this.id + "').copyToBBCode(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "B"); let f5Ds = ["custombuttons-contextpopup-saveAsHTML", "custombuttons-contextpopup-saveAsHTML-sub"]; addMenuItem(f5Ds, bIDs, "Сохранить код кнопки в HTML файл", saveImg5, "document.getElementById('" + this.id + "').saveToHTMLCode(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "H"); let f8Ds = ["custombuttons-contextpopup-saveAsHTMLAll", "custombuttons-contextpopup-AsHTMLAll-sub"]; addMenuItem(f8Ds, f5Ds, "Сохранить все кнопки в HTML файл", saveAll, "document.getElementById('" + this.id + "').saveToHTMLALLCode()"); let f6Ds = ["custombuttons-contextpopup-getButtonId", "custombuttons-contextpopup-getButtonId-sub"]; let b1IDs = ["custombuttons-contextpopup-remove", "custombuttons-contextpopup-remove-sub"]; addMenuItem(f6Ds, b1IDs, "Показать Id кнопки", saveImg6, "document.getElementById('" + this.id + "').idMIonclick(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode " + ": document.popupNode);", "D"); let f7Ds = ["custombuttons-contextpopup-addNextButton", "custombuttons-contextpopup-addNextButton-sub"]; var addMI = document.getElementById('custombuttons-contextpopup-addnewbutton'); addMI.setAttribute('image', iconADD); var addMI1 = document.getElementById('custombuttons-contextpopup-addnewbutton-sub'); addMI1.setAttribute('image', iconADD); var addMI2 = document.getElementById('custombuttons-contextpopup-move-moveToPanel'); addMI2.setAttribute('image', moveToMenu); var addMI3 = document.getElementById('custombuttons-contextpopup-move-removeFromToolbar'); addMI3.setAttribute('image', removeFromToolbar); var addMI4 = document.getElementById('custombuttons-contextpopup-customize'); addMI4.setAttribute('image', customBtn); ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Общие функци //////////////////////////////// ///////////////////////////////////////////////////////////////////////////// var options1 = {year: "numeric"}; var options2 = {day: "numeric", month: "long"}; var cDate = new Date().toLocaleDateString("ru-RU", options1); var dDate = new Date().toLocaleDateString("ru-RU", options2); var aDate = cDate + "г" + " " + dDate; var options3 = {weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false}; var bDate = new Date().toLocaleDateString("ru-RU", options3); var saveToFile = function (fileContent, fileName) { var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); uc.charset = 'utf-8'; fileContent = uc.ConvertFromUnicode(fileContent); var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker); fp.init( !("inIsolatedMozBrowser" in window.browsingContext.originAttributes) ? window.browsingContext : window, '', fp.modeSave); fp.defaultString = fileName; fp.appendFilters(fp.filterHTML); fp.appendFilters(fp.filterAll); fp.open(function (rv) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream); stream.init(fp.file, 0x02|0x20|0x08, 0666, 0); stream.write(fileContent, fileContent.length); stream.close(); } }); }; ///////////////////////////////////////////////////////////////////////////// ////////////////////////////Остальные функци //////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Показать Id кнопки /////////////////////////////// this.idMIonclick = function idMIonclick(aStrI) { var btn = aStrI.id; var box = custombuttons.confirmBox("Копировать в буфер", btn, "Да", "Нет"); if (box) { custombuttons.cbService.writeToClipboard(btn); custombuttons.alertSlide(btn, "Скопирована в буфер"); } } function mostRecentWindow(windowType) { return Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow(windowType); } /////////////////////////////// Копировать изображение кнопки в формате base64 /////////////////////////////// this.copyImageURI = function copyImageURI(aStrA) { var btn = aStrA; if (!btn) return; cbu.gClipboard.write(btn.image); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Изображение кнопки скопировано в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как текст /////////////////////////////// this.copyButtonsCodeText = function copyButtonsCodeText(aStrT) { var btn = aStrT; if (!btn) return; var code = ((btn.cbCommand == "") || (btn.Command == "/*CODE*/")) ? "" : ("\n/*CODE*/\n" + btn.cbCommand + "\n"); var init = ((btn.cbInitCode == "") || (btn.cbInitCode == "/*Initialization Code*/")) ? "" : ("\n/*Initialization Code*/\n" + btn.cbInitCode); cbu.gClipboard.write(code + init); //custombuttons.alertSlide(btn.name, "Код скопирван в буфер"); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Код скопирван в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как HTML ссылку /////////////////////////////// this.copyToHTMLCode = function copyToHTMLCode(aStrM) { var btn = aStrM; if (!btn) return; var code = "<p><div id=\"install\" style=\"background: transparent -moz-linear-gradient(center top , rgb(224, 102, 255) 30%, rgb(125, 38, 205) 55%); text-shadow: 0pt -1px 0pt rgb(122, 55, 139); border: 1px outset rgb(85, 26, 139); border-radius: 1em; padding: 0; width: 240px; text-align: center;\"><a href=\"" + btn.URI + "\" style=\"display: block; padding: 1em; color: #ffffff; text-decoration: none;\" title=\"Click here to install " + btn.name + "\" rel=\"nofollow\"><img src=\"" + btn.image + "\" alt=\"" + btn.name + "\" style=\"vertical-align: middle; float: left;\"/>" + btn.name + "</a></div></p>"; cbu.gClipboard.write(code); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "HTML кнопки скопирован в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как BBcode сылку /////////////////////////////// this.copyToBBCode = function copyToBBCode(aStrBB) { var btn = aStrBB; if (!btn) return; var code = "[url=" + btn.URI + "][B]" + btn.name + "[/B][/url]"; cbu.gClipboard.write(code); //.toXMLString()); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "BBCode кнопки скопирован в буфер", false, "", null); } /////////////////////////////// Сохранить изображение кнопки /////////////////////////////// this.saveImageURI = function saveImageURI(aStrU) { var remove = gBrowser.removeCurrentTab.bind(gBrowser); var promiseTargetFile = async (...args) => { var res = await window.promiseTargetFile(...args); setTimeout(remove, 0); return res; } var internalSave = eval(`(${window.internalSave})`); var save = eval(`(${window.saveDocument})`); var saveBrowser = eval(`(${window.saveBrowser})`) var btn = aStrU; if (!btn) return; (saveButtonImage = btn => { if (btn.image != "") { var tab = gBrowser.selectedTab; gBrowser.selectedTab = gBrowser.addTab(btn.image, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() }); setTimeout(function() { if (!!window.saveBrowser) { saveBrowser(gBrowser.selectedBrowser, true); } else { window.content.document.title = btn.name; save(window.content.document); } }, 2000); } else custombuttons.alertBox("Эта кнопка не имееет изображения!"); })(btn); } /////////////////////////////// Сохранить кнопку в XML файл /////////////////////////////// this.saveXML = function saveXML(aStrURI) { var cbURI = (aStrURI != undefined) ? aStrURI : readFromClipboard(); if (!cbURI || !/^custombutton\:\/\//.test(cbURI)) { custombuttons.uChelpButton(this); return; } var topicURL = "http://forum.mozilla-russia.org/viewforum.php?id=34" var cbXML = cbURI.replace(/^custombutton\:\/\//, ""); var decodeXML = unescape(cbXML); var btnName = decodeXML.match(/\<name\/?.+/).toString(); var name = "untitled"; if (!/\<name\/\>/.test(btnName)) { name = btnName.replace(/\<\/?\w+\>/g, "").toString(); } var image = decodeXML.match(/\<image\/?.+/).toString(); var icon = ""; if (!/\<\image.*\[\].*\>$/.test(image)) { icon = image.match(/[^\[\]]+/g)[2].toString() .replace(/custombuttons\-stdicon\-\d/, "").toString(); } function htmlEntities(str) { return str.replace(/&/g, "&").replace(/</g, "<") .replace(/>/g, ">").replace(/"/g, """); } var xmlTemplate = "custombuttons/\"\n\ xmlns:html=\"http://www.w3.org/1999/xhtml\">\n\ <html:head>\n\ <html:title><![CDATA[" + name + "]]></html:title>\n\ <html:link rel=\"shortcut icon\" href=\"" + icon + "\"/>\n\ <html:style type=\"text/css\"><![CDATA[\n\ body { font-size: medium; margin: 0; }\n\ body, code:before, help:before, initcode:before {\n\ font-family: \"Verdana\", sans-serif;\n\ }\n\ #wrapper { position: fixed; top: 1em; right: 1em; text-align: center; }\n\ p { font-size: small; text-align: center; }\n\ #button {\n\ background-color: rgb(85, 168, 2);\n\ background-image: linear-gradient(to bottom, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -moz-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -o-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -webkit-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ border: 1px solid rgb(58, 116, 4);\n\ border-radius: .5em;\n\ -moz-border-radius: .5em;\n\ -webkit-border-radius: .5em;\n\ padding: 0;\n\ margin-bottom: 1em;\n\ box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -moz-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ }\n\ #button a {\n\ color: #000;\n\ text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5);\n\ padding: 1em;\n\ text-decoration: none;\n\ }\n\ :-moz-any-link:focus {\n\ color: white;\n\ outline-color: transparent;\n\ text-decoration: none;\n\ }\n\ #button a, code, code:before, initcode, initcode:before, help, help:before {\ \n display: block;\n\ }\n\ #credits { position: fixed; bottom: 1em; right: 1em; font-size: small; }\n\ custombutton { background-color: rgb(171, 171, 171); margin: 1em; }\n\ date, image, mode, accelkey { display: none; }\n\ name { font-weight: bold; font-size: x-large; }\n\ code:before, help:before, initcode:before {\n\ font-weight: bold;\n\ font-size: large;\n\ margin: 0 0 1em;\n\ padding: .5em;\n\ }\n\ code:before { content: \"Код\"; }\n\ help:before { content: \"Справка\"; }\n\ initcode:before { content: \"Инициализация\"; }\n\ code, initcode, help {\n\ background-color: rgb(255, 255, 255);\n\ border: 1px inset rgb(170, 170, 170);\n\ font: medium monospace;\n\ margin: 1em 1em 2em 0;\n\ padding: 1em;\n\ text-align: left;\n\ width: 840px;\n\ white-space: pre-wrap;\n\ word-wrap: break-word;\n\ }\n\ .clear { clear: both; }\n\ ]]></html:style>\n\ </html:head>\n\ <html:body>\n\ <html:div id=\"wrapper\">\n\ <html:div id=\"button\">\n\ <html:a href=\"" + cbURI + "\" rel=\"nofollow\" title=\"Установить " + htmlEntities(name, "ENT_COMPAT") +"\">\n\ <![CDATA[Установить кнопку]]>\n\ </html:a>\n\ </html:div>\n\ <html:div id=\"credits\">\n\ <html:a href=\"" + topicURL +"\">\n\ <![CDATA[Другие кнопки]]><html:br/>\ <![CDATA[на форуме Mozilla Россия]]>\n\ </html:a>\n\ </html:div>\n\ </html:div>\n\ </html:body>"; decodeXML = decodeXML.replace(/custombuttons\/\"\>/, xmlTemplate); name += ".xml"; saveToFile(decodeXML, name); var btn = document.popupNode; var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в XML файл", false, "", null); } var mrw = mostRecentWindow('navigator:browser'); var css = '@-moz-document url("chrome://browser/content/browser.xul"){' + this.Help + '}'; var uri = makeURI('data:text/css,' + encodeURIComponent(css)); var sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) sss.loadAndRegisterSheet(uri, sss.USER_SHEET); /////////////////////////////// Добавить кнопку из XML файл /////////////////////////////// this.loadXML = function loadXML() { var nsIFilePicker = Ci.nsIFilePicker; var fp = window.makeFilePicker(); fp.init( !("inIsolatedMozBrowser" in window.browsingContext.originAttributes) ? window.browsingContext : window, "Установить кнопку из XML файла", nsIFilePicker.modeOpen); fp.appendFilters(fp.filterXML); fp.appendFilter("Все файлы", "*.*"); fp.open(re=> { if ( re == fp.returnOK ) gBrowser.selectedTab = gBrowser.addTrustedTab(fp.file.path); }) } /////////////////////////////// Сохранить все кнопки в HTML файл /////////////////////////////// this.saveToHTMLALLCode = function saveToHTMLALLCode() { var visibleCBbuttons = [...document.querySelectorAll('[cb-mode]')]; var paletteCBbuttons = [...custombuttons.palette.querySelectorAll('[cb-mode]')]; var allCBbuttons = visibleCBbuttons.concat(paletteCBbuttons); var gn = btn => btn.getAttribute("label") || "Без названия"; allCBbuttons.sort((a, b) => gn(a).localeCompare(gn(b))); var array = []; allCBbuttons.forEach(but=> { var uri = but.URI ? but.URI : getPaleteButtonsURI(but); var name1 = but.getAttribute("label") || "Без названия"; var image = but.getAttribute("image") || "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACNFBMVEXDRgDweQDnbwC0NgDCRQC7PQDtpTu+QQD78q3PUwDCRAD//8vbYQDLTgDocAD0iQX1jQbGSgD7iAD4gwDVaw7vdwDyegD+igDweQDlawDyhAXveADmZwDzmBbtcwDwkhHveADmhBTkgxbweADkfRH+igD7hADXZQX0gADyjA/tfgvveQDiawDQVADRXgfnbwD1jAb9iQD9z0PVZAbxpinykRHtdgD5mRbERQDDRgDOYArCRAD9iQD3ewDxegD3dwDFRgDAQAD+hgD4fQDucgDtgQftfwTISQDCRQDvdgD5lxb1kRb2qh7wnynkagD766LDRQDDRwDDRQDspjbtpzbuqDbvqzv//8DUZAbCRQD//83pjhvveQbvggW+QQDfcxLlmUb//8veYADMTwDHSADVVwC8PgDwixb78q3oZgDUWADRVADCRQD9iQDERwDBQQDYVQC+PgC0NgDbYQDWWgDUWADSVQDFSAC+QAC7PAC0NgD+wRL+/kD+/zb+7i3+8Cv+/DX+wBL/+DD/rwz+qgz+rwz/tAz+sQzfbAT+3iP/+jD//Dz1jwP+nwf5iwf7pBz2tRr4lwb/ogfsdQT+2R7/9ET+2iT8yyLmgBL5iQL2egLokhP7zzT60zv1zUr0gAL1ewP50yn9+UL++EXooyngaAH41EPzowzyySj+xxzlhhHvvyruwjXxvTnUag3+zxrwigP+swz86U/ZXwD75lHqegD6xzb//kn+uhPTXAG3OAD/+UC2vFeJAAAAe3RSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAACfnwAIaelpAAA2+wD7UQAAa3oArKzRzMysnwgAvPQA/gAAw3prw0oALr16vS4AACnF6bspAAAA/mIAADQAAAAAAI8AAEwA0vv7kd2yAuuvr+vKABL23U+8Sk/d9vUDIIAQAAAQgCAfvupHAAABB0lEQVR4Xi3IU3fDABgA0C+u26FdZ9u2bdu2vZSzbds2/tyac3IfLxjpGyA6MimqY6gHTNgiiNwkwRM1E7EhTrYyTfMzzsh0ZEPiH+D6+u5mV1jEhpe5haVCYW1T4suEvUOkk7PLpVJ5WFnl7hEUDN5LPvsHJ6cazdn13f3DYxu0B35+/Y2qVSr17NzGeUgohIVHLK/PMDa39qKieRATGxd/9cS4uU1MwnmQktqY/qGlaVr7/ZOVDTmQm5df8PwyNj4xOTVdjOM4kCRZOr+wWFa+srpWQVEU8PnV2zu7NbV19UfHDQRBAIfTdNHc0soVdnR2dfdgGAgEvW99/QNc4eDQ8O8Ihv0D77NPgbVLZ6kAAAAASUVORK5CYII="; array.push("<li>\n<img src=" + image + "> \<a href=" + uri + ">" + name1 +"</a><br>\n"); }); var before = "<html>\n<head>\n<title>Custom Buttons</title>\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n"; var before1 = "<style type='text/css'>\nbody {background: beige;} a:link {color: black; text-decoration: none;} img {border: 0; margin: 0px 10px;}\n</style>\n"; var before2 = "</head>\n<body>\nCustom Buttons\n<p>\n"; var info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); var before3 = info.vendor + " " + info.name + " " + info.version + " (build " + info.appBuildID + ")\n"; var after = "\n</ol>\n</body>\n</html>"; var text = before + before1 + before2 + before3 + "<p>\n" + bDate + "<p>\n" + "<ol>" + array.join("") + after; var name = "CB buttons " + aDate + ".html" saveToFile(text, name); var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) alertsService.showAlertNotification(saveImg5, "Экспорт в HTML", "Экспортировал все CB кнопки как HTML"); setTimeout(()=> alertsService.closeAlert(), 4000); }; function getPaleteButtonsURI(but) { var uri = "chrome://custombuttons/content/nbftemplate.xml"; var stream = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true}).open(); var doc = new DOMParser().parseFromStream(stream, null, stream.available(), "application/xml"); stream.close(); ["help,Help", "name,label", "image,image", "mode,cb-mode", "initcode,cb-init", "accelkey,cb-accelkey", "code,cb-oncommand"] .forEach(str=> { var arr = str.split(','); var value = but.getAttribute(arr[1]), name = arr[0]; custombutton.buttonSetText(doc, name, value, true); }); var ser = new XMLSerializer(); return "custombutton://" + escape(ser.serializeToString(doc)); }; /////////////////////////////// Сохранить кнопку в HTML файл /////////////////////////////// this.saveToHTMLCode = function saveToHTMLCode(aStrH) { var btn = aStrH; var xml = '<html xmlns="' + xhtmlns + '">\n'; xml += '<head>\n'; xml += '<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8"/>\n'; xml += '<title> ' + btn.name + ' для Custom Buttons </title>\n'; xml += '<link rel="icon" type="image/vnd.microsoft.icon" href = "'+ btn.image +'" />\n'; xml += '<style type="text/css">\n'; xml += '.button a{ \n'; xml += 'background-color: rgb(85, 168, 2); \n'; xml += 'background-image: linear-gradient(to bottom, rgb(147, 200, 94), rgb(85, 168, 2)); \n'; xml += 'background-image: -moz-linear-gradient(top, rgb(147, 200, 94), rgb(85, 168, 2)); \n'; xml += 'border: 1px solid rgb(58, 116, 4); \n'; xml += 'border-radius: .5em; \n'; xml += ' -webkit-border-radius: .5em; \n'; xml += 'padding: 0; \n'; xml += 'margin-bottom: 1em; \n'; xml += 'box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' color: #000; \n'; xml += ' text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5); \n'; xml += ' padding: 0.5em; \n'; xml += ' text-decoration: none; \n'; xml += '} '; xml += 'pre { border: 1px inset rgb(170, 170, 170); \n'; xml += 'background-color: rgb(255, 255, 255);} \n'; xml += 'body { background-color: rgb(245, 245, 220);} \n'; xml += '</style> \n'; xml += '</head>\n'; xml += '<body>\n'; xml += '<section id="install"><h1> ' + btn.name + ' </h1> \n'; xml += '</section>\n'; xml += '<div class="button"><a href = "' + btn.URI + '">Установить кнопку</a></div> \n'; xml += '<section id="init"><h2>Инициализация</h2><pre>' + e4xConv_encodeHTML(btn.cbInitCode) + '</pre></section>\n'; xml += '<section id="code"><h2>Код</h2><pre>' + e4xConv_encodeHTML(btn.cbCommand) + '</pre></section> \n'; xml += '<section id="help"><h2>Справка</h2><pre>' + e4xConv_encodeHTML(btn.Help) + '</pre></section> \n'; xml += '</body> \n'; xml += '</html> '; var html = '<!DOCTYPE html>\n' + xml; var name = btn.name + ".HTML"; saveToFile(html, name); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в HTML файл", false, "", null); } function e4xConv_encodeHTML(s, isAttr) { s = String(s) .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """); if(isAttr) { s = s .replace(/\t/g, "	") .replace(/\n/g, "
") .replace(/\r/g, "
"); } return s; }; /////////////////////////////// Переместить кнопку /////////////////////////////// this.MoveToolbarButtons = MTB = { // Start editable preferences MoveButtonMICBContext: true, // Add "Move button" menu item to Custom Buttons context menu? MoveButtonMITBarContext: false, // Add "Move button" menu item to toolbars context menu? ShowMoveAlert: false, // Show the alert with instructions when moving buttons? MoveBtnImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAYklEQVQ4jWNgGJTgaAXHf2LEcGrGZQBBQ45WcPz/fZ0XpwG45FAUEDIAqzyyJLIiZIxNHqdmYvHRCo7/DLhsIEYziivQDcHnBawxgqyQUCzgjQlC6YCotEB2QkJWTIzY4AAAezv/caeCLKcAAAAASUVORK5CYII=", // End editable preferences _UID: "__cb_move_toolbar_buttons_" + custombuttons.getNumber(self.id), WindowIDs: ["main-window", "messengerWindow", "msgcomposeWindow"], ToolbarContexIDs: ["toolbar-context-menu", "aios-toolbar-contextmenu", "aios-sbhtoolbar-contextmenu"], Pref: "extensions.custombuttons.MoveToolbarButtons.Id" + custombuttons.getNumber(self.id) + ".MoveButtonID", SP: Services.prefs, Init: function() { if (!(MTB._UID in window)) { window[MTB._UID] = { Initialized: false }; } if (!window[MTB._UID]["Initialized"]) { window[MTB._UID]["Initialized"] = true; custombuttons.isPref(MTB.Pref, ""); if ("CustomizableUI" in window) { var originalFunction = custombuttons.persistCurrentSets.toString(); eval("custombuttons.persistCurrentSets=" + originalFunction .replace(", newButtonId)", ", newButtonId, aToRight)") .replace("pos + 1", "aToRight ? pos : pos + 1")); } if (MTB.MoveButtonMICBContext) { var contextPops = document.getElementsByTagName("menupopup"); let p = 0, pLen = contextPops.length; for (; p < pLen; p++) { var cPopID = contextPops[p].id; if (cPopID.substr(0, 26) === "custombuttons-contextpopup") { var cPopEl = document.getElementById(cPopID); var moveMIID = "custombuttons-contextpopup-moveButton" + cPopID.slice(26); var moveMIEl = document.getElementById(moveMIID); if (!moveMIEl) MTB.CreateMoveMI(moveMIID, cPopEl); } } } if (MTB.MoveButtonMITBarContext) { Array.prototype.slice.call(MTB.ToolbarContexIDs).forEach(function(aTBCtxID, aIndex) { let Ctx = document.getElementById(aTBCtxID); let tBarCtxMIID = MTB._UID + "moveButton" + aIndex; if (!document.getElementById(tBarCtxMIID)) { if (Ctx) { MTB.CreateMoveMI(tBarCtxMIID, Ctx); Ctx.addEventListener("popupshowing", function(aE) { document.getElementById(tBarCtxMIID).hidden = (document.popupNode.tagName !== "toolbarbutton"); }, false); } } }); } addDestructor(function(aReason) { if (aReason === "delete") { SP.resetUserPrefs(MTB.Pref); delete window[_UID]; } if (aReason === "delete" || aReason === "update") { window[MTB._UID]["Initialized"] = false; } }); } }, getPopupNode: function(aEl) { if (custombuttons.popupNode) return custombuttons.popupNode; var popupNode = aEl; while (popupNode.tagName.toLowerCase() !== "toolbarbutton") { popupNode = popupNode.parentNode; } return popupNode; }, CreateMoveMI: function(aMItemID, aPopupEl) { let moveMIEl = aPopupEl.appendChild(document.createElementNS(xulns, "menuitem")); moveMIEl.setAttribute("id", aMItemID); moveMIEl.setAttribute("label", "Переместить кнопку..."); moveMIEl.setAttribute("class", "menuitem-iconic"); moveMIEl.setAttribute("image", MTB.MoveBtnImage); moveMIEl.setAttribute("tooltip", MTB._UID + "moveButtonMI_tooltip"); moveMIEl.setAttribute("onclick", "document.getElementById(\"" + self.id + "\").MoveToolbarButtons.MoveOnClick(event);"); }, MoveOnClick: function(aE) { var popupNode = MTB.getPopupNode(aE.target); if (!popupNode) return; aE.stopPropagation(); aE.preventDefault(); if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) { MTB.SP.setCharPref(MTB.Pref, popupNode.id); window.addEventListener('click', MTB.MoveListener, true); window.addEventListener('mouseup', MTB.DefaultPrevention, true); window.addEventListener('mousedown', MTB.DefaultPrevention, true); window.addEventListener('contextmenu', MTB.DefaultPrevention, true); MTB.HidePopup(aE.target); MTB.ShowMoveAlert && Services.prompt.alert(null, self.name, "Now click ANY toolbarbutton element inside ANY toolbar.\n" + "Left click will position the button to the left of the target.\n" + "Right click will position the button to the right of the target.\n\n" + "To cancel the movement, just click ANY element inside the browser that IS NOT a toolbarbutton.\n"); } }, MoveListener: function(aE) { MTB.DefaultPrevention(aE); window.removeEventListener('click', MTB.MoveListener, true); window.removeEventListener('mouseup', MTB.DefaultPrevention, true); window.removeEventListener('mousedown', MTB.DefaultPrevention, true); window.removeEventListener('contextmenu', MTB.DefaultPrevention, true); var anchor = aE.target; if (anchor.tagName !== "toolbarbutton") return; var toolbar = anchor.parentNode; var BtnToMove = document.getElementById(MTB.SP.getCharPref(MTB.Pref)); if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) toolbar.insertBefore(BtnToMove, anchor); else if (aE.button === 2 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) toolbar.insertBefore(BtnToMove, anchor.nextSibling); if ("CustomizableUI" in window) custombuttons.persistCurrentSets(toolbar.id, anchor.id, BtnToMove.id || BtnToMove.getAttribute("id"), !(aE.button === 2)); else { toolbar.setAttribute("currentset", toolbar.currentSet); document.persist(toolbar.id, "currentset"); } MTB.SP.setCharPref(MTB.Pref, ""); }, DefaultPrevention: function(aE) { aE.preventDefault(); aE.stopImmediatePropagation && aE.stopImmediatePropagation(); aE.stopPropagation(); }, Tooltips: function(aRem) { var popSetID = MTB._UID + "popupset"; var popSetEl = document.getElementById(popSetID); if (popSetEl) popSetEl.parentNode.removeChild(popSetEl); if (aRem) return; if (!popSetEl) { popSetEl = document.createElementNS(xulns, "popupset"); popSetEl.setAttribute("id", popSetID); } popSetEl.appendChild(MTB.parseXML("<tooltip xmlns=\"" + xulns + "\" xmlns:html=\"" + xhtmlns + "\" id=\"" + MTB._UID + "moveButtonMI_tooltip" + "\">" + "<description><html:b>Instructions</html:b> : After clicking this menu item, you can " + "click ANY toolbarbutton element inside the application to place the currently " + "selected button to the left (with Left click) or to the right (with Right click) " + "of the targeted toolbarbutton.</description>" + "<separator/>" + "<description><html:b>Note</html:b> : It can be ANY toolbarbutton, not just " + "other Custom Buttons.</description>" + "</tooltip>")); setTimeout(function() { Array.prototype.slice.call(MTB.WindowIDs).forEach(function(aWinID) { let win = document.getElementById(aWinID); if (win) !document.getElementById(popSetID) && win.appendChild(popSetEl); }); }, 100); }, parseXML: function(aXML) { // Return parsed XML aXML = aXML.replace(/>\s+</g, "><"); // Linearize XML return (new DOMParser).parseFromString(aXML, "application/xml").documentElement; }, HidePopup: function(aEl) { try { aEl.hidePopup(); } catch (aError) { try { aEl.parentNode.hidePopup(); } catch (aError) { try { aEl.parentNode.parentNode.hidePopup(); } catch (aError) { try { aEl.parentNode.parentNode.parentNode.hidePopup(); } catch (aError) {} } } } } }; this.MoveToolbarButtons.Init();
3. Autocopy
/*Initialization Code*/ (ps => { var s = "ucf.autocopy.enabled"; this._handleClick = () => cbu.setPrefs(s, cbu.getPrefs(s) == true ? false: true); var toggleImage = val => { self.image = cbu.getPrefs(s) ? 'data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgMBAAQIAAcEBwAIBAcACAQHAAgEBwAIBAcACAQHAAgEBwAIBAcACAMEAQEAAAAAAAAAAAAAAAACAwADAAAAABUnAB9cqgC3a7wB4Gq5Ad1qugHearoB3mq6Ad5qugHearoB3mi4AN1qugHgYrMAxR43AC8AAAAAAAEAAAECAAQAAAQAV6AAprP9Vv/W/qn80/+f/9T/ov/U/6L/1P+i/9T/ov/U/6L/1/+n/9X+pfy3/WL/Y7QAvwEAAQAAAAAAFSgAH1ehAKlyzwD1htgf/YzcJ/2K2yP9i9sk/YvbJf2L2yX9i9sm/YnaIv2b4kP92/21/Nf+qv9quwHdBQkACAAAAQBeqwCzr/tR/8X0j/u+8X//vvJ//77ygP++8oD/vvKA/77yf/+98n7/wvSH/4zcKv+e4kv93v+0/2i5AN0DBwAIBQkACGu8AdzV/af/4v/B/d//u//h/7//4f+//+H/v//h/7//4f+//9/+u//n/8n/w/GK/4zaK/3g/7r/aroC3gMHAAgEBwAIarkC3dX/pf/g/sD93v67/9/+vv/g/r//4P6//+D+v//f/r7/3f66/+T/xv/B8Yb/j9st/eT/w/9qugPeAwcACAQHAAhqugLe2v+w/+j/z/3l/8r/5//N/+f/zv/n/87/5//O/+f/zf/l/sj/7P/W/8Xyj/+Q2y/96f/N/2q6A94DBwAIBAcACGq6At7f/7n/7v/c/ev/1v/t/9n/7f/a/+3/2v/t/9r/7f/Z/+r+1f/y/+P/yPKW/5DbMf3s/9X/aroE3gMHAAgEBwAIaroC3uP/wf/z/+j98P/h//L/5P/z/+X/8//l//P/5f/y/+T/8P7g//j/7v/L8p3/kdsy/fD/3P9rugTeAwcACAQHAAhqugLe5v/J//j/8v31/+r/9v/t//f/7v/3/+//9//u//b/7f/0/un//f/4/87yo/+R2zL98f/f/2q5Bd0DBwAIBAcACGq6At7p/8///P/6/fj/8f/6//T/+v/1//r/9f/6//X/+v/0//f+8P//////0fGo/5PbNf30/+f/a7wE3AQJAAgEBwAIabkC3er/0f/+//79+v/0//v/9//8//j//P/4//z/+P/7//f/+f70///////T8qz/i9go+8P9ef9dqwCzAAACAAUJAAhquwHd7f7a//////z+//39/////f////3////9/////f////39/vz9/////dzzvv5v0AD1VqECqRUnAB8AAAAAAQACAGK0AL/J/Yf/8v7k/O3/1//u/9n/7v/Z/+7/2f/u/9n/7v/Z/+3/1//x/eP8vfxu/1WgAKYAAAUAAQIABAABAAAAAAAAHjcALmGzAMVquwLgarkC3Wq6At5qugLearoC3mq6At5qugLearkC3Wu8AeBbqgC3FScAHwAAAAACAwADAAAAAAAAAAAAAAAAAwQCAQQIAAgEBwAIBAcACAQHAAgEBwAIBAcACAQHAAgEBwAIBAgABwMDAgAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' : 'data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEDAAQACAcEAAcIBAAHCAQABwgEAAcIBAAHCAQABwgEAAcIBAAHCAMBBAEAAAAAAAAAAAAAAAACAAMDAAAAABUAJx9cAKq3awG84GoBud1qAbreagG63moBut5qAbreagG63mgAuN1qAbrgYgCzxR4ANy8AAAAAAAABAAEAAgQABAAAVwCgprNW/f/Wqf7805///9Si///Uov//1KL//9Si///Uov//16f//9Wl/vy3Yv3/YwC0vwEBAAAAAAAAFQAoH1cAoalyAM/1hh/Y/Ywn3P2KI9v9iyTb/Ysl2/2LJdv9iybb/Yki2v2bQ+L927X9/Neq/v9qAbvdBQAJCAABAABeAKuzr1H7/8WP9Pu+f/H/vn/y/76A8v++gPL/voDy/75/8v+9fvL/wof0/4wq3P+eS+L93rT//2gAud0DAAcIBQAJCGsBvNzVp/3/4sH//d+7///hv///4b///+G////hv///4b///9+7/v/nyf//w4rx/4wr2v3guv//agK63gMABwgEAAcIagK53dWl///gwP793rv+/9++/v/gv/7/4L/+/+C//v/fvv7/3br+/+TG///BhvH/jy3b/eTD//9qA7reAwAHCAQABwhqArre2rD//+jP//3lyv//583//+fO///nzv//587//+fN///lyP7/7Nb//8WP8v+QL9v96c3//2oDut4DAAcIBAAHCGoCut7fuf//7tz//evW///t2f//7dr//+3a///t2v//7dn//+rV/v/y4///yJby/5Ax2/3s1f//agS63gMABwgEAAcIagK63uPB///z6P/98OH///Lk///z5f//8+X///Pl///y5P//8OD+//ju///LnfL/kTLb/fDc//9rBLreAwAHCAQABwhqArre5sn///jy//316v//9u3///fu///37///9+7///bt///06f7//fj//86j8v+RMtv98d///2oFud0DAAcIBAAHCGoCut7pz////Pr//fjx///69P//+vX///r1///69f//+vT///fw/v//////0ajx/5M12/305///awS83AQACQgEAAcIaQK53erR///+/v/9+vT///v3///8+P///Pj///z4///79///+fT+///////TrPL/iyjY+8N5/f9dAKuzAAIAAAUACQhqAbvd7dr+//////z+/f/9/////f////3////9/////f////39/P79/////dy+8/5vAND1VgKhqRUAJx8AAAAAAQIAAGIAtL/Jh/3/8uT+/O3X///u2f//7tn//+7Z///u2f//7tn//+3X///x4/38vW78/1UAoKYABQAAAQACBAAAAQAAAAAAHgA3LmEAs8VqArvgagK53WoCut5qArreagK63moCut5qArreagK53WsBvOBbAKq3FQAnHwAAAAACAAMDAAAAAAAAAAAAAAAAAwIEAQQACAgEAAcIBAAHCAQABwgEAAcIBAAHCAQABwgEAAcIBAAIBwMCAwAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='; this.tooltipText = cbu.getPrefs(s) ? 'Autocopy' : 'Stop Autocopy'; } toggleImage(); ps.addObserver(s, toggleImage, false); addDestructor(() => ps.removeObserver(s, toggleImage)); })(Services.prefs); this.oncontextmenu =e=> { e.button && !e.ctrlKey && e.preventDefault() };
Будет время, посмотри пожалуйста.
Отсутствует
1. Экспорт в HTML файл в контекстном меню закладок
/* menuitem.setAttribute("oncommand", "exportFolder();"); menuitem.exportFolder = this.pick.bind(this); */ addEventListener("command", () => this.pick(), false, menuitem);
/* new this.nsvo.BookmarkExporter(bookmarks).exportToFile(path); }, get nsvo() { delete this.nsvo; return this.nsvo = Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm", {}); */ new this.exporter(bookmarks).exportToFile(path); }, get exporter() { var m = ChromeUtils.importESModule("resource://gre/modules/BookmarkHTMLUtils.sys.mjs"); delete this.exporter; return this.exporter = cbu.dbg.ref("BookmarkExporter", m.BookmarkHTMLUtils.exportToFile);
2.Дополнительные пункты в контекстном меню кнопки
Жуть какая.
Желание в этом копаться пропадает с первого же взгляда.
Возможно, хватит таких формальных правок, ну или нет.
/* function addMenuItem(aNewIDs, aNodeIDs, aLabel, aIcon, aCommand) { for (var i = 0; i < aNewIDs.length; i++) { if ($(aNewIDs[i])) $(aNewIDs[i]).parentNode.removeChild($(aNewIDs[i])); var mi = document.createXULElement("menuitem"); mi.setAttribute("id", aNewIDs[i]); mi.setAttribute("class", "menuitem-iconic"); mi.setAttribute("image", aIcon); mi.setAttribute("label", aLabel); mi.setAttribute("oncommand", aCommand); if (i == 0) mi.setAttribute("observes", "custombuttons-contextbroadcaster-primary"); if ($(aNodeIDs[i])) { if ($(aNodeIDs[i]).nextSibling) { $(aNodeIDs[i]).parentNode.insertBefore(mi, $(aNodeIDs[i]).nextSibling); } else { $(aNodeIDs[i]).parentNode.appendChild(mi); } } } }; */ var re = /\)\.(.+?)\(/; var listener = e => self[e.target.linkedMehtod](custombuttons.popupNode); function addMenuItem(ids, nodeIds, label, image, code) { var num = 0; for(var id of ids) { $(id)?.remove(); var menuitem = document.createXULElement("menuitem"); menuitem.id = id; menuitem.className = "menuitem-iconic"; menuitem.setAttribute("image", image); menuitem.setAttribute("label", label); menuitem.linkedMehtod = code.match(re)[1]; addEventListener("command", listener, false, menuitem); num || menuitem.setAttribute("observes", "custombuttons-contextbroadcaster-primary"); var node = $(nodeIds[num++]); node?.parentNode.insertBefore(menuitem, node.nextSibling); } }
/* moveMIEl.setAttribute("onclick", "document.getElementById(\"" + self.id + "\").MoveToolbarButtons.MoveOnClick(event);"); */ moveMIEl.onclick = e => this.MoveOnClick(e);
3. Autocopy
Здесь не вижу никакого отвала.
Кнопка всего лишь (и успешно) переключает настройку
ucf.autocopy.enabled
Отсутствует
Dumby
Большое спасибо!
И еще. Не знаю, как сразу не заметил
Toggle Restartless Add-ons
// http://infocatcher.ucoz.net/js/cb/toggleRestartlessAddons.js // https://forum.mozilla-russia.org/viewtopic.php?id=57948 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Toggle_Restartless_Add-ons // Toggle Restartless Add-ons button for Custom Buttons // (code for "initialization" section) // Also the code can be used from main window context (as Mouse Gestures code, for example) // Also you can check for add-ons updates using right-click: // copy all code from // https://github.com/Infocatcher/Custom_Buttons/blob/master/Check_for_Addons_Updates/checkForAddonsUpdates.js // after "//== Check for Addons Updates begin" // See "var style = " to modify styles for specific add-ons // (c) Infocatcher 2013-2019 // version 0.1.3pre4 - 2020-01-01 var options = { addonTypes: ["extension", "plugin"], // Possible values: "extension", "plugin" // From extensions: "userstyle" (Stylish), "greasemonkey-user-script" (Greasemonkey), "userscript" (Scriptish) // (swap to reorder in the menu) showVersions: 1, // 0 - don't show versions // 1 - show after name: "Addon Name 1.2" // 2 - show as "acceltext" (in place for hotkey text) showHidden: 0, // 0 - don't show hidden add-ons // -1 - show only enabled hidden add-ons (e.g. to track new items) // 1 - show all hidden add-ons sort: { enabled: 0, clickToPlay: 0, disabled: 1 // Sort order: // 0, 0, 0 - sort add-ons of each type alphabetically // 0, 0, 1 - show enabled add-ons (of each type) first // 0, 1, 2 - enabled add-ons, then click-to-play and then disabled }, closeMenu: false, // Close menu after left-click closeMenuClickToPlay: false // Close menu after left-click, for click to play plugins // Use Shift+click to invert closeMenu* behavior }; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var mp = document.createElementNS(xulns, "menupopup"); mp.setAttribute("onpopupshowing", "this.updateMenu();"); mp.setAttribute("oncommand", "if(!event.button) this.handleEvent(event);"); // Ignore middle-click in Firefox 89+ mp.setAttribute("onmousedown", "if(event.button == 0) this.handleEvent(event);"); mp.setAttribute("onclick", "if(event.button > 0) this.handleEvent(event);"); mp.setAttribute("oncontextmenu", "return false;"); mp.setAttribute("onpopuphidden", "this.destroyMenu();"); var tb = this.parentNode; if(tb && tb.getAttribute("orient") == "vertical") { // https://addons.mozilla.org/firefox/addon/vertical-toolbar/ var isRight = tb.parentNode.getAttribute("placement") == "right"; mp.setAttribute("position", isRight ? "start_before" : "end_before"); } var cleanupTimer = 0; mp.updateMenu = function() { clearTimeout(cleanupTimer); addStyle(); getRestartlessAddons(options.addonTypes, function(addons) { var df = document.createDocumentFragment(); var prevType; function sortPosition(addon) { if("STATE_ASK_TO_ACTIVATE" in AddonManager && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) return options.sort.clickToPlay; if(addon.isActive) return options.sort.enabled; return options.sort.disabled; } function key(addon) { return options.addonTypes.indexOf(addon.type) + "\n" + sortPosition(addon) + "\n" + addon.name.toLowerCase(); } addons.sort(function(a, b) { var ka = key(a); var kb = key(b); return ka == kb ? 0 : ka < kb ? -1 : 1; }).forEach(function(addon) { var type = addon.type; if(prevType && type != prevType) df.appendChild(document.createElementNS(xulns, "menuseparator")); prevType = type; var icon = addon.iconURL || addon.icon64URL; var mi = document.createElementNS(xulns, "menuitem"); mi.className = "menuitem-iconic"; var label = addon.name; if(options.showVersions == 1) label += " " + addon.version; else if(options.showVersions == 2) mi.setAttribute("acceltext", addon.version); mi.setAttribute("label", label); mi.setAttribute("image", icon || mp.icons[type] || ""); if(!icon && mp.icons.useSVG) mi.style.fill = "#15c"; var tip = addon.description || ""; var delay = "delayedStartupAddons" in Services && Services.delayedStartupAddons[addon.id] || null; var isDelayed = delay !== null; mi.classList.toggle("toggleRestartlessAddons-isDelayed", isDelayed); if(isDelayed) tip = "[Delayed Startup: " + delay.toLocaleString() + "]" + (tip ? "\n" + tip : ""); tip && mi.setAttribute("tooltiptext", tip); mi.classList.toggle("toggleRestartlessAddons-isHidden", addon.hidden || false); setDisabled(mi, addon.userDisabled); mi._cbAddon = addon; df.appendChild(mi); }); mp.textContent = ""; mp.appendChild(df); }); }; mp.handleEvent = function(e) { var mi = e.target; if(!("_cbAddon" in mi)) return; var addon = mi._cbAddon; if(e.type == "mousedown") { var closeMenu = isAskToActivateAddon(addon) ? options.closeMenuClickToPlay : options.closeMenu; if(e.shiftKey) closeMenu = !closeMenu; mi.setAttribute("closemenu", closeMenu ? "auto" : "none"); return; } var hasMdf = hasModifier(e); if(e.type == "command" && (!hasMdf || e.shiftKey)) { let newDis = setNewDisabled(addon); setDisabled(mi, newDis); } else if(e.type == "command" && hasMdf || e.type == "click" && e.button == 1) { openAddonPage(addon); closeMenus(mi); } else if(e.type == "click" && e.button == 2) { if(openAddonOptions(addon)) closeMenus(mi); } }; mp.destroyMenu = function() { removeStyle(); clearTimeout(cleanupTimer); cleanupTimer = setTimeout(function() { mp.textContent = ""; }, 5000); }; mp.icons = { get platformVersion() { delete this.platformVersion; return this.platformVersion = parseFloat(Services.appinfo.platformVersion); }, get useSVG() { delete this.useSVG; return this.useSVG = Services.appinfo.name == "Firefox" && this.platformVersion >= 57; }, get plugin() { delete this.plugin; return this.plugin = this.useSVG ? this.platformVersion >= 65 ? "chrome://global/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric-16.png"; }, get extension() { delete this.extension; return this.extension = this.useSVG ? this.platformVersion >= 76 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" // Or chrome://mozapps/skin/extensions/extension.svg : "chrome://mozapps/skin/extensions/extensionGeneric-16.svg" : "chrome://mozapps/skin/extensions/extensionGeneric-16.png"; } }; function isAskToActivateAddon(addon) { return addon.type == "plugin" && "STATE_ASK_TO_ACTIVATE" in AddonManager && Services.prefs.getBoolPref("plugins.click_to_play", true); } function setNewDisabled(addon) { var newDis = getNewDisabled(addon); var oldDis = addon.userDisabled; if(Components.interfaces.nsIWebTransportHash) { // random, Fx 123+ var func = function() { func = false; } var thread = Services.tm.currentThread; var meth = newDis ? "disable" : "enable"; addon[meth]({allowSystemAddons: true}).finally(func); while(func) thread.processNextEvent(true); } else try { addon.userDisabled = newDis; } catch(e) { // Error: Cannot disable hidden add-on firefox@getpocket.com _log("Can't set addon.userDisabled to " + newDis + ", error:\n" + e); if(addon.hidden) setNewDisabledRaw(addon, newDis); } var realDis = addon.userDisabled; if(realDis != newDis && addon.type == "extension") { // Firefox 62+? Weird things happens setNewDisabledRaw(addon, newDis); realDis = addon.userDisabled; } if(realDis != newDis) { // We can't enable vulnerable plugins let err = "Can't set addon.userDisabled to " + newDis + ", real value: " + realDis; if(newDis) { _log(err + "\nSTATE_ASK_TO_ACTIVATE not supported?"); newDis = false; } else { _log(err + "\nVulnerable plugin?"); if(oldDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = true; else newDis = AddonManager.STATE_ASK_TO_ACTIVATE; } addon.userDisabled = newDis; } ensureSpecialDisabled(addon, newDis); return addon.userDisabled; } function getNewDisabled(addon) { // disabled -> STATE_ASK_TO_ACTIVATE -> enabled -> ... var curDis = addon.userDisabled; var newDis; if("STATE_ASK_TO_ACTIVATE" in AddonManager && curDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = false; else if(!curDis) newDis = true; else { if(isAskToActivateAddon(addon)) newDis = AddonManager.STATE_ASK_TO_ACTIVATE; else newDis = false; } return newDis; } function setNewDisabledRaw(addon, newDis) { _log("Let's try set addon.userDisabled using raw hack"); if("lazy" in g) g = g.lazy; if("XPIDatabase" in g && "updateAddonDisabledState" in g.XPIDatabase) { // Firefox 61+ let rawAddon = g.XPIDatabase.getAddons().find(function(rawAddon) { return rawAddon.id == addon.id; }); g.XPIDatabase.updateAddonDisabledState( rawAddon, g.XPIDatabase.updateAddonDisabledState.length == 1 // Firefox 74+ ? { userDisabled: newDis } : newDis ); } else if("eval" in g) { // See "set userDisabled(val)" let addonFor = g.eval("addonFor"); let rawAddon = addonFor(addon); //rawAddon.userDisabled = newDis; g.XPIProvider.updateAddonDisabledState(rawAddon, newDis); } else { // Firefox 57+? See https://forum.mozilla-russia.org/viewtopic.php?pid=745272#p745272 updateAddonDisabledState(addon, newDis); } } function updateAddonDisabledState(addon, newDis) { var key = "_cbToggleRestartlessAddonsData"; var url = URL.createObjectURL(new Blob([ "XPIProvider.updateAddonDisabledState(addonFor(this." + key + "[0]), this." + key + "[1]); delete this." + key + ";" ])); addDestructor(function() { URL.revokeObjectURL(url); }); (updateAddonDisabledState = function(addon, newDis) { nsvo[key] = [addon, newDis]; Services.scriptloader.loadSubScript(url, nsvo); })(addon, newDis); } function setDisabled(mi, disabled) { var askToActivate = "STATE_ASK_TO_ACTIVATE" in AddonManager && disabled == AddonManager.STATE_ASK_TO_ACTIVATE; var cl = mi.classList; cl.toggle("toggleRestartlessAddons-askToActivate", askToActivate); cl.toggle("toggleRestartlessAddons-disabled", disabled && !askToActivate); } function ensureSpecialDisabled(addon, newDis) { if(addon.id == "screenshots@mozilla.org") Services.prefs.setBoolPref("extensions.screenshots.disabled", newDis); } if( this instanceof XULElement // Custom Buttons && typeof event == "object" && !("type" in event) && typeof _phase == "string" && _phase == "init" // Initialization ) { this.type = "menu"; this.orient = "horizontal"; this.appendChild(mp); this.onmouseover = function(e) { if(e.target != this) return; Array.prototype.some.call( this.parentNode.getElementsByTagName("*"), function(node) { if( node != this && node.namespaceURI == xulns // See https://github.com/Infocatcher/Custom_Buttons/issues/28 //&& node.boxObject //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && "open" in node && node.open && node.getElementsByTagName("menupopup").length ) { node.open = false; this.open = true; return true; } return false; }, this ); }; this.onmousedown = function(e) { if(e.target == this && e.button == 0 && hasModifier(e)) e.preventDefault(); }; this.oncontextmenu = function(e) { if(e.target == this && !hasModifier(e) && hasUpdater()) e.preventDefault(); }; this.onclick = function(e) { if(e.target != this) return; if(e.button == 0 && hasModifier(e) || e.button == 1) openAddonsManager(); else if(e.button == 2 && !hasModifier(e) && hasUpdater()) checkForAddonsUpdates.call(this); }; } else { // Mouse gestures or something other... let e; if(typeof event == "object" && event instanceof Event && "screenX" in event) // FireGestures e = event; else if( this instanceof Components.interfaces.nsIDOMChromeWindow && "mgGestureState" in window && "endEvent" in mgGestureState // Mouse Gestures Redox ) e = mgGestureState.endEvent; else { let anchor = this instanceof XULElement && this || window.gBrowser && gBrowser.selectedBrowser || document.documentElement; if("boxObject" in anchor) { let bo = anchor.boxObject; e = { screenX: bo.screenX, screenY: bo.screenY }; if(this instanceof XULElement) e.screenY += bo.height; } } if(!e || !("screenX" in e)) throw new Error("[Toggle Restartless Add-ons]: Can't get event object"); document.documentElement.appendChild(mp); mp.addEventListener("popuphidden", function destroy(e) { mp.removeEventListener(e.type, destroy, false); setTimeout(function() { mp.destroyMenu(); mp.parentNode.removeChild(mp); }, 0); }, false); mp.openPopupAtScreen(e.screenX, e.screenY); } function getRestartlessAddons(addonTypes, callback, context) { if(!("AddonManager" in window)); var then, promise = AddonManager.getAddonsByTypes(addonTypes, then = function(addons) { callback.call(context, addons.filter(function(addon) { var ops = addon.operationsRequiringRestart; return !addon.appDisabled && !(ops & AddonManager.OP_NEEDS_RESTART_ENABLE || ops & AddonManager.OP_NEEDS_RESTART_DISABLE) && ( !addon.hidden || options.showHidden > 0 || options.showHidden == -1 && !addon.userDisabled ) && (addon.iconURL || "").substr(0, 29) != "resource://search-extensions/"; })); }); promise && typeof promise.then == "function" && promise.then(then, Components.utils.reportError); // Firefox 61+ } function openAddonOptions(addon) { // Based on code from chrome://mozapps/content/extensions/extensions.js // Firefox 21.0a1 (2013-01-27) var optionsURL = addon.optionsURL; if(!addon.isActive || !optionsURL) return false; if(addon.type == "plugin") // No options for now! return false; if( addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_INFO || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_BROWSER || NaN) ) openAddonPage(addon, true); else if(addon.optionsType == AddonManager.OPTIONS_TYPE_TAB && "switchToTabHavingURI" in window) switchToTabHavingURI(optionsURL, true); else { let windows = Services.wm.getEnumerator(null); while(windows.hasMoreElements()) { let win = windows.getNext(); if(win.document.documentURI == optionsURL) { win.focus(); return true; } } // Note: original code checks browser.preferences.instantApply and may open modal windows window.openDialog(optionsURL, "", "chrome,titlebar,toolbar,centerscreen,dialog=no"); } return true; } function openAddonsManager(view) { var openAddonsMgr = window.BrowserOpenAddonsMgr || window.BrowserAddonUI.openAddonsMgr // Firefox || window.openAddonsMgr // Thunderbird || window.toEM; // SeaMonkey openAddonsMgr(view); } function openAddonPage(addon, scrollToPreferences) { var platformVersion = parseFloat( Services.appinfo.name == "Pale Moon" ? Services.appinfo.version : Services.appinfo.platformVersion ); scrollToPreferences = scrollToPreferences && platformVersion >= 12 ? "/preferences" : ""; openAddonsManager("addons://detail/" + encodeURIComponent(addon.id) + scrollToPreferences); } function hasModifier(e) { return e.ctrlKey || e.shiftKey || e.altKey || e.metaKey; } function addStyle() { if(addStyle.hasOwnProperty("_style")) return; var style = '\ .toggleRestartlessAddons-isDelayed > .menu-iconic-text {\n\ opacity: 0.75;\n\ color: #070;\n\ }\n\ .toggleRestartlessAddons-isHidden > .menu-iconic-text {\n\ color: #609;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-left {\n\ opacity: 0.4;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-text,\n\ .toggleRestartlessAddons-disabled > .menu-accel-container {\n\ opacity: 0.5;\n\ }\n\ .toggleRestartlessAddons-askToActivate {\n\ color: -moz-nativehyperlinktext;\n\ }'; addStyle._style = document.insertBefore( document.createProcessingInstruction( "xml-stylesheet", 'href="' + "data:text/css," + encodeURIComponent(style) + '" type="text/css"' ), document.documentElement ); } function removeStyle() { if(!addStyle.hasOwnProperty("_style")) return; var s = addStyle._style; s.parentNode.removeChild(s); delete addStyle._style; } function closeMenus(node) { // Based on function closeMenus from chrome://browser/content/utilityOverlay.js for(; node && "tagName" in node; node = node.parentNode) { if( node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.localName == "menupopup" || node.localName == "popup") ) node.hidePopup(); } } function _log(s) { if(typeof LOG == "function") // Custom Buttons LOG(s); else // Or something else Services.console.logStringMessage("Toggle Restartless Add-ons: " + s); } function hasUpdater() { var has = checkForAddonsUpdates.toString().indexOf("about:addons") != -1; hasUpdater = function() { return has; }; return has; }// http://infocatcher.ucoz.net/js/cb/toggleRestartlessAddons.js // https://forum.mozilla-russia.org/viewtopic.php?id=57948 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Toggle_Restartless_Add-ons // Toggle Restartless Add-ons button for Custom Buttons // (code for "initialization" section) // Also the code can be used from main window context (as Mouse Gestures code, for example) // Also you can check for add-ons updates using right-click: // copy all code from // https://github.com/Infocatcher/Custom_Buttons/blob/master/Check_for_Addons_Updates/checkForAddonsUpdates.js // after "//== Check for Addons Updates begin" // See "var style = " to modify styles for specific add-ons // (c) Infocatcher 2013-2019 // version 0.1.3pre4 - 2020-01-01 var options = { addonTypes: ["extension", "plugin"], // Possible values: "extension", "plugin" // From extensions: "userstyle" (Stylish), "greasemonkey-user-script" (Greasemonkey), "userscript" (Scriptish) // (swap to reorder in the menu) showVersions: 1, // 0 - don't show versions // 1 - show after name: "Addon Name 1.2" // 2 - show as "acceltext" (in place for hotkey text) showHidden: 0, // 0 - don't show hidden add-ons // -1 - show only enabled hidden add-ons (e.g. to track new items) // 1 - show all hidden add-ons sort: { enabled: 0, clickToPlay: 0, disabled: 1 // Sort order: // 0, 0, 0 - sort add-ons of each type alphabetically // 0, 0, 1 - show enabled add-ons (of each type) first // 0, 1, 2 - enabled add-ons, then click-to-play and then disabled }, closeMenu: false, // Close menu after left-click closeMenuClickToPlay: false // Close menu after left-click, for click to play plugins // Use Shift+click to invert closeMenu* behavior }; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var mp = document.createElementNS(xulns, "menupopup"); mp.setAttribute("onpopupshowing", "this.updateMenu();"); mp.setAttribute("oncommand", "if(!event.button) this.handleEvent(event);"); // Ignore middle-click in Firefox 89+ mp.setAttribute("onmousedown", "if(event.button == 0) this.handleEvent(event);"); mp.setAttribute("onclick", "if(event.button > 0) this.handleEvent(event);"); mp.setAttribute("oncontextmenu", "return false;"); mp.setAttribute("onpopuphidden", "this.destroyMenu();"); var tb = this.parentNode; if(tb && tb.getAttribute("orient") == "vertical") { // https://addons.mozilla.org/firefox/addon/vertical-toolbar/ var isRight = tb.parentNode.getAttribute("placement") == "right"; mp.setAttribute("position", isRight ? "start_before" : "end_before"); } var cleanupTimer = 0; mp.updateMenu = function() { clearTimeout(cleanupTimer); addStyle(); getRestartlessAddons(options.addonTypes, function(addons) { var df = document.createDocumentFragment(); var prevType; function sortPosition(addon) { if("STATE_ASK_TO_ACTIVATE" in AddonManager && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) return options.sort.clickToPlay; if(addon.isActive) return options.sort.enabled; return options.sort.disabled; } function key(addon) { return options.addonTypes.indexOf(addon.type) + "\n" + sortPosition(addon) + "\n" + addon.name.toLowerCase(); } addons.sort(function(a, b) { var ka = key(a); var kb = key(b); return ka == kb ? 0 : ka < kb ? -1 : 1; }).forEach(function(addon) { var type = addon.type; if(prevType && type != prevType) df.appendChild(document.createElementNS(xulns, "menuseparator")); prevType = type; var icon = addon.iconURL || addon.icon64URL; var mi = document.createElementNS(xulns, "menuitem"); mi.className = "menuitem-iconic"; var label = addon.name; if(options.showVersions == 1) label += " " + addon.version; else if(options.showVersions == 2) mi.setAttribute("acceltext", addon.version); mi.setAttribute("label", label); mi.setAttribute("image", icon || mp.icons[type] || ""); if(!icon && mp.icons.useSVG) mi.style.fill = "#15c"; var tip = addon.description || ""; var delay = "delayedStartupAddons" in Services && Services.delayedStartupAddons[addon.id] || null; var isDelayed = delay !== null; mi.classList.toggle("toggleRestartlessAddons-isDelayed", isDelayed); if(isDelayed) tip = "[Delayed Startup: " + delay.toLocaleString() + "]" + (tip ? "\n" + tip : ""); tip && mi.setAttribute("tooltiptext", tip); mi.classList.toggle("toggleRestartlessAddons-isHidden", addon.hidden || false); setDisabled(mi, addon.userDisabled); mi._cbAddon = addon; df.appendChild(mi); }); mp.textContent = ""; mp.appendChild(df); }); }; mp.handleEvent = function(e) { var mi = e.target; if(!("_cbAddon" in mi)) return; var addon = mi._cbAddon; if(e.type == "mousedown") { var closeMenu = isAskToActivateAddon(addon) ? options.closeMenuClickToPlay : options.closeMenu; if(e.shiftKey) closeMenu = !closeMenu; mi.setAttribute("closemenu", closeMenu ? "auto" : "none"); return; } var hasMdf = hasModifier(e); if(e.type == "command" && (!hasMdf || e.shiftKey)) { let newDis = setNewDisabled(addon); setDisabled(mi, newDis); } else if(e.type == "command" && hasMdf || e.type == "click" && e.button == 1) { openAddonPage(addon); closeMenus(mi); } else if(e.type == "click" && e.button == 2) { if(openAddonOptions(addon)) closeMenus(mi); } }; mp.destroyMenu = function() { removeStyle(); clearTimeout(cleanupTimer); cleanupTimer = setTimeout(function() { mp.textContent = ""; }, 5000); }; mp.icons = { get platformVersion() { delete this.platformVersion; return this.platformVersion = parseFloat(Services.appinfo.platformVersion); }, get useSVG() { delete this.useSVG; return this.useSVG = Services.appinfo.name == "Firefox" && this.platformVersion >= 57; }, get plugin() { delete this.plugin; return this.plugin = this.useSVG ? this.platformVersion >= 65 ? "chrome://global/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric-16.png"; }, get extension() { delete this.extension; return this.extension = this.useSVG ? this.platformVersion >= 76 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" // Or chrome://mozapps/skin/extensions/extension.svg : "chrome://mozapps/skin/extensions/extensionGeneric-16.svg" : "chrome://mozapps/skin/extensions/extensionGeneric-16.png"; } }; function isAskToActivateAddon(addon) { return addon.type == "plugin" && "STATE_ASK_TO_ACTIVATE" in AddonManager && Services.prefs.getBoolPref("plugins.click_to_play", true); } function setNewDisabled(addon) { var newDis = getNewDisabled(addon); var oldDis = addon.userDisabled; if(Components.interfaces.nsIWebTransportHash) { // random, Fx 123+ var func = function() { func = false; } var thread = Services.tm.currentThread; var meth = newDis ? "disable" : "enable"; addon[meth]({allowSystemAddons: true}).finally(func); while(func) thread.processNextEvent(true); } else try { addon.userDisabled = newDis; } catch(e) { // Error: Cannot disable hidden add-on firefox@getpocket.com _log("Can't set addon.userDisabled to " + newDis + ", error:\n" + e); if(addon.hidden) setNewDisabledRaw(addon, newDis); } var realDis = addon.userDisabled; if(realDis != newDis && addon.type == "extension") { // Firefox 62+? Weird things happens setNewDisabledRaw(addon, newDis); realDis = addon.userDisabled; } if(realDis != newDis) { // We can't enable vulnerable plugins let err = "Can't set addon.userDisabled to " + newDis + ", real value: " + realDis; if(newDis) { _log(err + "\nSTATE_ASK_TO_ACTIVATE not supported?"); newDis = false; } else { _log(err + "\nVulnerable plugin?"); if(oldDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = true; else newDis = AddonManager.STATE_ASK_TO_ACTIVATE; } addon.userDisabled = newDis; } ensureSpecialDisabled(addon, newDis); return addon.userDisabled; } function getNewDisabled(addon) { // disabled -> STATE_ASK_TO_ACTIVATE -> enabled -> ... var curDis = addon.userDisabled; var newDis; if("STATE_ASK_TO_ACTIVATE" in AddonManager && curDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = false; else if(!curDis) newDis = true; else { if(isAskToActivateAddon(addon)) newDis = AddonManager.STATE_ASK_TO_ACTIVATE; else newDis = false; } return newDis; } function setNewDisabledRaw(addon, newDis) { _log("Let's try set addon.userDisabled using raw hack"); if("lazy" in g) g = g.lazy; if("XPIDatabase" in g && "updateAddonDisabledState" in g.XPIDatabase) { // Firefox 61+ let rawAddon = g.XPIDatabase.getAddons().find(function(rawAddon) { return rawAddon.id == addon.id; }); g.XPIDatabase.updateAddonDisabledState( rawAddon, g.XPIDatabase.updateAddonDisabledState.length == 1 // Firefox 74+ ? { userDisabled: newDis } : newDis ); } else if("eval" in g) { // See "set userDisabled(val)" let addonFor = g.eval("addonFor"); let rawAddon = addonFor(addon); //rawAddon.userDisabled = newDis; g.XPIProvider.updateAddonDisabledState(rawAddon, newDis); } else { // Firefox 57+? See https://forum.mozilla-russia.org/viewtopic.php?pid=745272#p745272 updateAddonDisabledState(addon, newDis); } } function updateAddonDisabledState(addon, newDis) { var key = "_cbToggleRestartlessAddonsData"; var url = URL.createObjectURL(new Blob([ "XPIProvider.updateAddonDisabledState(addonFor(this." + key + "[0]), this." + key + "[1]); delete this." + key + ";" ])); addDestructor(function() { URL.revokeObjectURL(url); }); (updateAddonDisabledState = function(addon, newDis) { nsvo[key] = [addon, newDis]; Services.scriptloader.loadSubScript(url, nsvo); })(addon, newDis); } function setDisabled(mi, disabled) { var askToActivate = "STATE_ASK_TO_ACTIVATE" in AddonManager && disabled == AddonManager.STATE_ASK_TO_ACTIVATE; var cl = mi.classList; cl.toggle("toggleRestartlessAddons-askToActivate", askToActivate); cl.toggle("toggleRestartlessAddons-disabled", disabled && !askToActivate); } function ensureSpecialDisabled(addon, newDis) { if(addon.id == "screenshots@mozilla.org") Services.prefs.setBoolPref("extensions.screenshots.disabled", newDis); } if( this instanceof XULElement // Custom Buttons && typeof event == "object" && !("type" in event) && typeof _phase == "string" && _phase == "init" // Initialization ) { this.type = "menu"; this.orient = "horizontal"; this.appendChild(mp); this.onmouseover = function(e) { if(e.target != this) return; Array.prototype.some.call( this.parentNode.getElementsByTagName("*"), function(node) { if( node != this && node.namespaceURI == xulns // See https://github.com/Infocatcher/Custom_Buttons/issues/28 //&& node.boxObject //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && "open" in node && node.open && node.getElementsByTagName("menupopup").length ) { node.open = false; this.open = true; return true; } return false; }, this ); }; this.onmousedown = function(e) { if(e.target == this && e.button == 0 && hasModifier(e)) e.preventDefault(); }; this.oncontextmenu = function(e) { if(e.target == this && !hasModifier(e) && hasUpdater()) e.preventDefault(); }; this.onclick = function(e) { if(e.target != this) return; if(e.button == 0 && hasModifier(e) || e.button == 1) openAddonsManager(); else if(e.button == 2 && !hasModifier(e) && hasUpdater()) checkForAddonsUpdates.call(this); }; } else { // Mouse gestures or something other... let e; if(typeof event == "object" && event instanceof Event && "screenX" in event) // FireGestures e = event; else if( this instanceof Components.interfaces.nsIDOMChromeWindow && "mgGestureState" in window && "endEvent" in mgGestureState // Mouse Gestures Redox ) e = mgGestureState.endEvent; else { let anchor = this instanceof XULElement && this || window.gBrowser && gBrowser.selectedBrowser || document.documentElement; if("boxObject" in anchor) { let bo = anchor.boxObject; e = { screenX: bo.screenX, screenY: bo.screenY }; if(this instanceof XULElement) e.screenY += bo.height; } } if(!e || !("screenX" in e)) throw new Error("[Toggle Restartless Add-ons]: Can't get event object"); document.documentElement.appendChild(mp); mp.addEventListener("popuphidden", function destroy(e) { mp.removeEventListener(e.type, destroy, false); setTimeout(function() { mp.destroyMenu(); mp.parentNode.removeChild(mp); }, 0); }, false); mp.openPopupAtScreen(e.screenX, e.screenY); } function getRestartlessAddons(addonTypes, callback, context) { if(!("AddonManager" in window)); var then, promise = AddonManager.getAddonsByTypes(addonTypes, then = function(addons) { callback.call(context, addons.filter(function(addon) { var ops = addon.operationsRequiringRestart; return !addon.appDisabled && !(ops & AddonManager.OP_NEEDS_RESTART_ENABLE || ops & AddonManager.OP_NEEDS_RESTART_DISABLE) && ( !addon.hidden || options.showHidden > 0 || options.showHidden == -1 && !addon.userDisabled ) && (addon.iconURL || "").substr(0, 29) != "resource://search-extensions/"; })); }); promise && typeof promise.then == "function" && promise.then(then, Components.utils.reportError); // Firefox 61+ } function openAddonOptions(addon) { // Based on code from chrome://mozapps/content/extensions/extensions.js // Firefox 21.0a1 (2013-01-27) var optionsURL = addon.optionsURL; if(!addon.isActive || !optionsURL) return false; if(addon.type == "plugin") // No options for now! return false; if( addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_INFO || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_BROWSER || NaN) ) openAddonPage(addon, true); else if(addon.optionsType == AddonManager.OPTIONS_TYPE_TAB && "switchToTabHavingURI" in window) switchToTabHavingURI(optionsURL, true); else { let windows = Services.wm.getEnumerator(null); while(windows.hasMoreElements()) { let win = windows.getNext(); if(win.document.documentURI == optionsURL) { win.focus(); return true; } } // Note: original code checks browser.preferences.instantApply and may open modal windows window.openDialog(optionsURL, "", "chrome,titlebar,toolbar,centerscreen,dialog=no"); } return true; } function openAddonsManager(view) { var openAddonsMgr = window.BrowserOpenAddonsMgr || window.BrowserAddonUI.openAddonsMgr // Firefox || window.openAddonsMgr // Thunderbird || window.toEM; // SeaMonkey openAddonsMgr(view); } function openAddonPage(addon, scrollToPreferences) { var platformVersion = parseFloat( Services.appinfo.name == "Pale Moon" ? Services.appinfo.version : Services.appinfo.platformVersion ); scrollToPreferences = scrollToPreferences && platformVersion >= 12 ? "/preferences" : ""; openAddonsManager("addons://detail/" + encodeURIComponent(addon.id) + scrollToPreferences); } function hasModifier(e) { return e.ctrlKey || e.shiftKey || e.altKey || e.metaKey; } function addStyle() { if(addStyle.hasOwnProperty("_style")) return; var style = '\ .toggleRestartlessAddons-isDelayed > .menu-iconic-text {\n\ opacity: 0.75;\n\ color: #070;\n\ }\n\ .toggleRestartlessAddons-isHidden > .menu-iconic-text {\n\ color: #609;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-left {\n\ opacity: 0.4;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-text,\n\ .toggleRestartlessAddons-disabled > .menu-accel-container {\n\ opacity: 0.5;\n\ }\n\ .toggleRestartlessAddons-askToActivate {\n\ color: -moz-nativehyperlinktext;\n\ }'; addStyle._style = document.insertBefore( document.createProcessingInstruction( "xml-stylesheet", 'href="' + "data:text/css," + encodeURIComponent(style) + '" type="text/css"' ), document.documentElement ); } function removeStyle() { if(!addStyle.hasOwnProperty("_style")) return; var s = addStyle._style; s.parentNode.removeChild(s); delete addStyle._style; } function closeMenus(node) { // Based on function closeMenus from chrome://browser/content/utilityOverlay.js for(; node && "tagName" in node; node = node.parentNode) { if( node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.localName == "menupopup" || node.localName == "popup") ) node.hidePopup(); } } function _log(s) { if(typeof LOG == "function") // Custom Buttons LOG(s); else // Or something else Services.console.logStringMessage("Toggle Restartless Add-ons: " + s); } function hasUpdater() { var has = checkForAddonsUpdates.toString().indexOf("about:addons") != -1; hasUpdater = function() { return has; }; return has; }
Кнопка не срабатывает
Отсутствует