Полезная информация

Общайтесь со знакомыми и друзьями в нашем сообществе в Facebook.

№40113-07-2022 22:13:58

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

xrun1, спасибо.

А какие кнопки не работают в расширении и что с ним не так?

Не работало одно только выпадающее меню с расширениями, с другими кнопками все было нормально. Но теперь уже подсказали как поправить само расширение, теперь все работает без вопросов, так что коды кнопок уже не нужны. С ATB мне гораздо проще. Пользуюсь обычно четырьмя кнопками - восстановить закрытую вкладку, пароли, перезагрузка браузера и меню расширений. Иногда прокси вытаскиваю.

Отсутствует

 

№40213-07-2022 22:17:04

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1385
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac пишет

и заменял - эффекта нет

А перезапустить с очисткой кэша запуска...


Add. если проблема только в окошке с предупреждением...

скрыть

Выделить код

Код:

@-moz-document url-prefix("chrome://mozapps/content/extensions/aboutaddons.html"), url("about:addons"){
div.container {
   display: none !important;
}
}

добавить в userContent.css

Отредактировано kokoss (14-07-2022 19:50:13)


Win7

Отсутствует

 

№40313-07-2022 22:38:39

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kokoss

А перезапустить с очисткой кэша запуска...

Само собой.

Add. если проблема только в окошке с предупреждением...

Так пропало предупреждение. Спасибо :beer:
Не то, чтобы оно сильно мешало, но на мозги немного капало :D

Отсутствует

 

№40413-07-2022 22:57:32

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1385
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac
Странно что у вас в [firefox] 102 появилось это окошко с предупреждением..., у меня в [firefox] 102 такого окошка с предупреждением... нет! Оно попадалось мне только в ESR ветке при использовании настроек в конфиге:

Выделить код

Код:

extensions.experiments.enabled = true
xpinstall.signatures.required = false

отключающие проверку...

Отредактировано kokoss (13-07-2022 22:58:15)


Win7

Отсутствует

 

№40513-07-2022 23:23:29

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kokoss
У меня именно ESR и именно эти настройки в конфиге. При том, что их я не трогал точно. Обычно настраиваю только general.smoothScroll.mouseWheel.duration, мин-макс по 500 выставляю и browser.tabs.loadBookmarksInTabs - true. Все, больше ничего не трогаю.
Да и настройки эти неактивны, в смысле - я их не могу изменить. Скорее всего, автор сборки что-то там подкрутил. Ну, или она не дружит со 102-й версией. Я использовал архив для 91-й.

Отсутствует

 

№40613-07-2022 23:32:47

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1385
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac пишет

У меня именно ESR и именно эти настройки в конфиге.

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


Win7

Отсутствует

 

№40714-07-2022 19:20:43

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kokoss, дружище! Странный глюк вылез вот с этим кодом в userContent.css:

Выделить код

Код:

div.container {
   display: none !important;
}

Заметил не сразу, потому что он ломает только некоторые сайты. Вот хороший пример - http://tundra-japonamat.ru/index.html
По самому верху страницы ссылки навигации по сайту. Так вот при добавлении этого кода эти ссылки тупо пропадают. И еще счетчик от Хотлог в низу страницы. Ну, это мелочь. Перерыл все расширения и т.п., искал виновника, и вышел таки именно на этот код. Удаляю его из userContent - сайт начинает отображаться правильно, возвращаю - ломается опять...
Может там у меня со стилями что-то не то? Глянь, пожалуйста, если не в лом. Мой userContent.css без вот этого кода для скрытия предупреждений:

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

Выделить код

Код:

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document domain("www.google.ru")
{
#newsbox span.tl>a, #newsbox span.tl>a.l {
    font-size: 13px;
    text-decoration: underline;
}
#res h3 {
    font-size: medium;
    text-decoration: underline;
}
#tads a, #tadsb a, #res a, #rhs a, #taw a {
    text-decoration: underline ;
}
div.nrg-title>a, div.irg-title>a {
    font-size: medium;
}
span.tl>a {
    font-size: 13px;
}
.rgsep, .g-blk, #extrares {
    display: none !important;
}
div#pushdown, div.pdp-psy, div.pmoabs {
    display: none !important;
}
div.rhsvw.kno-ftr {
    display: none !important;
}
#res h3 {
    font-size: medium !important;
}
.spell {
    font-size: 15px !important;
}
#_L8b {
    display: none !important;
}
div._eNq span {
    font-size: 15px !important;
    text-decoration: underline !important;
}
div.gb_g.gb_Lc.gb_Xc.gb_Wc > .gb_ha {
    display: none !important;
}
.mslg .l {
    font-size: 15px !important;
}
._dTj {
    font-size: 14px !important;
}
._vSj {
    line-height: 16px !important;
}
.xIqs0b {
    font-size: 15px !important;
}
html, body {
text-shadow: 0px 0px 0px !important;
}
}

@-moz-document domain("www.google.com")
{
#botstuff {
    display: none !important;
}
#brs {
    display: none !important;
}
div.vk_c.rhsvw.vk_rhsc.kp-blk {
    display: none !important;
}
h3.r {
    font-size: 15px;
    text-decoration: underline;
}
h3.r a {
    font-size: 15px;
}
#newsbox span.tl > a {
    font-size: 13px;
    text-decoration: underline;
}
div.nrg-title._Hb>a, div.irg-title._Hb>a, div.nrg-title._zb>a, div._qi._zb>a, a._ef.nrg-footer, a._ef.irg-footer {
    font-size: 15px ;
    text-decoration: underline;
}
span.spell.ng,a.spell b i  {
    font-size: 15px;
}
._Dk, ._wI, ._wI a {
    font-size: 15px !important;
}
#res h3 {
    font-size: medium !important;
}
.spell {
    font-size: 15px !important;
}
#_L8b {
    display: none !important;
}
div._eNq span {
    font-size: 15px !important;
    text-decoration: underline !important;
}
div.gb_g.gb_Lc.gb_Xc.gb_Wc > .gb_ha {
    display: none !important;
}
.mslg .l {
    font-size: 15px !important;
}
._dTj {
    font-size: 14px !important;
}
._vSj {
    line-height: 16px !important;
}
.xIqs0b {
    font-size: 15px !important;
}
html, body {
text-shadow: 0px 0px 0px !important;
}
}

@-moz-document domain("yandex.ru")
{
.b-advertizing-and-wizards,.b-serp-item_last_yes {
    display: none !important;
}
.b-body-items_type_main .b-serp-item:nth-child(11), .b-body-items_type_main .b-serp-item:nth-child(12), .b-body-items_type_main .b-serp-item:nth-child(13), .b-body-items_type_main .b-serp-item:nth-child(14), .b-body-items_type_main .b-serp-item:nth-child(15), .b-body-items_type_main .b-serp-item:nth-child(16), .b-body-items_type_main .b-serp-item:nth-child(17) {
    display: none !important;
}
a.b-spec-adv__direct {
    display: none !important;
}
div.b-person-results.g-gap-vertical.g-gap-horizontal {
    display: none !important;
}
div.b-related.g-gap-vertical.g-gap-horizontal {
    display: none !important;
}
div.b-spec-adv.b-spec-adv_serp-margin_yes.g-gap-vertical.b-spec-adv.b-spec-adv_type_highlighted.i-bem {
    background-color: #fff;
    font-size: 0;
    height: 0;
    margin-left: -1200px;
    padding: 0;
    width: 0;
}
div.z-audio__flash {
    display: none !important;
}
li.z-audio.b-serp-item.i-bem.z-audio_js_inited {
    display: none !important;
}
p.b-filters__intents.b-filters__intents_level_1 {
    display: none !important;
}
.logo, .b-logo {
    opacity: 0.3 !important;
}
.logo:hover {
    opacity: 1 !important;
}
.serp-item__title {
    font-size: medium !important;
    font-weight: normal !important;
    text-decoration: underline;
}

a.link.serp-item__title-link {
    font-size: 15px !important;
    text-decoration: underline !important;
}

a.link.distro__link.distro__item, div.distro__item {
    display: none !important;
}

div.distro.scroll-spy, div.z-default-search {
    display: none !important;
}

div.footer-stripe, div.footer-stripe__content {
    display: none !important;
}
}

@-moz-document domain("ya.ru")
{
.suggest2-form__input {
    background-color: #eee !important;
}
.input__control {
	color: #444 !important;
}
.button_theme_websearch  {
    background-color: #eee !important;
	color: #aaa !important;
}
}

@-moz-document domain("new-rutor.org")
{
body {
    background-image: none !important;
    padding: 0 !important;
}
#pluso-panel, #all, div#ws {
    width: 100% !important;
}
div#ws div#content {
    width: 75% !important;
}
.sideblock2 {
    display: none !important;
}
}

@-moz-document domain("bing.com")
{
h2, h3, .b_no h1 {
    font-size: medium !important;
}
}

@-moz-document domain("duckduckgo.com")
{
a.large, a.result__a  {
    font-size: medium !important;
}
.add-to-browser-badge, div.foot-home.js-foot-home, div.tag-home.tag-home--slide.no-js__hide.js-tag-home, div.results--powered  {
    display: none !important;
}
div.header-wrap--home.js-header-wrap {
    opacity: .5 !important;
}
div.logo-wrap--home, span.header__logo, img#logo {
    opacity: .3 !important;
}
div.logo-wrap--home:hover, span.header__logo:hover, img#logo:hover {
    opacity: 1 !important;
}
.logo_homepage {
    background-size: 130px 100px !important;
    height: 100px !important;
    width: 130px !important;
}

a.badge-link__wrap.js-badge-main-msg,
div.badge-link.badge-link--top.js-badge-link,
div.tag-home,
div.onboarding-bottom-bathroomguy-slide,
div.onboarding-bottom.onboarding-bottom-bathroomguy {
    display: none !important;
}
div.tag-home__wrapper,div.hide--screen-xs {
    display: none !important;
}
div.onboarding-ed__slide,div.onboarding-ed,div.badge-link {
    display: none !important;
}
}

@-moz-document domain("1tv.ru")
{
body {
    background-color: #000 !important;
}
.navbar,
.menu {
    background-color: #eee !important;
}
article.live,
.theme-main {
    background-color: #f4f4f4 !important;
}
header#page-title {
    color: #b4b4b4 !important;
}
.theme-main > .live,
.theme-main > .live > .player-wrapper {
    background-color: #000 !important;
}
.footer {
    background-color: #000 !important;
	color: #f4f4f4 !important;
}

#mainalert,
#popupContainer,
#yandex_ad,
.itv-push-suggest,
.welcome-popup,
.promo-place,
.branding_promo_place,
.header-promo-place,
.side-promo-place-right,
.footer-promo-place,
.social-buttons-compact,
.social-widgets,
.small-social-buttons,
.footer-menu,
.yashare-auto-init.b-share_theme_counter,
.links > li:nth-of-type(7) {
    display: none !important;
}
}

@-moz-document domain("ntv.ru")
{
div.intop {
    display: none !important;
}
#newplayer {
    top: 0 !important;
}
div#push_alert,
div.wrap_top_flash,
input.check_rez,
ul.likeBtm.custom,
div.outtop,
#x8831 a img {
    display: none !important;
}
}

input:not([type="submit"]):not([type="reset"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]),
textarea {
    background: #ffff33 !important;
}


Собирал давно, таскал из версии в версию. Вполне возможно, что там куча лишнего или даже вредного. Может из-за этого и сайты ломаются, а твой код только катализатором выступает :D ...

Отсутствует

 

№40814-07-2022 19:47:18

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1385
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac
Спасибо за подсказку, не подумал что может что то скрывать на сайтах. Тогда так:

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

Выделить код

Код:

@-moz-document url-prefix("chrome://mozapps/content/extensions/aboutaddons.html"), url("about:addons"){
div.container {
   display: none !important;
}
}

Отредактировано kokoss (14-07-2022 19:49:21)


Win7

Отсутствует

 

№40914-07-2022 19:57:13

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kokoss
Да, с этим кодом все шоколадно. Спасибо еще раз за помощь :beer:

Отсутствует

 

№41015-07-2022 00:03:10

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Парни, а Simple Session Manager из шапки - куда код кидать?

Отсутствует

 

№41115-07-2022 02:01:59

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 276
UA: Firefox 97.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac пишет

Парни, а Simple Session Manager из шапки - куда код кидать?

смотрите в шапке Демо-профиль, в нём множество скриптов/стилей уже подключено - файл CustomStylesScripts.jsm

Выделить код

Код:

scriptsbackground: [ // В фоне [System Principal]
	{ path: "custom_script.js", },
	{ path: "ucf_SessionManager.js", },

Отсутствует

 

№41215-07-2022 03:27:06

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dobrov, спасибо, но мне этого мало. В том смысле, что я в этих вопросах почти полный валенок. Так, вершков некоторых нахватался...
Скачал этот профиль, посмотрел, почитал - слишком много разных фишек, многие мне ни о чем не говорят, другие мне просто не нужны. Я хотел попробовать именно менеджер сессий. Сейчас юзаю Tab Session Manager, в принципе, терпимо, но убивает когда он при восстановлении сессии тусует вкладки как карточную колоду. Еще один похожий есть, с похожим интерфейсом, но там точно такая же ерунда. Вот и хотел пощупать этот, но что, куда и как - не понимаю. UserChromeFiles в наличии, а вот куда там добавить код этого менеджера - не понимаю.
Я не спец от слова совсем, подсказки на лету не поймаю, увы... Мне разжевывать надо :D

Отсутствует

 

№41315-07-2022 03:54:58

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac
Вроде не тасует, если стоит галка "Восстановить расположение окон Восстановить размеры и расположение окон при открытии сессии."

Отсутствует

 

№41415-07-2022 04:19:12

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 276
UA: Firefox 97.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac пишет

UserChromeFiles в наличии, а вот куда там добавить код этого менеджера - не понимаю.

повторюсь - файл CustomStylesScripts.jsm – добавить строку в секцию scriptsbackground: [ // В фоне [System Principal]
В этой теме в различных вариантах расписан порядок установки, всё есть в шапке и справке Демо-профиля. Ссылки снабжены всплывающими подсказками, например наведите мышь на startupCache в последней строке встроенной справки
Если вам описание установки в шапке не ясно, тогда пользуйтесь обычными дополнениями…

Отредактировано Dobrov (15-07-2022 04:25:45)

Отсутствует

 

№41515-07-2022 04:25:38

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dobrov
Не все пользуются версией с CustomStylesScripts.jsm и прочими scriptsbackground: [ // В фоне [System Principal]. Мне эта версия UCF непонятна, лично я на старой остался.

Отредактировано xrun1 (15-07-2022 04:27:15)

Отсутствует

 

№41615-07-2022 04:32:07

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 276
UA: Firefox 97.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

xrun1 пишет

Не все пользуются версией с CustomStylesScripts.jsm. Мне эта версия UCF непонятна, лично я на старой остался.

Дополнил шапку, добавил custom_script.js - скрипты добавлять здесь: (async () => { ["ucf_SessionManager.js"]. Процитирую скрипт из шапки:

Выделить код

Код:

// Этот скрипт можно использовать для создания кнопок с помощью CustomizableUI.createWidget
(async (scripts) => { // подключить внешние скрипты
  [['ucf_QuickToggle.js'], ['UCFTitleChangedChild.jsm', 'registerUCFTitleChanged'], ['Test.jsm']]
  .forEach(function(js) { try { if (/\.jsm$/i.test(js[0])) { // [скрипт js или jsm, инициализация]
        var obj = ChromeUtils.import(scripts + js[0]);
        js[1] && obj[js[1]]();
      } else Services.scriptloader.loadSubScript(scripts + js[0]);
    } catch(ex) {Cu.reportError(ex);}
  });
})('chrome://user_chrome_files/content/custom_scripts/');

/* вариант с отдельными скриптами:
(async () => { var loadscript = (name, funcName) => {
  try { var {href, pathname} = new URL(`chrome://user_chrome_files/content/custom_scripts/${name}`);
    if (/\.jsm$/i.test(pathname)) {
      var obj = ChromeUtils.import(href);
      funcName && obj[funcName]();
    } else
      Services.scriptloader.loadSubScript(href);
  }
  catch(ex) {Cu.reportError(ex);}
}
loadscript("ucf_aom-button.js");
loadscript("UCFTitleChangedChild.jsm", "registerUCFTitleChanged");
})();
*/
ez7pac пишет

Скачал этот профиль, посмотрел, почитал - слишком много разных фишек, многие мне ни о чем не говорят, другие мне просто не нужны.

Какие фишки непонятны? Описание есть в спойлере шапки и встроенной справке (спойлер "Полный список▼").
Сообщите, какие конкретно скрипты непонятны и я дополню описание.
.


Ещё можно убрать ненужные скрипты из CustomStylesScripts.jsm и CustomStylesScriptsChild.jsm, оставив базовый ucf_hookClicks.js и нужный вам ucf_SessionManager.js. Впрочем дополнительные скрипты требуют значительно меньше памяти, чем дополнения.

Отредактировано Dobrov (15-07-2022 05:37:18)

Отсутствует

 

№41715-07-2022 19:26:54

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1385
UA: Firefox 102.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac
xrun1
Этот скрипт... вроде работает в версии UCF 2021-6-5 -> https://forum.mozilla-russia.org/viewto … 17#p797517, код под первым спойлером.


Add, добавить в user_chrome_files/custom_scripts/custom_script.js

Отредактировано kokoss (15-07-2022 20:02:14)


Win7

Отсутствует

 

№41815-07-2022 19:58:29

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dobrov пишет

Сообщите, какие конкретно скрипты непонятны и я дополню описание..

Да не то, чтобы непонятны, просто я мельком пробежался, сильно не вникал. Я ставлю обычно только то, что мне нужно и полезно на данный момент. Ставить пак, пусть и хороший, "шоб було" :D, ради одной фишки - не мое. Вот сейчас из всего списка меня заинтересовал только менеджер сессий. А перебирать пак, удаляя ненужное мне - это косяки, глюки, нервотрепка и т.п. Элементарно не хватит знаний.

kokoss пишет

Этот скрипт... вроде работает в версии UCF 2021-6-5 -> https://forum.mozilla-russia.org/viewto … 17#p797517, код под первым спойлером.

Спасибо. Но код - это хорошо, но еще бы знать куда его впихнуть и не накосячить при этом... :D
Я в принцип работы UCF не въезжаю вообще. userChrome, userContent - еще так, с пятое на десятое, и то нужно носом ткнуть - "вот этот код добавить вот сюда и не забудь вот эту запятую поставить". А UCF - это уже другой уровень.

Отсутствует

 

№41916-07-2022 03:13:10

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kokoss пишет

Add, добавить в user_chrome_files/custom_scripts/custom_script.js

Только сейчас увидел ответ. И снова спасибо! Добавил, кнопка появилась, работает менеджер. Я извиняюсь, конечно, но возникли пара вопросов.
1. Работает только ручное сохранение или можно выставить в авто? Если можно, то как включить и как настроить периодичность?
2. Где хранятся сессии?

Отсутствует

 

№42016-07-2022 03:33:00

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 276
UA: Firefox 97.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

ez7pac пишет

1. Работает только ручное сохранение или можно выставить в авто? Если можно, то как включить и как настроить периодичность?
2. Где хранятся сессии?

Сесии храняться в «Профиль Firefox//chrome/simple_session_manager.json»
С авто-сохранением и таймером для него надо обращаться к Dumby, он этот скрипт делал.

Отсутствует

 

№42116-07-2022 14:16:43

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 182
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dobrov, понял, спасибо.

Отсутствует

 

№42222-07-2022 05:51:36

kazarin
Участник
 
Группа: Members
Зарегистрирован: 23-11-2016
Сообщений: 80
UA: Firefox 101.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Уважаемые гуру, подскажите, пожалуйста. Есть вот такой скрипт, прекрасно работает на 78. А на 101 не грузится меню с подключёнными стилями (остальное работает). Это реально поправить?

Отсутствует

 

№42322-07-2022 13:38:45

Farby
Участник
 
Группа: Members
Зарегистрирован: 21-11-2012
Сообщений: 110
UA: Google 2.1

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

kazarin пишет

Пробуй, проверял на [firefox] 103, в консоли ошибок нет...

UserCSSLoader.uc.js

Выделить код

Код:

// ==UserScript==
// @name           UserCSSLoader
// @description    Stylish みたいなもの
// @namespace      http://d.hatena.ne.jp/Griever/
// @author         Griever
// @include        main
// @license        MIT License
// @compatibility  Firefox 4
// @charset        UTF-8
// @version        0.0.4改
// @startup        UCL.init();
// @note           0.0.4 Remove E4X
// @note           CSSEntry クラスを作った
// @note           スタイルのテスト機能を作り直した
// @note           ファイルが削除された場合 rebuild 時に CSS を解除しメニューを消すようにした
// @note           uc で読み込まれた .uc.css の再読み込みに仮対応
// ==/UserScript==

/****** 使い方 ******

chrome フォルダに CSS フォルダが作成されるのでそこに .css をぶち込むだけ。
ファイル名が "xul-" で始まる物、".as.css" で終わる物は AGENT_SHEET で、それ以外は USER_SHEET で読み込む。
ファイルの内容はチェックしないので @namespace 忘れに注意。

メニューバーに CSS メニューが追加される
メニューを左クリックすると ON/OFF
					中クリックするとメニューを閉じずに ON/OFF
					右クリックするとエディタで開く

エディタは "view_source.editor.path" に指定されているものを使う
フォルダは "UserCSSLoader.FOLDER" にパスを入れれば変更可能

 **** 説明終わり ****/

(function(){

let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
if (!window.Services)
	Cu.import("resource://gre/modules/Services.jsm");
// 起動時に他の窓がある(2窓目の)場合は抜ける
let list = Services.wm.getEnumerator("navigator:browser");
while(list.hasMoreElements()){ if(list.getNext() != window) return; }

if (window.UCL) {
	window.UCL.destroy();
	delete window.UCL;
}
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

window.UCL = {
	IN_TOOLMENU: false,	// true: ツールメニュー内、 false:メインメニューのヘルプの前
	USE_UC: "UC" in window,
	AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET,
	USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET,
	readCSS    : {},
	get disabled_list() {
		let obj = [];
		try {
			obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|");
		} catch(e) {}
		delete this.disabled_list;
		return this.disabled_list = obj;
	},
	get prefs() {
		delete this.prefs;
		return this.prefs = Services.prefs.getBranch("UserCSSLoader.")
	},
	get styleSheetServices(){
		delete this.styleSheetServices;
		return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
	},
	get FOLDER() {
		let aFolder;
		try {
			// UserCSSLoader.FOLDER があればそれを使う
			let folderPath = this.prefs.getCharPref("FOLDER");
			aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
			aFolder.initWithPath(folderPath);
		} catch (e) {
			aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
			aFolder.appendRelativePath("CSS");
		}
		if (!aFolder.exists() || !aFolder.isDirectory()) {
			aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0664);
		}
		delete this.FOLDER;
		return this.FOLDER = aFolder;
	},
	getFocusedWindow: function() {
		let win = document.commandDispatcher.focusedWindow;
		if (!win || win == window) win = content;
		return win;
	},
	init: function() {
		const cssmenu = $C("menu", {
			id: "usercssloader-menu",
			label: "CSS",
			accesskey: "C"
		});
		const menupopup = $C("menupopup", {
			id: "usercssloader-menupopup"
		});
		cssmenu.appendChild(menupopup);

		let menu = $C("menu", {
			label: "メニュ━━━(゚∀゚)━━━!!",
			accesskey: "C"
		});
		menupopup.appendChild(menu);
		let mp = $C("menupopup", { id: "usercssloader-submenupopup" });
		menu.appendChild(mp);
		mp.appendChild($C("menuitem", {
			label: "Rebuld",
			accesskey: "R",
			acceltext: "Alt + R",
			oncommand: "UCL.rebuild();"
		}));
		mp.appendChild($C("menuseparator"));
		mp.appendChild($C("menuitem", {
			label: "新規作成",
			accesskey: "N",
			oncommand: "UCL.create();"
		}));
		mp.appendChild($C("menuitem", {
			label: "CSS フォルダを開く",
			accesskey: "O",
			oncommand: "UCL.openFolder();"
		}));
		mp.appendChild($C("menuitem", {
			label: "userChrome.css を編集",
//			hidden: true,
			oncommand: "UCL.editUserCSS(\'userChrome.css\');"
		}));
		mp.appendChild($C("menuitem", {
			label: "userContent.css を編集",
//			hidden: true,
			oncommand: "UCL.editUserCSS(\'userContent.css\');"
		}));
		mp.appendChild($C("menuseparator"));
		mp.appendChild($C("menuitem", {
			label: "スタイルのテスト (Chrome)",
			id: "usercssloader-test-chrome",
			hidden: true,
			accesskey: "C",
			oncommand: "UCL.styleTest(window);"
		}));
		mp.appendChild($C("menuitem", {
			label: "スタイルのテスト (Webページ)",
			id: "usercssloader-test-content",
			hidden: true,
			accesskey: "W",
			oncommand: "UCL.styleTest();"
		}));
		mp.appendChild($C("menuitem", {
			label: "userstyles.org でスタイルを検索",
			accesskey: "S",
			oncommand: "UCL.searchStyle();"
		}));

		menu = $C("menu", {
			label: ".uc.css",
			accesskey: "U",
			hidden: !UCL.USE_UC
		});
		menupopup.appendChild(menu);
		mp = $C("menupopup", { id: "usercssloader-ucmenupopup" });
		menu.appendChild(mp);
		mp.appendChild($C("menuitem", {
			label: "Rebuild(.uc.js)",
			oncommand: "UCL.UCrebuild();"
		}));
		mp.appendChild($C("menuseparator", { id: "usercssloader-ucsepalator" }));

		if (this.IN_TOOLMENU) {
			$('menu_ToolsPopup').insertBefore(cssmenu, $('menu_preferences'));
		} else {
			$('main-menubar').insertBefore(cssmenu, $('helpMenu'));
		}

		$("mainKeyset").appendChild($C("key", {
			id: "usercssloader-rebuild-key",
			oncommand: "UCL.rebuild();",
			key: "R",
			modifiers: "alt",
		}));

		this.rebuild();
		this.initialized = true;
		if (UCL.USE_UC) {
			setTimeout(function() {
				UCL.UCcreateMenuitem();
			}, 1000);
		}
		window.addEventListener("unload", this, false);
	},
	uninit: function() {
		const dis = [];
		for (let x of Object.keys(this.readCSS)) {
			if (!this.readCSS[x].enabled)
				dis.push(x);
		}
		this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|")));
		window.removeEventListener("unload", this, false);
	},
	destroy: function() {
		var i = document.getElementById("usercssloader-menu");
		if (i) i.parentNode.removeChild(i);
		var i = document.getElementById("usercssloader-rebuild-key");
		if (i) i.parentNode.removeChild(i);
		this.uninit();
	},
	handleEvent: function(event) {
		switch(event.type){
			case "unload": this.uninit(); break;
		}
	},
	rebuild: function() {
		let ext = /\.css$/i;
		let not = /\.uc\.css/i;
		let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);

		while (files.hasMoreElements()) {
			let file = files.getNext().QueryInterface(Ci.nsIFile);
			if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
			let CSS = this.loadCSS(file);
			CSS.flag = true;
		}
		for (let leafName of Object.keys(this.readCSS)) {
			const CSS = this.readCSS[leafName];
			if (!CSS.flag) {
				CSS.enabled = false;
				delete this.readCSS[leafName];
			}
			delete CSS.flag;
			this.rebuildMenu(leafName);
		}
		if (this.initialized) {
			if (typeof(StatusPanel) !== "undefined")
				StatusPanel._label = "Rebuild しました";
			else
				XULBrowserWindow.statusTextField.label = "Rebuild しました";
		}
	},
	loadCSS: function(aFile) {
		var CSS = this.readCSS[aFile.leafName];
		if (!CSS) {
			CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
			if (this.disabled_list.indexOf(CSS.leafName) === -1) {
				CSS.enabled = true;
			}
		} else if (CSS.enabled) {
			CSS.enabled = true;
		}
		return CSS;
	},
	rebuildMenu: function(aLeafName) {
		var CSS = this.readCSS[aLeafName];
		var menuitem = document.getElementById("usercssloader-" + aLeafName);
		if (!CSS) {
			if (menuitem)
				menuitem.parentNode.removeChild(menuitem);
			return;
		}

		if (!menuitem) {
			menuitem = $C("menuitem", {
				label		: aLeafName,
				id			: "usercssloader-" + aLeafName,
				class		: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : "USER_SHEET"),
				type		: "checkbox",
				autocheck	: "false",
				oncommand	: "UCL.toggle('"+ aLeafName +"');",
				onclick		: "UCL.itemClick(event);"
			});
			document.getElementById("usercssloader-menupopup").appendChild(menuitem);
		}
		menuitem.setAttribute("checked", CSS.enabled);
	},
	toggle: function(aLeafName) {
		var CSS = this.readCSS[aLeafName];
		if (!CSS) return;
		CSS.enabled = !CSS.enabled;
		this.rebuildMenu(aLeafName);
	},
	itemClick: function(event) {
		if (event.button == 0) return;

		event.preventDefault();
		event.stopPropagation();
		let label = event.currentTarget.getAttribute("label");

		if (event.button == 1) {
			this.toggle(label);
		}
		else if (event.button == 2) {
			closeMenus(event.target);
			this.edit(this.getFileFromLeafName(label));
		}
	},
	getFileFromLeafName: function(aLeafName) {
		let f = this.FOLDER.clone();
		f.QueryInterface(Ci.nsIFile); // use appendRelativePath
		f.appendRelativePath(aLeafName);
		return f;
	},
	styleTest: function(aWindow) {
		aWindow || (aWindow = this.getFocusedWindow());
		new CSSTester(aWindow, function(tester){
			if (tester.saved)
				UCL.rebuild();
		});
	},
	searchStyle: function() {
		let word;
		try {
			word = gBrowser.currentURI.host;
		} catch {
			word = gBrowser.currentURI.spec;
		}
		let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
		openLinkIn("https://userstyles.org/styles/search/" + word, "tab", {
								private: false,
								inBackground: false,
								relatedToCurrent: true,
								triggeringPrincipal: systemPrincipal,
								});
	},
	openFolder: function() {
		this.FOLDER.launch();
	},
	editUserCSS: function(aLeafName) {
		let file = Services.dirsvc.get("UChrm", Ci.nsIFile);
		file.appendRelativePath(aLeafName);
		this.edit(file);
	},
	edit: function(aFile) {
		var editor = Services.prefs.getCharPref("view_source.editor.path");
		if (!editor) return alert("エディタのパスが未設定です。\n view_source.editor.path を設定してください");
		try {
			var UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
			UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8";
			var path = UI.ConvertFromUnicode(aFile.path);
			var app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
			app.initWithPath(editor);
			var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
			process.init(app);
			process.run(false, [path], 1);
		} catch (e) {}
	},
	create: function(aLeafName) {
		if (!aLeafName) aLeafName = prompt("ファイル名を入力してください", dateFormat(new Date(), "%Y_%m%d_%H%M%S"));
		if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
		if (!aLeafName || !/\S/.test(aLeafName)) return;
		if (!/\.css$/.test(aLeafName)) aLeafName += ".css";
		let file = this.getFileFromLeafName(aLeafName);
		this.edit(file);
	},
	UCrebuild: function() {
		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
		let query = "?" + new Date().getTime();
		Array.prototype.slice(document.styleSheets).forEach(function(css){
			if (!re.test(css.href)) return;
			if (css.ownerNode) {
				css.ownerNode.parentNode.removeChild(css.ownerNode);
			}
			let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"');
			document.insertBefore(pi, document.documentElement);
		});
		UCL.UCcreateMenuitem();
	},
	UCcreateMenuitem: function() {
		let sep = $("usercssloader-ucsepalator");
		let popup = sep.parentNode;
		if (sep.nextSibling) {
			let range = document.createRange();
			range.setStartAfter(sep);
			range.setEndAfter(popup.lastChild);
			range.deleteContents();
			range.detach();
		}

		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
		Array.prototype.slice(document.styleSheets).forEach(function(css) {
			if (!re.test(css.href)) return;
			let fileURL = decodeURIComponent(css.href).split("?")[0];
			let aLeafName = fileURL.split("/").pop();
			let m = $C("menuitem", {
				label		: aLeafName,
				tooltiptext	: fileURL,
				id			: "usercssloader-" + aLeafName,
				type		: "checkbox",
				autocheck	: "false",
				checked		: "true",
				oncommand	: "this.setAttribute('checked', !(this.css.disabled = !this.css.disabled));",
				onclick		: "UCL.UCItemClick(event);"
			});
			m.css = css;
			popup.appendChild(m);
		});
	},
	UCItemClick: function(event) {
		if (event.button == 0) return;
		event.preventDefault();
		event.stopPropagation();

		if (event.button == 1) {
			event.target.doCommand();
		}
		else if (event.button == 2) {
			closeMenus(event.target);
			let fileURL = event.currentTarget.getAttribute("tooltiptext");
			let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL);
			this.edit(file);
		}
	},
};

function CSSEntry(aFile) {
	this.path = aFile.path;
	this.leafName = aFile.leafName;
	this.lastModifiedTime = 1;
	this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ? 
		Ci.nsIStyleSheetService.AGENT_SHEET: 
		Ci.nsIStyleSheetService.USER_SHEET;
}
CSSEntry.prototype = {
	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
	_enabled: false,
	get enabled() {
		return this._enabled;
	},
	set enabled(isEnable) {
		var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
		aFile.initWithPath(this.path);
	
		var isExists = aFile.exists(); // ファイルが存在したら true
		var lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
		var isForced = this.lastModifiedTime != lastModifiedTime; // ファイルに変更があれば true

		var fileURL;
			try {
					fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile);
			} catch {
					fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
			}

		var uri = Services.io.newURI(fileURL, null, null);

		if (this.sss.sheetRegistered(uri, this.SHEET)) {
			// すでにこのファイルが読み込まれている場合
			if (!isEnable || !isExists) {
				this.sss.unregisterSheet(uri, this.SHEET);
			}
			else if (isForced) {
				// 解除後に登録し直す
				this.sss.unregisterSheet(uri, this.SHEET);
				this.sss.loadAndRegisterSheet(uri, this.SHEET);
			}
		} else {
			// このファイルは読み込まれていない
			if (isEnable && isExists) {
				this.sss.loadAndRegisterSheet(uri, this.SHEET);
			}
		}
		if (this.lastModifiedTime !== 1 && isEnable && isForced) {
			log(this.leafName + " の更新を確認しました。");
		}
		this.lastModifiedTime = lastModifiedTime;
		return this._enabled = isEnable;
	},
};

function CSSTester(aWindow, aCallback) {
	this.win = aWindow || window;
	this.doc = this.win.document;
	this.callback = aCallback;
	this.init();
}
CSSTester.prototype = {
	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
	preview_code: "",
	saved: false,
	init: function() {
		this.dialog = openDialog(
			"data:text/html;charset=utf8,"+encodeURIComponent('<!DOCTYPE HTML><html lang="ja"><head><title>CSSTester</title></head><body></body></html>'),
			"",
			"width=550,height=400,dialog=no");
		this.dialog.addEventListener("load", this, false);
	},
	destroy: function() {
		this.preview_end();
		this.dialog.removeEventListener("unload", this, false);
		this.previewButton.removeEventListener("click", this, false);
		this.saveButton.removeEventListener("click", this, false);
		this.closeButton.removeEventListener("click", this, false);
	},
	handleEvent: function(event) {
		switch(event.type) {
			case "click":
				if (event.button != 0) return;
				if (this.previewButton == event.currentTarget) {
					this.preview();
				}
				else if (this.saveButton == event.currentTarget) {
					this.save();
				}
				else if (this.closeButton == event.currentTarget) {
					this.dialog.close();
				}
				break;
			case "load":
				var doc = this.dialog.document;
				doc.body.innerHTML = '\
					<style type="text/css">\
						:not(input):not(select) { padding: 0px; margin: 0px; }\
						table { border-spacing: 0px; }\
						body, html, #main, #textarea { width: 100%; height: 100%; }\
						#textarea { font-family: monospace; }\
					</style>\
					<table id="main">\
						<tr height="100%">\
							<td colspan="4"><textarea id="textarea"></textarea></td>\
						</tr>\
						<tr height="40">\
							<td><input type="button" value="Preview" /></td>\
							<td><input type="button" value="Save" /></td>\
							<td width="80%"><span class="log"></span></td>\
							<td><input type="button" value="Close" /></td>\
						</tr>\
					</table>\
				';
				this.textbox = doc.querySelector("textarea");
				this.previewButton = doc.querySelector('input[value="Preview"]');
				this.saveButton = doc.querySelector('input[value="Save"]');
				this.closeButton = doc.querySelector('input[value="Close"]');
				this.logField = doc.querySelector('.log');

				var code = "@namespace url(" + this.doc.documentElement.namespaceURI + ");\n";
				code += this.win.location.protocol.indexOf("http") === 0?
					"@-moz-document domain(" + this.win.location.host + ") {\n\n\n\n}":
					"@-moz-document url(" + this.win.location.href + ") {\n\n\n\n}";
				this.textbox.value = code;
				this.dialog.addEventListener("unload", this, false);
				this.previewButton.addEventListener("click", this, false);
				this.saveButton.addEventListener("click", this, false);
				this.closeButton.addEventListener("click", this, false);

				this.textbox.focus();
				let p = this.textbox.value.length - 3;
				this.textbox.setSelectionRange(p, p);

				break;
			case "unload":
				this.destroy();
				this.callback(this);
				break;
		}
	},
	preview: function() {
		var code = this.textbox.value;
		if (!code || !/\:/.test(code))
			return;
		code = "data:text/css;charset=utf-8," + encodeURIComponent(this.textbox.value);
		if (code == this.preview_code)
			return;
		this.preview_end();
		var uri = Services.io.newURI(code, null, null);
		this.sss.loadAndRegisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET);
		this.preview_code = code;
		this.log("Preview");
	},
	preview_end: function() {
		if (this.preview_code) {
			let uri = Services.io.newURI(this.preview_code, null, null);
			this.sss.unregisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET);
			this.preview_code = "";
		}
	},
	save: function() {
		var data = this.textbox.value;
		if (!data) return;

		var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
		fp.init(window, "", Ci.nsIFilePicker.modeSave);
		fp.appendFilter("CSS Files","*.css");
		fp.defaultExtension = "css";
		if (window.UCL)
			fp.displayDirectory = UCL.FOLDER;
		var res = fp.show();
		if (res != fp.returnOK && res != fp.returnReplace) return;

		var suConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
		suConverter.charset = "UTF-8";
		data = suConverter.ConvertFromUnicode(data);
		var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
		foStream.init(fp.file, 0x02 | 0x08 | 0x20, 0664, 0);
		foStream.write(data, data.length);
		foStream.close();
		this.saved = true;
	},
	log: function() {
		this.logField.textContent = dateFormat(new Date(), "%H:%M:%S") + ": " + $A(arguments);
	}
};

UCL.init();

function $(id) { return document.getElementById(id); }
function $A(arr) { return Array.prototype.slice(arr); }
function $C(name, attr) {
	const el = document.createElementNS(XULNS, name);
	if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) });
	return el;
}
function dateFormat(date, format) {
	format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4));
	format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2));
	format = format.replace("%d", ("0" + date.getDay()).substr(-2));
	format = format.replace("%H", ("0" + date.getHours()).substr(-2));
	format = format.replace("%M", ("0" + date.getMinutes()).substr(-2));
	format = format.replace("%S", ("0" + date.getSeconds()).substr(-2));
	return format;
}

function log() { Application.console.log(Array.prototype.slice(arguments)); }

})();


Жизнь иногда такое выкидывает, что хочется подобрать...

На форуме

 

№42422-07-2022 23:24:10

kazarin
Участник
 
Группа: Members
Зарегистрирован: 23-11-2016
Сообщений: 80
UA: Firefox 101.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Farby
Меню появилось, но стили не отключаются и не обновляются. Проверял на чистой 102 ESR.


UPD Скрипт заработал! Правда, запускается он каким-то извращённым способом: во-первых, ему нужен пустой (ну или запиканный звёздочками) userChrome.css. В принципе, он его и так игнорит, но ни в 78, ни в доквантумных версиях наличие записей там ему не мешало. А во-вторых, после редактирования userChrome.css обновить надо через кнопку Reload user{Chrome, Content}.css. Тогда он видит изменения и потом уже начинает нормально работать.

Спасибо, что починили, очень уж удобный скрипт, приходилось держать вместо него три кнопки, которые не охватывали полностью его функций:)

Отредактировано kazarin (24-07-2022 15:22:42)

Отсутствует

 

№42526-07-2022 15:28:26

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 12-06-2018
Сообщений: 289
UA: Firefox 103.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby посмотрите пожалуйста кнопку Save.В ней не работает функция "Сохранить значок веб-сайта"

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

Выделить код

Код:

self.label = "Save";
self._handleClick =()=> menuPopup.openPopup(this, "after_start");
self.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==";

var folderpath="C:\\Users\\Firepox\\Desktop";         // папка для сохранения иконок для ярлыков и ярлыков сайтов

// Создать меню для кнопки .............
var array = [
   { label: "Сохранить значок веб-сайта", 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: "Запомнить значок веб-сайта как 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: "Кодировать изображение(текст.файл) в base64", func: "copyFaviconbase()", 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: "Сохранить всю страницу как 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: "Сохранить всю страницу или выбранное как HTML", func: "savePageToHTML()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACzElEQVQ4jV2STW8bZRDHf/Psrr11nZhgVKcKaSmUiArRKBRVIMgH4BKJ7xAp5MSFiA+Rc28ckBAoipC4koJQLyAaVFChIlQllDRWmjRev8Qvu14/+wwHx6ZlpNFcZn7zn79GVJW1tbXc6urqijHGqKoAPF3TgcVaq8owXJbphx99fOOnWzcHoqqsr68/t7y83BARVBXnHHraXo3a3HoUU8gFAHRTS2Bg/7C2Zx7vXPIBwjA0p3BU9Zns9i3vvVrhr6MWzlpee+EsRqAbHc3+/Pee7wPkcrkx4P+g0IMvb/5Iv5/iXEaWZQS+By578MaVy9YH8H3fE5FnANZajqMmgcAnH7yN73mICMYMd21sbLy7srKiPkA+n3/qBLhzv8p+EuOfTUjShPbODvOVWa5fnRsvKBaLAcAIMFbw+bc/EBVn8At7SPcQ60LSiVm++P0fGu0e7y++yalvHoABCILAiAj7hzU+vfcVT6zPVGmR3x4/xJoLSH6BVu4cN777nnQwQETI5XL/AYwxRkS4ff8BEk6Q2pBfq3dxUuHMmWt0kgFGStTDY/7YrTLybQwYPU2cpgzsCd1OgmSzWHeOR7VjWicxaT9lxn+HfjoYmWnGHgAiIsydf5HKnUXiThehQDG4Tr3e5KR7hN8XilnGKxfOoyrDgZECwIgIb125xIxxTGVdgjRG4pR2+zbG/sIkD7l2cYJyaYLMOZxzjBV4nueLCI1GnaWFab65t4OXt4gUuFqYJ8gGuPYBCxdLHNciys9PkaapjAHGGM8YQ7lcZv71OaYmC/xZPaJHTN4cUgpDXrr8MtOVaUqTRXzfY3t7u7O0tDR82a2trfkkSTSOY+31etrpdLTZbGoURRpFkdbrTY3qTW00mhrHse7u7t4tl8uhqg4VxHHcPDg4+ExVHeBU1YmIU1WnisucZtamLszn01ar9WRzc/PrWq2WAPwLJ7l2ULfXOAMAAAAASUVORK5CYII="},
   { label: "Сохранить выделенный текст как 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, в контекстном меню", value: "Save.WebScreenShotOnImage"},
   { 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", ()=> eval(m.func.toString()));
});
menuPopup.setAttribute("onclick", "event.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;
}
 

function WebScreenShotonImage(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 sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(base64, self.label, "Изображение копировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
};


var saveToFile = function (fileContent, fileName) {
    var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    uc.charset = 'utf-8';
    fileContent = uc.ConvertFromUnicode(fileContent);

    var nsIFilePicker = Components.interfaces.nsIFilePicker;
    var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
    fp.init(window, '', fp.modeSave);
    fp.defaultString = fileName;
    fp.appendFilters(fp.filterHTML);
    fp.appendFilters(fp.filterAll);
    fp.open(function (rv) {
  if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
    var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
    stream.init(fp.file, 0x02|0x20|0x08, 0666, 0);
    stream.write(fileContent, fileContent.length);
    stream.close();
  }
});
};


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.setAttribute('style','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. loadURI(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
};


function saveShortcuts() {
var file = Components.classes["@mozilla.org/file/local;1"].
           createInstance(Components.interfaces.nsIFile);
file.initWithPath(folderpath);

if( !file.exists() || !file.isDirectory() ) {   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1B6);}

var savetodir=folderpath+"\\"; 
var urllink=gBrowser.currentURI.spec;
var out=getTabLabel();
var filename=savetodir+out+'.url';
var data="[InternetShortcut]\r\nURL="+urllink+"\r\n";

saveToFile(data, filename);
 // стиль для изображения во всплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};

// Кодировать изображение или текстовой файл в base64 .............
function copyFaviconbase(){
var fp = window.makeFilePicker();
fp.init(window, "Открыть файл", fp.modeOpen);
fp.appendFilter("Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml; *.xhtml; *.jpe; *.jpg; *.jpeg;\
                                    *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw");
  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, 0600, 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);
   //Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Текст скопирован как  base64");
    // стиль для изображение в сплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Изображение скопировано как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Изображение скопировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
});
};

// Сохранить страницу как PDF файл через сервис 'pdfmyurl.com' .............
function savePageToPDF() {
      var loc = gBrowser.currentURI.spec;
   var vert = "http://pdfmyurl.com?url=" + loc;
  
   gBrowser. loadURI(vert, {
   triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
   });
};

// Сохранить иконку текущего сайта с диалогом сохранения .............
if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15
	? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
	: (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);
function saveFavicon() {
       var uri = gBrowser.currentURI;
       function getSiteName() {
                  try { var domain = uri.host.split('.') } catch(e) { return "" };
                   domain = (domain.length == 2) ? domain[0] : domain[1]
                   return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " ";  
            };
    var url = gBrowser.selectedTab.image;
    url && saveImageURL(
        url, getSiteName(), null, false, false, null, null,
        /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"]
            .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)),
        null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal
    );
};


// Копировать иконку текущего сайта в base64 .............
function copyFaviconData() {
   var img = new Image();
   img.src = gBrowser.selectedTab.image;
   WebScreenShotonImage(img);
};

//Добавыть в контекстное меню страницы пункт "Запомнить изображение как base64"..........................................................................................
(popup => addEventListener("popupshowing", {
    handleEvent(e) {
        if (this.shouldHide) return;

        var menuitem = document.createXULElement("menuitem");
        menuitem.id = "content-baseItem";
        menuitem.className = "menuitem-iconic";
        menuitem.setAttribute("oncommand", "copyImageAsBase64()");
        menuitem.setAttribute("label", "Запомнить изображение как base64");
        menuitem.setAttribute("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==");
        popup.append(menuitem);
        addDestructor(() => menuitem.remove());

        menuitem.copyImageAsBase64 = () => {
            var {osPid} = gContextMenu.actor.manager.browsingContext.currentWindowGlobal;
            if (osPid == -1) osPid = Services.appinfo.processID;
            for(var ind = 0, len = Services.ppmm.childCount; ind < len; ind++) {
                var pmm = Services.ppmm.getChildAt(ind);
                if (pmm.osPid == osPid) break;
            }
            pmm.loadProcessScript("data:;charset=utf-8," + encodeURIComponent(this.code()), false);
        }
        this.handleEvent = () => menuitem.hidden = this.shouldHide;
    },
    get shouldHide() {
        return !(gContextMenu.onImage && Services.prefs.getBoolPref("Save.WebScreenShotOnImage", false));
    },
    code: () => `(targetIdentifier => {

        var image = ChromeUtils.import("resource://gre/modules/ContentDOMReference.jsm")
            .ContentDOMReference.resolve(targetIdentifier);

        var canvas = image.ownerDocument.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();

        Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
            .copyStringToClipboard(base64, Ci.nsIClipboard.kGlobalClipboard);

        Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
            .showAlertNotification(base64, "${self.label}", "Запомнил изображение как base64");
    })(${
        JSON.stringify(gContextMenu.targetIdentifier)
    })`
}, false, popup || 1))(document.getElementById("contentAreaContextMenu"));


// Сохранить выделенный текст или весь текст на странице как txt файл .............
function saveSelectionToTxt() {
	var splice = saveURL.length == 10;
	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);
		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,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAA////AIiafwC85K4AS1ZGANLsyABKU0UAy+m+AL/lsQC14aQAn9WMAJ/QjQCsrKwAqNyXAOPz3ADe8dcA2e/QANPtyQDM68EAxei4AL7lrwC14aUArt6dAJfOhACdz4sAgICAALThpQDg8doA3vHVANjuzgDR7MYAyum+AMLmtQC7460AsuCjAK3dmgCUy4AArdedANDsxQDL6sAAz+PIAMviwwDH4L4Awd62ALvbrwC02KcArdafAKbTlgCEu3EAtNWoANPqywDa8NIA1u7NANHtxwDK6cAAw+e3ALzkrwC14aYAr9+dAKXbkQCJwnMA1+3QAKncmADd8dQAyuLBAMbgvAC6264AttmoAK/XoACn1JYAotKPAJbNgwB9tWgA4+zfANju0ADT7coAz+vFAMPntgC95K8Art6eAKndlQCa1IYAi8R3AP3+/QDD37kAvt2yALjarACz2KYArdaeAKHRjwCXzoUAj8V6AI6/ewDu8e4Awea2AMrqwQDG6LoAweazALnjqwCz4KQAr9+cAKbbkwCd2IkAlc1/AKbTlQC73K8At9qqALDXowCp1ZsApdOVAKDRjQCYzoUAksx7AIi+cwCu0aEAp9yUAMXougDC5rYAveSuALfipwCw4J8AqdyXAKLajwCd2IcAlNR9AI3FdwDU6ssAqdWZAKPSkgCe0YsAmc6GAJDLfQB/tmoA3enZAJfWhACc2IkApNuRAKTbkACj2pAAodqOAKHZjgCl25IAotmOAIzHdgAPAAAA2JIKAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOzARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcrkUA9CUMAAAAAAAAAAAAAAAAAAAAAAAAAA8AAQAAAAEAAAAAAAAAVCIMAAAAAAABAAAAuwP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAACZDSMAAQAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABAEAABHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGRkZGRkZGRkZAAAAAAAZAQEBAQEBAQEBARkAAIeHiImKi4yNjY5+AQEZAD4mJlZXRH+AgYKDhIVdGQBzJnR1dnd4eXp7fH1+ARkAGiYnaWprbG1ub3Bxcl0ZACdeJl9gYWJjZGVmZ2gBGQAAAyZUVVZXWEVZWltcXRkAAA1KS0wfTU45T1BRUlMZAAA+P0BBK0JDREVGR0hJGQAAAzIzNDU2Nzg5Ojs8PRkAACYnKCkqKywtLi8YMDEZAAAAGhscHR4fICEiIyQlGQAAAA0ODxAREhMUFRYXGBkAAAADBAUGBwYIBgkGChkAAAAAAAACAAIAAgACAAIAAPgBAADwAAAAwAAAAIAAAACAAAAAgAAAAIAAAADAAAAAwAAAAMAAAADAAAAAwAAAAOAAAADgAAAA4AEAAPqrAAA="); 
   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/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить всю страницу как PNG"
                value="all"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить видимую часть страницы как PNG"
                value="page"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAIBkAAAEAIAAMDQAAFgAAACgAAAAgAAAAMgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29fT/2tra/8jIyP/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8jIyP/a2tr/9vX0/+zs7P/ak0b/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/9qTRv/s7Oz/7Ozs/+J9Dv/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/6SdmP/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/+vn4//z7+v/6+fj/4n0O/+zs7P/s7Oz/4n0O//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/aFtT//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//j39v/ifQ7/7Ozs/+zs7P/ifQ7/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P9oW1P/7+zq/+/s6v/v7Or/8O3r//Dt6//w7ev/8O3r//Dt6//w7ev/8O3r/+/s6v/w7ev/9fTy/+J9Dv/s7Oz/7Ozs/+J9Dv/49/b/+Pf2//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4/2hbU//q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/y8O//4n0O/+zs7P/s7Oz/4n0O//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/aFtT/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe//Dt6//ifQ7/7Ozs/+zs7P/ifQ7/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P9oW1P/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/7uro/+J9Dv/s7Oz/7Ozs/+J9Dv/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx/2hbU//x7+3/8vDv//Hv7f/x7+3/8e/t//Lw7//x7+3/8e/t//Lw7//x7+3/8vDv//Hv7f/29fT/4n0O/+zs7P/s7Oz/4n0O//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//aFtT/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/8vGwf/ifQ7/7Ozs/+zs7P/ifQ7/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f9nWlL/aFtT/2hbU/9nWlL/Z1pS/2hbU/9oW1P/Z1pS/2daUv9oW1P/aFtT/2hbU/9nWlL/pJyX/+J9Dv/s7Oz/7Ozs/+J9Dv/w7ev/8O3r//Dt6//w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Hv7f/w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Dt6//w7ev/4n0O/+zs7P/s7Oz/4n0O/+/s6v/v7Or/7uro/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/u6uj/7+zq/+/s6v/ifQ7/7Ozs/+zs7P/ifQ7/7uro/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7Ojm/+J9Dv/s7Oz/7Ozs/+J9Dv/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/4n0O/+zs7P/s7Oz/4n0O/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/ifQ7/7Ozs/+zs7P/ifQ7/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+J9Dv/s7Oz/7Ozs/+J9Dv/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/4n0O/+zs7P/s7Oz/4n0O/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/ifQ7/7Ozs/+zs7P/ifQ7/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+J9Dv/s7Oz/7Ozs/+J9Dv/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/k39z/4n0O/+zs7P/s7Oz/4n0O/+Lc2f/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/ifQ7/7Ozs/+zs7P/ifQ7/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+J9Dv/s7Oz/9fTy/+J9Dv/8+/r/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/4n0O//X08v/8+/r/6KFU/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ooVT//Pv6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранный элемент страницы как PNG"
                value="click"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAADDn2Hfz5pE/8eVQP7IlkH/yJZB/8iWQf/IlUH/yJVA/8iVQP/IlED/yJQ//8iUP//IlD//yJM+/8iTPv/Hkj3/nI1w//bDbP//8OH//+zW///s1///69b//+rV///p1P//59L//+XQ///izf//38n//9vG///ZxP//1b///dG////Prf/KlkX/88N4/v37///99Pj//fT6//vy9v/68fT/+u/y//rt8P/66u3/+ufq//rl6P/64eT/+93h//3a3//71d7//9LK/86XR//0xHb//vv////18///9fT///f5///4////9f7///P8///v+f//7Pb//+nz///m8f//4eb//9vZ//3Y2v//1Mb/zphH//TGd//+/////Pj1///7///Q58r/m9aV/6TZnv+i15r/otWY/6LTlv+j0pb/mc6M/9DXuf//3+P//Nnc///Wyf/OmUf/9MZ3//7////8+/j//////53WnP+Y5pn/rvGv/6PvpP+e7p//me6b/5nvm/95533/mM+L///j7f/629z//9jL/86ZR//0xnf//v////z9+v//////qtup/8Xzxf/a/tn/z/vO/8n7yf/D+sL/xPvD/6Hzo/+j05b//+Tu//re3///2cz/zplI//XGeP/+/////P36//////+n26f/uvC6/9T71P/K+Mr/xvjG/8D3wP+/+L//nfCf/6LTlf//5u//+t/g///cz//OmUj/9MZ3//7////8/fr//////6rcqv/G9MX/3//f/9n92f/V/NX/0PzQ/9H+0P+s9a7/pdSY///o8f/64OL//9zP/86aSP/0xnf//v////z9+f//////ndid/5TjlP+v7q//qeyp/6jsqf+k7KX/p+6n/4Tlh/+Z0Y7//+r0//rh4v//3tH/zppI//TGd//+/////v77///////Y8Nj/p9+n/6/jr/+t4a3/rd2p/67bpv+u2ab/p9Wc/9jgx///6Oz//OPl///e0f/Omkj/9MV1//7//////fr///78///+/f///////////////////P////j////0+///8fn//+vu///m4v/94+P//97P/86ZSP/zx3v//v/////+/f///////f////v////7////+/////v+///7+///+/f///vz/P/98Pr//+33//3p9///5OL/zppL//a1Sv/0xoL/9cR7//XEfP/1xHz/9cR8//XEfP/1xH3/9cR8//XCev/1wXr/9b94//W9d//1u3X/87l0//y6bP/Llj7/+pMA/vWBAP/1gwD/9YMA//WDAP/1gwD/9YMA//WDAP/1gwD/9YQA//WEAP/1hAD/9YQA//WEAP/zhAH//okA/8qLIv3xpzP/4ptV/+OdU//jnVP/451T/+OdU//jnVP/451T/+OdU//jnVL/451S/+OdUv/jnVL/451S/+GdVf/qnUf/2aRJ/9q0c9/8yn7/98V5/vjGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6/vrIe/+jj2y4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранную область страницы как PNG"
                value="clipping"/>
        </menugroup>
    `);
    var menugroup = df.firstChild;
    menugroup.setAttribute("context", "");
    menugroup.setAttribute("oncommand", "handleCommand(event);");
    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, "Сохранить как…", 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
                ];
                var {length} = wbp.saveURI;
                length >= 9 && splice(args);
                length == 10 && args.splice(3, 0, null);
                wbp.saveURI(...args);
				
		setTimeout(async lp => {
			var d = await Downloads.createDownload({
				source: "about:blank", target: fp.file
			});
			(await lp).add(d);
			d.refresh(d.succeeded = true);
		}, 777, Downloads.getList(Downloads.ALL));				
            });
        }
        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);
    }
    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));
        }
    }`
});

Отсутствует

 

Board footer

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