Объявление

В связи с наплывом спама и ботов на форуме, регистрация новых пользователей будет приостановлена. О восстановлении регистрации будет сообщено дополнительно

Administrator

№2076Вчера 12:39:45

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

SearchModifiers.uc.js

Выделить код

Код:

/**
@UCF @param {"prop":"JsChrome.load","ucfobj":true,"disable":true} @UCF
*/
// Пункт для контекстного меню адресной строки, подставляющий модификаторы поиска
(async (
    id = "ucf_searchmodifiers",
    label = "Вставить mod",
    modifiers = [
        "* ― Закладки",
        "% ― Вкладки",
        "^ ― История",
        "> ― Действия",
        "# ― Названия",
        "+ ― С метками",
        "~ ― Набранные",
        "@ ― URL-адреса"
    ],
) => ({
    init() {
        var urlbar = this.urlbar = gURLBar.textbox;
        if (!urlbar) return;
        setUnloadMap(Symbol(id), this.destructor, this);
        urlbar.addEventListener("popupshowing", this);
    },
    handleEvent(e) {
        this[e.type](e);
    },
    popupshowing({target}) {
        if (target != (this.popup ||= gURLBar.inputField.parentElement.menupopup)) return;
        this.urlbar.removeEventListener("popupshowing", this);
        this.urlbar = null;
        var sep = this.popup.querySelector("menuseparator.menuseparator-add-engine") || this.popup.lastElementChild;
        var menu = this.append("menu", sep, {label}, "before");
        this.append("menuseparator", menu, null, "before");
        var pp = this.pp = this.append("menupopup", menu, null, "append");
        pp.addEventListener("command", this);
        var df = document.createDocumentFragment();
        for (let label of modifiers)
            this.append("menuitem", df, {label}, "append");
        pp.append(df);
    },
    command(e) {
        gURLBar.search(e.target.label[0]);
    },
    append(name, parent, attrs, func) {
        var elm = document.createXULElement(name);
        if (attrs) for (let a in attrs) elm.setAttribute(a, attrs[a]);
        parent[func](elm);
        return elm;
    },
    destructor() {
        this.urlbar?.removeEventListener("popupshowing", this);
        this.pp?.removeEventListener("command", this);
    },
}).init())();


Search_Image_ContextMenu.uc.js

Выделить код

Код:

/**
@UCF @param {"prop":"JsChrome.load","ucfobj":true,"disable":true} @UCF
*/
// Добавить подменю "Поиск изображения в" в контекстном меню изображений
(async (
    id = "ucf_searchimagecontextmenu",
    label = "Поиск изображения в ...",
    label2 = "Искать во всех поисковиках",
    engines = [
        ["Google", "https://www.google.lv/favicon.ico", "https://lens.google.com/v3/upload?url="],
        ["Яндекс", "https://yastatic.net/morda-logo/i/favicon_islands.ico", "https://yandex.ru/images/search?rpt=imageview&url="],
        ["Bing", "https://www.bing.com/s/a/bing_p.ico", "https://www.bing.com/images/search?view=detailv2&iss=sbi&form=SBIHMP&sbisrc=UrlPaste&q=imgurl:"],
        ["Tineye", "https://tineye.com/favicon.ico", "https://tineye.com/search?pluginver=bookmark_1.0&url="],
    ],
) => ({
    init() {
        var popup = this.popup = document.querySelector("#contentAreaContextMenu");
        if (!popup) return;
        setUnloadMap(Symbol(id), this.destructor, this);
        popup.addEventListener("popupshowing", this);
    },
    handleEvent(e) {
        this[e.type](e);
    },
    click(e) {
        if (e.target != this.menu) return;
        this.command(e);
        e.target.parentElement.hidePopup();
    },
    command({target}) {
        for (let engine of target._engines || [target._engine])
            gBrowser.selectedTab = gBrowser.addTrustedTab(engine[2] + encodeURIComponent(gContextMenu.imageInfo.currentSrc), { index: gBrowser.selectedTab._tPos + 1 });
    },
    popupshowing(e) {
        if (!gContextMenu?.imageInfo?.currentSrc || gContextMenu.webExtBrowserType === "popup") return;
        this.popupshowing = this.showing;
        var menu = this.menu = document.createXULElement("menu");
        menu.setAttribute("label", label);
        menu.setAttribute("class", "menu-iconic");
        menu.setAttribute("image", engines[0][1]);
        menu.addEventListener("click", this);
        menu._engine = engines[0];
        var mPopup = this.mPopup = document.createXULElement("menupopup");
        mPopup.addEventListener("command", this);
        menu.append(mPopup);
        for (let engine of engines) {
            let m = document.createXULElement("menuitem");
            m.setAttribute("label", engine[0]);
            m.setAttribute("image", engine[1]);
            m.setAttribute("class", "menuitem-iconic");
            m._engine = engine;
            mPopup.append(m);
        }
        var mItem = document.createXULElement("menuitem");
        mItem.setAttribute("label", label2);
        mItem._engines = engines;
        mPopup.append(mItem);
        this.popup.querySelector("#context-copyimage-contents")?.before(menu);
        this.popup.addEventListener("popuphiding", this);
    },
    showing({target}) {
        if (target != this.popup || !gContextMenu?.imageInfo?.currentSrc || gContextMenu.webExtBrowserType === "popup") return;
        this.menu.hidden = false;
    },
    popuphiding({target}) {
        if (target != this.popup) return;
        this.menu.hidden = true;
    },
    destructor() {
        this.popup.removeEventListener("popupshowing", this);
        this.popup.removeEventListener("popuphiding", this);
        this.menu.removeEventListener("click", this);
        this.mPopup.removeEventListener("command", this);
    },
}).init())();

Отсутствует

 

№2077Вчера 13:17:07

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 676
UA: Firefox 137.0

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

Вы здесь выложили два одинаковых.

Суть одна, а реализация разная. :)


«The Truth Is Out There»

Отсутствует

 

№2078Вчера 14:38:47

dinn
Участник
 
Группа: Members
Зарегистрирован: 28-09-2024
Сообщений: 94
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

unter_officer пишет

Суть одна, а реализация разная

А версия с cloneNode не зашла? Получилось бы три "одинаковых"

На форуме

 

№2079Вчера 14:49:14

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

_zt
"> ― Действия"
Про этот модификатор знаю, забыл добавить.
К слову, оба скрипта прекрасно работают в custom_script_win.js

Отсутствует

 

№2080Вчера 14:55:35

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

xrun1
А Google Translate как работает, через отключение параметра?

Отсутствует

 

№2081Вчера 16:09:28

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

_zt
Вы про ucfobj?
То, о чём написал yup на предыдущей странице для меня слишком заумно.
Раз мой вопрос дискуссии не вызвал, значит никто не знает для чего это. Я для себя давно сделал вывод, это моё личное мнение - это авторская метка.
Скрипты, сделанные лично/полностью переделанные автором UCF - "правильные" true.
А всякие *.uc.js от какого-нибудь alice0775 или Aris-t2, включая Dumby - это "неправильные", с авторской точки зрения, false-скрипты.
Если Вы про этот, то, конечно, true. Хотя у меня скрипт с поздними правками от Dumby.
Я выкладывал свой здесь.

Добавлено Вчера 16:19:45
Актуальный код у меня немного другой, если надо - выложу. Но думаю, не надо, раз пошла "большая перепись скриптов".

Отредактировано xrun1 (Вчера 16:19:45)

Отсутствует

 

№2082Вчера 16:40:59

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

xrun1
Я не про это, скрипт не работает, а в консоли

Uncaught EvalError: call to eval() blocked by CSP
и
Content-Security-Policy: Параметры страницы заблокировали выполнение JavaScript eval (script-src), поскольку он нарушает следующую директиву: «script-src chrome: moz-src: resource: 'report-sample'» (Отсутствует 'unsafe-eval')

Отсутствует

 

№2083Вчера 16:43:10

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1190
UA: Seamonkey 2.49

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

То, о чём написал yup на предыдущей странице для меня слишком заумно.
Раз мой вопрос дискуссии не вызвал, значит никто не знает для чего это.

Я могу разъяснить подробнее, что имел в виду Vitaliy V. Но во-первых, это получится достаточно пространно, и я не знаю, насколько оно здесь уместно. А во-вторых, кое-чего я сам не очень хорошо представляю (не в смысле "что это", а "почему автор UCF сделал именно так").


Но на второй странице этой темы есть вот такой его комментарий:

параметр ucfobj должен быть true для моих скриптов (если не указано), и false или отсутствовать для других (если автором скрипта не указано обратное)

xrun1 пишет

Скрипты, сделанные лично/полностью переделанные автором UCF - "правильные" true.
А всякие *.uc.js от какого-нибудь alice0775 или Aris-t2, включая Dumby - это "неправильные", с авторской точки зрения, false-скрипты.

Почти да. У тех скриптов, которые true, и тех, которые false, разные глобальные окружения.
Для false это window, а для true - отдельный объект, создаваемый UCF.
В результате true-скрипты в случае возникновения конфликта имён переменных/функций будут гадить только себе подобным, а false-скрипты - себе подобным и всему остальному браузеру в целом.

Отредактировано yup (Вчера 16:52:50)

Отсутствует

 

№2084Вчера 18:34:04

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

_zt
У меня работает. Только скрипт бесполезен, гугл-переводчик скриптовый г*о.
https://imgsh.net/i/0cc205e905

Добавлено Вчера 18:46:42
yup
Не помню, видел я комментарий автора или нет, но "опыт сын ошибок трудных"(с) меня в этом убедил.:)

Отредактировано xrun1 (Вчера 18:46:42)

Отсутствует

 

№2085Вчера 19:09:02

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 175
UA: Firefox 139.0

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

гугл-переводчик

https://github.com/Endor8/userChrome.js … nced.uc.js

Отсутствует

 

№2086Вчера 20:42:50

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1190
UA: Seamonkey 2.49

Re: UCF - ваши кнопки, скрипты…

xrun1
Портированный "на скорую руку" скрипт от другой системы, который прекрасно работает при false, может неправильно работать (или вообще не работать) при true.


Для true некоторые вещи нужно писать особым образом.
Потому автор и говорил использовать false, что людям, не разбирающимся в тонкостях внутренних дел UCF, так проще - можно всё делать так, как они привыкли.

Отредактировано yup (Вчера 20:45:39)

Отсутствует

 

№2087Вчера 21:04:12

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan
Спасибо, но нет. Перевод - то же самое гуано.
https://imgsh.net/i/72938ab41d
В моём варианте окошко подстраивается под размер текста и вообще привык. Ещё в фоне QTranslate работает.

Добавлено Вчера 21:30:09
yup
Сам я ничего не портирую. А чужие пишу с false. У меня сложился набор кнопок и скриптов и новые давно не ставлю.

Отредактировано xrun1 (Вчера 21:30:09)

Отсутствует

 

№2088Вчера 23:16:05

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

xrun1
Вы так и не ответили, каким образом он у вас работает? Или на 138 еще нет проблемы с eval?
Ну так следующее обновление это исправит. :)
А вот context-translate-enhanced.uc.js работает. И тоже подстраивается под размер текста, а минимальный размер в скрипте задается. Как и все остальное.
zuhvdz9k.png

Отредактировано _zt (Вчера 23:36:21)

Отсутствует

 

№2089Вчера 23:30:30

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

_zt
Я уже отвечал Вам на подобный вопрос. У меня релизные версии. Я обычный пользователь, не тестер, скрипты/css не пишу. Зачем мне альфы-беты-гаммы? Будет 139 - будет видно. На 138.0.3 работает.

И тоже подстраивается под размер текста

Да ладно.) А что так много пустого места снизу осталось?

Отредактировано xrun1 (Вчера 23:36:05)

Отсутствует

 

№2090Вчера 23:37:17

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

Я вам уже ответил - минимальный размер. Не вижу смысла делать меньше спичечного коробка.

Отредактировано _zt (Вчера 23:38:27)

Отсутствует

 

№2091Вчера 23:43:07

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

50х35 и ни миллиметра меньше. Сурово!))

Отсутствует

 

№2092Вчера 23:59:58

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

Я понял, чем длиннее строка, тем больше отступ снизу. Думаю это решаемо.

Отсутствует

 

№2093Сегодня 12:03:11

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

_zt
Просто в теме по поводу размера окна скриптом Google Translate был большой трёп и Dumby долго делал приемлемый вариант. У меня какой-то промежуточный этап, который лично меня устроил.
https://imgsh.net/i/b43778b539
Что касается перевода, то гугл то ли с февраля, то ли с марта изменил отдачу перевода скриптам. Я пытался посмотреть, какие там post/get запросы идут. Но быстро понял, что люди, понимающие в этом больше меня тоже в ах*е.:)
Раньше гугл отдавал 2 варианта.
Примерно, как сейчас перевод https://translate.google.com/translate_a/single?client=gt&sl=
И хороший и правильный при добавлении всего одной буковки (gt --> gtx) https://translate.google.com/translate_a/single?client=gtx&sl=
Теперь оба неприемлемые. В обоих скриптах используется этот запрос.

Отсутствует

 

№2094Сегодня 13:58:47

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1190
UA: Seamonkey 2.49

Re: UCF - ваши кнопки, скрипты…

xrun1
Набрал я руками в адресной строке браузера то, что на Вашей картинке. Получил перевод - тот самый, который "то же самое гуано".

скрытый текст
7a0fd8524b0610d3533d9245409e85bc.png


Тогда набрал просто "https://translate.google.com", на странице ввёл фразу - получил ровно тот же перевод.


Попробовал в другом браузере - "Ба, знакомые всё яйца!"


Как Вам удалось получить "хороший" перевод?

Отредактировано yup (Сегодня 14:24:19)

Отсутствует

 

№2095Сегодня 15:42:14

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

yup пишет

Тогда набрал просто "https://translate.google.com", на странице ввёл фразу - получил ровно тот же перевод.

Может, куки прицепились? У меня на сайте правильно переводит. Проверил сейчас эту же фразу в Cent, правильно перевёл.

Добавлено Сегодня 15:57:08
_zt
Менял сегодня иконки в кнопке Save_Script.js и столкнулся с проблемой. Если в секции с PNG заменить иконки на svg, отображаться не будут. В этом виновата кнопка Save_Button.js. Если я беру старую кнопку, которая у меня в custom_script.js, всё отображается правильно. Можете проверить и подтвердить или опровергнуть, а то я запутался?
Пути к скрипту поправьте только.

Save_Script.js с новыми иконками

Выделить код

Код:

// Скрипт Save
// Правка Vitaliy V. 2505
// Предыдущая версия
// https://forum.mozilla-russia.org/viewtopic.php?pid=781458#p781458
// https://forum.mozilla-russia.org/viewtopic.php?pid=799602#p799602
// https://forum.mozilla-russia.org/viewtopic.php?pid=799639#p799639
// https://forum.mozilla-russia.org/viewtopic.php?pid=805016#p805016

// Кнопка-виджет в Save_Button.js

self.label = "Save";
self.type = "menu";

// Создать меню для кнопки ...
var array = [
    { label: "Сохранить favicon сайта", func: () => saveFavicon(), image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACPVBMVEX09ff////C3L+Uq8+Vq8+Uqs+Zr9CZrtCZr9Gfu+ear8+mt9JRf8ORxl3t8vfF06+Twojs8/d9otl8o9s+aquZrs/X9KLp8Pft8fZhisf//+DBzN2hveihv+pii8hti9pgicl6oNlojs1zncNsi836/P2duebx8/eYyWqBp+Gn0IKBvlKHsm9qmaVuk8zt7/FEbauEv1Tp7/JdhL9oi9Pl8e2LwlmdsdD7/P76+/3H7ofo8+peh8eHwFaSteZ0pkp2gl7q8/Ohy5OApt2by2eZuOqbuOWaezWuvtd7nN2HvWxul9Ty9feQxV5ljcqBp+JEcLCVtOOo0nR7odx5n9suX6Z1mtBzmtSXyGPv9PewzfOzx+O6zu/s8fd9o95Xfrthi8lYhMN5oNnw9ffw9Pjw9Pf8/f6ewO/m8O9zmdE6aapsjdyUwouPxWPDzd6XteOSs9B5nNVpnpqHt7h/s6F6n9d7ntSTttGHwVh4qp+Ev1HH7ox6qk5wj+Hm8e3t9fOm0IKAtqOBpNrx+P9ljcyhs9FpkM2hv+/u8/fF0eOLu4N+vFKgzX3p9OSFqN13qExekIl4n9j7/P3x9PhxmNDm8e9Vg8Zfkozr8veq0YTX9qL//92AtamOwnHFz96Fot1diMh+pd13ntmatu+YyW/3+/+Tqs5UgcShzJNbhsdTf8GHs7bo8PaXtuqMr+Ty8/SZt+SUqs7r7Ox3ndb9/f7t8feZyXGYyWWCpNbz9PRuiteNtNDn7/V4ntjx8fGo3JqNAAAAv3RSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AEVuhDkAAAD+SURBVBhXY5jHzcUMAqxAICq9bx8D96adDFAgaGQOFOBaH7h7zoqZDTlFyptncAAFWBjyi52CXCI0unRLxcECPhsatbbzmlXMnS60hg0kkOxW0uNrq93tNaFpD1ggUm21QK532ZQdSm1hmXKdDCwdnOWVOi1RjNGMQCCrwMDMJ8NZ4LAynVGPkXFp8zpJBubYmn579wXtqhZb0iwn9a1iWLaViYmJ3891obOwYtLEvcYMGyWAAkwJdv6accEhi8LjGVr11SenpC5f61g3NcO0vjCAIc+DjZ2dnWexddWSbYa9nlkM+8BgWsxsK7FZ1VLzRaACNokmtdnyu1QMQgF7Rlh4zWWTAwAAAABJRU5ErkJggg=="},
    { label: "Копировать favicon сайта в base64", func: () => copyFaviconData(), image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAI2bv/9RVpf/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAACIkvD/Jia6/ywpq/8AAAAAAAAAAAAAAAAAAAD/AAAA/wbwAf90qpv/Ymic/1RWqP9OUKr/W2Ch/2dumf9YYKT/Ly/B/xQP3/8MB9P/JCGb/wAAAAAAAAAAAAAAAAAAAP8G8AH/U5ea/ycr8f8VIP3/HiP4/ywo8v8sIvb/LCL2/ywi9v8KBOj/BQDe/wQAtv8tK4P/AAAAAAAAAAAAAAD/BvAB/3Sqm/9iaJz/Tim3/0UuuP9GPrT/R0ex/zk8uf8gIMz/FRDe/xEMzv8jIJz/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8AAAD/SqOR/yImvP8sLKj/AAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/BvAB/3Sqm/9KW5r/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAABvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAG8AH/AAAAAAAAAP8G8AH/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/BvAB/wbwAf8AAAAAAAAA/wAAAP8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAG8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOesQQBjrEGAAaxBwACsQcABrEHDg6xBwAesQcAPrEHAD6xBw8+sQcPprEHD8axBwAGsQQABrEGAAaxB//+sQQ=="},
    { separator: ''},
    { label: "Сохранить ярлык страницы как …", func: () => saveShortcuts(), image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP8E/yT/BP8k/5XLDv/zqgD/86oA//I1///yNf//86oA//OqAP/zqgD/86oA//OqAP+Vyw7/lcsO/wT/JP8E/yT/BP8k/5XLDv+Vyw7/86oA//OqAP/yNf//8jX///OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//02AP/9NgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/9NgD//TYA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA/wA31v8AN9b/86oA//9If///SH//86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP8AN9b/ADfW//OqAP//SH///0h///OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/5XLDv+Vyw7/86oA//OqAP/zqgD/86oA/0CA//9AgP//86oA/07+9f9O/vX/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP9AgP//QID///OqAP9O/vX/Tv71//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/AACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQ=="},
    { separator: ''},
    { label: "Сохранить страницу как PDF", func: () => savePageToPDF(), image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYUw4pJt3V/+Rb1D8lnFP/55zTf+VcVH/lXJS/5VyUv+VclL/lXJS/5VyUv+VclL/k3BR/J56Wv9cRzSkAAAAAJNvUKTto2L/4ppe/uehZf/Pmmr/noZv/9Scav/Wl17/1plh/9eZYf/XmWH/15lh/9eZYf/WmGD/2Jlg/suRXP9mRiuk8rWA/397dP1akKn/rqqi/3LF3f8Mntj/4dLJ///+9f/48u3/9e7n//bt5v/47+f/+O/n//jv5//rvZP/1ZJX/a9/VP9+lrD8AIvz/xOt+f8Douv/ALb6/wC28/9tmar/z8jJ//Lq5/////7//v////n9///6/P3//////+Ta0P/PjVP/pnpT/IWds/+aiXj/5efl/8Px//951/3/LMz//wCx8/8GltL/NIu3/4ycqf/l29L////+//n6+//8/v//3tXM/8+OVP+oe1P/6K57/86QWP/r6Ob////////++v/r9/z/oOb9/zDL//8Arf//AI/r/ydysv+hpqr//PTr///////d1Mz/0I5U/6h7U//osH//wo5g/+fm5P/7/f//9vf5//z7+////vv/9/r8/5Dc/P8Oqv7/AJf//wF02v9ffZ7/8Ojh/+Ha1P/NjFL/qHtT/+ewf//Ej1//7O3r///////+/v7//v7+//f5+v/6+vv////8/8Tq/f8hp/7/AJH//wB18/8/bqj/1MGu/9mXXv+leVH/569+/8iSYv+/tKn/wLew/8O5sf/P0M////////7+/v/3+fv////7/9Hv/v8hoP3/AIn//wB4/v84ZqL/w4NH/619VP/nsYD/x45c/9W5of/bv6j/0Jxt/6J/YP+spqD/2N3i//7////6+/3///76/8vr/v8Slv7/AIb+/wBz//83VH7/nW1B/+ewfv/Fjl7/7Ozr///////9+/r/9d7K/9Ghdv+jd1D/pJ6Y/+jt8f/9///////7/6fb/v8Ahv7/AYD//wRp6f95YlT/57B//8SOXv/n5uT//v7///r7/P/8/v////////XRsv/DhEv/loBu/9DX3P/9/v/////7/2O6/f8Afv//FnTU/5JtTf/nsH//xY9e/+jn5f/+/f//+fj5//n4+P/5+Pn/+/////Xbxf/Wj1D/nX1h/+Ll6P////7/3+/3/w+V//8tcbP/qHJB/+WuffzCjV7/5efn///////+/v7//////////////v7///////XRsP/TnW3/8fT3//////////z/ddD//0Nxl/+zdkH88LmH/9CRWP2+qJT/0M7N/8/Jxv/Pysf/z8rH/8/Kxv/Py8n/zsO6/7+pmP/PzMv/zsnG/9bNyP+nsK7/h4R3/b2BT/+Sb1Ck7qxw/9GSW/69hlb/wYhX/8CIV//AiFf/wIhX/8CIVv/BiVj/xI1d/8CIVv/BiFf/vYZW/9STW/7ppmv/bE80pAAAAACUd16k+sui/+7AmPzwwpr/8MKa//DCmv/wwpr/8MKa//DCmf/vwZj/8MKa//DCmv/uwJj8+cui/5N3XaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
    { label: "Печать страницы / печать в PDF", func: () => document.querySelector("#mainCommandSet > command#cmd_print").doCommand(), image: "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAC6ElEQVRYCd2WzW8NURjGZ6hqKFckNIidhUY/fCysmm7KxkaIhAVNETtJcxf+AURISxMbEZvGBgtBokU3NrpxW410JxVarCiVNKQtx+/Re2TmzseZe29Xmud3zpz3fd53zkzn3ju+52X/M8Ycwn0V3kMBRkDzG9/3Dcdlyy+ngg2M498BpfpOYBS0GbupiSybyrwBTr6LE+gkTN4kwyZYAUn6RkKbsRTY0FtiIZWzgV4q87AAW0AnaGbeA7tBs9YrOU7SVxLBu/Qk0wa4+uUUToGueoArOcBxRPh0R5pI2A1pbmVdB3EqxAUjMRrvA6ujEUNKgKIaaIEuuA7DMA+SnqmU6mIKZz9IMwyriuGKJuo3wAJIF5xNcNXDLEi3nAUOA03OgJUe7PQKnMfBqj3d7c7SaBCkCbcbB84BkKYYlhGqWNTn4CdIfc5GuBrAPjCXnQUOA72Cd7PNYfc8CvJg1egscBho9BikdwzurwBMIyBl+7ymbIAm62EOpN4U62IKVxNYdS9GKx9pdBKs9jo74TwPkj6zm50FDgONBkGaZMh0+x9ilJ46ejvTNGkA+zBfCRWQaIW1oSALYo1wCbaxrEr06AarllAzondBn817zB3gvj2hDu4FPV+BNBpxEx2GoF6yOA2rI+YKAvRpBqt8pAWZIYjTD4J/70qkqIwAPS6C9ItB7xHhaoI3wKUXGE5A0u96uGlxhb8WPoE0VAyHJzJtkFVfMF6D7eEu8St8x8DqSLyLKA49iEyZ9RvnKUoTRd6HMZA+MuhtKeK3v25dZB5AVvkYN0KaDpPU6xiT18Nr3LwOUmGX++EZZFF/UjOK14Gumsnom68uyRsbp2on3IY5SNI0ifrSBorBc7A6WOrJvKbDVuiBGYjTfYI5NWTW/7yDeRysbipXNXTLwTn4AKWaJTBdhOmf7nBUU/XJgw1oWAudxpjXkKTPJM6CH6xd0mM1h3ZjTB+MgU76iLnTGLNmSU/23zf7A6yAD944M8WnAAAAAElFTkSuQmCC"},
    { label: "Сохранить страницу / выбор как HTML", func: () => savePageToHTML(), image: "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='context-fill' fill-opacity='context-fill-opacity'><path d='M12.225.01H2.656v5.993l.955-.125L3.569.677 11 .76l-.042 4.375h4.275l.041 10.125-12.575.042-.042.708h13.281V3.737L12.225.01zm-.272 1.613 2.384 2.394h-2.384V1.623zm2.93 10.318.062 1.333-2.992.063V8.003h1.328v4l1.601-.063zM4.647 8.002h-.664v1.334h.664v4h1.329v-4h.664V8.003H4.648zm5.313 0-.664 1.074-.664-1.074H7.305v5.334h1.328V10.53l.664 1.073.664-1.073v2.807h1.328V8.003H9.961zm-7.969 2h-.664v-2H0v5.334h1.328v-2h.664v2H3.32V8.003H1.992v2z'/></svg>"},
    { label: "Сохранить URL, страницу / выбор как TXT", func: () => saveSelectionToTxt(), image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAQE6AAAAZAAAAGgAAAJmAAACZgAAAGYAAABmAAAAZgAAAGYAAABmAAAAZgAAAGYAAABlAAAAaQABAmYAAQEjAAAAADlVkOdVcKHxVXKi8kdklPJLZpfyU3Cg8lJvn/JRbZ7yUW+g8lFun/JRbp/yUG6e8lVyofFVdKjzLkV45wAAAFABAQEAaIzF/3y34v9wsuL/cJe0/0lpgv9bjLP/dLLh/2+v3v9sq9v/cK3d/3Gv3v9sqtv/b7Df/4G77P9VcqT2AAAAVAMDAQBnir/+ZqfU/pDB4/7a3uD+j46N/kxYXv6To6/+1er4/tXp+P7J3/D+1ej4/svg8v6Gut/9aqzd/lhxnvAAAABSAwIBAGaIvv9pptX/ocfj//f4/P/P0tX/g4CA/1xZWf+Woqr/2uz8/9Hl+f/W5fT/2Of3/5fC4v5tq93/Vm+e8QAAAFIDAgEAaYm+/3mw2/+iyeX/9Pn8/+z0+//IzNL/d3h5/0tMTv+Mkpn/xdvs/9Hp/f/O4PL/msXk/nmz4/9XcJ/xAAAAUgMDAQBti7//k7/h/6fL5v/v9fn/4u73/9Dk9P+8wMT/YGpx/zJJWv94iJf/ztzo/9Pp/P+ZwuD+gLfk/1dwnvEAAABSAwMBAHOPwf+myub/sNHp//j7/P/6/P3/8fr///r39P+sxdP/IXWq/xJJcv+NjZD/0+Lu/6TN7f6Ft+L/WXGf8QAAAFIDAwEAd5LD/7PR6/+ZxOP/0ePx/97r9f/Y5/L/3e32/8Tc7f9gseT/CHK3/zBYdv+HiY7/lL/f/pLE7/9bcJ3xAAAAUgMDAQB4k8P/xNvx/5/F5f+kyOX/qMrn/6TH5f+kyOX/sM/q/5e51P9Mm83/GHm3/xxIav9fdYf+pMvs/1x1pfIAAABTAwMBAHmSxf/O4/T/y9/y/8Hb9P/C3PX/wNv0/7vW7/+93ff/utDm/42fsf9Gjbn/EXS2/ytSbv6Fj5r/WnGc8gAAAFICAwEBepPE/tHk9f/S5PX/vMjV/7fCzP+3w8//uMPP/7XBzP+6ytf/qa+4/3h/hv9Ghaz/JoO+/jNXdP82PVnyAAAAVgACAgCBmcb/2+r3/dHh8fyPkpX/kI6N/5yam/+dnJ3/paWk/6enpf+sr6//mpSR/3Bubf9SjbD8H4C+/QsrSvcCAAB/AAAAA3yVx//j8///3u/7/52gpf6pqKf+uLm5/rq7u/7Ly8v+ycnI/paWlf6LjY/+np2f/Xh+g/5gnL7/MX+y/xcgJ80BAgNNN1OUs6W84fDA1O73mJyj/ainpv+2trb/t7e4/8fHyP/Fxsb/kZGQ/4eGhP+vucT/j6G+/W53k/NlkbnwNoOv/AgiNb8CCBsQDRo/YwsaO3B0d33arKyp9q2trfWvr6/2u7u79ru7vPawr7H1sbCt9nJ2gOQIGD6bFCFEYB0qPE1Bf6SpEz9cggAAAAMCAQEBAQAAADIyMmlDQ0ONQUFBhUFBQYVCQkGFQkJBhUhISIRNTU2OKysrZAEAAAUBAQAAAgEAAAkEAAEDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
    { separator: ''},
    { label: "Копировать изображение / текст в base64", func: () => copyFileToBase(), image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AIAQ/wCAEf8AgA//AIAR/wCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AgBX/AIAVAAAAAAAAAAD/AIAo/wCA//8AgP//AID//wCA//8AgP//AIAoAAAAAAAAAAAAAAAAAAAAAP8AgBL/AID//wCA//8AgA3/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgBAAAAAAAAAAAAAAAAD/AIAR/wCA//8AgP//AIAK/wCACv8AgP//AID//wCAIf8AgAX/AIAh/wCA//8AgP//AIAQAAAAAAAAAAAAAAAA/wCACv8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAUAAAAA/wCABf8AgP//AID//wCACgAAAAD/AIAQ/wCADP8AgCH/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCABf8AgCH/AID//wCA//8AgAv/AIAh/wCA//8AgP//AID//wCA//8AgP//AIAH/wCAB/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AIAg/wCA//8AgP//AID//wCA//8AgP//AID//wCAB/8AgAf/AID//wCA//8AgP//AID//wCA//8AgP//AIAh/wCAC/8AgP//AID//wCAHP8AgBz/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCACf8AgA7/AIAMAAAAAP8AgAj/AID//wCA//8AgAP/AIAD/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCABQAAAAAAAAAA/wCADf8AgAr/AIAL/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCAB/8AgAr/AID//wCA//8AgCH/AIAH/wCAJf8AgP//AID//wCAI/8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAf/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgCT/AID//wCA//8AgAr/AIAK/wCA//8AgP//AIAKAAAAAP8AgCj/AID//wCA//8AgP//AID//wCA//8AgCP/AIAM/wCA//8AgP//AIAN/wCADf8AgP//AID//wCADQAAAAAAAAAA/wCAEP8AgBH/AIAP/wCAEf8AgBAAAAAAAAAAAP8AgBT/AIAVAAAAAAAAAAD/AIAV/wCAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQcH5rEGA8KxBAHCsQQBwrEEIQKxBAACsQQAArEEAAKxBAQCsQQwArEEAAKxBAACsQYAArEHBmaxB//+sQQ=="},
    { separator: ''},
    { label: "(Меню ПКМ) Сохр./добавить текст в файл", value: "Save.SelectionToFile" },
    { label: "(Меню ПКМ) Открыть текст в редакторе", value: "Save.TextToEditor"},
];

var menuPopup = self.appendChild(document.createXULElement("menupopup"));
array.forEach((m,i)=> {
    if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return };
    var mItem = menuPopup.appendChild(document.createXULElement("menuitem"));
    mItem.setAttribute("label", m.label);
    mItem.setAttribute("class", "menuitem-iconic");
    if ("image" in m) mItem.setAttribute("image", m.image || array[i-1].image);
    if ("value" in m) {
        mItem.setAttribute('type', 'checkbox');
        mItem.setAttribute('checked', cbu.getPrefs(m.value) );
        mItem.onclick =()=> cbu.setPrefs(m.value, !cbu.getPrefs(m.value));
        }
    if ("func" in m) mItem.addEventListener("command", m.func);
});
menuPopup.onclick = e => e.stopPropagation();


function aDate() {
    var t=new Date();
    var y=1900+t.getYear();
    var min=t.getMinutes(); if (min<10){min="0"+min};
    var h=t.getHours();
    var m=t.getMonth();switch(m){case 0: m="января";break;case 1: m="февраля";break;case 2: m="марта";break;case 3: m="апреля";break;case 4: m="мая";break;case 5: m="июня";break;case 6: m="июля";break;case 7: m="августа";break;case 8: m="сентября";break;case 9: m="октября";break;case 10: m="ноября";break;default: m="декабря";}
    var d=t.getDate();
    var curdate=d+" "+m+" "+y+" "+"г";
    var myfilename=curdate;
    return myfilename;
}


// Копировать favicon сайта в base64
function FaviconToBase(image) {
    var canvas = document.createElementNS(xhtmlns, 'canvas');
    canvas.width = image.naturalWidth;
    canvas.height = image.naturalHeight;
    var ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0);
    var base64 = canvas.toDataURL();
    gClipboard.write(base64);

    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "FaviconToBase";

    as.showAlertNotification(
        base64,
        "Скрипт Save - FaviconToBase",
        "Значок скопирован как base64",
        false,
        "",
        null,
        alertName
    );

    setTimeout(as.closeAlert, 5e3, alertName);
};

// Сохранить страницу / выбор как HTML
function savePageToHTML() {
var vert = String.raw`javascript:(function(){var getSelWin=function(w){if(w.getSelection().toString())return w;for(var i=0,f,r;f=w.frames[i];i++){try{if(r=getSelWin(f))return r}catch(e){}}};var selWin=getSelWin(window),win=selWin||window,doc=win.document,loc=win.location;var qualifyURL=function(url,base){if(!url||/^([a-z]+:|%23)/.test(url))return url;var a=doc.createElement('a');if(base){a.href=base;a.href=a.protocol+(url.charAt(0)=='/'%3F(url.charAt(1)=='/'%3F'':'//'+a.host):'//'+a.host+a.pathname.slice(0,(url.charAt(0)!='%3F'&&a.pathname.lastIndexOf('/')+1)||a.pathname.length))+url}else{a.href=url};return a.href};var encodeImg=function(src,obj){var canvas,img,ret=src;if(/^https%3F:%5C/%5C//.test(src)){canvas=doc.createElement('canvas');if(!obj||obj.nodeName.toLowerCase()!='img'){img=doc.createElement('img');img.src=src}else{img=obj};if(img.complete)try{canvas.width=img.width;canvas.height=img.height;canvas.getContext('2d').drawImage(img,0,0);ret=canvas.toDataURL((/%5C.jpe%3Fg/i.test(src)%3F'image/jpeg':'image/png'))}catch(e){};if(img!=obj)img.src='about:blank'};return ret};var toSrc=function(obj){var strToSrc=function(str){var chr,ret='',i=0,meta={'%5Cb':'%5C%5Cb','%5Ct':'%5C%5Ct','%5Cn':'%5C%5Cn','%5Cf':'%5C%5Cf','%5Cr':'%5C%5Cr','%5Cx22':'%5C%5C%5Cx22','%5C%5C':'%5C%5C%5C%5C'};while(chr=str.charAt(i++)){ret+=meta[chr]||chr};return'%5Cx22'+ret+'%5Cx22'},arrToSrc=function(arr){var ret=[];for(var i=0;i<arr.length;i++){ret[i]=toSrc(arr[i])||'null'};return'['+ret.join(',')+']'},objToSrc=function(obj){var val,ret=[];for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj,prop)&&(val=toSrc(obj[prop])))ret.push(strToSrc(prop)+': '+val)};return'{'+ret.join(',')+'}'};switch(Object.prototype.toString.call(obj).slice(8,-1)){case'Array':return arrToSrc(obj);case'Boolean':case'Function':case'RegExp':return obj.toString();case'Date':return'new Date('+obj.getTime()+')';case'Math':return'Math';case'Number':return isFinite(obj)%3FString(obj):'null';case'Object':return objToSrc(obj);case'String':return strToSrc(obj);default:return obj%3F(obj.nodeType==1&&obj.id%3F'document.getElementById('+strToSrc(obj.id)+')':'{}'):'null'}};var ele,pEle,clone,reUrl=/(url%5C(%5Cx22%3F)(.+%3F)(%5Cx22%3F%5C))/g;if(selWin){var rng=win.getSelection().getRangeAt(0);pEle=rng.commonAncestorContainer;ele=rng.cloneContents()}else{pEle=doc.documentElement;ele=(doc.body||doc.getElementsByTagName('body')[0]).cloneNode(true)};while(pEle){if(pEle.nodeType==1){clone=pEle.cloneNode(false);clone.appendChild(ele);ele=clone};pEle=pEle.parentNode};var sel=doc.createElement('div');sel.appendChild(ele);for(var el,all=sel.getElementsByTagName('*'),i=all.length;i--;){el=all[i];if(el.style&&el.style.backgroundImage)el.style.backgroundImage=el.style.backgroundImage.replace(reUrl,function(a,b,c,d){return b+encodeImg(qualifyURL(c))+d});switch(el.nodeName.toLowerCase()){case'link':case'style':case'script':el.parentNode.removeChild(el);break;case'a':case'area':if(el.hasAttribute('href')&&el.getAttribute('href').charAt(0)!='%23')el.href=el.href;break;case'img':case'input':if(el.hasAttribute('src'))el.src=encodeImg(el.src,el);break;case'audio':case'video':case'embed':case'frame':case'iframe':if(el.hasAttribute('src'))el.src=el.src;break;case'object':if(el.hasAttribute('data'))el.data=el.data;break;case'form':if(el.hasAttribute('action'))el.action=el.action;break}};var head=ele.insertBefore(doc.createElement('head'),ele.firstChild);var meta=doc.createElement('meta');meta.httpEquiv='content-type';meta.content='text/html; charset=utf-8';head.appendChild(meta);var title=doc.getElementsByTagName('title')[0];if(title)head.appendChild(title.cloneNode(true));head.copyScript=function(){if('$'in win)return;var f=doc.createElement('iframe');f.src='about:blank';f.style.cssText ='position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;';doc.documentElement.appendChild(f);var str,script=doc.createElement('script');script.type='text/javascript';for(var name in win){if(name in f.contentWindow||!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name))continue;try{str=toSrc(win[name]);if(!/%5C{%5Cs*%5C[native code%5C]%5Cs*%5C}/.test(str)){script.appendChild(doc.createTextNode('var '+name+' = '+str.replace(/<%5C/(script>)/ig,'<%5C%5C/$1')+';%5Cn'))}}catch(e){}};f.parentNode.removeChild(f);if(script.childNodes.length)this.nextSibling.appendChild(script)};head.copyScript();head.copyStyle=function(s){if(!s)return;var style=doc.createElement('style');style.type='text/css';if(s.media&&s.media.mediaText)style.media=s.media.mediaText;try{for(var i=0,rule;rule=s.cssRules[i];i++){if(rule.type!=3){if((!rule.selectorText||rule.selectorText.indexOf(':')!=-1)||(!sel.querySelector||sel.querySelector(rule.selectorText))){style.appendChild(doc.createTextNode(rule.cssText.replace(reUrl,function(a,b,c,d){var url=qualifyURL(c,s.href);if(rule.type==1&&rule.style&&rule.style.backgroundImage)url=encodeImg(url);return b+url+d})+'%5Cn'))}}else{this.copyStyle(rule.styleSheet)}}}catch(e){if(s.ownerNode)style=s.ownerNode.cloneNode(false)};this.appendChild(style)};var sheets=doc.styleSheets;for(var j=0;j<sheets.length;j++)head.copyStyle(sheets[j]);head.appendChild(doc.createTextNode('%5Cn'));var doctype='',dt=doc.doctype;if(dt&&dt.name){doctype+='<!DOCTYPE '+dt.name;if(dt.publicId)doctype+=' PUBLIC %5Cx22'+dt.publicId+'%5Cx22';if(dt.systemId)doctype+=' %5Cx22'+dt.systemId+'%5Cx22';doctype+='>%5Cn'};var href = 'data:text/html;charset=utf-8,' + encodeURIComponent(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->');var a = document.documentElement.appendChild(document.createElement("a"));a.setAttribute("href", href);var name = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());name=name.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');name += (function () {var d = new Date(), z=function(n){return '_' + (n < 10 ? '0' : '') + n};return z(d.getHours()) + z(d.getMinutes()) + z(d.getSeconds());})();a.setAttribute("download", name + ".html");a.click();a.remove();})();`;
gBrowser.fixupAndLoadURIString(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
};

// Получить имя файла
async function pick(fileName) {
    try {
        var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
        await IOUtils.makeDirectory(file.path);
    } catch {
        file = Services.dirsvc.get("Desk", Ci.nsIFile);
    }
    var fp = makeFilePicker();
    fp.init(window.browsingContext, "", fp.modeSave);
    fp.displayDirectory = file;
    fp.defaultString = fileName;
    return await new Promise(fp.open) != fp.returnCancel && fp.file;
}

// Сохранить favicon сайта
function saveFavicon() {
    var dn = "favicon";
    var re = /^data:(image\/[^;,]+)/i;
    var ms = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
    (saveFavicon = async () => {
        var url = gBrowser.selectedTab.image;
        if (!url) return;
        if (re.test(url)) {
            try {var name = gBrowser.currentURI.host || dn;} catch {name = dn;}
            name += "." + ms.getPrimaryExtension(RegExp.$1, "ico");
        } else
            var name = Services.io.newURI(url).QueryInterface(Ci.nsIURL).fileName;

        var file = await pick(name);
        file && IOUtils.write(file.path, new Uint8Array(await (await fetch(url)).arrayBuffer()));
    })();
}

// Сохранить ярлык страницы как …
function saveShortcuts() {
    var img = self.getAttribute("image");
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    (saveShortcuts = async () => {
        var file = await pick(getTabLabel() + ".url");
        if (file)
            await IOUtils.writeUTF8(file.path, `[InternetShortcut]\r\nURL=${gBrowser.currentURI.spec}\r\n`),
            as.showAlertNotification(
                gBrowser.selectedTab.image || img, file.leafName, "Сохранил в: " + file.parent.path
            );
    })();
}

// Копировать изображение или текстовой файл в base64 ...
function copyFileToBase(){
var fp = window.makeFilePicker();
fp.init(window.browsingContext, "Открыть файл", fp.modeOpen);
fp.appendFilter(
"Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml;\
                    *.xhtml; *.json; *.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg;\
                    *.svgz; *.tif; *.tiff; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp");
    fp.open(re=> {
    if ( re != fp.returnOK ) return;
    var file = fp.file;
    var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
    inputStream.init(file, 0x01, 0o600, 0);
    var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
    stream.setInputStream(inputStream);
    var encoded = btoa(stream.readBytes(stream.available()));
    var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file);
    var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded;
    gClipboard.write(dataURI);

    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "FileToBase";

    as.showAlertNotification(
        dataURI,
        "Скрипт Save - FileToBase",
        "Файл скопирован как base64",
        false,
        "",
        null,
        alertName
    );

    setTimeout(as.closeAlert, 5e3, alertName);
    });
};

// Сохранить страницу как PDF, скриптом ...
function savePageToPDF() {
    var ps = Ci.nsIPrintSettings, cfg = {

        paperWidth: 8.5,
        paperHeight: 11,
        paperSizeUnit: ps.kPaperSizeInches, // kPaperSizeMillimeters

        marginLeft: .2,
        marginRight: .2,
        marginTop: .2,
        marginBottom: .2,

        edgeLeft: .1,
        edgeRight: .1,
        edgeTop: 0,
        edgeBottom: 0,

        headerStrLeft: "&T",
        headerStrCenter: "",
        headerStrRight: "&U",

        footerStrLeft: "&PT",
        footerStrCenter: "",
        footerStrRight: "&D",

        printBGColors: true,
        printBGImages: false,

        scaling: 1,
        shrinkToFit: true, // overrides scaling
        orientation: ps.kPortraitOrientation, // kLandscapeOrientation

        printerName: "",
        printSilent: true,
        printToFile: true,
        showPrintProgress: false,
        isInitializedFromPrefs: false,
        isInitializedFromPrinter: false,
        outputFormat: ps.kOutputFormatPDF,
        outputDestination: ps.kOutputDestinationFile,
    };
    ps = Cc["@mozilla.org/gfx/printsettings-service;1"]
        .getService(Ci.nsIPrintSettingsService).createNewPrintSettings();
    for(var key in cfg) if (key in ps) ps[key] = cfg[key];
    (savePageToPDF = async () => {
        try {
            var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
            await IOUtils.makeDirectory(file.path);
        } catch {
            file = Services.dirsvc.get("Desk", Ci.nsIFile);
        }
        file.append(`Snap ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")}.pdf`);
        ps.toFileName = file.path;
        await gBrowser.selectedBrowser.browsingContext.print(ps);
        //file.launch();
    })();
};


// Копировать favicon сайта в base64 ...
function copyFaviconData() {
    var img = new Image();
    img.src = gBrowser.selectedTab.image;
    FaviconToBase(img);
};


// Сохранить URL, страницу / выбор как TXT ...
function saveSelectionToTxt() {
    // [129+] l11 = length >= 11; https://forum.mozilla-russia.org/profile.php?id=71856
    var {length} = saveURL, splice = length > 9, l11 = length >= 11;
    var msgName = _id + ":Save:GetSelection";
    var receiver = msg => {
        var args = [
            "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + msg.data),
            getTabLabel() + '   ' + aDate().replace(/:/g, ".") + ".txt",
            null, false, false, null, window.document
        ];
        splice && args.splice(5, 0, null) && l11 && args.splice(1, 0, null);
        saveURL(...args);
    }
    messageManager.addMessageListener(msgName, receiver);
    addDestructor(() => messageManager.removeMessageListener(msgName, receiver));

    var func = fm => {
        var res, fed, win = {};
        var fe = fm.getFocusedElementForWindow(content, true, win);
        var sel = (win = win.value).getSelection();
        if (sel.isCollapsed) {
            var ed = fe && fe.editor;
            if (ed && ed instanceof Ci.nsIEditor)
                sel = ed.selection, fed = fe;
        }
        if (sel.isCollapsed)
            fed && fed.blur(),
            docShell.doCommand("cmd_selectAll"),
            res = win.getSelection().toString(),
            docShell.doCommand("cmd_selectNone"),
            fed && fed.focus();

        res = res || sel.toString();
        /\S/.test(res) && sendAsyncMessage("NAME", res);
    }
    var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("NAME", msgName))
        + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));';
    (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))();
}


// Добавляем в контекстного меню страницы новые пункты ...
((contextMenu, el)=> {

    // в контекстное меню выделенного текста ...
    var saveItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
    saveItem.id = "content-saveItem";
    saveItem.setAttribute("label", "Сохр./добавить текст в файл");
    saveItem.setAttribute("class", "menuitem-iconic");
    saveItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
    saveItem.onclick =()=> saveSelectionToFile();

    var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
    editorItem.id = "content-editorItem";
    editorItem.setAttribute("label", "Открыть текст в редакторе");
    editorItem.setAttribute("class", "menuitem-iconic");
    editorItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcXFz/Wlpa/1paWv9aWlr/Wlpa/1paWv9aWlr/Wlpa/1paWv9aWlr/Wlpa/1paWv9cXFz/AAAAAAAAAAAAAAAAXFxc//n7+f39/v3+/f79/v7+/v7+/v7+/v7+/f7+/v3+/v78/v7+/P////v////2XV1d/wAAAAAAAAAAAAAAAF9fX//7/fv/FVcX/wBIAv8ASAL/AEgC/wBIAv8ASAL/AEgC/wBIAv8VVxf//f78/2BgYP8AAAAAAAAAAAAAAABhYWH/+/78/zRtNf8otUX/KLVF/yi1Rf8otUX/ZLal/ypBSf9Upcv/NG01//z+/P9kZGT/AAAAAAAAAAAAAAAAZGRk//v+/P9Yh1n/MtB1/zLQdf8y0HX/MtB1/3PZrv9Tpcz/AXfF/2WYiP/8/v3/Z2dn/wAAAAAAAAAAAAAAAGZmZv/8/v3/gKSB/zvdof873aH/O92h/zvdof873aH/Fsj4/wSo6/8Ldr3//f7+/2tra/8AAAAAAAAAAAAAAABpaWn//P/+/6fAqP9C4bn/QuG5/0Lhuf9C4bn/QuG5/1vkxf8GwP7/AXfH/5HD4v9ubm7/AAAAAAAAAAAAAAAAa2tr//z//v/L2sz/lt7S/5be0v+W3tL/lt7S/5be0v+W3tL/Ms34/wSv8P8Abr7/cnJy/wAAAAAAAAAAAAAAAG5ubv/9/v7/6vDq/2Xo3f9l6N3/Zejd/2Xo3f9l6N3/Zejd/2Xo3f8GwP7/AXvJ/1uPsP8AAAAAAAAAAAAAAABwcHD//v////Hu5//l4NT/5eDU/+Xg1P/l4NT/5eDU/+Xg1P/l4NT/XNT5/wS39/8Abr//5PH2GgAAAAAAAAAAc3Nz/////////////v79//7+/f/+/v3//v79//7+/f/+/v3//v79//////8Gwf7/AYPN/xh+wukAAAAAAAAAAHV1df//////7Onh/+Xg1P/l4NT/5eDU/+Xg1P/l4NT/gYGB/4CAgP+AgID/U67L/wS2+P8AbcD/4ezzIAAAAAB4eHj///////39/P///////////////////////Pv6/4CAgP/9/f3//f39/4GBgf4Nwv3+UI+q/4x+d9IAAAAAenp6//////+Wlpf/9/X0/5OTlP/18/L/k5OU//Lv7f+AgID//f39/4GBgf6EhIRd8OXhU8yplP9yWU7/zsjCXH19ff+3t7f/////KLq6uv////8ourq6/////yi6urr/gICA/4GBgf6EhIRdAAAAAAAAAACxqMC5HhmE/wAAdP+AgID/gICA/56entOBgYH/n5+f1oGBgf+fn5/WgYGB/4GBgf+EhIRJAAAAAAAAAAAAAAAA5Of3EAcKj/8AAHP/AAesQQAHrEEAB6xBAAesQQAHrEEAB6xBAAesQQAHrEEAB6xBAAOsQQADrEEAAaxBAAGsQQAArEEAGKxBADisQQ==");
    editorItem.onclick =()=> textToEditor();


// устанавливаем где и при каких настройках показывать новые пункты ....
    addEventListener('popupshowing', e=> {
        if (e.target != e.currentTarget) return;
        var sel = gContextMenu.isTextSelected;
        saveItem.hidden = !sel || !cbu.getPrefs("Save.SelectionToFile");
        editorItem.hidden = !sel || !cbu.getPrefs("Save.TextToEditor");
        }, false, contextMenu);

    // удалять новые пункти при изменениях ....
    addDestructor(()=> {
        saveItem.remove(); editorItem.remove();
    });
})(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open"));


// Сохранить или добавить выделенный текст в файл в папке загрузок, если назначена,
// иначе на Рабочий стол .............
function saveSelectionToFile() {
    var line = ".".repeat(62) + "\n";
    var hint = "Нажмите чтобы открыть файл";
    var prfx = "Выбранный текст сохранен в файл ";

    var img = self.getAttribute("image");
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);

    (saveSelectionToFile = async () => {
        var time = aDate(), url = gBrowser.currentURI.displaySpec;
        var text = `${line}${getTabLabel()} - ${time}\n${url}\n\n${
            gContextMenu.contentData.selectionInfo.fullText
        }\n\n\n`;
        try {
            var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
            var msg = prfx + "в папку " + file.leafName;
            await IOUtils.makeDirectory(file.path);
        } catch(ex) {
            file && Cu.reportError(ex);
            file = desk.clone();
            var msg = prfx + "на рабочий стол";
        }
        file.append(`Save - ${time}.txt`);
        await IOUtils.writeUTF8(file.path, text, {mode: file.exists() ? "append" : "create"});

        var name = "sstf-" + Cu.now();
        as.showAlertNotification(
            gBrowser.selectedTab.image || img, msg, hint, true, "",
            (s, t) => t == "alertclickcallback" && file.launch(), name
        );
        setTimeout(as.closeAlert, 8e3, name);
    })();
};


// Создать текстовой файл с выбранным текстом в папке загрузок, если назначена,
// иначе на Рабочий стол, и открыть в редакторе ...
function textToEditor() {
let browserMM = gBrowser.selectedBrowser.messageManager;
browserMM.addMessageListener('getSelect', function listener(message) {
    // создать текст для записи
    var text = convertFromUnicode("UTF-8", message.data);
    try {var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {file = Services.dirsvc.get("Desk", Ci.nsIFile);}
    file.append("TextToEditor.txt");
    custombuttonsUtils.writeFile(file.path, text);
    file.launch();

    browserMM.removeMessageListener('getSelect', listener, true);
});
    browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false);
};


// Конвертировать текст в юникод ...
function convertFromUnicode(charset, str) {
     var converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.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);
};
((main, parts) => this.onmousedown = e => {
    if (e.button) return;
    this.onmousedown = null;

    var df = MozXULElement.parseXULToFragment(`
        <menugroup orient="vertical">
            <menuseparator/>
            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity' d='M13.946 2.353c.273 0 .498.23.498.513v10.262l-.156-.209-4.233-5.647a.737.737 0 0 0-1.183 0l-2.584 3.446-.95-1.37a.732.732 0 0 0-1.214.003l-2.49 3.594-.14.199V2.866c0-.282.224-.513.498-.513h11.954zM1.992.813C.893.813 0 1.732 0 2.865v10.268c0 1.133.893 2.054 1.992 2.054h11.954c1.098 0 1.992-.921 1.992-2.054V2.866c0-1.133-.894-2.054-1.992-2.054H1.992zm2.49 6.16a1.494 1.54 0 1 0 0-3.08 1.494 1.54 0 1 0 0 3.08z'/></svg>"
                label="Сохранить всю страницу как PNG"
                value="all"/>

            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity' d='M13.946 2.353c.273 0 .498.23.498.513v10.262l-.156-.209-4.233-5.647a.737.737 0 0 0-1.183 0l-2.584 3.446-.95-1.37a.732.732 0 0 0-1.214.003l-2.49 3.594-.14.199V2.866c0-.282.224-.513.498-.513h11.954zM1.992.813C.893.813 0 1.732 0 2.865v10.268c0 1.133.893 2.054 1.992 2.054h11.954c1.098 0 1.992-.921 1.992-2.054V2.866c0-1.133-.894-2.054-1.992-2.054H1.992zm2.49 6.16a1.494 1.54 0 1 0 0-3.08 1.494 1.54 0 1 0 0 3.08z'/></svg>"
                label="Сохранить видимую часть как PNG"
                value="page"/>

            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><g style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity'><path d='M11.108 8.852c.327 0 .591-.27.591-.602a.596.596 0 0 0-.59-.602c-.327 0-.591.27-.591.602 0 .332.264.602.59.602z'/><path d='M4.808 7.047c0-.665.53-1.203 1.182-1.203h6.3c.652 0 1.18.538 1.18 1.203v4.01c0 .665-.528 1.203-1.18 1.203h-6.3a1.192 1.192 0 0 1-1.182-1.203v-4.01zm1.182 0v3.524l1.639-1.808a.972.972 0 0 1 1.446 0l2.074 2.287-.008.007h1.149v-4.01h-6.3zm2.362 2.691-1.195 1.32h2.39l-1.195-1.32z'/><path d='M3.036 1.833C1.406 1.833.083 3.18.083 4.841v6.818c0 1.661 1.323 3.008 2.953 3.008h9.844c1.631 0 2.953-1.347 2.953-3.008V4.84c0-1.661-1.322-3.008-2.953-3.008H3.036zM1.265 4.841c0-.997.793-1.805 1.771-1.805h9.844c.979 0 1.772.808 1.772 1.805v6.818c0 .997-.793 1.805-1.772 1.805H3.036c-.978 0-1.771-.808-1.771-1.805V4.84z'/></g></svg>"
                label="Сохранить выбранный элемент как PNG"
                value="click"/>

            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='context-fill' fill-opacity='context-fill-opacity'><path fill-rule='evenodd' d='M2.63 1.255c-.76 0-1.375.616-1.375 1.375v2.685a.625.625 0 0 1-1.25 0V2.63A2.625 2.625 0 0 1 2.63.005h2.685a.625.625 0 1 1 0 1.25H2.63ZM10.06.63c0-.345.28-.625.625-.625h2.685a2.625 2.625 0 0 1 2.625 2.625v2.685a.625.625 0 1 1-1.25 0V2.63c0-.76-.616-1.375-1.375-1.375h-2.685A.625.625 0 0 1 10.06.63Zm5.31 9.43c.345 0 .625.28.625.625v2.685a2.625 2.625 0 0 1-2.625 2.625h-2.685a.625.625 0 1 1 0-1.25h2.685c.76 0 1.375-.616 1.375-1.375v-2.685c0-.345.28-.625.625-.625ZM2.729 7.3c-.79 0-1.43.64-1.43 1.429v4.542c0 .79.64 1.43 1.43 1.43H7.27c.79 0 1.43-.64 1.43-1.43V8.73c0-.79-.64-1.43-1.43-1.43H2.73ZM0 8.728A2.729 2.729 0 0 1 2.729 6H7.27A2.729 2.729 0 0 1 10 8.729v4.542A2.729 2.729 0 0 1 7.271 16H2.73A2.729 2.729 0 0 1 0 13.271V8.73Z' clip-rule='evenodd'/><path d='M6.9 14.005H2.73a.5.5 0 0 1-.372-.835l2.085-2.317a.5.5 0 0 1 .744 0l2.085 2.317a.5.5 0 0 1-.371.835ZM8 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'/></svg>"
                label="Сохранить выбранную область как PNG"
                value="clipping"/>
        </menugroup>
    `);
    var menugroup = df.firstChild;
    menugroup.setAttribute("context", "");
    menugroup.handleCommand = e => {
        var name = _id + ":DataURLReady";
        main = main.replace("%MESSAGE_NAME%", name);

        var urls = {}, configurable = true, enumerable = true;
        Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, {
            configurable, enumerable, get() {
                var value = `data:;charset=utf-8,({${
                    encodeURIComponent(main + part)
                }%0A}).init("${key}")`;
                Object.defineProperty(urls, key, {configurable, enumerable, value});
                return value;
        }}));
        var getTabLabel = () => {
            var label = gBrowser.selectedTab.label;
            var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
            return label.substring(0, 50);
        }
        var listener = msg => {
            var fp = makeFilePicker();
            fp.init(window.browsingContext, "Сохранить как…", fp.modeSave);
            fp.appendFilter("", "*.png");
            fp.defaultString = getTabLabel() + ".png";
            fp.open(res => {
                if (res == fp.returnCancel || !fp.file) return;
                var wbp = makeWebBrowserPersist(), args = [
                    Services.io.newURI(msg.data), document.nodePrincipal,
                    null, null, null, null, fp.file, null
                ];
                //wbp.saveURI.length == 9 && splice(args);
                var {length} = wbp.saveURI;
                length >= 9 && splice(args);
                length == 10 && args.splice(3, 0, null);
                wbp.saveURI(...args);
            });
        }
        var splice = arr => {
            var fox74 = parseInt(Services.appinfo.platformVersion) >= 74;
            var args = [fox74 ? 7 : 2, 0, fox74 ? Ci.nsIContentPolicy.TYPE_IMAGE : null];
            (splice = arr => arr.splice(...args))(arr);
        }
        messageManager.addMessageListener(name, listener);
        addDestructor(() => messageManager.removeMessageListener(name, listener));

        (menugroup.handleCommand = e => gBrowser.selectedBrowser.messageManager
            .loadFrameScript(urls[e.target.value], false)
        )(e);
    }
    menugroup.addEventListener("command", e => menugroup.handleCommand(e));
    menuPopup.querySelector('menuitem[label*="ярлык"]').after(df);
})(`
    init(cmd) {
        cmd.startsWith("c")
            ? this[cmd].init(this[cmd].parent = this)
            : this[cmd]();
    },
    capture(win, x, y, width, height) {
        var canvas = win.document.createElementNS("${xhtmlns}", "canvas");
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        var tryDraw = ind => {
            try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")}
            catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);}
        }
        tryDraw(17);
        sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png"));
    },
    `, {

    all: `all() {
        var win = content;
        this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY);
    }`,
    page: `page() {
        var win = content, doc = win.document, body = doc.body, html = doc.documentElement;
        var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft;
        var scrY = (body.scrollTop || html.scrollTop) - html.clientTop;
        this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight);
    }`,
    clipping: `clipping: {
        handleEvent(e) {
            if (e.button) return false;
            e.preventDefault();
            e.stopPropagation();
            switch(e.type) {
                case "mousedown":
                    this.downX = e.pageX;
                    this.downY = e.pageY;
                    this.bs.left = this.downX + "px";
                    this.bs.top = this.downY + "px";
                    this.body.appendChild(this.box);
                    this.flag = true;
                    break;
                case "mousemove":
                    if (!this.flag) return;
                    this.moveX = e.pageX;
                    this.moveY = e.pageY;
                    if (this.downX > this.moveX) this.bs.left = this.moveX + "px";
                    if (this.downY > this.moveY) this.bs.top    = this.moveY + "px";
                    this.bs.width = Math.abs(this.moveX - this.downX) + "px";
                    this.bs.height = Math.abs(this.moveY - this.downY) + "px";
                    break;
                case "mouseup":
                    this.uninit();
                    break;
            }
        },
        init() {
            var win = {};
            Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
                .getFocusedElementForWindow(content, true, win);
            this.win = win.value;

            this.doc = this.win.document;
            this.body = this.doc.body;
            if (!HTMLBodyElement.isInstance(this.body)) {
                Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
                    .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!");
                return false;
            }
            this.flag = null;
            this.box = this.doc.createElement("div");
            this.bs = this.box.style;
            this.bs.border = "#0f0 dashed 2px";
            this.bs.position = "absolute";
            this.bs.zIndex = "2147483647";
            this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor;
            this.body.style.cursor = "crosshair";
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)];
            this.body.style.cursor = this.defaultCursor;
            this.body.removeChild(this.box);
            this.parent.capture.apply(this, pos);
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`,
    click: `click: {
        getPosition() {
            var html = this.doc.documentElement;
            var body = this.doc.body;
            var rect = this.target.getBoundingClientRect();
            return [
                this.win,
                Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft,
                Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop,
                parseInt(rect.width),
                parseInt(rect.height)
            ];
        },
        highlight() {
            this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false;
            this.target.style.cssText += "outline: red 2px solid; outline-offset: 2px; -moz-outline-radius: 2px;";
        },
        lowlight() {
            if (this.orgStyle) this.target.style.cssText = this.orgStyle;
            else this.target.removeAttribute("style");
        },
        handleEvent(e) {
            switch(e.type){
                case "click":
                    if (e.button) return;
                    e.preventDefault();
                    e.stopPropagation();
                    this.lowlight();
                    this.parent.capture.apply(this, this.getPosition());
                    this.uninit();
                    break;
                case "mouseover":
                    if (this.target) this.lowlight();
                    this.target = e.target;
                    this.highlight();
                    break;
            }
        },
        init() {
            this.win = content;
            this.doc = content.document;
            ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            this.target = false;
            ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`
});


Save_Button.js

Выделить код

Код:

/**
@UCF @param {"prop":"JsBackground"} @UCF
*/
// Кнопка Save - Основной скрипт в Save_Script.js
// Правка Vitaliy V. 2505
// Предыдущая версия
// https://forum.mozilla-russia.org/viewtopic.php?pid=809376#p809376

(async () => CustomizableUI.createWidget({
  id: "ucf-cbbtn-Save",
  tooltiptext: "Сохранить страницу\n/ часть / выбранное",
  nameSaveScript: "Save_Script.js",
  localized: false,
  cbu: {
    types: {
      128: "Bool", boolean: "Bool",
      64: "Int", number: "Int",
      32: "String", string: "String"
    },
    getPrefs(pref) {
      try {
        return Services.prefs[`get${
          this.types[Services.prefs.getPrefType(pref)]
        }Pref`](pref);
      }
      catch {return null;}
    },
    setPrefs(pref, val) {
      Services.prefs[`set${this.types[typeof val]}Pref`](pref, val);
    }
  },
  gClipboard: {
    get ch() {
      delete this.ch;
      return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"]
        .getService(Ci.nsIClipboardHelper);
    },
    write(str) {
      this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard);
    }
  },
  custombuttonsUtils: {
    writeFile(path, data) {
      try {
        if (path.includes(":\\")) path = path.replace(/\//g, "\\");
        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        file.exists() && file.remove(false);

        var strm = Cc["@mozilla.org/network/file-output-stream;1"]
          .createInstance(Ci.nsIFileOutputStream);
        strm.init(file, 0x04 | 0x08, 420, 0);
        strm.write(data, data.length);
        strm.flush();
        strm.close();
      } catch(ex) {
        Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n"));
      }
    }
  },
  addDestructor(destructor, context) {
    this._destructors.push({destructor, context});
  },
  addEventListener(...args) {
    var trg = args[3];
    if (!trg) trg = args[3] = this.ownerGlobal;
    trg.addEventListener(...args);
    this._handlers.push(args);
  },

  onCreated(btn) {
    var win = btn.ownerGlobal;
    btn._handlers = new win.Array();
    btn._destructors = new win.Array();
    win.addEventListener("unload", this, {once: true});
    btn.self = btn;
    btn._id = this.id;
    btn.cbu = this.cbu;
    btn.xhtmlns = "http://www.w3.org/1999/xhtml";
    btn.addDestructor = this.addDestructor.bind(btn);
    btn.addEventListener = this.addEventListener.bind(btn);
    btn.gClipboard = this.gClipboard;
    btn.custombuttonsUtils = this.custombuttonsUtils;
    Services.scriptloader.loadSubScript(`chrome://user_chrome_files/content/custom_scripts/cs/${this.nameSaveScript}`, btn);
    btn.setAttribute("image", this.image);
  },
  get image() {
    var img = `${this.id.toLowerCase()}-img`;
    Services.io.getProtocolHandler("resource")
      .QueryInterface(Ci.nsIResProtocolHandler)
      .setSubstitution(img, Services.io.newURI("data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="));
      delete this.image;
      return this.image = `resource://${img}`;
  },
  handleEvent(e) {
    var btn = e.target.getElementById(this.id);
    for(var args of btn._handlers)
      args.pop().removeEventListener(...args);
    delete btn._handlers;
    for(var {destructor, context} of btn._destructors)
      try {destructor.call(context, "destructor");}
      catch(ex) {Cu.reportError(ex);}
    delete btn._destructors;
  }
}))();


custom_script.js

Выделить код

Код:

/**
@UCF @param {"prop":"JsBackground","disable":true} @UCF
*/
(async () => CustomizableUI.createWidget({
  id: "ucf-cbbtn-Save",
  tooltiptext: "Сохранить",
  localized: false,
    get initCode() {
    var count = 0;
    var prfx = "ucf-cbbtn-save-resurl-";
    var rph = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
    var ss = url => {
      var subst = prfx + ++count;
      rph.setSubstitution(subst, Services.io.newURI(url));
      return "resource://" + subst;
    }
    this.image = ss("data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
    var arr = [
      "@-moz-document url(chrome://browser/content/browser.xhtml) {",
      `  #${this.id} menuitem, #content-baseItem, #content-saveItem, #content-editorItem {`,
      "    fill: currentColor !important;",
      "    -moz-context-properties: fill, fill-opacity !important;",
      "  }",
      "}",

      "}"
    ];
    var url = "data:text/css;charset=utf-8," + encodeURIComponent(arr.join("\n"));
    var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
    sss.loadAndRegisterSheet(Services.io.newURI(ss(url)), sss.USER_SHEET);

    delete this.initCode;
    return this.initCode = Cu.readUTF8URI(Services.io.newURI(
      "chrome://user_chrome_files/content/custom_scripts/cs/Save_Script.js"
    ))
      .replace(/data:image\/svg[^"]+/g, ss);
  },
  cbu: {
    types: {
      128: "Bool", boolean: "Bool",
      64: "Int", number: "Int",
      32: "String", string: "String"
    },
    getPrefs(pref) {
      try {
        return Services.prefs[`get${
          this.types[Services.prefs.getPrefType(pref)]
        }Pref`](pref);
      }
      catch {return null;}
    },
    setPrefs(pref, val) {
      Services.prefs[`set${this.types[typeof val]}Pref`](pref, val);
    }
  },
  gClipboard: {
    get ch() {
      delete this.ch;
      return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"]
        .getService(Ci.nsIClipboardHelper);
    },
    write(str) {
      this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard);
    }
  },
  custombuttonsUtils: {
    writeFile(path, data) {
      try {
        if (path.includes(":\\")) path = path.replace(/\//g, "\\");
        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        file.exists() && file.remove(false);

        var strm = Cc["@mozilla.org/network/file-output-stream;1"]
          .createInstance(Ci.nsIFileOutputStream);
        strm.init(file, 0x04 | 0x08, 420, 0);
        strm.write(data, data.length);
        strm.flush();
        strm.close();
      } catch(ex) {
        Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n"));
      }
    }
  },
  addDestructor(destructor, context) {
    this._destructors.push({destructor, context});
  },
  addEventListener(...args) {
    var trg = args[3];
    if (!trg) trg = args[3] = this.ownerGlobal;
    trg.addEventListener(...args);
    this._handlers.push(args);
  },

    onCreated(btn) {
    var win = btn.ownerGlobal;
    btn._handlers = new win.Array();
    btn._destructors = new win.Array();
    win.addEventListener("unload", this, {once: true});
    new win.Function(
      "self,_id,cbu,xhtmlns,addDestructor,addEventListener,gClipboard,custombuttonsUtils",
      this.initCode
    ).call(
      btn, btn, this.id, this.cbu,
      "http://www.w3.org/1999/xhtml",
      this.addDestructor.bind(btn),
      this.addEventListener.bind(btn),
      this.gClipboard, this.custombuttonsUtils
    );
        btn.setAttribute("image", this.image);
    },
  handleEvent(e) {
    var btn = e.target.getElementById(this.id);
    for(var args of btn._handlers)
      args.pop().removeEventListener(...args);
    delete btn._handlers;
    for(var {destructor, context} of btn._destructors)
      try {destructor.call(context, "destructor");}
      catch(ex) {Cu.reportError(ex);}
    delete btn._destructors;
  }
}))();

Добавлено Сегодня 16:07:18
https://imgsh.net/i/794afa4da1

Отредактировано xrun1 (Сегодня 16:07:18)

Отсутствует

 

№2096Сегодня 16:56:25

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 676
UA: Firefox 137.0

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

Если в секции с PNG заменить иконки на svg, отображаться не будут.

Попробовал. В консоли две ошибки: Ошибка синтаксического анализа XML и Uncaught Error: not well-formed XML.
Что с этим делать я не знаю. Может знатоки подскажут.

Отредактировано unter_officer (Сегодня 17:12:31)


«The Truth Is Out There»

Отсутствует

 

№2097Сегодня 17:33:50

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1190
UA: Seamonkey 2.49

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

Может, куки прицепились? У меня на сайте правильно переводит.

Попробовал из абсолютно нового профиля (причём в этом профиле и набор предпочитаемых языков другой, и даже язык интерфейса программы). Результат такой же, как и раньше.


Может, у Google ещё и какие-то географические привязки есть?


Из любопытства попробовал ту же фразу перевести ещё несколькими переводчиками. Получил:

  • Google: Вы кладете это на немного толстого.
  • DeepL: Вы слишком много говорите. (Вы слишком много на себя берете.)
  • Яндекс: Ты немного сгущаешь краски.
  • Reverso: Ты накладываешь его немного туго.
  • Translate.com: Вы укладываете его немного толстее.

В общем, "не Гуглом единым..."

Отредактировано yup (Сегодня 17:34:19)

Отсутствует

 

№2098Сегодня 18:12:46

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1849
UA: Firefox 140.0

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

Если в секции с PNG заменить иконки на svg, отображаться не будут

Я в другом скрипте с этим столкнулся, конвертируйте файл svg в base.
   

xrun1 пишет

У меня какой-то промежуточный этап

Выложите его, может смогу скрестить. А то вчера поковырял, там непонятная для меня формула или ее отсутствие.
Перевод реально уг, раньше в Simple Translate нормальный был, а теперь так же.

Отсутствует

 

№2099Сегодня 18:57:11

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 23-07-2024
Сообщений: 34
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

xrun1 пишет

Менял сегодня иконки в кнопке Save_Script.js и столкнулся с проблемой. Если в секции с PNG заменить иконки на svg, отображаться не будут. В этом виновата кнопка Save_Button.js.

замените в своем Save_Script.js

Выделить код

Код:

((main, parts) => this.onmousedown = e => {
.......
        </menugroup>
    `);

на

скрытый текст

Выделить код

Код:

((main, parts) => this.onmousedown = e => {
    if (e.button) return;
    this.onmousedown = null;

    const icon1 = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity' d='M13.946 2.353c.273 0 .498.23.498.513v10.262l-.156-.209-4.233-5.647a.737.737 0 0 0-1.183 0l-2.584 3.446-.95-1.37a.732.732 0 0 0-1.214.003l-2.49 3.594-.14.199V2.866c0-.282.224-.513.498-.513h11.954zM1.992.813C.893.813 0 1.732 0 2.865v10.268c0 1.133.893 2.054 1.992 2.054h11.954c1.098 0 1.992-.921 1.992-2.054V2.866c0-1.133-.894-2.054-1.992-2.054H1.992zm2.49 6.16a1.494 1.54 0 1 0 0-3.08 1.494 1.54 0 1 0 0 3.08z'/></svg>`);
    
    const icon2 = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><g style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity'><path d='M11.108 8.852c.327 0 .591-.27.591-.602a.596.596 0 0 0-.59-.602c-.327 0-.591.27-.591.602 0 .332.264.602.59.602z'/><path d='M4.808 7.047c0-.665.53-1.203 1.182-1.203h6.3c.652 0 1.18.538 1.18 1.203v4.01c0 .665-.528 1.203-1.18 1.203h-6.3a1.192 1.192 0 0 1-1.182-1.203v-4.01zm1.182 0v3.524l1.639-1.808a.972.972 0 0 1 1.446 0l2.074 2.287-.008.007h1.149v-4.01h-6.3zm2.362 2.691-1.195 1.32h2.39l-1.195-1.32z'/><path d='M3.036 1.833C1.406 1.833.083 3.18.083 4.841v6.818c0 1.661 1.323 3.008 2.953 3.008h9.844c1.631 0 2.953-1.347 2.953-3.008V4.84c0-1.661-1.322-3.008-2.953-3.008H3.036zM1.265 4.841c0-.997.793-1.805 1.771-1.805h9.844c.979 0 1.772.808 1.772 1.805v6.818c0 .997-.793 1.805-1.772 1.805H3.036c-.978 0-1.771-.808-1.771-1.805V4.84z'/></g></svg>`);
    
    const icon3 = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='context-fill' fill-opacity='context-fill-opacity'><path fill-rule='evenodd' d='M2.63 1.255c-.76 0-1.375.616-1.375 1.375v2.685a.625.625 0 0 1-1.25 0V2.63A2.625 2.625 0 0 1 2.63.005h2.685a.625.625 0 1 1 0 1.25H2.63ZM10.06.63c0-.345.28-.625.625-.625h2.685a2.625 2.625 0 0 1 2.625 2.625v2.685a.625.625 0 1 1-1.25 0V2.63c0-.76-.616-1.375-1.375-1.375h-2.685A.625.625 0 0 1 10.06.63Zm5.31 9.43c.345 0 .625.28.625.625v2.685a2.625 2.625 0 0 1-2.625 2.625h-2.685a.625.625 0 1 1 0-1.25h2.685c.76 0 1.375-.616 1.375-1.375v-2.685c0-.345.28-.625.625-.625ZM2.729 7.3c-.79 0-1.43.64-1.43 1.429v4.542c0 .79.64 1.43 1.43 1.43H7.27c.79 0 1.43-.64 1.43-1.43V8.73c0-.79-.64-1.43-1.43-1.43H2.73ZM0 8.728A2.729 2.729 0 0 1 2.729 6H7.27A2.729 2.729 0 0 1 10 8.729v4.542A2.729 2.729 0 0 1 7.271 16H2.73A2.729 2.729 0 0 1 0 13.271V8.73Z' clip-rule='evenodd'/><path d='M6.9 14.005H2.73a.5.5 0 0 1-.372-.835l2.085-2.317a.5.5 0 0 1 .744 0l2.085 2.317a.5.5 0 0 1-.371.835ZM8 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'/></svg>`);

    const df = MozXULElement.parseXULToFragment(`
        <menugroup orient="vertical">
            <menuseparator/>
            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,${icon1}"
                label="Сохранить всю страницу как PNG"
                value="all"/>
            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,${icon1}"
                label="Сохранить видимую часть как PNG"
                value="page"/>
            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,${icon2}"
                label="Сохранить выбранный элемент как PNG"
                value="click"/>
            <menuitem class="menuitem-iconic"
                image="data:image/svg+xml;charset=utf-8,${icon3}"
                label="Сохранить выбранную область как PNG"
                value="clipping"/>
        </menugroup>
    `);

7c10ab52fa37288a5ac0a86554a2f216.png

Отредактировано egorsemenov06 (Сегодня 20:51:47)

Отсутствует

 

№2100Сегодня 19:39:55

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1311
UA: Firefox 138.0

Re: UCF - ваши кнопки, скрипты…

Там eval есть, не знаю, будет ли работать не 139. То, что закомментировал - убирать не стал. Там есть ссылки, почему и откуда.

скрытый текст

Выделить код

Код:

// https://forum.mozilla-russia.org/viewtopic.php?pid=780231#p780231
// мой пост с этой версией https://forum.mozilla-russia.org/viewtopic.php?pid=807350#p807350
(this.googletranslate = {
            init(that) {
                var lc = navigator.lastClick = {}, w = null, xhtmlns = 'http://www.w3.org/1999/xhtml';
                var mouseUp = (e) => {
                    if (e.button) return;
                    lc.X = e.screenX - mozInnerScreenX;
                    lc.Y = e.screenY - mozInnerScreenY;
                };
                gBrowser.tabpanels.addEventListener('mouseup', mouseUp, false);
/* https://forum.mozilla-russia.org/viewtopic.php?pid=812525#p812525
                this.destructor = () => {
                    gBrowser.tabpanels.removeEventListener('mouseup', mouseUp, false);
                    if (w)
                        w.closeWin();
                };
                that.unloadlisteners.push("googletranslate"); */
// правка для деструктора из ссылки выше 
                setUnloadMap("googletranslate", () => {
                    gBrowser.tabpanels.removeEventListener("mouseup", mouseUp, false);
                    w?.closeWin();
                });
                var createWindow = function(text, status, title, id, pos, size) {
                    var win = window, doc = win.document, wId = 'ujs_window'+(id || '');
                    w = doc.getElementById(wId);
                    var keyDown = function(e) {if (!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode == 27)doc.getElementById(wId).closeWin();};
                    var mouseDown = function() {doc.getElementById(wId).closeWin();};

                    if (w)
                        w.closeWin();
                    w = doc.createElementNS(xhtmlns, 'div');
                    w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#eaeaea;padding-top:0px;border-radius:4px;box-shadow:0 0 15px rgba(0,0,0,.4);' : 'background:-o-skin("Window Skin");'));
                    w.id = wId;
                    w.closeWin = function() {
                        doc.removeEventListener('keydown', keyDown, false);
                        gBrowser.tabpanels.removeEventListener('mousedown', mouseDown, false);
                        this.parentNode.removeChild(this);
                        w = null;
                    };
                    w.addEle = function(str, style) {
                        var ele = doc.createElementNS(xhtmlns, 'div');
                        ele.setAttribute('style', style);
                        if (str) {
                            ele.innerHTML = str;
                            for (var el, all = ele.getElementsByTagName('*'), i = all.length; i--;) {
                                el = all[i];
                                if (/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)) {
                                    el.parentNode.removeChild(el);
                                } else {
                                    for (var att = el.attributes, j = att.length; j--;) {
                                        if (/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                                    }
                                }
                            }
                        }
                        return this.appendChild(ele);
                    };
/* https://forum.mozilla-russia.org/viewtopic.php?pid=807299#p807299
                    w.addEle1 = function(str, style) {
                        var ele = doc.createElementNS(xhtmlns, 'textarea');
                        ele.setAttribute('style', style);
                        if (str) {
                            ele.innerHTML = str;
                            for (var el, all = ele.getElementsByTagName('*'), i = all.length; i--;) {
                                el = all[i];
                                if (/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)) {
                                    el.parentNode.removeChild(el);
                                } else {
                                    for (var att = el.attributes, j = att.length; j--;) {
                                        if (/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                                    }
                                }
                            }
                        }
                        return this.appendChild(ele);
                    };
*/
                    var img = doc.createElementNS(xhtmlns, 'div');
                    img.setAttribute('style', 'display:block;float:right;width:16px;height:16px;padding:0;margin-top:2px;margin-right:1px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVR4Xm2SPUhbURTHfzfNJ4nU0Axx7CJCN2kQtIgVCtq6OdQuBUftWIQqFNsKDo6iHTqIqN3a0kklUKTS2AZrcOjioFtRjFWUfH+803cS9GHwB4dzcu75/+8L9xgaSEDbLXhaASzAyXAMn5/DHxwwjeJgKLRxd3Q0atxuLhGgWqmQmp9PJ7LZJ5Ow3WhQFweDG20LC1FfRwc3kUsm+T48fPIzl3s8VTdxxLt+/2FhdlZkc1MkmdR8Pba2ajlrz3z1+9OvIOaIfb7DwsSEyNKSyM6OSLksEo/rbw2ttadntV7Gnv3k86VfqskvmDzv7hZ580Zkelrk4kJqFIsii4satVrRs+rYmBQHBuRvS4u8g/fuCmDOz+HgAIWpKRgfh3AYhoZQ8Hqxjo4o9PdT3d1FcQEl8KoBnJ7C/j6KZkZGYG4OIhEUFed7erD29q69jGrd1qVBqcQVKgwEuMSEQhjtXRk4JvW/kM1i2WGMga4uzMoKBIOIfbNiolEC6+uU+/qQRALFA1QBlwVYxmBcLmhuxqytQSgEKu7t1dBavwKvbeINh/Has2IMqnXpem4bky6qWLdvZgaOj2FwEHNyoqG19vRMZ8jZs1+NOfsNcZS3EFvzeNL51laRe/dEYrFadsLpZeyZDx7P6QN4Btwx1OE1xO4HAquP2tsjAZ+Pm8gWi3xMpc6W8/kXPyAO/DM4oOsZa2pafdjZGXF7PAgOpXKZL4nE2XImcyUGMDSg63kbhgvgtYCq8+akIL4J3y7Fyn+DokZOnLlMyQAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
                    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
                    img.addEventListener('click', function() {this.parentNode.closeWin();}, false);
                    w.appendChild(img);
                    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
                    title.onclick = e => {
                        e.preventDefault();
                        var url = e.target.href;
                        // Здесь открываем url как хотим.
                        var ctabpos = gBrowser.selectedTab._tPos +1;
                        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
                        doc.getElementById(wId).closeWin();
                    };
/* https://forum.mozilla-russia.org/viewtopic.php?pid=807299#p807299
                    var cnt = w.addEle1(text, 'display:block;border:1px solid #aaa;padding-bottom:3px;padding-left:3px;background-color:#fafcfe;color:#000;font:16px Times New Roman;width:310px;height:160px;overflow:auto;cursor:text;-moz-user-focus:normal;-moz-user-select:text;');
                    cnt.contentEditable="true";
                    cnt.context="contentAreaContextMenu";
*/
                    var cnt = doc.createElement("textarea");
                    cnt.style.cssText = `
                        color: #000;
                        width: 310px;
                        height: 160px;
                        outline: none;
                        padding-left: 3px;
                        padding-bottom: 3px;
                        border: 1px solid #aaa;
                        background-color: #fafcfe;
                        font: 17px Times New Roman;
                    `;
// if (text) cnt.value = text; --> if (text) cnt.value = text.trim();
                    if (text) cnt.value = text.trim();
                    w.append(cnt);
                    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
                    w.addEventListener('mousedown', function(e) {
                        if (e.target == w) {
                            e.preventDefault();
/* https://forum.mozilla-russia.org/viewtopic.php?pid=807257#p807257
                            var grabX = e.clientX, grabY = e.clientY, origX = parseInt(w.style.left), origY = parseInt(w.style.top);
                            var mouseMove = function(ev) {
                                w.style.left = origX+ev.clientX-grabX+'px';
                                w.style.top = origY+ev.clientY-grabY+'px';
                            };
*/
                            var st = w.style;
                            var mouseMove = e => {
                                st.top = parseInt(st.top) + e.movementY + "px";
                                st.left = parseInt(st.left) + e.movementX + "px";
                            }
                            doc.addEventListener('mousemove', mouseMove, false);
                            doc.addEventListener('mouseup', function() {doc.removeEventListener('mousemove', mouseMove, false);}, false);
                        }
                    }, false);
                    doc.documentElement.appendChild(w);

                    if (size) {
                        cnt.style.height = size.height;
                        cnt.style.width = size.width;
                    } else {
                        for (var i = 3; i < 10; i++) {
                            if (cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth) {
                                cnt.style.height = 80*i+'px';
                                cnt.style.width = 160*i+'px';
                            } else
                                break;
                        }
                    }

                    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? doc.documentElement : doc.body;
                    var mX = docEle.clientWidth-w.offsetWidth, mY = docEle.clientHeight-w.offsetHeight;
                    if (mX < 0) {cnt.style.width = parseInt(cnt.style.width)+mX+'px'; mX = 0;}
                    if (mY < 0) {cnt.style.height = parseInt(cnt.style.height)+mY+'px'; mY =0;}
                    var hW = parseInt(w.offsetWidth/2);
                    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
                    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
                    w.style.visibility = 'visible';
                    doc.addEventListener('keydown', keyDown, false);
                    gBrowser.tabpanels.addEventListener('mousedown', mouseDown, false);
// https://forum.mozilla-russia.org/viewtopic.php?pid=807326#p807326
                    if (text) {
                        var st = cnt.style;
                        var div = cnt.editor.rootElement;

                        var range = new Range();
                        range.selectNode(div.firstChild);
                        var rect = range.getBoundingClientRect();

                        let w = Math.ceil(rect.width);
                        if (cnt.scrollTopMax) {
                            if (!matchMedia("(-moz-overlay-scrollbars)").matches) // ???
                                w += InspectorUtils.getChildrenForNode(div, true, false).at(-1).clientWidth;
                        }
                        else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";
// к строке выше; изменить, если font-size > 22 https://forum.mozilla-russia.org/viewtopic.php?pid=807332#p807332
                        st.width = Math.max(200, w) + "px";
                    }
                    return w;
                };

                var getHash = function (txt) {
                    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
                    function sM(a) {
                        var b;
                        if (null !== yr)
                            b = yr;
                        else {
                            b = wr(String.fromCharCode(84));
                            var c = wr(String.fromCharCode(75));
                            b = [b(), b()];
                            b[1] = c();
                            b = (yr = window[b.join(c())] || "") || "";
                        }
                        var d = wr(String.fromCharCode(116)), c = wr(String.fromCharCode(107)), d = [d(), d()];
                        d[1] = c();
                        c = "&" + d.join("") + "=";
                        d = b.split(".");
                        b = Number(d[0]) || 0;
                        for (var e = [], f = 0, g = 0; g < a.length; g++) {
                            var l = a.charCodeAt(g);
                            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                            e[f++] = l >> 18 | 240,
                            e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                            e[f++] = l >> 6 & 63 | 128),
                            e[f++] = l & 63 | 128);
                        }
                        a = b;
                        for (f = 0; f < e.length; f++)
                            a += e[f],
                        a = xr(a, "+-a^+6");
                        a = xr(a, "+-3^+b+-f");
                        a ^= Number(d[1]) || 0;
                        0 > a && (a = (a & 2147483647) + 2147483648);
                        a %= 1E6;
                        return c + (a.toString() + "." + (a ^ b));
                    }

                    var yr = null;
                    var wr = function(a) {
                        return function() {
                            return a;
                        };
                    }, xr = function(a, b) {
                        for (var c = 0; c < b.length - 2; c += 3) {
                            var d = b.charAt(c + 2), d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d), d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
                            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d;
                        }
                        return a;
                    };
                    return sM(txt);
                };

                var ujs_google_translate = function (dir) {
                    var lng = window.navigator.language.slice(0, 2), txt = gContextMenu.selectionInfo.fullText, l = dir.split('|');
                    var encTxt = encodeURIComponent(txt);
                    var winWait = function(lng) {createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick);};
                    if (txt) {
                        winWait(lng);
                        var xhr = new XMLHttpRequest();
                        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
// для urlt изменил http --> https (14.10.2023); тестирую
                        var urlt = "https://translate.google.com/translate_t?text=" + encTxt + "&sl=' + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
                        xhr.open('POST', url, true);
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
                        xhr.onreadystatechange = function() {
                            try {
                                if (xhr.readyState == 4 && xhr.status == 200) {
//                                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
                                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));
                                    for (var i = 0, n; n = tmp[0][i]; i++) {
                                        if (n[0])result += n[0].toString();
                                    };
                                   status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                                   createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                                }
                            } catch(e) {};
                        };
                        xhr.send('q=' + encodeURIComponent(txt));
                    } else {
                        var urlt = gBrowser.currentURI.spec;
// Изменил строку ниже. Добавил параметр '&tl='+l[1] https://forum.mozilla-russia.org/viewtopic.php?pid=796999#p796999 & http --> https (14.10.2023)
                        var url = "https://translate.google.com/translate?u=" + encodeURIComponent(urlt) + '&tl=' + l[1] + "&hl=" + lng + "&langpair=" + dir + "&tbb=1";
                        var ctabpos = gBrowser.selectedTab._tPos +1;
                        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
                    };
                };
                var contextMenu = document.getElementById("contentAreaContextMenu");
                var nextEleMenu = document.getElementById("context-inspect");

                var menuItem = document.createXULElement("menuitem");
                menuItem.setAttribute("id", "context-ru-google-translate");
                menuItem.setAttribute("label", "Перевести на русский");
                menuItem.setAttribute("class", "menuitem-iconic");
                menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABBUlEQVR4Ac2RMU4DMRREB2MqihQpAkUaqnAduuQw4Sx03CGcJYIiDYqQ0lCsZ77535ZFcgAkRuPvV7zd/dLiz3N1PFb8hmRckrfELZrF9ONQ1B6Yz0MyM7S0O6zGkVprh/3+Kw/JzkHSpRpJKZkpr9fYbOx0cjVsCbWG31oHBM9mtt0q73ZcrdLhAMlYQKkUI22aqsNo8HKZAMQhvVaKSHWj2Q2aPU3mJQFY7nuHyvYFduP83WF3AJRfcPNYnr/Lp1G1uK4m9sno1LaUbnX/htf8BNzoneUD5NhjvLCMhURQSQ93QCZwXYjFwg3I0NZKrvoknQPMIHkt/jRAQKMeG2yX89/mB4EJbKbZxIhFAAAAAElFTkSuQmCC");
                menuItem.addEventListener("command", function() {ujs_google_translate('auto|ru');}, false);
                contextMenu.insertBefore(menuItem, nextEleMenu);

                menuItem = document.createXULElement("menuitem");
                menuItem.setAttribute("id", "context-en-google-translate");
                menuItem.setAttribute("label", "Перевести на английский");
                menuItem.setAttribute("class", "menuitem-iconic");
                menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAAB5UlEQVR4AWOgPZg0c9+Oq2+qpx9LaQaiw4mNB27efbs2uXFNQh2Q4Zm9zSNth23MhqjGnXMC86vnHmUS4udxv7OvOd2yPE7PTlfCTk9GVVEoyJA7WI8dyPA0k3U1l+jJMV7CeThpTZeoKDdDUsvBPSff/V+6/P/Bvf///2+bdvU/EKRm/k9IBNIlfZe+LFrzvbsbyJ636pKkyQyQhoUb7tZNvPpw3/0/TfX/ISAm5n94BIiRm/n/xYsLd946ei4vajoiqDuRAejQf//+o4PQ0P9+fmhiQGVnrr1kXJNYG2zEzXDxDsPv3wy/fkFJoOTPn39+/fr/69e/37//AUX+/mXRkO458wWHDba2f8wswCyQ3N+/f//8/fP7z5+TV18w2Mdt6plzPiptx5Wr7/+/ffMzOR6kysjkt74hWMPfp06O+2dulZCeFZKwnkE4m8E8bN3i9aCQ+dxY96GrK6bkGJD9R1v3l6Y20NVW9kt+/v//ZdbcFwkxTVPPMQimM8XEqkb7a/zoqLxkH9v4zVyI5+///wyMmtKMmhJAnbLqQjHxaw5r2orOmZN5uj470Zahat6BKS7JzpmLBHXm8GhM5lCdcP7ai1ZpixZxk9NXXjKIFzOIFjAI54oY1vXuue5qmscw+AAAW0tKxtPoicEAAAAASUVORK5CYII=");
                menuItem.addEventListener("command", function() {ujs_google_translate('auto|en');}, false);
                contextMenu.insertBefore(menuItem, nextEleMenu);

                contextMenu.insertBefore(document.createXULElement("menuseparator"), nextEleMenu);
            }
        }).init(this);


yup
Удачная тестовая фраза попалась.:D

Добавлено Сегодня 19:59:17
unter_officer
Скрестить ужа и ежа: старая кнопка из custom_script.js + новый скрипт. Я буду пока так делать, конвертировать иконки не хочу. Когда отвалится - буду здесь плакаться.:)

Отредактировано xrun1 (Сегодня 19:59:17)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]