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

Список ответов на каверзные вопросы можно получить в FAQ-разделе форума.

№1617627-01-2022 15:53:06

Ki_rrrilll
Участник
 
Группа: Members
Зарегистрирован: 22-11-2013
Сообщений: 127
UA: Firefox 85.0

Re: Custom Buttons

Dumby пишет

Ki_rrrilll пишет

    Может подскажете еще одну вещь.

Не, в контентских делах я не помощник.
И «некоторые» сайты, видимо, настолько забористые,
что их адреса даже нельзя называть, а то, может,
у других заинтересованных ответить было бы больше шансов.

Нет, сайты не забористые, просто я не хотел обвинений в рекламе. Вот один из этих сайтов: https://www.yaplakal.com/


Там из всех элементов при наведении курсора только ссылки имеют псевдокласс :hover, остальные элементы нет.
Почему? Может кто ответит?


И хотел попросить у вас, Dumby, код чтобы при закрытии вкладки, открытой из СВ, возвращаться на последнюю активную вкладку. Сейчас если я закрываю вкладку  созданную из СВ, перехожу на крайнюю правую.

Отредактировано Ki_rrrilll (27-01-2022 16:53:56)

Отсутствует

 

№1617727-01-2022 17:50:23

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

Re: Custom Buttons

unter_officer пишет

я ничего из вашего ответа не понял

Думаю наоборот, это я без понятия что есть
«принудительное использование однооконного режима браузера».


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


Вот и поставил упомянутое расширение, чтоб посмотреть.
Нужен bootstapLoader. Есть у xiao, или, может, парафраз,
смысл которого только в простоте копипасты в config.js


ВВП пишет

Накрутил кнопку

Уж поверь наслово, я, обычно, не склонен
критиковать чужой код, если не попросят, но это ...


выкинь немедленно, чтоб такого говнокода
в браузере даже духу никогда не было.


Наверно и рад бы был помочь исправить, но, нужно
объяснение замысла, которое, разумеется, взять будет негде.


Ki_rrrilll пишет

Там из всех элементов при наведении курсора только ссылки имеют псевдокласс :hover, остальные элементы нет.

Ух ты! Я вижу это.
Дело, каким-то ..., в кривом <!DOCTYPE>


Например, воспроизводится по адресу
data:text/html;charset=utf-8,<center><h1>TEST</h1></center>


и не воспроизводится по адресу
data:text/html;charset=utf-8,<!DOCTYPE html><center><h1>TEST</h1></center>

при закрытии вкладки, открытой из СВ

Уволь.

Отсутствует

 

№1617827-01-2022 19:08:49

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

Re: Custom Buttons

Dumby пишет

Думаю наоборот, это я без понятия что есть
«принудительное использование однооконного режима браузера».

Я же выше два раза написал, что под этим имеется ввиду.


Хорошо. Сформулирую иначе.
Мне надо, чтобы при попытке открыть новое окно FF, вместо нового окна открывалась новая вкладка в текущем окне.
Такое можно реализовать в FF 91 ESR?


Если нет, то нет. Переживу.
А ставить расширения, от которых я всеми силами стараюсь избавится заменяя функции этих расширений кнопками СВ и UCF, я не хочу.


«The Truth Is Out There»

Отсутствует

 

№1617927-01-2022 22:03:53

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

Re: Custom Buttons

Dumby
Помните скрипт "сохранить сессию" А как бы туда втулить " Удалить все сессии" ? А то кнопу новую делать ,плюс батник...
Да и восстановить сессию тоже желательно в новой вкладке...

Отредактировано ВВП (27-01-2022 22:06:01)

Отсутствует

 

№1618028-01-2022 03:10:46

Ki_rrrilll
Участник
 
Группа: Members
Зарегистрирован: 22-11-2013
Сообщений: 127
UA: Firefox 85.0

Re: Custom Buttons

Dumby пишет

при закрытии вкладки, открытой из СВ

Уволь.

Очень жаль.

Отсутствует

 

№1618129-01-2022 07:18:43

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

Re: Custom Buttons

Есть старый код, подобный расширению locationbar - позволяет при клике на часть url перейти к нему. Например, есть некий url с адресом site.domen/forum/loremipsum, и при клике на слово "forum" в нём, браузер переходил на адрес site.domen/forum.
Как переделать этот код для работы с UCF (такое расширение не нашёл)

Выделить код

Код:

(function () {
        if (location != "chrome://browser/content/browser.xul") return;
        var URLBarInput = gURLBar.mInputField;
        var locationBar = URLBarInput.parentNode.appendChild(document.createElement("hbox"));
        locationBar.style.display = "none";
        URLBarInput.parentNode.addEventListener("click", function () {
            if (URLBarInput.style.display === "none") {
                URLBarInput.style.display = "";
                locationBar.style.display = "none";
                gURLBar.select();
            }
        }, false);
        URLBarInput.parentNode.addEventListener("mouseout", function () {
            if (document.activeElement !== gURLBar.inputField) {
                locationBar.style.display = "none";
                URLBarInput.style.display = "";
                gURLBar._urlTooltip && gURLBar._hideURLTooltip();
            }
        }, false);
        URLBarInput.addEventListener("mouseover", function (event) {
            if (event.ctrlKey || document.activeElement === gURLBar.inputField) {
                return;
            }
            locationBar.parentNode.removeChild(locationBar);
            locationBar = URLBarInput.parentNode.appendChild(document.createElement("hbox"));
            locationBar.style.overflow = "hidden";
            locationBar.style.width = URLBarInput.clientWidth + "px";
            gURLBar.value.split("?")[0].split("/").map(function (value, index, arr) {
                return index + 1 === arr.length ? (gURLBar.value.split("?")[1] ? (value + "?" + gURLBar.value.split("?")[1]) : value) : value;
            }).map(function (value, index, arr) {
                var sec = locationBar.appendChild(document.createElement("label"));
                //sec.style.margin = "5px";
                sec.style.margin = "5px 0 0 0";
                sec.value = value;
                if (index < arr.length - 1) sec.value = value.replace(/[^\/]$/, "$&/");
                index === 0 && (sec.style.marginLeft = "1px");
                if (index === 0 && /:\/$/.test(sec.value)) {
                    sec.value += "/";
                } else {
                    sec.onmouseover = function () {
                        this.style.textDecoration = "underline";
                        this.style.color = "blue";
                        this.style.fontWeight = "bold";
                        this.style.cursor = "pointer";
                        //this.setAttribute("style", "font-weight: bold;");
                    }
                    sec.onmouseout = function () {
                        this.style.textDecoration = "";
                    }
                    sec.onclick = function (event) {
                        if (event.button === 0) {
                                var vert=URLBarInput.value.split(this.value)[0] + this.value;
                                                    getBrowser (). loadURI(vert, {
                                                    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
                                                                  });
                            //loadURI(URLBarInput.value.split(this.value)[0] + this.value);
                            while (this.nextSibling) {
                                this.nextSibling.parentNode.removeChild(this.nextSibling);
                            }
                            event.stopPropagation();
                        }
                    }
                    URLBarInput.style.display = "none";
                    locationBar.style.display = "";
                }
            })
        }, false);
    })();

Отсутствует

 

№1618230-01-2022 09:32:26

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

Re: Custom Buttons

Dobrov пишет

(такое расширение не нашёл)

Scroll Up Folder https://addons.mozilla.org/ru/firefox/a … -up-folder

Отсутствует

 

№1618303-02-2022 09:19:05

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

Re: Custom Buttons

unter_officer

скрытый текст
Пытался размышлять над однооконным режимом, и понял,
что ничего хорошего у меня придумать не получится.


Есть вариант просто тупо закрывать окна, что уже нехорошо.
Вот так, например, перекрывает основной попс — окна,
создаваемые с участием parent (docShell).


Но без него — нет, для таких окон непонятно где взять адрес,
который пойдёт загружаться, а когда пойдёт загружаться,
то закрывать поздновато — браузерные коды уже на него рассчитывают.


Увы, для WebExtensions, браузер создаёт окна именно так.
Вписал некое вмешательство в создание, но закомментировал.
Можно раскомментировать, посмотреть что ещё может сломаться.


Вобщем, частично и грубо.

Выделить код

Код:

(br => ({
	async init() {
		lockPref("browser.link.open_newwindow", 3);
		lockPref("browser.link.open_newwindow.restriction", 0);
		lockPref("browser.link.open_newwindow.override.external", 3);
		lockPref("browser.link.open_newwindow.disabled_in_fullscreen", true);

		var self = this;
		var topic = "webNavigation-createdNavigationTarget-from-js";
		var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

		obs.addObserver(this, topic);
		obs.addObserver(function quit(s, t) {
			obs.removeObserver(quit, t);
			obs.removeObserver(self, topic);
		}, "quit-application-granted");

		delete this.init;
		this.imp = Cu.getGlobalForObject(Cu).ChromeUtils.import;
/*
		var url = "resource://gre/modules/ExtensionParent.jsm";
		var mgr = this.imp(url).ExtensionParent.apiManager;
		await new Promise(resolve => mgr.once("ready", resolve));

		var g = mgr.global;
		g.Object.defineProperty(g, "windows", {
			configurable: true, enumerable: true, set(val) {
				var proto = val.prototype;
				g.Object.assign(proto, g.eval(`({${proto.getAPI}})`.replace(
					/\n\n[^\n]+?Services.ww/,
					"\n\n          var res = redirectBWCArgs(args, features, windowManager);" +
					"\n          if (res) return res;$&"
				)));
				delete this.windows;
				this.windows = val;
			}
		});
		g.redirectBWCArgs = (arr, features, wm) => {
			var pr = features.at(-1);
			var win = this.getWin(null, pr.startsWith("p"));
			if (!win) {
				if (features.length > 3)
					features.join = () => "dialog=no,all," + pr;
				return;
			}
			var args = [];
			for(var ind = 0, len = arr.length; ind < len; ind++) {
				var item = arr.GetElementAt(ind);
				if (item) {
					if (ind == 5) item = item.QueryInterface(Ci.nsISupportsPRUint32).data;
					else if (ind > 5 && ind < 9) item = item.QueryInterface(Ci.nsIPrincipal);
					else if (ind == 9) item = false;
				}
				args.push(item);
			}
			this.onArgs(win, args);
			return g.Promise.resolve(wm.getWrapper(win).convert({populate: true}));
		}
*/
	},
	getWin(win, p) {
		var url = "resource:///modules/BrowserWindowTracker.jsm";
		var bwt = this.imp(url).BrowserWindowTracker;
		return (this.getWin = (win, p) => bwt.getTopWindow({
			private: win ? win.browsingContext.usePrivateBrowsing : p
		}))(win, p);
	},
	observe(subj) {
		var bag = subj.QueryInterface(Ci.nsIPropertyBag2);
		if (bag.get("url") != br) return;

		var w = bag.get("createdTabDocShell").domWindow;
		if (w) {
			var win = this.getWin(w);
			if (win)
				w.close(),
				w.arguments ? this.onArgs(win, w.arguments): this.tab(win);
		}
	},
	onArgs(win, args) {
		var [arg] = args;
		if (arg) {
			if (win.XULElement.isInstance(arg))
				return win.gBrowser.duplicateTab(arg, true, {inBackground: false});

			if (arg instanceof Ci.nsIArray)
				arg = Array.from(arg.enumerate(Ci.nsISupportsString), ss => ss.data);
			else if (arg instanceof Ci.nsISupportsString) arg = arg.data;
		}
		else arg = args[0] = "about:blank";

		win.arguments = args;
		win.gBrowserInit.uriToLoadPromise = arg;
		this.tab(win, args[5]);
		win.gBrowserInit._handleURIToLoad();
	},
	tab(win, id) {
		var index = win.gBrowser.selectedTab._tPos + 1;
		win.gBrowser.selectedTab = win.gBrowser
			.addTrustedTab("about:blank", {index, userContextId: id});
		win.focus();
	}
}).init())("chrome://browser/content/browser.xhtml");

ВВП пишет

Помните скрипт "сохранить сессию" А как бы туда втулить " Удалить все сессии" ?

Да, что-то припоминаю. Хорошо, попробую добавить.

Да и восстановить сессию тоже желательно в новой вкладке...

Это что значит? Если как при клике по пункту «Восстановить»
с зажатым Ctrl или средней кнопкой мыши, когда (тогда)
вкладки первого окна сессии добавляются в окно к уже имеющимся,
то можно инвертировать: найти
//return this[cmd](arg, !e.button && !e.ctrlKey && e.view);
и расскомментировать, а строку перед ней закомментировать или удалить.

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

Выделить код

Код:

(async (pid, mp) => CustomizableUI.createWidget(({
	id: "797321",
	label: "Simple Session Manager",
	tooltiptext: "Simple Session Manager",
	localized: false,
	init() {
		this.handleEvent = e => this[e.type](e);
		this.onTimeout = () => this.saveSession() || this.save();
		Services.obs.addObserver(this, "quit-application");
		var {openMenu} = this;
		this.render = function() {
			this.openMenu = openMenu;
			this.constructor.prototype.render.call(this);
		}
		delete this.init;
		return this;
	},
	onCreated(btn) {
		btn.type = "menu";
		btn.phTimestamp = 0;
		btn.render = this.render;
		btn._handleClick = this.click;
		btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC");

		var popup = btn.ownerDocument.createXULElement("menupopup");
		popup.filler = this;
		popup.id = pid;
		popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)");
		btn.prepend(popup);

		btn.addEventListener("mousedown", this);
		popup.addEventListener("command", this);
		btn.ownerGlobal.addEventListener("unload", () => {
			btn.removeEventListener("mousedown", this);
			popup.removeEventListener("command", this);
			if (popup.filler != this)
				popup.removeEventListener("dragstart", this),
				popup.removeEventListener("popuphidden", this);
		}, {once: true});
	},
	openMenu(arg) {
		var pos;
		if (this.matches(".widget-overflow-list > :scope"))
			pos = "after_start";
		else var win = this.ownerGlobal, {width, height, top, bottom, left, right} =
			this.closest("toolbar").getBoundingClientRect(), pos = width > height
				? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
				: `${win.innerWidth - right > left ? "end" : "start"}_before`;
		this.firstChild.setAttribute("position", pos);
		delete this.openMenu;
		this.openMenu(arg);
	},

	mousedown(e) {
		if (e.button) return;
		var trg = e.target;
		if (trg.nodeName.startsWith("t")) {
			trg.mdTimestamp = Cu.now();
			trg.tid = e.view.setTimeout(this.onTimeout, 500);
			return e.preventDefault();
		}
		e.detail == 2 && trg.nodeName == "menu" && this.boot(trg);
	},
	boot(trg) {
		var popup = trg.parentNode;
		var old = popup.querySelector("[boot]");
		if (old != trg) old?.removeAttribute("boot");
		trg.toggleAttribute("boot");
		popup.dblMD = true;
	},
	click() {
		var win = this.ownerGlobal;
		if (win.event.target != this) return;
		win.clearTimeout(this.tid);
		if (this.mdTimestamp - this.phTimestamp > 50) this.open = true;
	},
	command(e) {
		var arg, trg = e.target, cmd = trg.value;
		if (cmd.startsWith("r")) {
			arg = trg.parentNode.parentNode.label;
			if (cmd.startsWith("res"))
				return this[cmd](arg, (e.button == 1 || e.ctrlKey) && e.view);
				//return this[cmd](arg, !e.button && !e.ctrlKey && e.view);
		}
		this[cmd](arg) || this.save();
	},

	dragstart(e) {
		var trg = e.target;
		if (trg.nodeName != "menu") return;

		var popup = trg.parentNode;
		this.dragData = {trg, mouse: true};
		trg.menupopup.hidePopup();

		var win = trg.ownerGlobal;
		win.setCursor("grabbing");
		var {width} = trg.getBoundingClientRect();
		trg.setAttribute("maxwidth", width);

		win.addEventListener("mouseup", this);
		popup.addEventListener("mousemove", this);
	},
	mousemove(e) {
		var trg = e.target, dtrg = this.dragData.trg;
		if (trg == dtrg || trg.nodeName != "menu") return;

		e.movementY > 0
			? trg.nextSibling != dtrg && trg.after(dtrg)
			: trg.previousSibling != dtrg && trg.before(dtrg);
	},
	mouseup(arg) {
		if (arg.constructor.isInstance?.(arg)) {
			arg.preventDefault();
			var {trg} = this.dragData;
			this.dragData.mouse = false;
		}
		else var trg = arg;

		trg.removeAttribute("maxwidth");
		trg.ownerGlobal.setCursor("auto");
		trg.ownerGlobal.removeEventListener("mouseup", this);
		trg.parentNode.removeEventListener("mousemove", this);
	},

	popuphidden(e) {
		if (!e.target.id) return;
		e.view.removeEventListener("keydown", this, true);
		var popup = e.target;
		popup.parentNode.phTimestamp = Cu.now();
		if (!this.dragData && !popup.dblMD) return;

		var save;
		if (this.dragData) {
			var {trg, mouse} = this.dragData;
			mouse && this.mouseup(trg);
	
			delete this.dragData;
			var order = Array.from(popup.getElementsByTagName("menu"), m => m.label);
			if (order.toString() != this.meta.order.toString()) {
				var hasBoot = this.meta.boot != null;
				if (hasBoot) var bootName = this.meta.order[this.meta.boot];
				this.meta.order = order;
				if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName);
				save = true;
			}
		}
		if (popup.dblMD) {
			delete popup.dblMD;
			var {boot} = this.meta;
			var bootNode = e.target.querySelector("[boot]");
			var ind = bootNode && this.meta.order.indexOf(bootNode.label);
			if (ind != boot)
				this.meta.boot = ind,
				save = true;
		}
		save && this.save(e.view);
	},

	sku: `#${pid} > menu[maxwidth]`,
	skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`,
	keydown(e) {
		if (e.repeat && e.key == "Shift" || !e.shiftKey) return;
		var func = this.keyHandlers[e.key];
		if (!func) return;

		var menu = e.view.windowRoot
			.ownerGlobal.document.querySelector(this.skd);
		if (menu)
			e.stopImmediatePropagation(),
			func.call(this, menu);
	},
	keyup(e) {
		if (e.key != "Shift") return;
		var win = e.view.windowRoot.ownerGlobal;
		win.removeEventListener("keyup", this, true);
		win.document.querySelector(this.skd)?.removeAttribute("maxwidth");
	},
	keyHandlers: {
		Enter(menu) {
			this.boot(menu);
		},
		ArrowDown(menu) {
			var ns = menu.nextSibling;
			if (ns) ns.after(menu), this.arrow(menu);
		},
		ArrowUp(menu) {
			var ps = menu.previousSibling;
			if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu);
		}
	},
	arrow(menu) {
		if (menu.hasAttribute("maxwidth")) return;
		menu.setAttribute("maxwidth", menu.getBoundingClientRect().width);
		menu.ownerGlobal.addEventListener("keyup", this, true);
		this.dragData = {trg: menu};
	},

	fill(e) {
		var mxe = e.view.MozXULElement;

		var initFrag = mxe.parseXULToFragment(`
			<menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/>
			<menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/>
			<menuseparator/>
		`);
		this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup>
			<menuitem label="Восстановить"
				class="menuitem-iconic" value="restoreSession"/>
			<menuitem label="Переименовать"
				class="menuitem-iconic" value="renameSession"/>
			<menuitem label="Удалить"
				class="menuitem-iconic" value="removeSession"/>
		</menupopup></menu>`);

		this.regStyle();

		var filler = {fill: e => e.target.id
			? e.view.addEventListener("keydown", this, true)
				|| e.target.fillFlag || this.fillSessions(e.target)
			: this.dragData?.mouse && e.preventDefault()
		};

		(this.fill = e => {
			var trg = e.target;
			trg.setAttribute("context", "");
			trg.append(trg.ownerDocument.importNode(initFrag, true));
			(trg.filler = filler).fill(e);
			trg.addEventListener("dragstart", this);
			trg.addEventListener("popuphidden", this);
		})(e);
	},
	fillSessions(popup) {
		while(popup.lastChild.nodeName == "menu") popup.lastChild.remove();
		var ind = 0, {boot} = this.meta;
		for(var name of this.meta.order) {
			var df = popup.ownerDocument.importNode(this.menuFrag, true);
			df.firstChild.setAttribute("label", name);
			if (ind++ == boot) df.firstChild.toggleAttribute("boot");
			popup.append(df);
		}
		popup.fillFlag = true;
	},
	regStyle() {
		delete this.regStyle;
		var subst = "ucf-ssm-style-resurl";
		Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution(
			subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(`
			@-moz-document url-prefix(chrome://browser/content/browser.xhtml) {
				#${pid} > menu {
					list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC");
				}
				#${pid} > [value=saveSession] {
					list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC");
				}
				#${pid} [value=restoreSession] {
					list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII=");
				}
				#${pid} [value=renameSession] {
					list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII=");
				}
				#${pid} :is([value=removeSession], [value=deleteAllSessions]) {
					list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg==");
				}
				#${pid} > menuseparator:last-child,
				#${pid} > menu[maxwidth] > .menu-right,
				#${pid} > [value=deleteAllSessions]:nth-last-child(2) {
					display: none;
				}
				#${pid} > menu[boot] {
					color: red;
					font-weight: bold;
				}
				#${pid} > menu[maxwidth] {
					color: blue;
					font-weight: bold;
					outline-offset: -2px;
					outline: 2px solid orangered;
				}
			}
		`.replace(/;$/gm, " !important;"))));
		var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
		sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET);
	},

	get gs() {
		delete this.gs;
		return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {});
	},
	getState() {
		return JSON.parse(this.gs.SessionStore.getBrowserState());
	},
	splice(name, newName) {
		var ind = this.meta.order.indexOf(name);
		if (ind == -1) return;
		var args = [ind, 1];

		if (1 in arguments) args.push(newName);
		else {
			if (ind == this.meta.boot) this.meta.boot = null;
			else if (ind < this.meta.boot) this.meta.boot--;
		}
		this.meta.order.splice(...args);
	},

	get meta() {
		var file = Services.dirsvc.get("UChrm", Ci.nsIFile);
		file.append("simple_session_manager.json");
		this.path = file.path;
		try {
			this.data = JSON.parse(Cu.readUTF8File(file));
		} catch {
			this.pp = file.parent.path;
			this.data = Object.create(null);
		}
		var meta = this.data[mp];
		if (!meta) {
			var order = Object.keys(this.data);
			meta = this.data[mp] = {order, boot: null};
		}
		delete this.meta;
		return this.meta = meta;
	},
	async save(excWin) {
		var io = Cu.getGlobalForObject(Cu).IOUtils;
		if (this.pp)
			await io.makeDirectory(this.pp), delete this.pp;
		(this.save = excWin => {
			this.meta.order.length
				? io.writeJSON(this.path, this.data)
				: io.remove(this.path, {ignoreAbsent: true});
			for(var win of CustomizableUI.windows) {
				if (win == excWin) continue;
				var popup = win.document.getElementById(pid);
				if (popup) popup.fillFlag = false;
			}
		})(excWin);
	},

	get prompter() {
		var {prompt} = Services;
		var p = {}, args = [null, null, "UCF Simple Session Manager"];
		p.alert = prompt.alert.bind(...args);
		p.confirm = prompt.confirm.bind(...args);
		var pr = prompt.prompt.bind(...args);
		p.prompt = (msg, value) => {
			var res = {value};
			return pr(msg, res, null, {}) ? res.value : null;
		}
		delete this.prompter;
		return this.prompter = p;
	},
	observe(s, t, data) {
		Services.obs.removeObserver(this, "quit-application");
		if (data.includes("restart")) return;

		var {boot} = this.meta;
		if (boot == null) return;
		
		var state = this.data[this.meta.order[boot]];
		//this.gs.SessionStoreInternal.getCurrentState = () => state;
		var ssi = this.gs.SessionStoreInternal;
		ssi.getCurrentState = () => state;
		Services.obs.removeObserver(ssi, "browser:purge-session-history");

		Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
	},

	get bwt() {
		delete this.bwt;
		var url = "resource:///modules/BrowserWindowTracker.jsm";
		return this.bwt = ChromeUtils.import(url).BrowserWindowTracker;
	},
	getName(state) {
		var wl = state.windows.length, tl = 0;
		for(var w of state.windows) tl += w.tabs.length;
		return `${
			this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70)
		} ${wl}/${tl} [${
			new Date().toLocaleString("mn").replace(" ", "-")
		}]`;
	},
	exists(name) {
		this.meta;
		return (this.exists = name => name in this.data &&
			!this.prompter.alert("Сессия с тем же именем уже существует!"))(name);
	},
	saveSession(state = this.getState(), name = this.getName(state)) {
		var name = this.prompter.prompt("Сохранить:", name);
		if (name == null) return true;

		if (this.exists(name)) return this.saveSession(state, name);

		this.data[name] = state;

		this.meta.order.push(name);
		//this.meta.order.unshift(name);
		//if (this.meta.boot != null) this.meta.boot++;
	},
	restoreSession(name, win) {
		var ss = this.gs.SessionStore;
		var state = JSON.stringify(this.data[name]);
		win ? ss.setWindowState(win, state) : ss.setBrowserState(state);
	},
	renameSession(name, newName = name) {
		var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName);
		if (newName == null || newName == name) return true;

		if (this.exists(newName)) return this.renameSession(name, newName);

		var {data} = this;
		this.splice(name, newName);
		data[newName] = data[name];
		delete data[name];
	},
	removeSession(name) {
		if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`))
			return true;
		delete this.data[name];
		this.splice(name);
	},
	deleteAllSessions() {
		if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`))
			return true;
		delete this.dragData;
		delete this.bwt.getTopWindow().document.getElementById(pid).dblMD;
		this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null};
	}
}).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");

Dobrov пишет

Как переделать этот код

В смысле как? Всякий древний стафф зачистить, типа
mInputField - inputField, createElement - createXULElement, getBrowser () - gBrowser, ...
Никогда что ли не делал такое.

для работы с UCF

В custom_script_win.js проверка location не требуется.
Подключать из «по событию "load"».

такое расширение не нашёл

Вроде заявлен какой-то AdvancedLocationbar².
Ещё есть скрипт dav_LinkifiesLocationBar.uc.js,
(там проверка адреса идёт интервалом, долбёжка 20 раз в секунду).

Отсутствует

 

№1618403-02-2022 14:18:12

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

Re: Custom Buttons

Dumby
Теперь класс ! resource://usercontext-content/cart.svg - это обратно подставил. return this[cmd](arg, !e.button && !e.ctrlKey && e.view); -это тоже.
Хорошая фишка получилась. Жаль сессия в фоне открывается , как бы последняя вкладка активной была ?

Отредактировано ВВП (03-02-2022 18:03:41)

Отсутствует

 

№1618503-02-2022 14:41:35

ALEX_45_ORP
Участник
 
Группа: Members
Зарегистрирован: 18-01-2018
Сообщений: 162
UA: Firefox 93.0

Re: Custom Buttons

ВВП пишет

Хорошая фишка получилась

в 93 или новее затачиваешь?


Win 10х64

Отсутствует

 

№1618604-02-2022 02:06:07

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

Re: Custom Buttons

Dumby пишет

unter_officer

скрытый текст
Пытался размышлять над однооконным режимом, и понял,
что ничего хорошего у меня придумать не получится.


Есть вариант просто тупо закрывать окна, что уже нехорошо.
Вот так, например, перекрывает основной попс — окна,
создаваемые с участием parent (docShell).


Но без него — нет, для таких окон непонятно где взять адрес,
который пойдёт загружаться, а когда пойдёт загружаться,
то закрывать поздновато — браузерные коды уже на него рассчитывают.


Увы, для WebExtensions, браузер создаёт окна именно так.
Вписал некое вмешательство в создание, но закомментировал.
Можно раскомментировать, посмотреть что ещё может сломаться.


Вобщем, частично и грубо.

Выделить код

Код:

(br => ({
	async init() {
		lockPref("browser.link.open_newwindow", 3);
		lockPref("browser.link.open_newwindow.restriction", 0);
		lockPref("browser.link.open_newwindow.override.external", 3);
		lockPref("browser.link.open_newwindow.disabled_in_fullscreen", true);

		var self = this;
		var topic = "webNavigation-createdNavigationTarget-from-js";
		var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

		obs.addObserver(this, topic);
		obs.addObserver(function quit(s, t) {
			obs.removeObserver(quit, t);
			obs.removeObserver(self, topic);
		}, "quit-application-granted");

		delete this.init;
		this.imp = Cu.getGlobalForObject(Cu).ChromeUtils.import;
/*
		var url = "resource://gre/modules/ExtensionParent.jsm";
		var mgr = this.imp(url).ExtensionParent.apiManager;
		await new Promise(resolve => mgr.once("ready", resolve));

		var g = mgr.global;
		g.Object.defineProperty(g, "windows", {
			configurable: true, enumerable: true, set(val) {
				var proto = val.prototype;
				g.Object.assign(proto, g.eval(`({${proto.getAPI}})`.replace(
					/\n\n[^\n]+?Services.ww/,
					"\n\n          var res = redirectBWCArgs(args, features, windowManager);" +
					"\n          if (res) return res;$&"
				)));
				delete this.windows;
				this.windows = val;
			}
		});
		g.redirectBWCArgs = (arr, features, wm) => {
			var pr = features.at(-1);
			var win = this.getWin(null, pr.startsWith("p"));
			if (!win) {
				if (features.length > 3)
					features.join = () => "dialog=no,all," + pr;
				return;
			}
			var args = [];
			for(var ind = 0, len = arr.length; ind < len; ind++) {
				var item = arr.GetElementAt(ind);
				if (item) {
					if (ind == 5) item = item.QueryInterface(Ci.nsISupportsPRUint32).data;
					else if (ind > 5 && ind < 9) item = item.QueryInterface(Ci.nsIPrincipal);
					else if (ind == 9) item = false;
				}
				args.push(item);
			}
			this.onArgs(win, args);
			return g.Promise.resolve(wm.getWrapper(win).convert({populate: true}));
		}
*/
	},
	getWin(win, p) {
		var url = "resource:///modules/BrowserWindowTracker.jsm";
		var bwt = this.imp(url).BrowserWindowTracker;
		return (this.getWin = (win, p) => bwt.getTopWindow({
			private: win ? win.browsingContext.usePrivateBrowsing : p
		}))(win, p);
	},
	observe(subj) {
		var bag = subj.QueryInterface(Ci.nsIPropertyBag2);
		if (bag.get("url") != br) return;

		var w = bag.get("createdTabDocShell").domWindow;
		if (w) {
			var win = this.getWin(w);
			if (win)
				w.close(),
				w.arguments ? this.onArgs(win, w.arguments): this.tab(win);
		}
	},
	onArgs(win, args) {
		var [arg] = args;
		if (arg) {
			if (win.XULElement.isInstance(arg))
				return win.gBrowser.duplicateTab(arg, true, {inBackground: false});

			if (arg instanceof Ci.nsIArray)
				arg = Array.from(arg.enumerate(Ci.nsISupportsString), ss => ss.data);
			else if (arg instanceof Ci.nsISupportsString) arg = arg.data;
		}
		else arg = args[0] = "about:blank";

		win.arguments = args;
		win.gBrowserInit.uriToLoadPromise = arg;
		this.tab(win, args[5]);
		win.gBrowserInit._handleURIToLoad();
	},
	tab(win, id) {
		var index = win.gBrowser.selectedTab._tPos + 1;
		win.gBrowser.selectedTab = win.gBrowser
			.addTrustedTab("about:blank", {index, userContextId: id});
		win.focus();
	}
}).init())("chrome://browser/content/browser.xhtml");

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


Ну, а пока всё нормально. Большое спасибо за код.


«The Truth Is Out There»

Отсутствует

 

№1618704-02-2022 11:12:35

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

Re: Custom Buttons

ВВП пишет

как бы последняя вкладка активной была ?

В смысле которая была активной в сессии?
Если да, то можно такую правку попробовать

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

Выделить код

Код:

/*
	restoreSession(name, win) {
		var ss = this.gs.SessionStore;
		var state = JSON.stringify(this.data[name]);
		win ? ss.setWindowState(win, state) : ss.setBrowserState(state);
	},
*/
	restoreSession(name, win) {
		var ss = this.gs.SessionStore;
		var state = this.data[name];
		if (!win) return ss.setBrowserState(JSON.stringify(state));

		var [w] = state.windows;
		var tab = w.tabs[w.selected - 1];
		var ext = tab.extData;
		(ext || (tab.extData = {}))[mp] = "1";

		win.addEventListener("SSWindowRestored", this.winRetored, {once: true});
		ss.setWindowState(win, JSON.stringify(state));
		ext ? delete tab.extData[mp] : delete tab.extData;
	},
	winRetored(e) {
		var {gBrowser, SessionStore} = e.target;
		for(var tab of gBrowser.visibleTabs)
			if (SessionStore.getCustomTabValue(tab, mp) == "1") {
				gBrowser.selectedTab = tab;
				SessionStore.deleteCustomTabValue(tab, mp);
				break;
			}
	},

Отсутствует

 

№1618804-02-2022 12:21:49

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

Re: Custom Buttons

Dumby

Dumby пишет

Если да, то можно такую правку попробовать

От теперь класс !  . Как бы еще автосубтиры на ютубе загасит ? Приходиться аж две кнопки лепить. т. е. стилем гасить...
А, как на "Отмена" можно код всунуть ? Не важно какой , ну, чтоб окно закрылось , и чтоб код нужный сработал ?
if (Services.prompt.confirm(null, "ВНИМАНИЕ !", "Открытые вкладки не восстановятся !" + "\nПерезапустить с зачисткой профиля ?", "Да", "Отмена"))

ТИПА,  else Services.prefs.setIntPref а дальше не знаю...

Отредактировано ВВП (04-02-2022 23:20:01)

Отсутствует

 

№1618905-02-2022 04:20:52

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

Re: Custom Buttons

Dumby
Вы когда-то давно написали вот этот код:

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

Выделить код

Код:

/*Initialization Code*/

// Закрытие вкладки = переход на предыдущую посещенную ..........
// https://forum.mozilla-russia.org/viewtopic.php?pid=759770#p759770 .....
((blurTab, dummy, s, lastSelect) => {
    (s = () => lastSelect = Date.now())();
    addEventListener("TabSelect", s, false, gBrowser.tabContainer || 1);
    gBrowser._blurTab = tab => {
        if (!tab.selected) return;
        var tabToSelect = dummy;
        for(var t of gBrowser.tabs) if (
            !t.hidden && !t.closed
            && t.lastAccessed > tabToSelect.lastAccessed
            && t.lastAccessed < lastSelect
        )
            tabToSelect = t;
        if (tabToSelect == dummy) blurTab.call(gBrowser, tab);
        else gBrowser.selectedTab = tabToSelect;
    }
    addDestructor(() => gBrowser._blurTab = blurTab);
})(gBrowser._blurTab, {lastAccessed: 0});

Либо я не совсем понимаю алгоритм работы этого кода, либо он просто устарел.
В общем, он не всегда срабатывает как надо - то переходит на предыдущую посещенную вкладку, то вдруг переходит на какую ему вздумается вкладку.
Какой-то закономерности я не смог заметить.


У меня две просьбы.
1. Подправить, чтобы код срабатывал нормально.
2. Переделать этот код для UCF.


«The Truth Is Out There»

Отсутствует

 

№1619006-02-2022 09:02:33

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

Re: Custom Buttons

ВВП пишет

А, как на "Отмена" можно код всунуть ? Не важно какой , ну, чтоб окно закрылось , и чтоб код нужный сработал ?
ТИПА,  else

Как-то так, наверно. Если код синхронный.

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

Выделить код

Код:

else if (WindowIsClosing()) {

	// Здесь код

	window.close();
}

unter_officer пишет

то переходит на предыдущую посещенную вкладку, то вдруг переходит на какую ему вздумается вкладку

Ну, раз так, можно попробовать свой трекер запилить.


Допустим, под «предыдущей посещенной вкладкой»,
подразумевается предыдущая (по времени)
активировавшаяся вкладка, не скрытая и не закрытая.
Следует понимать, что такой может не быть,
тогда переход пойдёт туда, куда перейдёт сам браузер.

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

Выделить код

Код:

(async ucf => {
	await delayedStartupPromise;
	var set = new Set([gBrowser.selectedTab]);
	var bt = gBrowser._blurTab;
	gBrowser._blurTab = tab => {
		if (!tab.selected) return;
		set.delete(tab);
		var res;
		for(var t of set) t.hidden || (res = t);
		res ? gBrowser.selectedTab = res : bt.call(gBrowser, tab);
	}
	var arr = [
		["TabClose", e => set.delete(e.target)],
		["TabSelect", e => set.add(e.target, set.delete(e.target))]
	];
	var id, tc = gBrowser.tabContainer;
	for(var args of arr) tc.addEventListener(...args);
	ucf.unloadlisteners.push(id = Symbol());
	ucf[id] = {destructor() {
		set.clear();
		for(var args of arr) tc.removeEventListener(...args);
	}};
})(ucf_custom_script_win);

Отсутствует

 

№1619106-02-2022 11:01:03

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

Re: Custom Buttons

Dumby пишет

Ну, раз так, можно попробовать свой трекер запилить.

Как я понял, это для custom_script_win.js и куда его там надо разместить? А то у меня не срабатывает.
Спасибо. Отлично работает.

Отредактировано voqabuhe (06-02-2022 11:37:14)

Отсутствует

 

№1619206-02-2022 12:18:46

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

Re: Custom Buttons

Dumby

Dumby пишет

Как-то так, наверно. Если код синхронный.

Не догоняю, как использовать с этим ?

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

Выделить код

Код:

if(event.button == 1 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){

 if (custombuttons.confirmBox(null, "Сброс Кукситов !", "Да", "Отмена") ) {
  SiteDataManager.removeSiteData();


alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
                      alertsService.showAlertNotification("chrome://global/skin/icons/cpd_OK.png", "Кукситы", "Куки Сброшены" );
                       setTimeout(()=> alertsService.closeAlert(), 1600); 
}
}


Или этим ?
скрытый текст

Выделить код

Код:

/*CODE*/

 if (Services.prompt.confirm(null, "ВНИМАНИЕ !", "Открытые вкладки не восстановятся !" + "\nПерезапустить с зачисткой профиля ?", "Да", "Отмена")){		 

var file = Services.dirsvc.get('ProfD', Ci.nsIFile);
         file.initWithPath(file.path + "\\memory\\del.vbs");
         
file.launch();  


}

Отредактировано ВВП (06-02-2022 12:23:27)

Отсутствует

 

№1619306-02-2022 13:33:41

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

Re: Custom Buttons

ВВП пишет

Не догоняю, как использовать с этим ?

Добавляешь в код после закрывающей скобки «}» от if с confirm'ом.
В приведённых кодах эта скобка:
в первом — предпоследняя, во втором — последняя.

Отсутствует

 

№1619406-02-2022 14:11:56

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

Re: Custom Buttons

Dumby
Куда ? Ни фига не врубаюсь .

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

Выделить код

Код:

else if (WindowIsClosing()) {
CustomizableUI.setToolbarVisibility("PersonalToolbar", document.querySelector("#PersonalToolbar").closed);
window.close();
}

Разобрался window.close(); - убрать

Отредактировано ВВП (06-02-2022 15:06:19)

Отсутствует

 

№1619506-02-2022 19:47:41

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

Re: Custom Buttons

Dumby пишет

Ну, раз так, можно попробовать свой трекер запилить.


Допустим, под «предыдущей посещенной вкладкой»,
подразумевается предыдущая (по времени)
активировавшаяся вкладка, не скрытая и не закрытая.
Следует понимать, что такой может не быть,
тогда переход пойдёт туда, куда перейдёт сам браузер.

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

Выделить код

Код:

(async ucf => {
	await delayedStartupPromise;
	var set = new Set([gBrowser.selectedTab]);
	var bt = gBrowser._blurTab;
	gBrowser._blurTab = tab => {
		if (!tab.selected) return;
		set.delete(tab);
		var res;
		for(var t of set) t.hidden || (res = t);
		res ? gBrowser.selectedTab = res : bt.call(gBrowser, tab);
	}
	var arr = [
		["TabClose", e => set.delete(e.target)],
		["TabSelect", e => set.add(e.target, set.delete(e.target))]
	];
	var id, tc = gBrowser.tabContainer;
	for(var args of arr) tc.addEventListener(...args);
	ucf.unloadlisteners.push(id = Symbol());
	ucf[id] = {destructor() {
		set.clear();
		for(var args of arr) tc.removeEventListener(...args);
	}};
})(ucf_custom_script_win);

Dumby, спасибо большое.


«The Truth Is Out There»

Отсутствует

 

№1619607-02-2022 10:40:50

Азат55555
Участник
 
Группа: Members
Зарегистрирован: 01-11-2018
Сообщений: 28
UA: Yandex 22

Re: Custom Buttons

unter_officer благодарю за ответ по поводу создания rar файла.

Отсутствует

 

№1619708-02-2022 13:11:25

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

Re: Custom Buttons

Dumby
Как , кодом, стилем , настройкой можно вкл/выкл превью вкладок ?
pnc7u7ob.jpg

Отсутствует

 

№1619808-02-2022 22:21:16

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

Re: Custom Buttons

Dumby
Я для себя переделывал одну кнопочку из СВ в UCF.
В принципе кнопка получилась рабочей, но что-то мне подсказывает, что код получился "кривой".


Посмотрите пожалуйста своим профессиональным взглядом. Хотелось бы услышать ваше мнение.
И ещё. В моём коде мне не нравится использование eval(), но как избавится от eval что-то не соображу. Может подскажете?


Код кнопки

Выделить код

Код:

try {
CustomizableUI.createWidget({
	id: "ucf_exportsBookmarksToHTMLFile",
	label: "Экспорт закладок в HTML-файл",
	image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII=",
	// defaultArea: CustomizableUI.AREA_NAVBAR,
	localized: false,
	onCreated(btn) {
		btn.setAttribute("type", "menu");
		btn.setAttribute("image", this.image);
		btn.onmouseover =()=> {
			var path = getPathToBookmarksFolder();
			btn.setAttribute("tooltiptext", "ЛКМ: Открыть меню кнопки\n\nПапка для экспорта закладок:\n" + path);
		}
		var doc = btn.ownerDocument;
		var win = doc.defaultView;
		var popup = doc.createXULElement("menupopup");
		var alertsImage = this.image;

		var array = [
			["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", "exportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="],
			["separator"],
			["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", "setPathAndExportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="],
			["separator"],
			["ucf_AllBookmarks", "Показать все закладки", "win.PlacesCommandHook.showPlacesOrganizer('AllBookmarks');", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="],
			["separator"],
			["ucf_TotalNumberOfBookmarks", "Общее количество закладок", "totalNumberOfBookmarks();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="],
		];
		array.forEach(m => {
			if (m[0] == "separator") { popup.append(doc.createXULElement("menuseparator")); return; };
			var menuitem = popup.appendChild(doc.createXULElement("menuitem"));
			menuitem.setAttribute("id", m[0]);
			menuitem.setAttribute("label", m[1]);
			menuitem.className = "menuitem-iconic";
			menuitem.setAttribute("image", m[3]);
			menuitem.addEventListener("command", ()=> eval(m[2]));
		});
		btn.prepend(popup);

		function exportsBookmarksToHTMLFile() {
			var filePath = getPathToBookmarksFolder();

			YMD = new Date().toLocaleString("af").slice(0, 10).replace(/-/g, "_");
			HMS = new Date().toLocaleTimeString('de', '%H_%M_%S').replace(/:/g, "_");
			myDate = (YMD + '\u00F7' + HMS);

			var path = filePath + "\\bookmarks_(" + myDate + ").html";

			Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
			BookmarkHTMLUtils.exportToFile(path).then(null, Cu.reportError);

			var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
			alertsService.showAlertNotification(alertsImage, "Экспорт закладок в HTML-файл", "Файл сохранен в " + filePath);

			// стиль всплывающей подсказки
			var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
			var uri = win.makeURI('data:text/css,'+ encodeURIComponent('\
				#alertBox { border: 1px solid threedshadow !important; border-radius: 3px !important; background-color: -moz-Dialog !important; width: 360px !important; height: 80px !important; }\
				#alertImage { height: 20px !important; width: 20px !important; object-fit: contain !important; margin: 3px 0 20px 20px !important; }\
				#alertNotification:hover { cursor: pointer !important; }\
				.alertTitle { color: #003366 !important; text-align: center !important; font-family: Segoe UI !important; font-size: 120% !important; }\
				#alertTextLabel { color: #2B552B !important; text-align: center !important; text-decoration: underline !important; font-weight: bold !important; }\
			'));
			sss.loadAndRegisterSheet(uri, 0);

			// удалить стиль и подсказку через указанное время
			setTimeout(()=> { sss.unregisterSheet(uri, 0); alertsService.closeAlert(); }, 3500);
		}

		function openBookmarksFolder() {
			var folder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
			folder.initWithPath(getPathToBookmarksFolder());
			folder.launch();
		}

		function setPathAndExportsBookmarksToHTMLFile() {
			var fp = win.makeFilePicker();
			fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder);
			fp.open(re=> {
				if ( re != fp.returnOK ) return;
				Services.prefs.setCharPref("CB.exportsBookmarksToHTMLFile.path", convertFromUnicode("UTF-8", fp.file.path));
				exportsBookmarksToHTMLFile();
			})
		}

		function getPathToBookmarksFolder() {
			try { return Services.prefs.getComplexValue("CB.exportsBookmarksToHTMLFile.path", Ci.nsIPrefLocalizedString).data }
			catch(e) { return "C:" };
		}

		function convertFromUnicode(charset, str) {
			var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
			converter.charset = charset;
			str = converter.ConvertFromUnicode(str);
			return str + converter.Finish();
		}

		function totalNumberOfBookmarks() {
			var statement = PlacesUtils.history.DBConnection
				.createStatement("SELECT count(fk) FROM moz_bookmarks");
			statement.executeStep();
			var bkmcnt = statement.getInt32(0);
			statement.finalize();
			var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
			prompts.alert(null, "Общее количество закладок", "Общее количество закладок = " + bkmcnt);
		}

	},
});
} catch(ex) { Cu.reportError(ex); }


«The Truth Is Out There»

Отсутствует

 

№1619909-02-2022 11:21:21

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

Re: Custom Buttons

ВВП пишет

Как , кодом, стилем , настройкой можно вкл/выкл превью вкладок ?

Есть код, добавляет в контекстное меню CB-кнопок
чекбокс-пункт «[✔] Включить инициализацию».
Если «превью вкладок» оформлено отдельной кнопкой, то можно использовать.


unter_officer пишет

не нравится использование eval()

А что, вроде бочку катят только на оконный eval(),
а на от сандбокса и глобального объекта JSM'ок нет.
Но можно и без eval. И ["separator"]'ы можно убрать,
если таков замысел, что они всегда присутствуют между menuitem'ами.

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

Выделить код

Код:

/*
		var array = [
			["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", "exportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="],
			["separator"],
			["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", "setPathAndExportsBookmarksToHTMLFile();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="],
			["separator"],
			["ucf_AllBookmarks", "Показать все закладки", "win.PlacesCommandHook.showPlacesOrganizer('AllBookmarks');", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="],
			["separator"],
			["ucf_TotalNumberOfBookmarks", "Общее количество закладок", "totalNumberOfBookmarks();", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="],
		];
		array.forEach(m => {
			if (m[0] == "separator") { popup.append(doc.createXULElement("menuseparator")); return; };
			var menuitem = popup.appendChild(doc.createXULElement("menuitem"));
			menuitem.setAttribute("id", m[0]);
			menuitem.setAttribute("label", m[1]);
			menuitem.className = "menuitem-iconic";
			menuitem.setAttribute("image", m[3]);
			menuitem.addEventListener("command", ()=> eval(m[2]));
		});
*/
		[
			["ucf_ExportsBookmarksToHTMLFile", "Экспорт без запроса на сохранение", exportsBookmarksToHTMLFile, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACeElEQVQ4y5WSXWjOURzHP0/+FyJqUqOVNS8rmrd5GRNNJtNWoibiYqGN5qVEbpYLoZQVYWVxMYVi0Z55aTGvCQslXOBCLjByw57/eT/PcfGfzUOS783p/M63z+93vudE9CsCCCGEaKASQgg5RzneX/VnIc58C70fP/D5Sy8vnj8jEiJGCIGSInEoIVBKIJUcZCgZhzjTh4gzfO/7hohjMpmYN69fJQYpY6QQCCmQSiH7KQOEpCARcQYlBEoqtPylRWdHO39TxD8Uram7EVqPzqJ20z1O7J9EzdYHnGoqomLnfdzTfanIZT0jRuYhvWFC8RSk7WbBokqcuZEQjHV8/fwJZTUvnz/huxF0d12BnzkY7xmdP5bYCEqmz0aYayxZVgOuMzFop3n/7i3COHoe30crwdWOC6BVf/jOUFg0iT57mbllC8FcpHrFamhIrh71pNenWlt6w4G1Q2htaebkjsJk3VtGQ+PFJId1G24G6wPOO3zwWOswWY/xDu0MyhuEcWijEFYRe4vsaUoNBGl9lraWcoYOGw5AZW07pw9No3B8MQATK49zdl8JZeUVAKRmNnHyxOHQ0LgrFQE471m98TbGe0wwaOtYtf0h0t1BGYe0jqW7H6HNbYzVoA2QN/iU2jnOHJvDqNH5AMyobuPcoalMKSkFYOS8g6QPlFKxpCqZYOLm3L+gvWFl/V2Us0iv0MaxvPEBmexNtNXEVrF4Wzf4LnAalP0N4Aznj5RRMK4IgILFR0g3z2XW7PKk4+Q9XD88n6rqVcl+zNpcQGw0VfW3EEYinEV4zbwtXTjdCU6BNSzffA2yafASvMsFPLtal+I/1dB4CYAfXqtvWdjPXR4AAAAASUVORK5CYII="],
			["ucf_SetPathAndExportsBookmarksToHTMLFile", "Экспорт закладок в HTML-файл", setPathAndExportsBookmarksToHTMLFile, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACY0lEQVQ4y42SXWiPYRjGf0/eAxFFK0lZ8xVrPmcfDQtNESfURBwIWZqIyIEdLZSaTGy1xQGFAyuZKG0MS2yxWigfB3KAkRPb/33e53OPg3f7b0NxHd7P/Vx310fEECKAEEKIspMQQkCIkacxu6Px5yDO/Ax9Xz7z7Xsfr3p7iKSMkVJStnKtAIiUlCglAQiQ3lVJHOLMADLO0D/wExnHZDIx79+9SY8kSUwiJTKRJEpRVFouAJoa6lKGREqUSpBxBiWH6EcLuXO7hT8gBAJExD8QbdvVFprPF1K59wkNJ+ey6cBTLtXksfpIJ+5lrYjcoGfS5Ckk3jB7Xj6JfcCK8gqcaUsZjHX8+PYVZTWve1/QbyRCCMH8wyFd8J6cadOJjaRg8XKkuUeAIN6eS53TTvPp4wekcXR3daJHuShARLEz5ObNZcDeorhkFZibY1V0t+4UzY194dT2cTQ3nqXpUC5UgwCRzXPH7vZgfcB5hw8eax1m0GO8QzuD8gZpHNoopFXE3pJ014wQWD/IlcYyxk+YCEBFZQuXzywid9Y8AOZUXORabQElZavTEJbW0NRQF6qqj6ZJOO/ZuqcD4z0mGLR1bDn4jMQ9QhlHYh3rjj1Hmw6M1aANMGWkkto5rl4oYmrONACWbLzC9TMLyS9YBsDk0tMMdJ0Qw84BVFWP6rT2hs37HqOcJfEKbRwbqp+SGWxHW01sVdbVAAF+M1E7w436EmbMzANgxpp6Ws8WU7i8LNW84PjYhoVAECJkCWKjWb/vIdIkSGeRXlO6/z5O3wGnwJq/VjlL0HN3l+A/MfxxGL8A8lFUSnL6gNAAAAAASUVORK5CYII="],
			["ucf_AllBookmarks", "Показать все закладки", win.PlacesCommandHook.showPlacesOrganizer.bind(null, "AllBookmarks"), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAACXBIWXMAAAAAAAAAAAHqZRakAAACsElEQVQ4y42RW2gUdxSHv40TDSlSNYqFhorxEqFiiIovtkghXqCPIhQUbw+aB6FF0JcIRhC8PBmISKEPXmiK4oMVg9ZKJGrUKCQmRDSxcc3GNeuSnd2ZnZmdmf/NB6uLqLTn9Xzn9+PwWeev3eVs14CxAM4easZqaWkxl15WYy1etxX/5O9Y56/dZbBQacayeXp6erAAbvYO4LgFjDFYV65eNx0P07zI2EzkXKye7i5mLfoR18rxarIPa3wsSdvB77jYPcjQoz6s0ZGnNO1tJ/A9gH9bbnea5LSFOF5I3gtw/JAgjN8CAE4hz5yVC6nyQ2YKQSbn8M/IkzLw/NkwU+ZOcHrfJgB++LmNd2MBjI89x3yTZnXzcaQUKCXKwMDjEXPjr05eZyYYnbqIvFei4JUoBiGHt65NWBc6ziCE+Gj524FdZFJJLK0URmvm1y9lhh/iFEs4fqlc4RYdtNIQRrT+tJrdbZcplYIyULBttFK0b1kDwLn9G9l2tKMM2JNZjIEjf9ykvrYG2/VJpl+Xgbxto7Xh1qNhrt8PEXGMlLIM+EUXY0B7HlIIlJQoJdnWeopjOze8dfGF8cy9O92s27yHZfO/4v/M8u2tHN2xPmEBPLh3h4qKBFfPnODvFZuIpSISijCWlGJJFEsiIYgiwdOhfk4fbMYYU1blex6JBEipqIwksRSEsWJJ7Sx6h9OEUUwcC0Ih3x9+4Nop5AFQSlLlB0RKsr5xAU2NdSz5eia/dvbiBwEiFh+9YgHkclkSVGCModIt8mV1FU2NdQCsqq/lz9uDpF5l0Up+OiBv2yQArTWVBZeGebP5pf0Sw6kMNdOr+b6hjlv9AVrrTwc4dg4AY6Ci4HCh6yFKarRWuK7DaCqN1gptPhPw7dIG+vt6wYA/mf1PhZlUMnFs5wYA3gDhGJMMzu9r5wAAAABJRU5ErkJggg=="],
			["ucf_TotalNumberOfBookmarks", "Общее количество закладок", totalNumberOfBookmarks, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEX///+coqK4vLzc5PG4vLxKktduu5N9brKcoqK4vLzR2d7b5PHc5PHc5vLd5vLe5/Te6PTg6vbg6/Xg6/bh6vXh6vbi7fjk7/rk8Prl7/rl8Prl8Pvn8vzn8/zn8/3o9P7p9P7p9f7q9v////8h14CvAAAABXRSTlMAf39/mY/u188AAABxSURBVBgZBcCBhgJAEADQN2uiO+dIovT/X5YUgkCy7UziBwB4Z5/BNYGILQDwzjgBcHsxuFwAIBV9hzhAWsde+9AUpHrYDT3agjSpJ8QfpPnfcztK9ILUT78+ohSkYn0gEtLaqAEWDACAnBsAJgAAfAEU/Sr37SwFHgAAAABJRU5ErkJggg=="],
		]
			.forEach((m, ind) => {
				ind && popup.append(doc.createXULElement("menuseparator"));

				var menuitem = popup.appendChild(doc.createXULElement("menuitem"));
				menuitem.id = m[0];
				menuitem.setAttribute("label", m[1]);
				menuitem.className = "menuitem-iconic";
				menuitem.setAttribute("image", m[3]);
				menuitem.addEventListener("command", m[2]);
			});


И, вот здесь, без var (let, const)
YMD, HMS, и myDate, при вызове функции,
уйдут как глобальные переменные, как свойства самого сандбокса,
что не столько даже плохо, сколько не нужно.
Можно так
скрытый текст

Выделить код

Код:

/*
			YMD = new Date().toLocaleString("af").slice(0, 10).replace(/-/g, "_");
			HMS = new Date().toLocaleTimeString('de', '%H_%M_%S').replace(/:/g, "_");
			myDate = (YMD + '\u00F7' + HMS);
*/
			var myDate = new Date().toLocaleString("mn")
				.replace(/(?:(\.|:))/g, "_").replace(" ", "\u00F7");


И, чуть далее, симилярно этому.
Cu.import() — стоит оставить лишь для особых случаев,
ChromeUtils в сандбокс проброшен, вроде нет причин не использовать его.


Но это не строго, теоретически, может случиться ошибка,
тогда алерт будет вроде как некстати, то есть, лучше бы сделать
exportsBookmarksToHTMLFile как async function,
а await ….exportToFile() завернуть в try {...} catch(ex) {Cu.reportError(ex); return;}
или алерт и дальнейшее записать как функцию вместо null, где ….then(null, …
но с чего бы, мы же, наверно, разумные люди, и назначать папку
для экспорта такую, куда браузер не сможет записать, не будем.

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

Выделить код

Код:

/*
			Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
			BookmarkHTMLUtils.exportToFile(path).then(null, Cu.reportError);
*/
			ChromeUtils.import("resource://gre/modules/BookmarkHTMLUtils.jsm")
				.BookmarkHTMLUtils.exportToFile(path).catch(Cu.reportError);


Ещё, setCharPref, getComplexValue, convertFromUnicode,
как-то это всё слишком старомодно.
Полагаю, Services.prefs.{g, s}etStringPref() должно работать.
скрытый текст

Выделить код

Код:

/*
		function setPathAndExportsBookmarksToHTMLFile() {
			var fp = win.makeFilePicker();
			fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder);
			fp.open(re=> {
				if ( re != fp.returnOK ) return;
				Services.prefs.setCharPref("CB.exportsBookmarksToHTMLFile.path", convertFromUnicode("UTF-8", fp.file.path));
				exportsBookmarksToHTMLFile();
			})
		}

		function getPathToBookmarksFolder() {
			try { return Services.prefs.getComplexValue("CB.exportsBookmarksToHTMLFile.path", Ci.nsIPrefLocalizedString).data }
			catch(e) { return "C:" };
		}

		function convertFromUnicode(charset, str) {
			var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
			converter.charset = charset;
			str = converter.ConvertFromUnicode(str);
			return str + converter.Finish();
		}
*/
		var pref = "CB.exportsBookmarksToHTMLFile.path"; // CB -> UCF ?

		function setPathAndExportsBookmarksToHTMLFile() {
			var fp = win.makeFilePicker();
			fp.init(win, "Укажите папку для экспорта закладок!", fp.modeGetFolder);
			fp.open(re => {
				if (re != fp.returnOK) return;
				Services.prefs.setStringPref(pref, fp.file.path);
				exportsBookmarksToHTMLFile();
			});
		}

		function getPathToBookmarksFolder() {
			return Services.prefs.getStringPref(pref, "C:");
		}


И, function openBookmarksFolder()
я не вижу что (пока?) где-то используется.
Да там до бесконечности можно копаться,
так, по верхушкам прошёлся, надеюсь, ничего не испортил.

Отсутствует

 

№1620009-02-2022 13:21:49

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

Re: Custom Buttons

Dumby

Dumby пишет

Если «превью вкладок» оформлено отдельной кнопкой

В том то и дело, что скриптом... Стилем можно, но не то ...Tab:hover {display: initial !important; }
Ладно итак сойдет.

Отредактировано ВВП (10-02-2022 11:42:15)

Отсутствует

 

Board footer

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