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

Будьте в курсе последних изменений в мире Mozilla, следя за нашим микроблогом в Twitter.

№1545101-05-2021 22:11:39

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

Re: Custom Buttons

momo2000 спасибо большое!

voqabuhe
Тут

Отсутствует

 

№1545202-05-2021 03:09:21

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 88.0

Re: Custom Buttons

kazarin пишет

Тут

Сам то проверял ссылки? Поэтому и спросил, что эти после пожара накрылись. :)

Отсутствует

 

№1545302-05-2021 03:13:40

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

Re: Custom Buttons

kazarin - надо проверять ссылки, которые даёшь! Там файлы недоступны уже!


custom_buttons-0.0.7.0.0.17-fx-paxmod.xpi bootstrap
dom_inspector-7.0.9-fx-paxmod.xpi bootstrap

Отсутствует

 

№1545402-05-2021 22:25:35

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

Re: Custom Buttons

voqabuhe, Dobrov, не проверил, извините!:/

Отредактировано kazarin (02-05-2021 22:26:47)

Отсутствует

 

№1545503-05-2021 10:46:02

Cytrus
Участник
 
Группа: Members
Зарегистрирован: 30-04-2021
Сообщений: 10
UA: Firefox 78.0

Re: Custom Buttons

Привет.  Подскажите, почему я не могу получить выделенный текст?
И как можно получить выделенный текст самым простым способом?


Выделить код

Код:

var w = document.commandDispatcher.focusedWindow, d = w.document, q = w.getSelection().toString(); 
alert(q);

Отсутствует

 

№1545603-05-2021 18:12:01

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

Re: Custom Buttons

Cytrus пишет

почему я не могу получить выделенный текст?

Что значит «не могу»? Вместо alert'а что? Вообще ничего не происходит?
Или сразу краш? Или фига (кукиш) во весь экран? Или что-то ещё альтернативное?

Отсутствует

 

№1545703-05-2021 19:07:51

Cytrus
Участник
 
Группа: Members
Зарегистрирован: 30-04-2021
Сообщений: 10
UA: Firefox 78.0

Re: Custom Buttons

Путой алерт получается. Текст на странице выделен, клик по кнопке, а алерт пустой.

Отсутствует

 

№1545803-05-2021 22:02:42

Deriax
Участник
 
Группа: Members
Зарегистрирован: 27-03-2021
Сообщений: 37
UA: Chrome 90.0

Re: Custom Buttons

Необходимо получить куки, определённой вкладки, я новичок, помогите! Тут нашёл,

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab

Что нужно подключить, чтобы работало? Нужно получить все куки вкладки, включая HttpOnly.

Отредактировано Deriax (03-05-2021 22:08:23)

Отсутствует

 

№1545903-05-2021 23:44:59

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

Re: Custom Buttons

Cytrus пишет

Путой алерт получается.

Пустой алерт означает, что в окне «document.commandDispatcher.focusedWindow»
ничего не выделено (выделенное в текстовых полях не считается, и никогда не считалось).

Текст на странице выделен, клик по кнопке

Кнопка находится в одном, родительском, процессе,
а текст на странице, как и сама страница, скорее всего, в другом, контентском, процессе.
Можешь проверить на странице, которая заведомо откроется в основном процессе,
например about:support (там выделенное будет алертиться так, как, наверно, и ожидалось).


Deriax пишет

Тут нашёл,
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab

Где, интересно, «тут» могли куки померещиться? :/

Отсутствует

 

№1546003-05-2021 23:58:36

Deriax
Участник
 
Группа: Members
Зарегистрирован: 27-03-2021
Сообщений: 37
UA: Chrome 90.0

Re: Custom Buttons

Dumby пишет
Cytrus пишет

Путой алерт получается.

Пустой алерт означает, что в окне «document.commandDispatcher.focusedWindow»
ничего не выделено (выделенное в текстовых полях не считается, и никогда не считалось).

Текст на странице выделен, клик по кнопке

Кнопка находится в одном, родительском, процессе,
а текст на странице, как и сама страница, скорее всего, в другом, контентском, процессе.
Можешь проверить на странице, которая заведомо откроется в основном процессе,
например about:support (там выделенное будет алертиться так, как, наверно, и ожидалось).


Deriax пишет

Тут нашёл,
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab

Где, интересно, «тут» могли куки померещиться? :/

14f477a2ce81.png

Отсутствует

 

№1546104-05-2021 02:11:12

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

Re: Custom Buttons

Deriax пишет

14f477a2ce81.png

Фу, в переводе это выглядит ещё более непонятно, чем в оригинале.
На самом деле, cookieStoreId — это всего лишь id'шник контейнера,
то есть, всего лишь уточняющий параметр для cookies.get() (и компании), не более того.


Типа — кука, именуемая так-то, с урлом каким-то эдаким, ограниченная контейнером (cookieStoreId) таким-то.
Еще раз: никакого «Хранилища файлов cookie вкладки» (так, как это звучит!) не существует.

Отредактировано Dumby (04-05-2021 02:11:30)

Отсутствует

 

№1546204-05-2021 12:42:17

Cytrus
Участник
 
Группа: Members
Зарегистрирован: 30-04-2021
Сообщений: 10
UA: Firefox 78.0

Re: Custom Buttons

Подскажите, а как можно получить URL по клику на ссылке?



Выделить код

Код:

document.addEventListener('click',e => {
if (e.button!=0){return;}
  if (e.altKey){
        e.preventDefault();
//         console.log("IMG URL: "+e.target.src);
        console.log("IMG URL: "+e.target.href);
//         return;
//           }

//     let zzz = e.target.closest('href');
//         console.log("URL:    " + zzz.href);
//        return;
//
  }
});

Отсутствует

 

№1546306-05-2021 14:50:20

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

Re: Custom Buttons

Dumby
В кнопке ucf Quick Toggle Settings на 88 не работает функция перезапуска, которая назначается в пунктах (restart: true,).
Поправьте пожалуйста.
Вот моя кнопка, не помню публиковалась ли она целиком, со всеми вашими правками на тот момент. Никаких недавно обсуждаемых новшеств я в нее не добавлял.

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

Выделить код

Код:

// Quick Toggle от Damby - Быстрое переключение параметров about:config
// https://forum.mozilla-russia.org/viewtopic.php?pid=784165#p784165
// Ctrl+ЛКМ или ПКМ - сброс параметра по-умолчанию FF или удаление
(async (name, id, func) => {
	if (name == "Object") return CustomizableUI.createWidget(func());
	var win = name == "Window", g = Components.utils.import("resource://gre/modules/Services.jsm", {});
	if (g[id]) {if (win) return;} else g[id] = func();
	if (win) return CustomizableUI.createWidget(g[id]);
	addDestructor(r => r[5] == "e" && delete g[id]);
	g[id].onCreated(this);
})(this.constructor.name, "QuickToggleAboutConfigSettings", () => {

	var {prefs} = Services, db = prefs.getDefaultBranch("");
	var pv = parseInt(Services.appinfo.platformVersion);
	var xul_ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

//=============================================================================

	// refresh:
	//	false - перезагрука текущей вкладки
	//	true  - перезагрука текущей вкладки минуя кэш
	//
	// restart:
	//	false - перезапуск браузера
	//	true  - перезапуск браузера с подтверждением
	//
	// userChoice:
	//  ваше значение - иконка назначается в 372 строке
	//
	// userAlt:
	//  альтернативное значение - иконка назначается в 374 строке

	var primary = [{

			pref: ["network.proxy.type", "Настройки прокси"],
			userChoice: 5, userAlt: 2, refresh: true,
			values: [
				[0, "Не проксировать", "0"],
				[5, "Системные (IE)", "5"],
				[2, "Авто (pacfile)", "2"],
				[1, "Прописанные", "1"],
				[4, "Автоопределение", "4"]
	]},{
			pref: ["network.trr.uri", "DoH DNS провайдер"],
			userChoice: "https://firefox.dns.nextdns.io/",
			userAlt: "https://doh.dns.sb/dns-query",
			restart: true,
			values: [
				["https://firefox.dns.nextdns.io/", "NextDNS"],
				["https://mozilla.cloudflare-dns.com/dns-query", "Cloudflare"],
				["https://dns.comss.one/dns-query", "Comss DNS"],
				["https://dns.google/dns-query", "Google DNS"]
	]},{
			pref: ["network.trr.mode", "DoH DNS режим (trr)"],
			userChoice: 3, userAlt: 2, refresh: true,
			values: [
				[1, "Быстрейший"],
				[2, "DoH+St.as.reserve"],
				[3, "Строгий"]
	]},
			null,
	{
			pref: ["permissions.default.image", "Загружать web-графику"],
			userChoice: 1, userAlt: 2, refresh: true,
			values: [
				[1, "Да"],
				[3, "С сайта"],
				[2, "Нет"]
	]}
];

//=============================================================================

	var secondary = [{

			pref: ["ui.prefersReducedMotion", "Анимация chrome"],
			userChoice: 1, userAlt: 0, restart: true,
			values: [[1, "Отключена"], [0, "Включена"]]
	},{
			pref: ["gfx.webrender.enabled", "Web render"],
			userChoice: true, userAlt: false, restart: true,
			values: [[true, "Включен"], [false, "Отключен"]]
	},{
			pref: ["gfx.webrender.force-disabled", "Web render (force-disabled)"],
			userChoice: false, userAlt: true, restart: true,
			values: [[true, "Да"], [false, "Нет"]]
	}
	];

	return {
		id: "QuickToggleAboutConfigSettings",
		label: "Quick Toggle Settings",
		tooltiptext: "Quick Toggle Settings\n	ЛКМ	ПКМ",
		localized: false,
		image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAKdSURBVDhPjZNLTxNRFMenM9OWTulTEx4KkSg+0mCCujExNTyiLKiQAUofIcR+AOPOlStdGDd+AzdGDQvF+IhBBY0ro8aNUkAXxFhKERRaYOhjOuP/j0NidONNfj2Puef0nHvPFUzT/C9EQQiC5p/JoXeQJ8Ax2jZ+/HtJNpsDwqiapm7ZnmoqWchq2qNGRYl8yRdetPq83dLN20zyezEIiNwMsxZ4obuAm/aitvVQkeX9CBoIOp1N6bX8K/g92+W1u1x+ZAqwJDOVNAsj0TfQW+EPQbbk4uoD+qGfAz2gn/a02vtSsEuSj0Za7b2BD8f10eGKtfnMcmLgg6WfnlUjk7DnGLySGJydUXunoPeIhmG4C+XK2yP+2ovo870kybKuV8rQJ3bX1LRPZXO3UGrwkN/bmdsq5uAfXy4Ws4f9vg74FSERCJxCppNmKmYS6IldkhSlXh0d1mHH6LMYYiWQbIPthG0sk/+EbAIOKA5RBuu08W/PKLnwLQaxBTYAr457SuJOMLbzZye4ZLG9MptaGqIINIsVkAerwgGHI45SBnlYVgvdLI221YIKoqAPdH6N9j+B5O20gr02/HQ87+k639lYP4KM26ta1Us4TCf1hU1tunls/Craufs5X5g86PN2za9vTLR4as+iraOIF1YYjEH5CMcQgnVJsjk5ME8z2bE9biXERJ9W114HnY4m+Pu8dvu+ubXCFNwBVlCviGKdZhh+OPyZmHqlQXG1YWOyTpYrS7peTquRC7xG+HjIPCM7r5PTyAQcXR+zAb4BjjHLNwDfAg/WPjMQucwK6u7cu/Q9MXiNsxC6//i6iAfDjDzRBbBkyXnwDWQs3zJ7/1EsZ/4ZpD+eqwPIwAX4dInHshtAGwhz/iE5SLgdIfwLnaFD0PXeqXgAAAAASUVORK5CYII=",
		onCreated(btn) {
			btn.setAttribute("image", this.image);
			var doc = btn.ownerDocument;

			btn.btn = true;
			btn.domParent = null;
			btn.popups = new btn.ownerGlobal.Array();
			this.createPopup(doc, btn, "primary", primary);
			this.createPopup(doc, btn, "secondary", secondary);
			this.createCloseMenusOption(doc, btn);

			btn.linkedObject = this;
			for(var type of ["command", "contextmenu"])
				btn.setAttribute("on" + type, `linkedObject.${type}(event)`);
		},
		createPopup(doc, btn, name, data) {
			var popup = doc.createElementNS(xul_ns, "menupopup");
			var prop = name + "Popup";
			btn.popups.push(btn[prop] = popup);
			popup.id = this.id + "-" + prop;
			for (var type of ["popupshowing", "click"])
				popup.setAttribute("on" + type, `parentNode.linkedObject.${type}(event)`);
			for(var obj of data) popup.append(this.createElement(doc, obj));
			btn.append(popup);
		},
		map: {b: "Bool", n: "Int", s: "String"},
		createElement(doc, obj) {
			if (!obj) return doc.createElementNS(xul_ns, "menuseparator");
			var pref = doc.ownerGlobal.Object.create(null), node, img, bool;
			for(var [key, val] of Object.entries(obj)) {
				if (key == "pref") {
					var [apref, lab, akey, ttt] = val;
					pref.pref = apref; pref.lab = lab || apref;
					if (ttt) pref.ttt = ttt;
				}
				else if (key == "image") img = val, pref.img = true;
				else if (key != "values") pref[key] = val;
				else pref.hasVals = true;
			}
			var type = prefs.getPrefType(pref.pref);
			var str = this.map[type == prefs.PREF_INVALID
				? obj.values ? (typeof obj.values[0][0])[0] : "b"
				: type == prefs.PREF_BOOL ? "b" : type == prefs.PREF_INT ? "n" : "s"
			];
			pref.get = prefs[`get${str}Pref`];
			pref.set = prefs[`set${str}Pref`];

			node = doc.createElementNS(xul_ns, "menu");
			node.className = "menu-iconic";
			node.setAttribute("closemenu", "none");
			img && node.setAttribute("image", img);
			akey && node.setAttribute("accesskey", akey);
			(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
			this.createRadios(doc,
				str.startsWith("B") && !pref.hasVals ? [[true, "true"], [false, "false"]] : obj.values,
				node.appendChild(doc.createElementNS(xul_ns, "menupopup"))
			);
			if ("userChoice" in obj) pref.noAlt = !("userAlt" in obj);
			return node;
		},
		createCloseMenusOption(doc, btn) {
			var pn = this.closePref = "QuickToggleAboutConfigSettings.closeMenus";
			var data = [null, {
				pref: [pn, "Автозакрытие этого меню"], values: [[true, "Да"], [false, "Нет"]]
			}];
			var setCloseMenus = e => {
				e.stopPropagation();
				var trg = e.target, {pref, val} = trg, updPopup = true, clear;
				switch(e.type) {
					case "command": pref = (trg = trg.closest("menu")).pref; updPopup = false; break;
					case "click": if (e.button) return; break;
					case "contextmenu": e.preventDefault(); clear = pref;
				}
				if (!pref) return;
				if (clear) prefs.clearUserPref(pn);
				else if (!updPopup && val === pref.val) return;
				else pref.set(pn, val !== undefined ? val : !pref.val);
				this.upd(trg);
				updPopup && this.popupshowing(null, trg.querySelector("menupopup"));
			}
			(this.createCloseMenusOption = (doc, btn) => {
				for(var obj of data)
					btn.secondaryPopup.append(this.createElement(doc, obj));
				var m = btn.secondaryPopup.lastChild;
				m.style.cssText = "fill: lightblue !important; list-style-image: url(chrome://browser/skin/menu.svg) !important;";
				m.setAttribute("oncommand", "setCloseMenus(event)");
				m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus;
			})(doc, btn);
		},
		UserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHqSURBVDhPpVJBTxNBGH1LLakxVEJQQIkhlZCAJDYR/BGScNCDwZMcuEji2ZP+BD14MCGciDEaEw8e1At3QGLlwAUOFtm6tut2uwtb2t3p8GbZ0iXlVF/y5ttkv+/Nmzej5XI5/A+6otoxTh1ks9mwhniJHvRiBAHXLjRIEy7yeIqjqAPNuXYHS5jGVby7PTT27eHo7Or9zL3Va/19Xyj5FsuYjLpOcdbBG9xFGh+fZRaGJ5O3tB7tMrcXcGQZP+pb8tXuyjpdPcA89HYHynYazxdvzg5nkgOapFsPNleXP+uY6L6hzYxMT+EC5vCVa4SWAM880Ju4cyVxUXNkERUeuyJLIR1+O6wTqcEEUngEA5eiqZgAAxtMpfur0sIBLA7+hS2NkK5UGVpsqgEJjLMkT4biAkzbE27D5u7/ZAFWSB1l0iRtUokyEj+aCBEXMHcOA70Y/IElfsMUeyiJPIpBHiZZEvv4Vcsrge9Mi1ZO0BJQ98yw9w4tWT4yYNV1ki78AuyggHLNwLZjC1Txnpl60VRMQD2SBl5sGsHaT88XJd+DEzioCAd6rYpN1xf7Jj5T4BMe00eE9pf4GteZ8Ry6mbYKDDyzxAblP4TDT1BUbc2585+yumd1Vc201ZmV7djObQKdopVBRwCOAVyl9qcQtNEaAAAAAElFTkSuQmCC",
		notUserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHqSURBVDhPpVJNSxtRFD1PJ9GMMVpaKyWhRGwRFy7Utv+gVFyUgoWif8Ct+APMsvQX+BuUWhdBcOvSDwi1XVhK0WgmTr4mmphoJvPRe5NnxhLdpAcO9828d869794nXNfF/6BLxo7RqiAcDjciYx3oDwFRBxikT4ey5CtAcg64aZ4ANE1rxDaDLeB176Aae/zx/ZR/NDqEuu1UD39oxsZ2wnIRmwV+8rl7DeLAGzXg+/pidSWivBwVCPQDvH91AfPot/tn6fOedW3NzTT0TYNWD7hsVfWtjH1ZjCjPggImFV25AKpE+xr+6CMxsvzpVXePmE8AipR5Bnzn4bcT0yJoCZSyQDkPXOrEDDHXYG8k0B18/nSBdvukzDPghqlB/xOUi4BBgiIJDUleF0lmVaEo7ngd8EnZP2N0uiolBwXKmksDegrISubovvyPWauR3kPLgBb5q+O8hnMyOD8jJoknTaZPKZLRSQp2+eaA6q9JmWcwTHPWv2cT0E0XGcqos4lkhgz4X7Jql3O1NZNaK2WewSQ9EtqIHcWPd5FybWQNoECNNApkdgmcwv61k47TbDbf0VykrP0hfaPlADAfCmFBERiHQN2sY79UwTqLP1BX+NyDL5HBc+ZR3Xab78xl383cZtAp7o6xAwB/AT+Y7GFJS/NjAAAAAElFTkSuQmCC",
		UserAltImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAH7SURBVDhPpVJLa1NBFP5mJolNcrWhtiq9Betjk0VFfNS1O7ciXbQguBDXxR9g3Lnown8g3SqCi24K/gCxVbqogiBaxdyY5nFrkt5H5j7GmZvxphDdxA8+Dgzn+86Zcw4RQuB/QHUcG2kHpmkmUWHtEo6DY55mUCIhYkHQOlXA97vv4esUWJaVxBGDp2Vcz54klakbN69kZ8wZRHHsVT9b7e2tHdFH5eEuPqi8vxqsLWDxmIGX5+8/mMufPkdA8zIBiMMuvNo3sbf+bCt2cWd1V+kHBukMVNuFE3h08d7SXHF6glC4oHFXGnTBmA9j1iBnb9+6xvJYfryIjJYdGaL889TlC1cLkyFhQQek3wThjYSUt8GCX9Iky/JniitGF0WtGhpQgdLEJJvO8AMpUgIbtK/JbflmI0cc2Y0oy/JZLRsaEIKYcCemXgvUlVXdOpj/c0Bnf0BXdhXxQEsSpAZqVU7NtkRPJh5aoAmrCYnzA9SpIbDr4G74Lsihr2VDA7Xn5kdvx2mGgnr7soNaSubXQb0GelUv8lt4Pj8rJ6yRGqgjERyVT68P3rarJIo6HojrJOS2h8Yejb6+OdyIe3i1tIlIy0YP6ckCTCOH5WIJKxmGsnwKeB/bbgcvlHj1Cxoq75+XqKD2rFb1Z9rqz6rto5VHDMZFOoPxAPwGQ077rbKVfhEAAAAASUVORK5CYII=",
		upd(node) {
			var {pref} = node, def = false, user = false, val;
			if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
				var pn = pref.pref;
				try {val = pref.defVal = db[pref.get.name](pn); def = true}
				catch(ex) {def = false;}
				var user = prefs.prefHasUserValue(pn);
				if (user) try {val = pref.get(pn, undefined);} catch(ex) {}
			}
			if (val == pref.val && def == pref.def && user == pref.user) return;
			pref.val = val; pref.def = def; pref.user = user;
			var exists = def || user;

			var ttt = exists ? val : "Этот преф не существует";
			if (ttt === "") ttt = "[ empty_string ]";
			ttt += "\n" + pref.pref;
			if (pref.ttt) ttt += "\n" + pref.ttt;
			node.tooltipText = ttt;

			var img, alt = "userAlt" in pref && val == pref.userAlt;
			if (alt) img = this.UserAltImg;
			if ("userChoice" in pref)
				if (val == pref.userChoice)
					//node.style.removeProperty("color"),
					img = this.UserChoiceImg;
				else {
					//node.style.setProperty("color", "maroon", "important");
					if (!alt) img = this.notUserChoiceImg;
				}
			if (!pref.img) img
				? node.setAttribute("image", img)
				: node.removeAttribute("image");
			user
				? node.style.setProperty("font-style", "italic", "important")
				: node.style.removeProperty("font-style");

			var {lab} = pref;
			if (exists && pref.hasVals) {
				if (val in pref.vals) var sfx = pref.vals[val] || val;
				else var sfx = user ? "Другое" : "По умолчанию";
				lab += ` — "${sfx}"`;
			}
			node.setAttribute("label", lab);
		},
		createRadios(doc, vals, popup) {
			for(var arr of vals) {
				if (!arr) {
					popup.append(doc.createElementNS(xul_ns, "menuseparator"));
					continue;
				}
				var [val, lab, key, ttt] = arr;
				var menuitem = doc.createElementNS(xul_ns, "menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("closemenu", "none");
				menuitem.style.setProperty("font-style", "italic", "important"),
				menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab);
				key && menuitem.setAttribute("accesskey", key);
				var tip = menuitem.val = val;
				if (ttt) tip += "\n" + ttt;
				menuitem.tooltipText = tip;
				popup.append(menuitem);
			}
		},
		openPopup(popup) {
			var btn = popup.parentNode;
			if (btn.domParent != btn.parentNode) {
				btn.domParent = btn.parentNode;
				var pos;
				if (btn.matches(".widget-overflow-list > :scope"))
					pos = "after_start";
				else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
					btn.closest("toolbar").getBoundingClientRect(), pos = width > height
						? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
						: `${win.innerWidth - right > left ? "end" : "start"}_before`;
				for(var p of btn.popups) p.setAttribute("position", pos);
			}
			popup.openPopup(btn);
		},
		maybeRestart(node, conf) {
			var msgRest = "Перезапустить браузер?", msgAbort = "Запрос на выход отменен.";
			if (pv >= 77) {
				var title = node.closest("toolbarbutton").label;
				var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({
					domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW
				});
				var confirm = win => pp(win).confirm(title, msgRest);
				var alert = win => pp(win).alert(title, msgAbort);
			} else {
				var confirm = win => win.confirm(msgRest);
				var alert = win => win.alert(msgAbort);
			}
			return (this.mayBeRestart = (node, conf) => {
				var win = node.ownerGlobal;
				if (conf && !confirm(win)) return;
				if (win.BrowserUtils.restartApplication() === false) alert(win);
				else return true;
			})(node, conf);
		},
		regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
		maybeRe(node, fe) {
			var {pref} = node;
			if ("restart" in pref) {
				if (this.maybeRestart(node, pref.restart)) return;
			}
			else this.popupshowing(fe, node.parentNode);
			if ("refresh" in pref) {
				var win = node.ownerGlobal;
				if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
					? win.BrowserReloadSkipCache() : win.BrowserReload();
			}
		},
		maybeClosePopup(e, trg) {
			!e.ctrlKey && prefs.getBoolPref(this.closePref, undefined)
				&& trg.parentNode.hidePopup();
		},
		command(e) {
			var trg = e.target;
			if (trg.btn) return this.openPopup(trg.primaryPopup);

			var menu = trg.closest("menu"), newVal = trg.val;
			this.maybeClosePopup(e, menu);
			if (newVal != menu.pref.val)
				menu.pref.set(menu.pref.pref, newVal),
				this.maybeRe(menu, true);
		},
		popupshowing(e, trg = e.target) {
			if (trg.state == "closed") return;
			if (trg.id) {
				for(var node of trg.children) {
					if (node.nodeName.endsWith("r")) continue;
					this.upd(node);
					!e && node.open && this.popupshowing(null, node.querySelector("menupopup"));
				}
				return;
			}
			var {pref} = trg.closest("menu"), findChecked = true;

			var findDef = "defVal" in pref;
			var checked = trg.querySelector("[checked]");
			if (checked) {
				if (checked.val == pref.val) {
					if (findDef) findChecked = false;
					else return;
				}
				else checked.removeAttribute("checked");
			}
			if (findDef) {
				var def = trg.querySelector("menuitem:not([style*=font-style]");
				if (def)
					if (def.val == pref.defVal) {
						if (findChecked) findDef = false;
						else return;
					}
					else def.style.setProperty("font-style", "italic", "important");
			}
			for(var node of trg.children) if ("val" in node) {
				if (findChecked && node.val == pref.val) {
					node.setAttribute("checked", true);
					if (findDef) findChecked = false;
					else break;
				}
				if (findDef && node.val == pref.defVal) {
					node.style.removeProperty("font-style");
					if (findChecked) findDef = false;
					else break;
				}
			}
		},
		contextmenu(e) {
			var trg = e.target;
			if (trg.btn) {
				if (e.ctrlKey || e.shiftKey) return;
				if (e.detail == 2) return trg.secondaryPopup.hidePopup();
				this.openPopup(trg.secondaryPopup);
			}
			else if ("pref" in trg) {
				this.maybeClosePopup(e, trg);
				if (trg.pref.user)
					prefs.clearUserPref(trg.pref.pref),
					this.maybeRe(trg);
			}
			e.preventDefault();
		},
		click(e) {
			if (e.button) return;
			var trg = e.target, {pref} = trg;
			if (!pref) return;

			this.maybeClosePopup(e, trg);
			if (!("noAlt" in pref)) return;

			if (pref.val == pref.userChoice)
				if (pref.noAlt) return;
				else  pref.set(pref.pref, pref.userAlt);
			else
				pref.set(pref.pref, pref.userChoice);
			this.maybeRe(trg);
		}
	};
});

Отсутствует

 

№1546406-05-2021 17:05:47

dezhnev
Участник
 
Группа: Members
Зарегистрирован: 21-04-2016
Сообщений: 72
UA: Firefox 88.0

Re: Custom Buttons

_zt пишет

Dumby
В кнопке ucf Quick Toggle Settings на 88 не работает функция перезапуска, которая назначается в пунктах (restart: true,).
Поправьте пожалуйста.
Вот моя кнопка, не помню публиковалась ли она целиком, со всеми вашими правками на тот момент. Никаких недавно обсуждаемых новшеств я в нее не добавлял.

строка 282
//if (win.BrowserUtils.restartApplication() === false) alert(win);
if (Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit) === false) alert(win);

Отсутствует

 

№1546506-05-2021 18:22:10

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

Re: Custom Buttons

_zt пишет

не работает функция перезапуска

Да, BrowserUtils изрядно покромсали.
Ещё, смотрю, на 89, так сделанный alert/confirm
уходит в ихний новомодный внутриоконный вариант,
что не очень хорошо сочетается с незакрывающимся меню.
Вобщем, такая правка

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

Выделить код

Код:

/*
		maybeRestart(node, conf) {
			var msgRest = "Перезапустить браузер?", msgAbort = "Запрос на выход отменен.";
			if (pv >= 77) {
				var title = node.closest("toolbarbutton").label;
				var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({
					domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW
				});
				var confirm = win => pp(win).confirm(title, msgRest);
				var alert = win => pp(win).alert(title, msgAbort);
			} else {
				var confirm = win => win.confirm(msgRest);
				var alert = win => win.alert(msgAbort);
			}
			return (this.mayBeRestart = (node, conf) => {
				var win = node.ownerGlobal;
				if (conf && !confirm(win)) return;
				if (win.BrowserUtils.restartApplication() === false) alert(win);
				else return true;
			})(node, conf);
		},
*/
		maybeRestart(node, conf) {
			if (conf && !Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) return;

			var cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
			Services.obs.notifyObservers(cancel, "quit-application-requested", "restart");
			return cancel.data ? Services.prompt.alert(null, this.label, "Запрос на выход отменен.") : this.restart();
		},
		async restart() {
			var meth = Services.appinfo.inSafeMode ? "restartInSafeMode" : "quit";
			Services.startup[meth](Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
		},

Отсутствует

 

№1546607-05-2021 03:14:03

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

Re: Custom Buttons

Dumby просьба «косметически» доработать кнопку Quick Toggle about:config
я добавил скобки [] для строк меню, преф которых не существует (по-умолчанию).


Есть строки, требующие перезапуск браузера или обновление страницы. «Название меню» и «Значение» разделены тире —.
Нужно вместо тире — для строк, требующих refresh, подставлять например символ «»; а для restart символ «»
чтобы строка, запрашивающая например перезапуск (restart), выглядела так:  Провайдер DNS ↯ Cloudflare

Выделить код

Код:

// строка 400 кнопки https://forum.mozilla-russia.org/viewtopic.php?pid=789824#p789824
lab += ` — "${sfx}"`; // тире - обычный параметр, ⩫ требуется обновить страницу, ↯ нужен перезапуск браузера

Отсутствует

 

№1546707-05-2021 03:48:07

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

Re: Custom Buttons

Dumby
Перезапуск работает. Спасибо.
   
Действительно, индикация перезапуска не помешала бы.

Отредактировано _zt (07-05-2021 03:48:23)

Отсутствует

 

№1546807-05-2021 10:12:03

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

Re: Custom Buttons

Dobrov пишет

я добавил скобки [] для строк меню, преф которых не существует

Так и это, вроде как, не сложнее

Выделить код

Код:

lab += ` ${"restart" in pref ? "↯" : "refresh" in pref ? "⩫" : "—"} "${sfx}"`;

Отсутствует

 

№1546907-05-2021 11:44:14

Deriax
Участник
 
Группа: Members
Зарегистрирован: 27-03-2021
Сообщений: 37
UA: Chrome 90.0

Re: Custom Buttons

Dumby пишет
Deriax пишет

14f477a2ce81.png

Фу, в переводе это выглядит ещё более непонятно, чем в оригинале.
На самом деле, cookieStoreId — это всего лишь id'шник контейнера,
то есть, всего лишь уточняющий параметр для cookies.get() (и компании), не более того.


Типа — кука, именуемая так-то, с урлом каким-то эдаким, ограниченная контейнером (cookieStoreId) таким-то.
Еще раз: никакого «Хранилища файлов cookie вкладки» (так, как это звучит!) не существует.

Пожалуйста, подскажите как получить id контейнера, вообще как это выглядит? Нашёл такое расширение,
https://chrome.google.com/webstore/detail/cookie-tab-viewer/fdlghnedhhdgjjfgdpgpaaiddipafhgk
функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (

Отредактировано Deriax (07-05-2021 12:52:42)

Отсутствует

 

№1547007-05-2021 22:42:46

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

Re: Custom Buttons

Deriax пишет

вообще как это выглядит?

В реальности — это атрибут "usercontextid" <tab>'а и <browser>'а.
Выглядит как число.


А в WebExtensions представлении — ну, смотри сам.
Допустим, например:
Открываем какое-то количество вкладок, в разных контейнерах и не в контейнере.
Берём аддон с нужными permissions и переходим на любой его moz-extension://… адрес.
Открываем там веб-консоль (Ctrl+Shift+K), запускаем код типа такого и смотрим результат.

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

Выделить код

Код:

(await browser.tabs.query({}))
	.map(tab => tab.cookieStoreId.padEnd(30) + tab.title.slice(0, 100))
	.join("\n");

Deriax пишет

функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (

Может официальный пример немного прояснит.

Отсутствует

 

№1547108-05-2021 14:17:44

Deriax
Участник
 
Группа: Members
Зарегистрирован: 27-03-2021
Сообщений: 37
UA: Chrome 90.0

Re: Custom Buttons

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

Dumby пишет
Deriax пишет

вообще как это выглядит?

В реальности — это атрибут "usercontextid" <tab>'а и <browser>'а.
Выглядит как число.


А в WebExtensions представлении — ну, смотри сам.
Допустим, например:
Открываем какое-то количество вкладок, в разных контейнерах и не в контейнере.
Берём аддон с нужными permissions и переходим на любой его moz-extension://… адрес.
Открываем там веб-консоль (Ctrl+Shift+K), запускаем код типа такого и смотрим результат.
[spoiler]

Выделить код

Код:

(await browser.tabs.query({}))
	.map(tab => tab.cookieStoreId.padEnd(30) + tab.title.slice(0, 100))
	.join("\n");

Deriax пишет

функционал этого расширения даёт возможность это реализовать, значит это возможно, но как это сделать для firefox не знаю (

Может официальный пример немного прояснит.

[/spoiler]

На будущее может пригодиться.

Отредактировано Deriax (11-05-2021 19:11:23)

Отсутствует

 

№1547209-05-2021 08:57:59

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

Re: Custom Buttons

Dumby - спасибо, кнопку переключения настроек обновил.
Почините скрипт Save HTML, он не работает в Firefox 78 ESR, ошибка консоли: IOUtils is not defined

Выделить код

Код:

(async (id, func) => { // дополнительные клики на downloads-button для custom_script_win.js
	await window.delayedStartupPromise;
	var btn = document.getElementById("downloads-button");
	if (!btn) return;
	btn.setAttribute("context", "event.stopPropagation()"); // откл контекстное меню
	btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +`

ПКМ:	Сохранить единый .html
…Shift	Обзор папки «Загрузки»
Ролик:	Сохранить как файл .txt
		всё | выделенный текст
…Shift	Сайт: графика Вкл/Выкл
Alt⇧S	нажать SingleSave`; // если такой кнопки нет, то выполнить save()

	var addDestructor = nextDestructor => {
		var {destructor} = ucf[id];
		ucf[id].destructor = () => {
			try {destructor();} catch(ex) {Cu.reportError(ex);}
			nextDestructor();
		}
	}
	var saveSelectionToTxt = async () => { // сохранить страницу или выделенный текст как файл .txt
		var splice = saveURL.length == 10;
		var msgName = id + ":Save:GetSelection";

		var receiver = msg => {
			var title = document.title || gBrowser.selectedTab.label;
			var args = [
				"data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\n\n" + msg.data),
				title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt',
				null, false, true, 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("saveSelectionToTxt", res);
		}
		var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));';

		(saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))();
	} // end

	var save = async () => { // автор: Лекс, правка: Dumby, Dobrov
		var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML";
		var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8";

		var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0)
			var title = (document.title || gBrowser.selectedTab.label);
			if ( !type ) return title; // заголовок
			if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/  /g,' ').substr(0, type).trim(); // ограничить длину имени
			var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,'');
			return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns');
		};
		var msgListener = async msg => {
			var [fileContent, fileName] = msg.data;
			var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен
			var path = PathUtils.join(savedir, fileName);
			await IOUtils[write](path, fileContent);
			var d = await Downloads.createDownload({ source: "about:blank", target: FileUtils.File(path)});
			(await Downloads.getList(Downloads.ALL)).add(d);
			d.refresh(d.succeeded = true); // помигать кнопкой Загрузки
		}
		messageManager.addMessageListener(msgName, msgListener);
		addDestructor(() => messageManager.removeMessageListener(msgName, msgListener));

		var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services';
		var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName));
		(save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))();
	} // end save

	var listener = e => { // Clicks
		var trg = e.target, {prefs} = Services;
		if (e.button == 1) {
			if (e.shiftKey) { // СКМ + Shift
				if ( prefs.getIntPref("permissions.default.image", 1) == 1)
					prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)"
				else
					prefs.setIntPref("permissions.default.image", 1), trg.style.filter = "";
				BrowserReload();
			} else	// СКМ Click
				saveSelectionToTxt(); // сохранить .txt
		} else if (e.button == 2) {
			if (e.shiftKey)
				Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError) // Обзор папки «Загрузки»
			else	// ПКМ Click
				save(); // Single HTML
		}
	}
	var keydown_win = e => { // нажатие клавиш
		if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return;
		var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave
		singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID
	}
	btn.addEventListener("click", listener);
   window.addEventListener("keydown", keydown_win);
	var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win;
	ucf[id] = {destructor() {
		btn.removeEventListener("click", listener);
		window.removeEventListener("keydown", keydown_win);
	}};
	ucf.unloadlisteners.push(id);

})("downloads-button-click-listener", ({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(/\s+/g, ' ').slice(0, 100).trim();
	fileName += "_" + new Date().toLocaleString("ru").replace(", ","-").replace(/:/g, "։");
	if (!/\.html?$/.test(fileName)) fileName += '.html';

	sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]);

}); // END hookClicks

Отсутствует

 

№1547309-05-2021 15:49:56

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

Re: Custom Buttons

Deriax пишет

куки нужной активной вкладки, как это реализовать через xpcom или модуль Services?

Без понятия что значит «куки вкладки», вообще кук не держу.
Возможно что-то типа такого

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

Выделить код

Код:

var {host, originAttributes} = gBrowser.contentPrincipal;
var cookies = Services.cookies.getCookiesFromHost(host, originAttributes);

var resultAsJSON = JSON.stringify(cookies, null, "\t");
gBrowser.selectedTab = gBrowser.addTrustedTab(
	"data:text/plain;charset=utf-8," + encodeURIComponent(resultAsJSON)
);

Dobrov пишет

Почините скрипт Save HTML, он не работает в Firefox 78 ESR

Что значит «почините»?
Он и не должен работать «в Firefox 78».
Можно попробовать добавить перед строкой с ошибкой

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

Выделить код

Код:

…
		if (typeof IOUtils != "object") {
			var {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
			var PathUtils = {join: (...args) => OS.Path.join(...args)};
			var IOUtils = {writeUTF8: (path, txt) => OS.File.writeAtomic(path, new TextEncoder().encode(txt))};
		}

Отсутствует

 

№1547409-05-2021 16:05:34

Cytrus
Участник
 
Группа: Members
Зарегистрирован: 30-04-2021
Сообщений: 10
UA: Firefox 78.0

Re: Custom Buttons

Подскажите, есть ли способ, чтобы определить в приватном ли режиме окно или в обычном режиме?

Отсутствует

 

№1547509-05-2021 16:39:00

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

Re: Custom Buttons

Cytrus
PrivateBrowsingUtils.isWindowPrivate(window);

Отсутствует

 

Board footer

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