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

В мире Mozilla происходит много интересных событий. Но вам не нужно постоянно посещать новостные сайты, чтобы быть в курсе всех изменений. Зайдите на ленту новостей Mozilla Россия.

№1605110-12-2021 14:23:06

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 78.0

Re: Custom Buttons

Custom Buttons не отключается в приватном режиме, хотя соответствующая птичка поставлена. Это исправимо?

Отсутствует

 

№1605210-12-2021 16:25:43

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 336
UA: Firefox 93.0

Re: Custom Buttons

Dumby
А можно как-то стили на кнопки по другому задать? А то в HELP  типа, этого и стили в custom_падают...А если не через #nav-bar-customization-target , то в кнопке стиль не того.
#nav-bar-customization-target > #id > image {height: 18px !important; width: 18px !important; margin-left: -1px !important; margin-right: -1px !important;}
Теперь так: #nav-bar > hbox > #id{background: none !important; }
А раньше просто #id{background: none !important; } и этого хватало... Да, и сам код в ini

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

Выделить код

Код:

var style = custombutton.buttonGetHelp(self).replace(/id/g, _id);
var uri = makeURI('data:text/css,'+ encodeURIComponent(style));
var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
sss.loadAndRegisterSheet(uri, 0);

Отредактировано ВВП (10-12-2021 17:20:56)

Отсутствует

 

№1605310-12-2021 20:15:17

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 68.0

Re: Custom Buttons

shadow_user пишет

Custom Buttons не отключается в приватном режиме, хотя соответствующая птичка поставлена. Это исправимо?

Никогда и не отключался. Исправлять нечего.


ВВП
Уж не знаю о чём ты, но, помимо отсутствия деструктора,
/id/g — не слишком ли странно? Так ведь и какой-нибудь width разреплейситься.

Отсутствует

 

№1605411-12-2021 19:57:31

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 336
UA: Firefox 95.0

Re: Custom Buttons

Dumby
Точно с width это перебор. Но остальное устаканил. Короче, рихтанул 95 конкретно и на основе Iceweasel очень даже неплохо.

Отсутствует

 

№1605513-12-2021 13:33:53

Senflex
Участник
 
Группа: Members
Зарегистрирован: 18-07-2021
Сообщений: 29
UA: Chrome 96.0

Re: Custom Buttons

Приветствую всех! Как можно имитировать нахождение на странице как бы в развёрнутом состоянии в свёрнутом браузере? На некоторых сайтах при свёрнутом режиме некоторые функции переходят в стадию заморозки и не подгружаются.

Отредактировано Senflex (13-12-2021 17:33:13)

Отсутствует

 

№1605615-12-2021 15:12:21

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 322
UA: Firefox 95.0

Re: Custom Buttons

Dumby, приветствую!
Вы помогли написать код для аддона ContextSearch https://forum.mozilla-russia.org/viewto … 07#p770807
В результате работы кода в контекстном меню сразу виднелись значки всех поисковых машин
Автор ContextSearch обновил свой аддон и теперь наш код не работает
Можно ли попростить вас подправить?
Я думал просто изменился ID аддона, но там что-то посерьезней в чем я совершенно не разбираюсь.



вот обновленный аддон
https://github.com/ssborbis/ContextSear … tag/1.32a2

а вот код

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

Выделить код

Код:

/*ContextSearch-web-ext*/

(popup => {
    var id = "cswem-menugroup";
    var mid = "_5dd73bb9-e728-4d1e-990b-c77d8e03670f_-menuitem-_search_engine_menu";
    var css = `
        #${id} {
            padding-left: 30px;

            display: grid;
            grid-template-columns: repeat(auto-fill, 32px);
            grid-auto-rows: 26px;
        }
        #${id} > menuitem {
            -moz-box-pack: center;
        }
        #${mid},
        #${id}:empty,
        #${id} > menuitem > :not(.menu-iconic-left) {
            display: none;
        }

    `.replace(/;/g, " !important;");
    var url = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
    windowUtils.loadSheetUsingURIString(url, type);

    var menugroup = document.createXULElement("menugroup");
    menugroup.setAttribute("oncommand", "this.onclick(event)");
    menugroup.id = id;
    menugroup.onclick = e => {
        var target = e.target.linkedMenuitem;
        if (!target) return;
        var handler = Services.els.getListenerInfoFor(target)
            .find(info => info.type == e.type).listenerObject;
        var {button, ctrlKey, shiftKey} = e;
        handler({button, ctrlKey, shiftKey, target, currentTarget: target});
    }
    document.getElementById("context-searchselect").after(menugroup);

    addEventListener("popuphidden", e => {
        if (menugroup.firstChild && e.target == popup) menugroup.textContent = "";
    }, false, popup);

    var fillMenugroup = menu => {
        var p = menu.querySelector(":scope > menupopup");
        for(var menuitem of menu.getElementsByTagName("menuitem")) {

            var m = document.createXULElement("menuitem");
            m.className = "menuitem-iconic";
            m.setAttribute("image", menuitem.getAttribute("image"));

            var tt = menuitem.getAttribute("label");
            if (menuitem.closest("menupopup") != p)
                tt = menuitem.closest("menu").getAttribute("label") + "\n" + tt;
            m.setAttribute("tooltiptext", tt);

            m.linkedMenuitem = menuitem;
            menugroup.append(m);
        }
        var lc = menugroup.lastChild;
        menugroup.style.setProperty(
            "height", (lc.screenY + lc.scrollHeight - menugroup.screenY) + "px", "important"
        );
    }
    var mo = new MutationObserver(muts => {
        for(var mut of muts) for(var node of mut.addedNodes) 
            if (node.id == mid) return fillMenugroup(node);
    });
    mo.observe(popup, {childList: true});
    addDestructor(() => {
        mo.disconnect();
        menugroup.remove();
        windowUtils.removeSheetUsingURIString(url, type);
    });
})(document.getElementById("contentAreaContextMenu"));

(ss => ss.collapsed = !addDestructor(() => ss.collapsed = false))(
    document.getElementById("context-searchselect")
);

Отредактировано leex (15-12-2021 15:13:41)

Отсутствует

 

№1605715-12-2021 16:29:22

beggrr
Участник
 
Группа: Members
Зарегистрирован: 04-02-2014
Сообщений: 128
UA: Firefox 85.0

Re: Custom Buttons

Можно ли сделать, чтобы одна конкретная кнопка инициализировалась только на одном домене?
У меня есть кнопка, весь код которой заточен для одного домена. На остальных доменах кнопка просто висит и ничего не делает.

Отсутствует

 

№1605815-12-2021 19:06:10

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 68.0

Re: Custom Buttons

leex пишет

Я думал просто изменился ID аддона

Изменился id <menu>.
Ещё, я смотрю, только событие "command" осталось.

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

Выделить код

Код:

(popup => {
	var id = "cswem-menugroup";
	var mid = "_5dd73bb9-e728-4d1e-990b-c77d8e03670f_-menuitem-_root_menu";
	var css = `
		#${id} {
			padding-left: 30px;

			display: grid;
			grid-template-columns: repeat(auto-fill, 32px);
			grid-auto-rows: 26px;
		}
		#${id} > menuitem {
			-moz-box-pack: center;
		}
		#${mid},
		#${id}:empty,
		#context-searchselect,
		#${id} > menuitem > :not(.menu-iconic-left) {
			display: none;
		}
		/*
		#${id} > menuitem > .menu-iconic-left > .menu-iconic-icon {
			margin-inline: 2px -3px;
		}
		*/

	`.replace(/;$/gm, " !important;");
	var url = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
	windowUtils.loadSheetUsingURIString(url, type);

	var menugroup = document.createXULElement("menugroup");
	menugroup.id = id;
	menugroup.hidden = true;

	var find = info => info.type == "command";
	menugroup.setAttribute("oncommand", "handleCommand(event);");
	menugroup.handleCommand = e => {
		var target = e.target.linkedMenuitem;
		var {button, ctrlKey, shiftKey, altKey, metaKey} = e;
		Services.els.getListenerInfoFor(target).find(find).listenerObject({
			button, target, currentTarget: target,
			ctrlKey, shiftKey, altKey, metaKey
		});
	}
	document.getElementById("context-searchselect").after(menugroup);

	addEventListener("popuphidden", e => {
		if (menugroup.firstChild && e.target == popup) menugroup.textContent = "";
	}, false, popup);

	var fillMenugroup = menu => {
		var p = menu.querySelector(":scope > menupopup");
		for(var menuitem of menu.getElementsByTagName("menuitem")) {

			var m = document.createXULElement("menuitem");
			m.className = "menuitem-iconic";
			m.setAttribute("image", menuitem.getAttribute("image"));

			var tt = menuitem.getAttribute("label");
			if (menuitem.closest("menupopup") != p)
				tt = menuitem.closest("menu").getAttribute("label") + "\n" + tt;
			m.setAttribute("tooltiptext", tt);

			m.linkedMenuitem = menuitem;
			menugroup.append(m);
		}
		var lc = menugroup.lastChild;
		menugroup.style.setProperty(
			"height", (lc.screenY + lc.scrollHeight - menugroup.screenY) + "px", "important"
		);
	}
	var mo = new MutationObserver(muts => {
		for(var mut of muts) for(var node of mut.addedNodes) 
			if (node.id == mid) return fillMenugroup(node);
	});
	mo.observe(popup, {childList: true});
	addDestructor(() => {
		mo.disconnect();
		menugroup.remove();
		windowUtils.removeSheetUsingURIString(url, type);
	});
})(document.getElementById("contentAreaContextMenu"));

beggrr пишет

чтобы одна конкретная кнопка инициализировалась только

Словно сама госпожа Конкретность поцеловала в лоб.
Кнопка инициализируется при добавлении на DOM-дерево, cbClass.connectedCallback()

Отсутствует

 

№1605915-12-2021 20:45:00

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 322
UA: Firefox 95.0

Re: Custom Buttons

Благодарю Dumby!
Все супер как и всегда :)
.
А можно ли попросить убрать из контекстного меню фразу
"добавить краткое имя для данного поиска"
Она появляется в контекстном меню, если выделить текст в любой поисковой строке, на любом сайте.
Этот пункт нам уже не нужен, так как мы используем аддон для этих целей

скрытый текст
118bc912fb93850f529b8d47591364b1.jpg

Отредактировано leex (15-12-2021 20:46:04)

Отсутствует

 

№1606015-12-2021 23:04:28

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 68.0

Re: Custom Buttons

leex пишет

А можно ли попросить убрать из контекстного меню фразу
"добавить краткое имя для данного поиска"

Убрать — нет, а скрыть — вписал, надеюсь.

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

Выделить код

Код:

(popup => {
	var id = "cswem-menugroup";
	var mid = "_5dd73bb9-e728-4d1e-990b-c77d8e03670f_-menuitem-_root_menu";
	var css = `
		#${id} {
			padding-left: 30px;

			display: grid;
			grid-template-columns: repeat(auto-fill, 32px);
			grid-auto-rows: 26px;
		}
		#${id} > menuitem {
			-moz-box-pack: center;
		}
		#${mid},
		#${id}:empty,
		#context-searchselect,
		#context-keywordfield,
		#${id} > menuitem > :not(.menu-iconic-left) {
			display: none;
		}
		/*
		#${id} > menuitem > .menu-iconic-left > .menu-iconic-icon {
			margin-inline: 2px -3px;
		}
		*/

	`.replace(/;$/gm, " !important;");
	var url = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
	windowUtils.loadSheetUsingURIString(url, type);

	var menugroup = document.createXULElement("menugroup");
	menugroup.id = id;
	menugroup.hidden = true;

	var find = info => info.type == "command";
	menugroup.setAttribute("oncommand", "handleCommand(event);");
	menugroup.handleCommand = e => {
		var target = e.target.linkedMenuitem;
		var {button, ctrlKey, shiftKey, altKey, metaKey} = e;
		Services.els.getListenerInfoFor(target).find(find).listenerObject({
			button, target, currentTarget: target,
			ctrlKey, shiftKey, altKey, metaKey
		});
	}
	document.getElementById("context-searchselect").after(menugroup);

	var kwf = document.getElementById("context-keywordfield");
	Object.defineProperty(kwf, "hidden", {
		configurable: true, enumerable: true, get: () => true, set() {}
	});
	addEventListener("popuphidden", e => {
		if (menugroup.firstChild && e.target == popup) menugroup.textContent = "";
	}, false, popup);

	var fillMenugroup = menu => {
		var p = menu.querySelector(":scope > menupopup");
		for(var menuitem of menu.getElementsByTagName("menuitem")) {

			var m = document.createXULElement("menuitem");
			m.className = "menuitem-iconic";
			m.setAttribute("image", menuitem.getAttribute("image"));

			var tt = menuitem.getAttribute("label");
			if (menuitem.closest("menupopup") != p)
				tt = menuitem.closest("menu").getAttribute("label") + "\n" + tt;
			m.setAttribute("tooltiptext", tt);

			m.linkedMenuitem = menuitem;
			menugroup.append(m);
		}
		var lc = menugroup.lastChild;
		menugroup.style.setProperty(
			"height", (lc.screenY + lc.scrollHeight - menugroup.screenY) + "px", "important"
		);
	}
	var mo = new MutationObserver(muts => {
		for(var mut of muts) for(var node of mut.addedNodes) 
			if (node.id == mid) return fillMenugroup(node);
	});
	mo.observe(popup, {childList: true});
	addDestructor(() => {
		mo.disconnect();
		delete kwf.hidden;
		menugroup.remove();
		windowUtils.removeSheetUsingURIString(url, type);
	});
})(document.getElementById("contentAreaContextMenu"));

Отсутствует

 

№1606115-12-2021 23:27:05

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 322
UA: Firefox 95.0

Re: Custom Buttons

Сердечно благодарен, бро!
Теперь все отлично!
:beer:

Отсутствует

 

№1606215-12-2021 23:29:22

beggrr
Участник
 
Группа: Members
Зарегистрирован: 04-02-2014
Сообщений: 128
UA: Firefox 85.0

Re: Custom Buttons

Dumby пишет
beggrr пишет

чтобы одна конкретная кнопка инициализировалась только

Словно сама госпожа Конкретность поцеловала в лоб.
Кнопка инициализируется при добавлении на DOM-дерево, cbClass.connectedCallback()

А что именно надо конкретизировать?
Вот есть кнопка, она инициализируется вместе с остальными при запуске браузера.
Но остальные мне нужны постоянно, а эта только когда я открываю определенный сайт/домен.
Я взял весь код кнопки (вкладка инициализация, другого там нет) и заключил в условие

Выделить код

Код:

if(content.location.hostname==my_domain){
     //...........  Код кнопки
}

Теперь если домен "не тот", код просто не исполняется. Но кнопка то все равно потребляет ресурсы и нагружает браузер. Так вот я и думал, может можно сделать, чтоб она инициализировалась только если я захожу на определенный сайт?

Отсутствует

 

№1606316-12-2021 12:23:19

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Custom Buttons

beggrr пишет

Вот есть кнопка, она инициализируется вместе с остальными при запуске браузера.
Но остальные мне нужны постоянно, а эта только когда я открываю определенный сайт/домен.
Я взял весь код кнопки (вкладка инициализация, другого там нет) и заключил в условие

Вот и переложи (добавь) код в одну из тех остальных, которые нужны постоянно.
А эту кнопку удали. Нет кнопки — нет и этой скряжной проблемы.

Отсутствует

 

№1606418-12-2021 19:08:45

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

Re: Custom Buttons

Dumby
Возможно ли переделать эту кнопку для UCF?

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

Выделить код

Код:

/*Initialization Code*/

self._handleClick =()=> Translate.openPopup(this, "after_start");

var array = [
  [ "Выделенный текст в G.Перевод (Auto –> Ru)", "https://translate.google.com/#view=home&op=translate&sl=auto&tl=ru&text=", "GTranslateEnRu", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACy0lEQVQ4y32SX2iVdRjHP7/3fd7Xbe3M4aYzxW2gOMHUBNEisTRQ2NFwLgwz8sIlVDeiMBZCHIkgCTcpKFCv1IuEUep0HMwSEXWBiM4ksOafmqCVM/d6ztzO+/s9XrzHtXnh9/LH7/k+3z+PvNP+3/7D2ypbJO/8zekvc5ulqT3SH7aljHRssDTVH1dpao9093rLnuwIbY0xkns0/M2Hh8KPjCnj4cN+pLkj0tjB0e0pAyDVKY9/Iujvv6PGgFiFiWVK15krrHl9PtJ/3+IUjjxYxorcHWRdR6QYD1VwCgsHb03IZOaOUITEDr5+d4Rjl4XlDZa27+uHe3uvUVVVmXywFj4+FAKQ/dXDqfLtuRTTOcWGlUuRE62JvKf4YOvJW+lVk+pm1i/BOYe8vSdSq6AKJfGDZd+11p4dOyCKhwEUyJvSn4Fg/AeFtsYChRh2Zcuk9+pvOrm6ElXFWpsE8fmJgF3NBVThfF/Axc6D7NyyEVVNGHakC0SPDarQ/UcNrY1vcuX6DV6aWYc4B591BSgktM5w5PQvtKxdQRzHSGwtFEUm8FiwcCX3Bu4zfUoVkm2rGJfD6vey+nJ6BmGYCJXmjkiN8ZIVRapkHehw7sDRT6Zs4jkQB5gxGkaHAcIX3v+q8+aSVfPi38NQnIioc2Ctw/NU8/n4sGixhR3pAt1XfS796ZEqgcGh5P2n25Mb5r94o2FqdSlhGOL7hiDwUVVSKX+tOAem6NKYZGjOVMdrsxy7TwrWGfZdKGFeeQ8iPhZlIMoxo6aat5YuQpwmFnZ2/d9wT59HT583Gv2ATmNCxQL+vdtDaUlIy+rliEgxgyLBU6jq+FqKefz4Vy1bFz9mqJCj8/QFmt94NTmV7mfOdSwymYtlZ6/9nQMoL/cJXqmhtnYic+qmjdqW51WUySzKf/pFdsvc2RV7Z9WVEgQ+zlmMMYm1waG9TwBslkaEyL4QewAAAABJRU5ErkJggg==" ],
  [ "separator" ],
  [ "Выделенный текст в G.Перевод (Ru –> En)", "https://translate.google.com/#view=home&op=translate&sl=ru&tl=en&text=", "GTranslateRuEn", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACy0lEQVQ4y32SX2iVdRjHP7/3fd7Xbe3M4aYzxW2gOMHUBNEisTRQ2NFwLgwz8sIlVDeiMBZCHIkgCTcpKFCv1IuEUep0HMwSEXWBiM4ksOafmqCVM/d6ztzO+/s9XrzHtXnh9/LH7/k+3z+PvNP+3/7D2ypbJO/8zekvc5ulqT3SH7aljHRssDTVH1dpao9093rLnuwIbY0xkns0/M2Hh8KPjCnj4cN+pLkj0tjB0e0pAyDVKY9/Iujvv6PGgFiFiWVK15krrHl9PtJ/3+IUjjxYxorcHWRdR6QYD1VwCgsHb03IZOaOUITEDr5+d4Rjl4XlDZa27+uHe3uvUVVVmXywFj4+FAKQ/dXDqfLtuRTTOcWGlUuRE62JvKf4YOvJW+lVk+pm1i/BOYe8vSdSq6AKJfGDZd+11p4dOyCKhwEUyJvSn4Fg/AeFtsYChRh2Zcuk9+pvOrm6ElXFWpsE8fmJgF3NBVThfF/Axc6D7NyyEVVNGHakC0SPDarQ/UcNrY1vcuX6DV6aWYc4B591BSgktM5w5PQvtKxdQRzHSGwtFEUm8FiwcCX3Bu4zfUoVkm2rGJfD6vey+nJ6BmGYCJXmjkiN8ZIVRapkHehw7sDRT6Zs4jkQB5gxGkaHAcIX3v+q8+aSVfPi38NQnIioc2Ctw/NU8/n4sGixhR3pAt1XfS796ZEqgcGh5P2n25Mb5r94o2FqdSlhGOL7hiDwUVVSKX+tOAem6NKYZGjOVMdrsxy7TwrWGfZdKGFeeQ8iPhZlIMoxo6aat5YuQpwmFnZ2/d9wT59HT583Gv2ATmNCxQL+vdtDaUlIy+rliEgxgyLBU6jq+FqKefz4Vy1bFz9mqJCj8/QFmt94NTmV7mfOdSwymYtlZ6/9nQMoL/cJXqmhtnYic+qmjdqW51WUySzKf/pFdsvc2RV7Z9WVEgQ+zlmMMYm1waG9TwBslkaEyL4QewAAAABJRU5ErkJggg==" ],
  [ "separator" ],
  [ "Выделенный текст в Y.Перевод (Auto –> Ru)", "https://translate.yandex.ru/?lang=auto-ru&text=", "YTranslateEnRu", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACnElEQVQ4y22TXyidYRzHP297at7N2cmx4ghXLg7bboy8b1ygxFlTsivypxWiLPk37kYuRoqMqWWFC/+WbE3LWtRWJ+c5h62shXCh6KSUZSesdk7PLjDH8r39fn+f5/n+6icA0tLSmoSCVjye5wLAMIxJoTweld/RgeBMhmGo6elphIJp4BFSosXGaqGJAyml7RyiampqAJRQoDg+pmJuDk3TlgULC9DWxuvJyTsarP5jnI2+z87Ozrfb7WRmZlJZWRkQAArmgDykxFdYyE5qKk1NTQBCKPgNXKelBRoaiImKYtVm++B3OFqllD+EBmEK/tDVJejqAvDmHBw8ZHERgEt/ME1TV0p5gWggV0r57VLAbrcf9/b2srKywu7u7lelVEroJp74fD62trbQdZ2ZmRk0TfsoFNwG9pGSX0LQMD5OY2MjPT09VFVV+QSwD4Dfzy2LhRdTU3TGxODxeAgLC0s7fcLlguhosFi44fczPz9f7Xa7X1202N6GoyNYXweHg3PzPPCYkpJhABwOgIjQZpdqhiojIyMiGAx+UkqlJCYmsra2FmoHgAop5eiVANM07wUCge/x8fEkJydTXFzMyMgIOzs76LqO1+sVwIhhGA8uARTcA9LnNjfzP0dGshwMsh8Xh8ViISEhAavVimmaOJ1O2tvbAfKFAh1wAckA5OTgLCvDWVp6Sl1e5t3eHgVDQ/T39zMxMUFWVhYAmqY9E4AXuAtAXh4MDsLAAIyOQnk5KEXB2BitS0t8sdkAcLvdb4QQ1S6X66cAYgBIT4fZWdjbg/p6CA+Hujro6wOgc2OjVoOX/+9LAE50fZGiomskJcHm5oXb3Q1WKxwevr1qGEBo4OXkRKja2vvAUyAXuAms09w8DAxqp0dzpf4Cgj71r0vtOwcAAAAASUVORK5CYII=" ],
  [ "separator" ],
  [ "Выделенный текст в Y.Перевод (Ru –> En)", "https://translate.yandex.ru/?lang=ru-en&text=", "YTranslateRuEn", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACnElEQVQ4y22TXyidYRzHP297at7N2cmx4ghXLg7bboy8b1ygxFlTsivypxWiLPk37kYuRoqMqWWFC/+WbE3LWtRWJ+c5h62shXCh6KSUZSesdk7PLjDH8r39fn+f5/n+6icA0tLSmoSCVjye5wLAMIxJoTweld/RgeBMhmGo6elphIJp4BFSosXGaqGJAyml7RyiampqAJRQoDg+pmJuDk3TlgULC9DWxuvJyTsarP5jnI2+z87Ozrfb7WRmZlJZWRkQAArmgDykxFdYyE5qKk1NTQBCKPgNXKelBRoaiImKYtVm++B3OFqllD+EBmEK/tDVJejqAvDmHBw8ZHERgEt/ME1TV0p5gWggV0r57VLAbrcf9/b2srKywu7u7lelVEroJp74fD62trbQdZ2ZmRk0TfsoFNwG9pGSX0LQMD5OY2MjPT09VFVV+QSwD4Dfzy2LhRdTU3TGxODxeAgLC0s7fcLlguhosFi44fczPz9f7Xa7X1202N6GoyNYXweHg3PzPPCYkpJhABwOgIjQZpdqhiojIyMiGAx+UkqlJCYmsra2FmoHgAop5eiVANM07wUCge/x8fEkJydTXFzMyMgIOzs76LqO1+sVwIhhGA8uARTcA9LnNjfzP0dGshwMsh8Xh8ViISEhAavVimmaOJ1O2tvbAfKFAh1wAckA5OTgLCvDWVp6Sl1e5t3eHgVDQ/T39zMxMUFWVhYAmqY9E4AXuAtAXh4MDsLAAIyOQnk5KEXB2BitS0t8sdkAcLvdb4QQ1S6X66cAYgBIT4fZWdjbg/p6CA+Hujro6wOgc2OjVoOX/+9LAE50fZGiomskJcHm5oXb3Q1WKxwevr1qGEBo4OXkRKja2vvAUyAXuAms09w8DAxqp0dzpf4Cgj71r0vtOwcAAAAASUVORK5CYII=" ],
  [ "separator" ],
  [ "Выделенный текст в DeepL.Перевод (Auto –> Ru)", "https://www.deepl.com/translator#en/ru/", "DeeplTranslateEnRu", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACNwAAAjcB9wZEwgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGZSURBVDiNjZKxaxRBFMZ/b2ZHbWITUxkRC4PnBUW0k1gkoFlMYmIR8R+w0UZBFAvtLAMS0ipC0guCd0GOa23EJGTPkBRCSCNHKiEgMzvPwmjCuiv3lft97zff7BuhQraWTouJLwE0mmf518a7spwUPxwZvlmLms8B4wWrLZhHPvuwUg44N9afGPcc4T5gK4pFgSUv/jHrre8HgKHJE4nzHWBgn/sZdBuYqQB1Q+5rbLR2DUBy1J89GIbEmNmQNW8DqxWAgcS5IQBT5vqYP3H1Gw9AHyosAKECVA4QuKfIPMhHVKygV4OVU8ByT4BDsiI6rWpusdbYUdgpBpLSMeGTRLYx2o5q9kT0ja2P3xU401ODQJz1neYdVRkT9C1gyob/Ngg/3VbifJf9TVg1L2Q43UC1eo3eb8KfB7O7uRf7T782Yo8hXBG4DFwvaRgFFoP4GTqt7u/bFuTOp5dU9BUw8u/BOhqy5fZ//4HvNL6ErHlNkSmFb4e9YM1WMV+5xjxrvM+P99VBngI/qnK96UI66OrpEhcnThatXx/tiqJJdDA6AAAAAElFTkSuQmCC" ],
  [ "separator" ],
  [ "Выделенный текст в DeepL.Перевод (Ru –> En)", "https://www.deepl.com/translator#ru/en/", "DeeplTranslateRuEn", "data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACNwAAAjcB9wZEwgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGZSURBVDiNjZKxaxRBFMZ/b2ZHbWITUxkRC4PnBUW0k1gkoFlMYmIR8R+w0UZBFAvtLAMS0ipC0guCd0GOa23EJGTPkBRCSCNHKiEgMzvPwmjCuiv3lft97zff7BuhQraWTouJLwE0mmf518a7spwUPxwZvlmLms8B4wWrLZhHPvuwUg44N9afGPcc4T5gK4pFgSUv/jHrre8HgKHJE4nzHWBgn/sZdBuYqQB1Q+5rbLR2DUBy1J89GIbEmNmQNW8DqxWAgcS5IQBT5vqYP3H1Gw9AHyosAKECVA4QuKfIPMhHVKygV4OVU8ByT4BDsiI6rWpusdbYUdgpBpLSMeGTRLYx2o5q9kT0ja2P3xU401ODQJz1neYdVRkT9C1gyob/Ngg/3VbifJf9TVg1L2Q43UC1eo3eb8KfB7O7uRf7T782Yo8hXBG4DFwvaRgFFoP4GTqt7u/bFuTOp5dU9BUw8u/BOhqy5fZ//4HvNL6ErHlNkSmFb4e9YM1WMV+5xjxrvM+P99VBngI/qnK96UI66OrpEhcnThatXx/tiqJJdDA6AAAAAElFTkSuQmCC" ]
            ];
var Translate = this.appendChild(document.createXULElement("menupopup"));
array.forEach((m)=> {
  if ( m[0] == "separator" ) { Translate.appendChild(document.createXULElement("menuseparator")); return };
  var mItem = Translate.appendChild(document.createXULElement("menuitem"));
  mItem.setAttribute("label", m[0]);
  mItem.setAttribute("class", "menuitem-iconic");
  mItem.setAttribute("id", m[2]);
  mItem.setAttribute("image", m[3]);
  mItem.onclick =e=>
  {
    let browserMM = gBrowser.selectedBrowser.messageManager;
      browserMM.addMessageListener('getSelect', function listener(message) {
        var selectionTxt = message.data; 
        var url = m[1];
        var txtUrl = (url + encodeURIComponent(selectionTxt));
        gBrowser.selectedTab = gBrowser.addTab(txtUrl, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() });
        browserMM.removeMessageListener('getSelect', listener, true);
      });
    browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false);
  };
});
Translate.setAttribute("onclick", "event.stopPropagation()");

Для FF91.

Отредактировано unter_officer (18-12-2021 19:10:24)


«The Truth Is Out There»

Отсутствует

 

№1606519-12-2021 15:19:21

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Custom Buttons

unter_officer
Выделенное через clipboard. Не то же самое, но, надеюсь, не проблема.
id, label, tooltiptext не дадены, вписал pid поста. Но id лучше сразу
задать окончательный, они сами из browser.uiCustomization.state не исчезают.

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

Выделить код

Код:

(async () => CustomizableUI.createWidget({
	id: "796945",
	label: "796945",
	tooltiptext: "796945",
	image: "chrome://devtools/skin/images/tool-application.svg",
	data: `
		G.Перевод (Auto –> Ru)
		translate.google.com/#view=home&op=translate&sl=auto&tl=ru&text=
		iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACy0lEQVQ4y32SX2iVdRjHP7/3fd7Xbe3M4aYzxW2gOMHUBNEisTRQ2NFwLgwz8sIlVDeiMBZCHIkgCTcpKFCv1IuEUep0HMwSEXWBiM4ksOafmqCVM/d6ztzO+/s9XrzHtXnh9/LH7/k+3z+PvNP+3/7D2ypbJO/8zekvc5ulqT3SH7aljHRssDTVH1dpao9093rLnuwIbY0xkns0/M2Hh8KPjCnj4cN+pLkj0tjB0e0pAyDVKY9/Iujvv6PGgFiFiWVK15krrHl9PtJ/3+IUjjxYxorcHWRdR6QYD1VwCgsHb03IZOaOUITEDr5+d4Rjl4XlDZa27+uHe3uvUVVVmXywFj4+FAKQ/dXDqfLtuRTTOcWGlUuRE62JvKf4YOvJW+lVk+pm1i/BOYe8vSdSq6AKJfGDZd+11p4dOyCKhwEUyJvSn4Fg/AeFtsYChRh2Zcuk9+pvOrm6ElXFWpsE8fmJgF3NBVThfF/Axc6D7NyyEVVNGHakC0SPDarQ/UcNrY1vcuX6DV6aWYc4B591BSgktM5w5PQvtKxdQRzHSGwtFEUm8FiwcCX3Bu4zfUoVkm2rGJfD6vey+nJ6BmGYCJXmjkiN8ZIVRapkHehw7sDRT6Zs4jkQB5gxGkaHAcIX3v+q8+aSVfPi38NQnIioc2Ctw/NU8/n4sGixhR3pAt1XfS796ZEqgcGh5P2n25Mb5r94o2FqdSlhGOL7hiDwUVVSKX+tOAem6NKYZGjOVMdrsxy7TwrWGfZdKGFeeQ8iPhZlIMoxo6aat5YuQpwmFnZ2/d9wT59HT583Gv2ATmNCxQL+vdtDaUlIy+rliEgxgyLBU6jq+FqKefz4Vy1bFz9mqJCj8/QFmt94NTmV7mfOdSwymYtlZ6/9nQMoL/cJXqmhtnYic+qmjdqW51WUySzKf/pFdsvc2RV7Z9WVEgQ+zlmMMYm1waG9TwBslkaEyL4QewAAAABJRU5ErkJggg==

		G.Перевод (Ru –> En)
		translate.google.com/#view=home&op=translate&sl=ru&tl=en&text=

		Y.Перевод (Auto –> Ru)
		translate.yandex.ru/?lang=auto-ru&text=
		iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACnElEQVQ4y22TXyidYRzHP297at7N2cmx4ghXLg7bboy8b1ygxFlTsivypxWiLPk37kYuRoqMqWWFC/+WbE3LWtRWJ+c5h62shXCh6KSUZSesdk7PLjDH8r39fn+f5/n+6icA0tLSmoSCVjye5wLAMIxJoTweld/RgeBMhmGo6elphIJp4BFSosXGaqGJAyml7RyiampqAJRQoDg+pmJuDk3TlgULC9DWxuvJyTsarP5jnI2+z87Ozrfb7WRmZlJZWRkQAArmgDykxFdYyE5qKk1NTQBCKPgNXKelBRoaiImKYtVm++B3OFqllD+EBmEK/tDVJejqAvDmHBw8ZHERgEt/ME1TV0p5gWggV0r57VLAbrcf9/b2srKywu7u7lelVEroJp74fD62trbQdZ2ZmRk0TfsoFNwG9pGSX0LQMD5OY2MjPT09VFVV+QSwD4Dfzy2LhRdTU3TGxODxeAgLC0s7fcLlguhosFi44fczPz9f7Xa7X1202N6GoyNYXweHg3PzPPCYkpJhABwOgIjQZpdqhiojIyMiGAx+UkqlJCYmsra2FmoHgAop5eiVANM07wUCge/x8fEkJydTXFzMyMgIOzs76LqO1+sVwIhhGA8uARTcA9LnNjfzP0dGshwMsh8Xh8ViISEhAavVimmaOJ1O2tvbAfKFAh1wAckA5OTgLCvDWVp6Sl1e5t3eHgVDQ/T39zMxMUFWVhYAmqY9E4AXuAtAXh4MDsLAAIyOQnk5KEXB2BitS0t8sdkAcLvdb4QQ1S6X66cAYgBIT4fZWdjbg/p6CA+Hujro6wOgc2OjVoOX/+9LAE50fZGiomskJcHm5oXb3Q1WKxwevr1qGEBo4OXkRKja2vvAUyAXuAms09w8DAxqp0dzpf4Cgj71r0vtOwcAAAAASUVORK5CYII=

		Y.Перевод (Ru –> En)
		translate.yandex.ru/?lang=ru-en&text=

		DeepL.Перевод (Auto –> Ru)
		www.deepl.com/translator#en/ru/
		iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACNwAAAjcB9wZEwgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGZSURBVDiNjZKxaxRBFMZ/b2ZHbWITUxkRC4PnBUW0k1gkoFlMYmIR8R+w0UZBFAvtLAMS0ipC0guCd0GOa23EJGTPkBRCSCNHKiEgMzvPwmjCuiv3lft97zff7BuhQraWTouJLwE0mmf518a7spwUPxwZvlmLms8B4wWrLZhHPvuwUg44N9afGPcc4T5gK4pFgSUv/jHrre8HgKHJE4nzHWBgn/sZdBuYqQB1Q+5rbLR2DUBy1J89GIbEmNmQNW8DqxWAgcS5IQBT5vqYP3H1Gw9AHyosAKECVA4QuKfIPMhHVKygV4OVU8ByT4BDsiI6rWpusdbYUdgpBpLSMeGTRLYx2o5q9kT0ja2P3xU401ODQJz1neYdVRkT9C1gyob/Ngg/3VbifJf9TVg1L2Q43UC1eo3eb8KfB7O7uRf7T782Yo8hXBG4DFwvaRgFFoP4GTqt7u/bFuTOp5dU9BUw8u/BOhqy5fZ//4HvNL6ErHlNkSmFb4e9YM1WMV+5xjxrvM+P99VBngI/qnK96UI66OrpEhcnThatXx/tiqJJdDA6AAAAAElFTkSuQmCC

		DeepL.Перевод (Ru –> En)
		www.deepl.com/translator#ru/en/
	`,
	localized: false,
	onCreated(btn) {
		var urls = [];
		var arr = this.data.split("\n").filter(s => /\S/.test(s)).map(s => s.trim());

		var doc = btn.ownerDocument, count = 0;
		var popup = doc.createXULElement("menupopup");
		popup.setAttribute("oncommand", "transTab(event.target.value);");

		for(var ind = 0, num = arr.length - 1; ind < num; ind++) {
			var menuitem = doc.createXULElement("menuitem");
			menuitem.setAttribute("value", count++);
			menuitem.setAttribute("label", "Выделенный текст в " + arr[ind]);

			urls.push(arr[++ind]);

			menuitem.className = "menuitem-iconic";
			if (count % 2) var img = "data:image/png;base64," + arr[++ind];
			menuitem.setAttribute("image", img);
			popup.append(menuitem);
			ind < num && popup.append(doc.createXULElement("menuseparator"));
		}
		delete this.data;
		var xul = popup.outerHTML;

		var write, read = () => {
			var cb = Services.clipboard, gc = cb.kGlobalClipboard, fl = "text/unicode";
			var ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
			write = str => ch.copyStringToClipboard(str, gc);

			var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
			trans.init(null);

			return (read = () => {
				trans.addDataFlavor(fl);
				cb.getData(trans, gc);
				var res = {};
				trans.getTransferData(fl, res);
				res = res.value?.QueryInterface(Ci.nsISupportsString).data;
				trans.removeDataFlavor(fl);
				return res;
			})();
		}
		var tt = async function(ind) {
			var clip = read();
			clip && write("");

			var win = this.ownerGlobal;
			win.docShell.doCommand("cmd_copy");
			await new Promise(resolve => setTimeout(resolve, 100));

			var sel = read();
			clip && write(clip);
			if (sel) {
				var gb = win.gBrowser;
				gb.selectedTab = gb.addTrustedTab(`https://${urls[ind]}${encodeURIComponent(sel)}`);
			}
		};
		(this.onCreated = (btn, node = btn.ownerGlobal.MozXULElement.parseXULToFragment(xul)) => {
			btn.setAttribute("type", "menu");
			btn.setAttribute("image", this.image);
			btn.prepend(node);
			btn.firstChild.transTab = tt;
		})(btn, popup);
	}
}))();

Отредактировано Dumby (19-12-2021 15:24:41)

Отсутствует

 

№1606619-12-2021 16:12:00

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

Re: Custom Buttons

Dumby
Как всегда супер! Большое спасибо.


«The Truth Is Out There»

Отсутствует

 

№1606719-12-2021 20:45:37

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

Re: Custom Buttons

Dumby
А ещё одну кнопочку не переделаете для UCF?

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

Выделить код

Код:

/*Initialization Code*/

// Кнопка сохраняет страницу с картинками или её часть, если она выделена, в html одним файлом ..........
// Dumby: https://forum.mozilla-russia.org/viewtopic.php?pid=782032#p782032 .....

(func => this._handleClick = () => {
	var saveToFile = (fileContent, fileName) => {
		var uc = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
		uc.charset = "utf-8";
		fileContent = uc.ConvertFromUnicode(fileContent);

		var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
		fp.init(window, "", fp.modeSave);
		fp.defaultString = fileName;
		fp.appendFilters(fp.filterHTML);
		fp.appendFilters(fp.filterAll);
		fp.open(rv => {
			if (rv != fp.returnOK && rv != fp.returnReplace) return;

			var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
			stream.init(fp.file, 0x02|0x20|0x08, 0o666, 0);
			stream.write(fileContent, fileContent.length);
			stream.close();
		});
	}
	var msgName = _id + ":SaveSnapshotToHTML";
	var msgListener = msg => saveToFile(...msg.data);
	messageManager.addMessageListener(msgName, msgListener);
	addDestructor(() => messageManager.removeMessageListener(msgName, msgListener));

	var url = "data:," + encodeURIComponent(
		`(${func})(ChromeUtils.import("resource://gre/modules/Services.jsm").Services);`.replace("%MSG_NAME%", msgName)
	);
	(this._handleClick = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))();

})(({io, focus}) => {
	var resolveURL = function (url, base) {
		try {
			return io.newURI(url, null, io.newURI(base)).spec;
		} catch {}
	};

	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 encodeImg = function (src, obj) {
		var canvas, img, ret = src;
		if (/^https?:\/\//.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((/\.jpe?g/i.test(src) ? '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 = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
			while (chr = str.charAt(i++)) {
				ret += meta[chr] || chr;
			};
			return '\x22' + ret + '\x22';
		},
		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 (obj.hasOwnProperty(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) ? String(obj) : 'null';
			case 'Object': return objToSrc(obj);
			case 'String': return strToSrc(obj);
			default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
		}
	};

	var mainWin = {};
	focus.getFocusedElementForWindow(content, true, mainWin);
	mainWin = mainWin.value;

	var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
	var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/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, prev, url, next) {
			if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
			return prev + encodeImg(url) + next;
		});
		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) != '#') 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 (unsafeWin) {
		if ('$' in unsafeWin) 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 unsafeWin) {
			if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
			try {
				str = toSrc(unsafeWin[name]);
				if (!/\{\s*\[native code\]\s*\}/.test(str)) {
					script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
				}
			} catch (e) {};
		};
		f.parentNode.removeChild(f);
		if (script.childNodes.length) this.nextSibling.appendChild(script);
	};
	head.copyScript(win.wrappedJSObject || win);

	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))) {
						var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
							if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
							if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
							return prev + url + next;
						});
						style.appendChild(doc.createTextNode(css + '\n'));
					}
				} 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('\n'));

	var doctype = '', dt = doc.doctype;
	if (dt && dt.name) {
		doctype += '<!DOCTYPE ' + dt.name;
		if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
		if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
		doctype += '>\n';
	};

	var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
	fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '').replace(/[\.]+/ig, ' ').replace(/[\,]+/ig, ' ').replace(/\s+/g, '_').slice(0, 100).replace(/^\s+|\s+$/g, '');
	fileName += (function () {
		var d = new Date(), z = function(n){return (n < 10 ? '0' : '') + n};
		return '_' + '[' + z(d.getFullYear()) + '_' + z(d.getMonth()+1) + '_' + z(d.getDate()) + '\u2014' + z(d.getHours()) + '_' + z(d.getMinutes()) + '_' + z(d.getSeconds()) + ']';
	})();

	if(!/\.html?$/.test(fileName))fileName += '.html';

	sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName]);

});

Для FF91.


«The Truth Is Out There»

Отсутствует

 

№1606820-12-2021 05:59:03

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

Re: Custom Buttons

unter_officer
А №14713 и пост ниже не работает?

Отредактировано xrun1 (20-12-2021 05:59:30)

Отсутствует

 

№1606920-12-2021 06:08:23

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

Re: Custom Buttons

xrun1
Это же целый комбайн, из которого мне надо только: "Сохранить всю страницу или выбранное как HTML".
Не вижу смысла ставить лишнее.


«The Truth Is Out There»

Отсутствует

 

№1607020-12-2021 07:26:21

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

Re: Custom Buttons

unter_officer
Есть для меню гамбургера строка.

скрытый текст
rq8DrGE.png

https://forum.mozilla-russia.org/viewtopic.php?pid=790890#p790890

Отсутствует

 

№1607120-12-2021 13:06:50

Пострел
Участник
 
Группа: Members
Зарегистрирован: 08-04-2021
Сообщений: 51
UA: Firefox 95.0

Re: Custom Buttons

Выложу кнопку. В ней код попроще, может кому-то пригодится.
   

Сохранить страницу как...

Выделить код

Код:

custombutton://%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0D%0A%3Ccustombutton%20xmlns%3Acb%3D%22http%3A//xsms.nm.ru/custombuttons/%22%3E%0A%20%20%3Cname%3E%u0421%u043E%u0445%u0440%u0430%u043D%u0438%u0442%u044C%20%u0441%u0442%u0440%u0430%u043D%u0438%u0446%u0443%20%u043A%u0430%u043A...%3C/name%3E%0A%20%20%3Cimage%3E%3C%21%5BCDATA%5Bdata%3Aimage/svg+xml%3Bbase64%2CPCEtLSBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljCiAgIC0gTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpcwogICAtIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uIC0tPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIGZpbGw9ImNvbnRleHQtZmlsbCAjMGMwYzBkIj4KICA8cGF0aCBkPSJNNCAwaDhhMyAzIDAgMCAxIDMgM3YxMGEzIDMgMCAwIDEtMyAzSDRhMyAzIDAgMCAxLTMtM1YzYTMgMyAwIDAgMSAzLTN6bTAgMmExIDEgMCAwIDAtMSAxdjEwYTEgMSAwIDAgMCAxIDFoOGExIDEgMCAwIDAgMS0xVjNhMSAxIDAgMCAwLTEtMUg0ek0zIDdoMTB2MUgzVjd6TTkuNSA0aC0zYS41LjUgMCAwIDAgMCAxaDNhLjUuNSAwIDAgMCAwLTF6TTkuNSAxMGgtM2EuNS41IDAgMCAwIDAgMWgzYS41LjUgMCAwIDAgMC0xeiIvPgo8L3N2Zz4K%5D%5D%3E%3C/image%3E%0A%20%20%3Cmode%3E0%3C/mode%3E%0A%20%20%3Cinitcode%3E%3C%21%5BCDATA%5B/*Initialization%20Code*/%5D%5D%3E%3C/initcode%3E%0A%20%20%3Ccode%3E%3C%21%5BCDATA%5BsaveBrowser%28gBrowser.selectedBrowser%29%3B%5D%5D%3E%3C/code%3E%0A%20%20%3Caccelkey%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/accelkey%3E%0A%20%20%3Chelp%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/help%3E%0A%20%20%3Cattributes/%3E%0A%3C/custombutton%3E

Отсутствует

 

№1607221-12-2021 00:03:59

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Custom Buttons

unter_officer пишет

А ещё одну кнопочку не переделаете для UCF?

Переложил в JSM'ку, вроде завелось.
Как импортировать следует напомнить?

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

Выделить код

Код:

var name = "UCFSaveSnapshotToHTML", EXPORTED_SYMBOLS = [name + "Child"];

if (!ChromeUtils.domProcessChild.childID) {
	ChromeUtils.import("resource:///modules/CustomizableUI.jsm").CustomizableUI.createWidget({
		label: "796961",
		tooltiptext: "796961",

		id: "796961",
		localized: false,
		onCreated(btn) {
			btn._handleClick = click;
			btn.setAttribute("image", "chrome://devtools/skin/images/tool-application.svg");
		}
	});
	var click = async function() {
		var win = this.ownerGlobal;
		var bc = win.gBrowser.selectedBrowser.browsingContext;
		var fbc = win.Services.focus.focusedContentBrowsingContext;
		if (!fbc || fbc.top.id != bc.id) fbc = bc;

		var cwg = fbc.currentWindowGlobal;
		var fp = picker(win, "", Ci.nsIFilePicker.modeSave);
		var [fileContent, fileName] =
			await cwg.domProcess.getActor(name).sendQuery("", cwg.innerWindowId);

		fp.defaultString = fileName;
		fp.appendFilters(fp.filterHTML);
		fp.appendFilters(fp.filterAll);

		await new Promise(fp.open) != fp.returnCancel &&
			IOUtils.writeUTF8(fp.file.path, fileContent, {mode: "overwrite"});
	}
	var picker = (...args) => {
		ChromeUtils.registerProcessActor(name, {
			includeParent: true,
			child: {moduleURI: __URI__}
		});
		return (picker = Components.Constructor(
			"@mozilla.org/filepicker;1", "nsIFilePicker", "init"
		))(...args);
	}
}
class UCFSaveSnapshotToHTMLChild extends JSProcessActorChild {
	receiveMessage(msg) {
		return snap(WindowGlobalChild.getByInnerWindowId(msg.data).browsingContext.window);
	}
}

var snap = mainWin => {

	var resolveURL = function (url, base) {
		try {
			return (new URL(url, base)).href;
		} catch {}
	};

	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 encodeImg = function (src, obj) {
		var canvas, img, ret = src;
		if (/^https?:\/\//.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((/\.jpe?g/i.test(src) ? '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 = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
			while (chr = str.charAt(i++)) {
				ret += meta[chr] || chr;
			};
			return '\x22' + ret + '\x22';
		},
		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 (obj.hasOwnProperty(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) ? String(obj) : 'null';
			case 'Object': return objToSrc(obj);
			case 'String': return strToSrc(obj);
			default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
		}
	};

	var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
	var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/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, prev, url, next) {
			if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
			return prev + encodeImg(url) + next;
		});
		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) != '#') 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 (unsafeWin) {
		if ('$' in unsafeWin) 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 unsafeWin) {
			if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
			try {
				str = toSrc(unsafeWin[name]);
				if (!/\{\s*\[native code\]\s*\}/.test(str)) {
					script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
				}
			} catch (e) {};
		};
		f.parentNode.removeChild(f);
		if (script.childNodes.length) this.nextSibling.appendChild(script);
	};
	head.copyScript(win.wrappedJSObject || win);

	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))) {
						var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
							if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
							if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
							return prev + url + next;
						});
						style.appendChild(doc.createTextNode(css + '\n'));
					}
				} 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('\n'));

	var doctype = '', dt = doc.doctype;
	if (dt && dt.name) {
		doctype += '<!DOCTYPE ' + dt.name;
		if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
		if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
		doctype += '>\n';
	};

	var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
	fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '').replace(/[\.]+/ig, ' ').replace(/[\,]+/ig, ' ').replace(/\s+/g, '_').slice(0, 100).replace(/^\s+|\s+$/g, '');
	fileName += (function () {
		var d = new Date(), z = function(n){return (n < 10 ? '0' : '') + n};
		return '_' + '[' + z(d.getFullYear()) + '_' + z(d.getMonth()+1) + '_' + z(d.getDate()) + '\u2014' + z(d.getHours()) + '_' + z(d.getMinutes()) + '_' + z(d.getSeconds()) + ']';
	})();

	if(!/\.html?$/.test(fileName))fileName += '.html';

	return [doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName];
}

Отсутствует

 

№1607321-12-2021 00:18:51

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

Re: Custom Buttons

Dumby
Всё отлично. Большое спасибо.

Отредактировано unter_officer (21-12-2021 00:31:11)


«The Truth Is Out There»

Отсутствует

 

№1607421-12-2021 04:50:36

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

Re: Custom Buttons

Dumby
Помогите ещё вот с таким вопросом.


Я решил сам попробовать переделать простенькую СВ-кнопку под UCF. Для примера взял кнопку, которую когда-то делали вы:

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

Выделить код

Код:

// Перейти в начало/конец страницы - Центрирование страницы ..........
// https://forum.mozilla-russia.org/viewtopic.php?pid=781993#p781993 .....
(u => {
	var id, lfs = url => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false);
	var max = () => {
		var url = u([
			"var args = [scroller.scrollHeight, 0];",
			"scroller.scrollTop != 0 || args.reverse();",
			"content.scrollTo(...args);"
		].join("\n\t"));
		(max = () => lfs(url))();
	}
	var mid = () => {
		var url = u("content.scrollTo(0, (scroller.scrollHeight - scroller.clientHeight) / 2);");
		(mid = () => id = lfs(url))();
	}
	var obj = {
		mousedown: () => id = setTimeout(mid, 500),
		mouseup: () => id && max(id = clearTimeout(id))
	};
	this.onmousedown = this.onmouseup = e => e.button || obj[e.type]();
	this.tooltipText = "Л:   Вверх/Вниз по странице \nдЛ: Центрирование страницы";
})
(code => "data:," + encodeURIComponent(`(doc => {
	var root = doc.documentElement;
	var body = doc.body || root;
	var scroller = body.scrollHeight > root.scrollHeight ? body : root;
	${code}
})(content.document)`));


Но видимо у меня совсем не хватает знаний в этой области. Единственное, как мне удалось заставить эту кнопку работать, это подключить её из отдельного файла. Пример:
скрытый текст

Выделить код

Код:

try {
	CustomizableUI.createWidget({
		id: "0123456789",
		label: "0123456789",
		// tooltiptext: "0123456789",
		img: "data:image/png;.....",
		defaultArea: CustomizableUI.AREA_NAVBAR,
		localized: false,
		get initCode() {
			delete this.initCode;
			return this.initCode = Cu.readUTF8URI(Services.io.newURI(
				"chrome://user_chrome_files/content/custom_scripts/ucf_user_script/cb_Button.js"
			));
		},
		onCreated(btn) {
			var win = btn.ownerGlobal;
			new win.Function(this.initCode).call(btn);
			btn.image = this.img;
		}
	});
} catch(ex) {Cu.reportError(ex);}


Вопрос вот в чём. Возможно ли код этой СВ-кнопки не подключать отдельным файлом, а прописать прямо в UCF-кнопку?


«The Truth Is Out There»

Отсутствует

 

№1607521-12-2021 19:53:34

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Custom Buttons

unter_officer пишет

Я решил сам попробовать переделать простенькую СВ-кнопку под UCF. Для примера взял кнопку

Похвально, но, мне кажется, выбор кнопки не совсем удачный.
То есть не то чтобы какая-то особая сложность,
надо просто окно пробросить, но сама цепочка длинновата.


И ещё, что-то мне исходник не слишком понятен.
Вобщем, переделал. Надо смотреть не испортил ли чего.

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

Выделить код

Код:

(async lfs => CustomizableUI.createWidget({
	id: "0123456789",
	label: "0123456789",
	tooltiptext: "Л:   Вверх/Вниз по странице \nдЛ: Центрирование страницы",
	defaultArea: CustomizableUI.AREA_NAVBAR,
	localized: false,
	onCreated(btn) {
		var id, u = code => `data:,(se => se && content.scrollTo(0, ${code}))(content.document.scrollingElement);`;
		this.mousedown = w => {
			var url = u("(se.scrollHeight - se.clientHeight) / 2");
			var mid = w => id = lfs(url, w);
			(this.mousedown = w => id = w.setTimeout(mid, 500, w))(w);
		}
		this.mouseup = w => {
			var max = lfs.bind(null, u("se.scrollTop == 0 && se.scrollHeight"));
			(this.mouseup = w => id && max(w, id = w.clearTimeout(id)))(w);
		}
		var mouse = e => e.button || this[e.type](e.view);

		(this.onCreated = btn => {
			btn.onmousedown = btn.onmouseup = mouse;
			btn.setAttribute("image", "resource://usercontext-content/fence.svg");
		})(btn);
	}
}))((url, w) => w.gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false));

Единственное, как мне удалось заставить эту кнопку работать, это подключить её из отдельного файла.

Содержимое файла можно было разместить там же, внутри кода.
Напрямую как `строку`, но там много экранировать нужно,
или как тело функции и дальше func.toString().slice(N, -M);

Отсутствует

 

Board footer

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