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

Заказывай стафф с атрибутикой Mozilla и... пусть все вокруг завидуют тебе! Быть уникальным - быть с Mozilla!

№122631-12-2023 16:19:51

b0ttle
Участник
 
Группа: Members
Зарегистрирован: 22-10-2020
Сообщений: 182
UA: Firefox 121.0

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

Northtech
Обычно скрываю эти кнопки, пользуюсь через PanelUI. Всех с новым годом.

Отредактировано b0ttle (19-01-2024 13:21:26)

Отсутствует

 

№122731-12-2023 19:37:43

Northtech
Участник
 
Группа: Members
Зарегистрирован: 16-04-2011
Сообщений: 261
UA: Firefox 121.0

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

b0ttle
Спасибо, помогло :)
я у себя их просто уменьшил, чтобы не такие огромные были.

#titlebar-buttonbox > .titlebar-button, .titlebar-buttonbox > :-moz-any(.titlebar-min,.titlebar-max,.titlebar-close,.titlebar-restore), #minimize-button, #restore-button, #close-button {
margin: 0 !important;
padding: 4px 8px !important;
}

Всех с праздником, наступившим и наступающим! :beer:

Отредактировано Northtech (31-12-2023 19:39:18)

Отсутствует

 

№122831-12-2023 22:03:49

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

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

Northtech пишет

в новой версии ucf_hookClicks.js пропадает блок кнопок закрытия окна (#minimize-button, #restore-button, #close-button).

Попробуй включить "Кнопки управления окна" в диалоге "Настройки UserChromeFiles"

Отсутствует

 

№122919-02-2024 15:40:28

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

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

egorsemenov06
У меня кнопка
//Искать в...............
от Vitaliy V. отвалилась давно. Перешёл на вариант Dumby, работает прекрасно ссылка. Хотя, как там на 123-й не знаю, не обновлялся.

Отредактировано xrun1 (19-02-2024 15:48:33)

Отсутствует

 

№123019-02-2024 17:32:09

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

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

egorsemenov06
Пробуйте..

Browser search engine

Выделить код

Код:

// ==UserScript==
// @name      Browser search engine
// @author    Vitaliy V.
// @include   main
// @shutdown  window.contextsearch.destructor();
// @note      https://forum.mozilla-russia.org/viewtopic.php?pid=780283#p780283
// ==/UserScript==

(this.contextsearch = {
    topic: "browser-search-engine-modified",
    hide: "browser.search.hiddenOneOffs",
    defaultImg: "chrome://browser/skin/search-engine-placeholder.png",
    searchSelect: null,
    popup: null,
    init(that) {
        var searchSelect = this.searchSelect = document.querySelector("#context-searchselect");
        if (!searchSelect)
            return;
        var popup = this.popup = searchSelect.closest("menupopup");
        popup.addEventListener("popupshowing", this);
        that.unloadlisteners?.push("contextsearch");
    },
    destructor() {
        this.popup.removeEventListener("popupshowing", this);
        if (this.popupshowing == this.handler) {
            this.popup.removeEventListener("popuphidden", this);
            Services.obs.removeObserver(this, this.topic);
            Services.prefs.removeObserver(this.hide, this);
        }
    },
    handleEvent(e) {
        this[e.type](e);
    },
    popupshowing(e) {
        var popup = this.popup;
        var searchSelect = this.searchSelect;
        if (e.target != popup || searchSelect.hidden) return;

        var menu = document.createXULElement("menu");
        menu.className = "menu-iconic";
        var menupopup = document.createXULElement("menupopup");
        menu.append(menupopup);
        menu.ePopup = menupopup;
        searchSelect.style.setProperty("display", "none", "important");
        searchSelect.before(menu);
        menu.onclick = this.search.bind(this);
        this.handler = e => e.target != popup || (menu.hidden = searchSelect.hidden);
        this.handlerRebuild = e => this.handler(e) || this.rebuild(menu);
        this.popuphidden = ev => {
            if (ev.target != popup) return;
            menu.hidden = true;
        };
        this.popup.addEventListener("popuphidden", this);
        this.rebuild(menu);
    },
    getEngines() {
        var args = "hideOneOffButton" in Services.search.defaultEngine
            ? [e => !e.hideOneOffButton]
            : Object.defineProperty(
                [function(e) {return !this.includes(e.name);}], "1", {
                    get: () => Services.prefs.getStringPref(this.hide)?.split(",") || []
                }
            );
        return (this.getEngines = async () =>
            (await Services.search.getVisibleEngines()).filter(...args)
        )();
    },
    async rebuild(menu) {
        var de = Services.search.defaultEngine;
        de = de.wrappedJSObject || de;
        this.setAttrs(menu, de, `Искать в ${de.name} или в ...`);
        menu.ePopup.textContent = "";
        for(let engine of await this.getEngines()) {
            if (engine == de) continue;
            var menuitem = document.createXULElement("menuitem");
            menuitem.className = "menuitem-iconic";
            this.setAttrs(menuitem, engine);
            menu.ePopup.append(menuitem);
        }
        this.popupshowing = this.handler;
        Services.obs.addObserver(this, this.topic, false);
        Services.prefs.addObserver(this.hide, this);
    },
    setAttrs(node, engine, label = engine.name) {
        node.engine = engine;
        node.setAttribute("label", label);
        node.setAttribute("image", engine._iconURI ? engine._iconURI.spec : engine.iconURI ? engine.iconURI.spec : this.defaultImg);
    },
    observe() {
        this.popupshowing = this.handlerRebuild;
        Services.obs.removeObserver(this, this.topic);
        Services.prefs.removeObserver(this.hide, this);
    },
    search(e) {
        var {engine} = e.target;
        if (!engine) return;
        var searchSelect = this.searchSelect;
        var submission = engine.getSubmission(
            searchSelect.searchTerms, null, "contextmenu"
        );
        if (submission) {
            let tab = gBrowser.addTab(submission.uri.spec, {
                postData: submission.postData,
                index: (gBrowser.selectedTab._tPos + 1),
                triggeringPrincipal: searchSelect.principal
            });
            if (e.button == 0)
                gBrowser.selectedTab = tab;
        }
        var popup = this.popup;
        e.button != 1 && popup.state == "open" && popup.hidePopup();
    }
}).init(this);


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

Отсутствует

 

№123119-02-2024 19:18:10

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

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

egorsemenov06 пишет

А с первой не поможите?

Это баг 1872673 - Remove 'console' export from Console.sys.mjs
То есть, дело не в коде кнопки, а в само́м UCF.


Но держать отладочный консольский стафф в кнопке постоянно
не требуется, можешь просто удалить console.log(req)


Однако, вернуть в укфский сандбокс консоль не помешает.
Я тут в user_chrome.js так переставлял

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

Выделить код

Код:

/*
                if ("defineLazyModuleGetters" in XPCOMUtils)
                    XPCOMUtils.defineLazyModuleGetters(scope, {
                        console: "resource://gre/modules/Console.jsm",
                        AddonManager: "resource://gre/modules/AddonManager.jsm",
                        AppConstants: "resource://gre/modules/AppConstants.jsm",
                        E10SUtils: "resource://gre/modules/E10SUtils.jsm",
                        FileUtils: "resource://gre/modules/FileUtils.jsm",
                        OS: "resource://gre/modules/osfile.jsm",
                        PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
                        setTimeout: "resource://gre/modules/Timer.jsm",
                        setTimeoutWithTarget: "resource://gre/modules/Timer.jsm",
                        clearTimeout: "resource://gre/modules/Timer.jsm",
                        setInterval: "resource://gre/modules/Timer.jsm",
                        setIntervalWithTarget: "resource://gre/modules/Timer.jsm",
                        clearInterval: "resource://gre/modules/Timer.jsm",
                    });
*/
                var data = {
                    AddonManager: null, AppConstants: null, E10SUtils: null, FileUtils: null, PlacesUtils: null,
                    Timer: ["setTimeout", "setTimeoutWithTarget", "clearTimeout", "setInterval", "setIntervalWithTarget", "clearInterval"]
                };
                var sfx, def, modules = {};
                var vers = parseInt(Services.appinfo.platformVersion);
                if (vers <= 114) data.osfile = "OS";
                if (vers <= 122) def = XPCOMUtils.defineLazyModuleGetters, sfx = "jsm", data.Console = "console";
                else def = ChromeUtils.defineESModuleGetters, sfx = "sys.mjs",
                    ChromeUtils.defineLazyGetter(scope, "console", () => Cu.getGlobalForObject(Cu).console.createInstance());
                var set = (key, val) => modules[key] = `resource://gre/modules/${val}.${sfx}`;
                for(var key in data) {
                    var val = data[key] || key;
                    if (Array.isArray(val)) for(var str of val) set(str, key);
                    else set(val, key);
                }
                def(scope, modules);

Отсутствует

 

№123219-02-2024 21:43:04

b0ttle
Участник
 
Группа: Members
Зарегистрирован: 22-10-2020
Сообщений: 182
UA: Firefox 122.0

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

В шапке бы поправить ссылку на рабочую - "Восстановить фавиконки закладок".
Похож чем-то, с тем что выше. Тоже рабочий, пользуюсь. ucf_contextsearch.js
Да они идентичны, с мелкими различиями в коде)

Отредактировано b0ttle (19-02-2024 21:44:24)

Отсутствует

 

№123319-02-2024 22:12:42

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

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

b0ttle пишет

В шапке бы поправить ссылку

На этом форуме нет шапок, есть только первый пост, посему это могут сделать либо создатель либо модератор...

b0ttle пишет

Да они идентичны, с мелкими различиями в коде)

Если у вас все работает,

b0ttle пишет

Тоже рабочий, пользуюсь. ucf_contextsearch.js

пользуйтесь... Речь шла про 1945 год, ой про 123 найди различия...

Отредактировано Farby (19-02-2024 22:22:14)


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

Отсутствует

 

№123419-02-2024 23:25:44

b0ttle
Участник
 
Группа: Members
Зарегистрирован: 22-10-2020
Сообщений: 182
UA: Firefox 122.0

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

Farby
Сорри, этот момент упустил. Вы его сами подправили, вроде разбирайтесь в коде?
Надеюсь, что обновят некоторые ссылки с первого поста, а так скорее затеряется.

Отредактировано b0ttle (19-02-2024 23:27:47)

Отсутствует

 

№123525-02-2024 06:52:58

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

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

b0ttle пишет

В шапке бы поправить ссылку на рабочую - "Восстановить фавиконки закладок".

Раз это не в скрипте проблема, шапку пока не менял.


Dumby пишет

Это баг 1872673 - Remove 'console' export from Console.sys.mjs
То есть, дело не в коде кнопки, а в само́м UCF.

Dumby - Благодарю! :beer:
Обновил на гитхабе chrome/user_chrome_files/user_chrome.js
в Demo-профиле - сборке полезных скриптов немного поправил:
user_chrome.js, UcfPrefs.jsm, ucf_UrlTooltip, ucf_contextmenuopenwith, ucf_contextsearch, ucf_hookClicks

Отсутствует

 

№123625-02-2024 12:00:42

b0ttle
Участник
 
Группа: Members
Зарегистрирован: 22-10-2020
Сообщений: 182
UA: Firefox 123.0

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

Dobrov. Ура, ждал обновы)

Отсутствует

 

№123726-02-2024 08:26:11

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

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

Dobrov пишет

Раз это не в скрипте проблема

Кстати, скрипт под багом ходит (1552815).
Движуха там затихла, но в любой момент это дело могут пнуть,
и баг вывалится как "FIXED". Прикинь тогда разгребать.

.jsm

А вот и баг о временах и сроках.


Может завести какую-нибудь папку с любым условным названием типа «129».
Запилить на неё readme, мол здесь вам (пока) не что-то готовое,
но всего лишь WIP-полигон миграции JSM —> ESM.


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

Отсутствует

 

№123827-02-2024 15:22:40

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

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

Dumby пишет

.jsm
А вот и баг о временах и сроках.

когда JSM уберут, то UCF практически перестанет работать!
Я не осилю добавить ESM в UCF-user_chrome.js и в CustomStylesScripts.jsm загрузчик скриптов/стилей…

Отсутствует

 

№123927-02-2024 16:19:42

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

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

Dobrov пишет

Я не осилю добавить ESM

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


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

Отсутствует

 

№124028-02-2024 12:36:01

Northtech
Участник
 
Группа: Members
Зарегистрирован: 16-04-2011
Сообщений: 261
UA: Firefox 123.0

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

Dobrov
есть возможность сделать в ucf_contextsearch.js открытие вкладки поиска фоном? Или зависящим от этой настройки: user_pref("browser.search.context.loadInBackground", true);

Отсутствует

 

№124129-02-2024 01:50:06

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

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

Northtech пишет

есть возможность сделать в ucf_contextsearch.js открытие вкладки поиска фоном? Или зависящим от этой настройки: user_pref("browser.search.context.loadInBackground", true);

Поиск и так открывается в фоновой вкладке по клику правой кнопкой или колёсиком на любых строках меню и подменю.

Отредактировано Dobrov (29-02-2024 01:51:11)

Отсутствует

 

№124229-02-2024 05:12:23

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

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

egorsemenov06
Я так понял. Когда накроется jsm, отвалится весь UCF. Куда Вы будете эти кнопки писать, если CustomStylesScripts.jsm не будет работать? Или пересаживаться на старую версию версию UCF?

Отредактировано xrun1 (29-02-2024 05:31:45)

Отсутствует

 

№124329-02-2024 06:06:58

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

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

Dumby возникла хотелка для менюшки кнопки, которую я немного доработал.


это меню создаётся однократно и перед кликом на кнопке его не существует, т.е. однократно выполняется menu.render = this.render;
Нужно, чтоб менялись строки меню перед его открытием в зависимости от опций about:config и прочих проверок, например "Графика сайтов включена" вместо "Графика сайтов вкл/выкл"


Прошу доработать код, чтоб ключи «lab» могли быть с backticks-кавычками и текст мог обновляться перед каждым открытием меню:
lab: `${проверка условия ? "√ Да, всё OK" : "Х Нет"}`

Автономное меню для тех, кому не нужен ucf_hookClicks.js

Выделить код

Код:

(async id => { // by Dumby forum.mozilla-russia.org/viewtopic.php?pid=807581#p807581

MyMenu = { //массив команд пользователя, alt() клик правой кнопкой
	Pics: {
		lab: `Графика сайтов вкл/выкл | Right Click`,
		inf: 'текст обновляется перед открытием меню',
		cmd(){
			var n = uc.pref(E.v) == 2; uc.pref(E.v, n ? 1 : 2);
			BrowserReload();
		},
		alt(){ /* для этих действий нужен ucf_hookClicks.js */},
	},
	"Прочие команды": { sep: 1, //сперва разделитель
		cmd(){console.log("OK");}
	},
}

CustomizableUI.createWidget({
		id: id, label: id, tooltiptext: id, localized: false,
		defaultArea: CustomizableUI.AREA_NAVBAR,
		onCreated(btn) {
			btn.style.setProperty("list-style-image", "url(chrome://branding/content/icon32.png)");
			btn.type = "menu";
			var doc = btn.ownerDocument, m = nn => doc.createXULElement(nn);
			var popup = m("menupopup"), menu = m("menuitem");
			menu.m = m;
			menu.fill = this.fill;
			menu.render = this.render;
			popup.append(menu);
			btn.prepend(popup);
		},
		render(){
			var popup = this.parentNode;
			this.remove();
			this.fill(MyMenu, popup);
		},
		fill(o, popup){
			if (typeof o == "object") for (key in o){
			var {lab, sep, sub, cmd, alt, inf, img} = o[key];
			var name = sub ? "menu" : "menuitem";
			sep && popup.append(this.m("menuseparator"));
			var item = this.m(name);
			item.setAttribute("label", lab || key); //update при изменении настроек
			if (img)
				item.className = name +"-iconic", item.setAttribute("image",img);
			if (inf) item.tooltipText = inf;
			item.alt = alt; //cmd2
			sub || cmd && item.setAttribute("oncommand", cmd.toString().replace(/cmd\(.*?\){/,'{var trg = event.target || event;'));
			/^(sub|sep|inf|lab|img)$/.test(key) || popup.append(item);
			sub && this.fill(o[key], item.appendChild(this.m("menupopup")));
			}
		},
});

E = {
	v: "permissions.default.image"
}
window.uc = { //all ChromeOnly-scripts
	pref(key,set){ //или key = [key,default]
		if (!Array.isArray(key)) key = [key];
		var t = prefs.getPrefType(key[0]), m = {b:"Bool",n:"Int",s:"String"};
		t = m[t == 128 ? "b" : t == 64 ? "n" : t == 32 ? "s" : ""];
		if (set == "get") return t; //тип опции
		if (!t) t = m[set != undefined ? (typeof set)[0] : (typeof key[1])[0]];
		if (t) if (set != undefined)
			prefs[`set${t}Pref`](key[0],set)
		else
			set = prefs[`get${t}Pref`](...key);
		return set;
	}
}

})("ucf_test_menu");


xrun1 я просто останусь на старой версии браузера, как это делает Dumby (у него вроде FF78)

Отсутствует

 

№124429-02-2024 15:21:27

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

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

egorsemenov06 пишет

Ссылки кликабельны

Здесь можно переделать. Переименовать UcfTextToLinkActorChild.{ jsm —> mjs } и правки

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

В text-to-link.js

Выделить код

Код:

/*
                    moduleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.jsm",
*/
                    esModuleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.mjs"

В UcfTextToLinkActorChild.mjs

Выделить код

Код:

/*
var EXPORTED_SYMBOLS = ["UcfTextToLinkActorChild"];
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["NodeFilter", "Node"]);
XPCOMUtils.defineLazyGetter(this, "excludedTags", () => {
    return new Set(["a","svg","canvas","applet","input","button","area","embed","noembed","frame","frameset","head","iframe","img","select","option","datalist","map","meta","noscript","video","audio","object","param","script","style","textarea","code"]);
});

class UcfTextToLinkActorChild extends JSWindowActorChild {
*/
var excludedTags = Object.defineProperty({}, "has", {
    value: tag => (excludedTags = new Set([
        "a","svg","canvas","applet","input","button","area","embed","noembed","frame","frameset","head","iframe","img",
        "select","option","datalist","map","meta","noscript","video","audio","object","param","script","style","textarea","code"
    ])).has(tag)
});

export class UcfTextToLinkActorChild extends JSWindowActorChild {

переключение раскладки клавиатуры по F8

Для этого кода нужен дебаггер.
В UCF 3 вообще необходимо встраивать дебаггер,
не городить же в каждом скрипте, где он нужен, свой собственный.


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

special_widgets.js

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

и еще одна

Здесь можно попробовать влепить что-нибудь такое,
тогда, надеюсь, не будет импорта никаких jsm'ок.

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

Выделить код

Код:

/*
	try {
*/
	if(Components.interfaces.nsIWebTransportHash) { // random, Fx 123+
		var func = function() {
			func = false;
		}
		var thread = Services.tm.currentThread;
		var meth = newDis ? "disable" : "enable";
		addon[meth]({allowSystemAddons: true}).finally(func);
		while(func) thread.processNextEvent(true);
	}
	else try {


Dobrov пишет

немного доработал

Ничего себе «немного». Как там задумана обработка
структуры MyMenu я сходу понять не могу, субменю вообще в примере нет.


Ну хорошо хоть вопрос не об этом.
Добавил туда var {prefs} = Services; и заработало.


Можно ввести ещё один ключ — upd
который будет представлять собой функцию,
которая перекроет метод render() для item'а.


Ключевое слово this в этой функции будет ссылаться на сам item.
Например, вместо lab и inf пишем:


upd() {
        //var {uc, E} = this.ownerGlobal;
        var val = uc.pref(E.v);
        this.label = `${E.v} is ${val == 1 || val == 2 ? val : "not 1 and not 2"}`;
        this.tooltipText = val;
},


Далее, учитываем новый ключ в var {lab, sep, sub, cmd, alt, inf, img, upd} = o[key];
И дописываем подмену после добавления item'а в popup:
/^(sub|sep|inf|lab|img)$/.test(key) || popup.append(item) || upd && (item.render = upd).call(item);


Однако, хоть lab и убран, код тогда всё равно проставляет вместо него label — key,
а upd() уже затем ставит свой. Это слегка нехорошо, но тут уж думай сам, или забей.

Отсутствует

 

№124529-02-2024 15:59:36

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

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

Dumby пишет

Ничего себе «немного». Как там задумана обработка структуры MyMenu я сходу понять не могу, субменю вообще в примере нет.

Спасибо за помошь! :beer:
P.S. Массив вместе с субменю есть в ucf_hookClicks.js, вложенность любая.

Отсутствует

 

№124601-03-2024 16:45:40

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

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

Dobrov пишет

Массив вместе с субменю есть в ucf_hookClicks.js, вложенность любая.

Да, теперь чуть понятнее, наверно.
А то я думал, к чему это /^(sub|sep|inf|lab|img)$/.test(key)


Оказывается, что если вписан sub, код прогоняет через for in
объект в который вписан sub.
То есть, и для ключей, упомянутых в этом регулярном выражении
тоже создаётся (ненужный) элемент (как минимум <menuitem>)
и ему присваивается одноимённый атрибут "label".


Если значение ключа окажется строкой, то тогда создаётся не <menuitem>,
а <menu>, и создаётся <menupopup>, который добавляется к этому menu.
Всё потому, что у строки есть sub.
Вот проверь с консоли: var {sub} = "bla-bla"; alert(sub);
Это будет — String.prototype.sub().


Эти ненужные элементы можно посмотреть в консоли,
если добавить в конец метода fill() строку
if (!item.parentNode) console.log(item.outerHTML);


Вот чтобы всё это низачем-созданное добро
не попало в итоговую DOM-структуру и нужен этот regexp.
Может этого как-то избежать, типа

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

Выделить код

Код:

//
	fill(o, popup) {
		for (key in o) {
			var val = o[key];
			if (typeof val != "object") continue;

			var {lab, sep, sub, cmd, alt, inf, img, upd} = val;

			sep && popup.append(this.m("menuseparator"));
			var name = sub ? "menu" : "menuitem";
			var item = this.m(name);

			item.setAttribute("label", lab || key);
			if (img)
				item.className = name + "-iconic",
				item.setAttribute("image", img);

			item.alt = alt; //cmd2
			if (inf) item.tooltipText = inf;
			sub || cmd && item.setAttribute("oncommand", cmd.toString().replace(
				/cmd\(.*?\){/, "{var trg = event.target || event;"
			));
			popup.append(item);
			upd && (item.render = upd).call(item);
			sub && this.fill(val, item.appendChild(this.m("menupopup")));
		}
	},

egorsemenov06 пишет

сделайте пожалуйста из этих 2-х

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

Выделить код

Код:

// Switch Keyboard Layout
(async keybUtils => CustomizableUI.createWidget(({
	localized: false,
	id: "SwitchKeyboardLayout",
	init() {
		this.label = this.tooltiptext = "Switch Keyboard Layout";
		var args = ["keydown", e => {
			if (e.key != "F8" || e.ctrlKey || e.shiftKey || e.altKey || e.repeat) return;
			//e.preventDefault();
			//e.stopPropagation();
			this.switch(e.view.document);
		}, true];
		var unload = e => e.target.ownerGlobal.removeEventListener(...args);
		var obs = win => {
			win.addEventListener(...args);
			win.addEventListener("unload", unload, {once: true});
		}
		var topic = "browser-delayed-startup-finished";
		Services.obs.addObserver(obs, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(quit, t);
			Services.obs.removeObserver(obs, topic);
		}, "quit-application-granted");
		return this;
	},
	onCreated(btn) {
		btn.linkedObj = this;
		btn._handleClick = this.click;
		btn.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAk1BMVEX///8/Pz8BAQF8fHwJCQkCAgIJCQl8fHx9fX0AAABJSUkBAQENDQ0wMDBVVVUAAABra2t0dHR7e3thYWEBAQEAAAAAAAABAQEAAAAgICABAQEBAQH8/Pzw8PDp6en39/fj4+Pe3t41V9I/YeWKioqDg4N9fX0jRa8wUrVoaGhkhuxWeNx1dXVCZMhvb28kRqsqTL4KidXxAAAAHHRSTlMAAABndwAAAAA0blVZcm1naWhNa6hrcJ8AAKRU4jk/3gAAAHVJREFUeF6FyMUCwjAUBdEbaQupUMOjqMv/fx1dQN6yZ3aDcWnyw6ezoRWNYc15kqKQZCFlgTKQQwgllL/dn5f3+bPb+6P3CpWNw56srdCZOMzDmA61i8O9nKvRaHLVukEryFKIFtnkj7ENYxmNdd5v+5xj1BcJ/w9Kj6K7ZAAAAABJRU5ErkJggg==";
	},
	click() {
		this.linkedObj.switch(this.ownerDocument);
	},
	switch(doc) {
		var br = doc.activeElement;
		br && br.localName == "browser" && br.isRemoteBrowser
			? br.messageManager.loadFrameScript(this.url, false)
			: this.keybUtils.switchSelKeybLayout();
	},
	get url() {
		delete this.url;
		return this.url = `data:;charset=utf-8,(${
			encodeURIComponent(keybUtils)
		}).switchSelKeybLayout()`;
	},
	get keybUtils() {
		delete this.keybUtils;
		var def = "let{KeyEvent,HTMLInputElement,HTMLTextAreaElement}=Cu.getGlobalForObject(Services);";
		var url = `data:;charset=utf-8,${def}%0Athis.keybUtils=${encodeURIComponent(keybUtils)}`;
		Services.scriptloader.loadSubScript(url, this);
		var {id} = this;
		this.keybUtils.getFocusedElement = function(_subCall, _focusFixed) {
			var window = Services.focus.activeWindow, {document} = window;
			var button = document.getElementById(id);
			if(
				!_focusFixed
				&& "closeMenus" in window
				&& document.commandDispatcher.focusedElement == button
			) {
				window.closeMenus(button);
				window.setTimeout(function(_this) {
					_this.switchSelKeybLayout(_subCall, true);
				}, 0, this);
				return;
			}
			return document.commandDispatcher.focusedElement;
		}
		return this.keybUtils;
	}
}).init()))(`{
	//== Options
	noSelBehavior:
		"BeginLine",
		//"EndLine",
		//"All",
		//"Top",
		//"Bottom",
		//"PageUp",
		//"PageDown",
		// etc

	// falsy - do nothing
	// Or use string like following to call cmd_select{string}

	convTableForward: { // ru -> en
		"\\"": "@",
		":": "^",
		";": "$",
		"?": "&",
		",": "?",
		"/": "|",
		".": "/",
		"э": "'",
		"б": ",",
		"ю": ".",
		"Ж": ":",
		"ж": ";",
		"Б": "<",
		"Ю": ">",
		"Э": "\\"",
		"х": "[",
		"ъ": "]",
		"ё": "\`",
		"Х": "{",
		"Ъ": "}",
		"Ё": "~",
		"№": "#",
		"Ф": "A",
		"ф": "a",
		"И": "B",
		"и": "b",
		"С": "C",
		"с": "c",
		"В": "D",
		"в": "d",
		"У": "E",
		"у": "e",
		"А": "F",
		"а": "f",
		"П": "G",
		"п": "g",
		"Р": "H",
		"р": "h",
		"Ш": "I",
		"ш": "i",
		"О": "J",
		"о": "j",
		"Л": "K",
		"л": "k",
		"Д": "L",
		"д": "l",
		"Ь": "M",
		"ь": "m",
		"Т": "N",
		"т": "n",
		"Щ": "O",
		"щ": "o",
		"З": "P",
		"з": "p",
		"Й": "Q",
		"й": "q",
		"К": "R",
		"к": "r",
		"Ы": "S",
		"ы": "s",
		"Е": "T",
		"е": "t",
		"Г": "U",
		"г": "u",
		"М": "V",
		"м": "v",
		"Ц": "W",
		"ц": "w",
		"Ч": "X",
		"ч": "x",
		"Н": "Y",
		"н": "y",
		"Я": "Z",
		"я": "z",
		__proto__: null
	},
	//== End of options

	get convTableBackward() {
		var ctb = { __proto__: null };
		var ctf = this.convTableForward;
		for(var c in ctf)
			ctb[ctf[c]] = c;
		delete this.convTableBackward;
		return this.convTableBackward = ctb;
	},
	inPrimaryLayout: function(s) {
		for(var i = 0, l = s.length; i < l; ++i) {
			var c = s.charAt(i);
			var primary = c in this.convTableForward;
			if(primary ^ c in this.convTableBackward)
				return primary;
		}
		return false;
	},
	switchKeybLayout: function(s, convTable) {
		var res = "";
		for(var i = 0, l = s.length; i < l; ++i) {
			var c = s.charAt(i);
			res += c in convTable ? convTable[c] : c;
		}
		return res;
	},
	getFocusedElement: function() {
		return Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
			.getFocusedElementForWindow(content, true, {});
	},
	switchSelKeybLayout: function(_subCall, _focusFixed) {
		var fe = this.getFocusedElement(_subCall, _focusFixed);
		if(!fe)
			return;
		if(HTMLInputElement.isInstance(fe) || HTMLTextAreaElement.isInstance(fe)) {
			var ta = fe;
			try {
				var val = ta.value;
				var sel = val.substring(ta.selectionStart, ta.selectionEnd);
			}
			catch(e) { // Non-text HTMLInputElement
				return;
			}
			if(!sel && val && this.noSelBehavior && !_subCall) {
				if(this.noSelBehavior == 1) {
					ta.selectionStart = 0;
					ta.selectionEnd = val.length;
					sel = val;
				}
				else {
					this.handleNoSel(ta);
					return;
				}
			}
			if(!sel)
				return;
			var res = this.switchKeybLayout(
				sel,
				this.inPrimaryLayout(sel)
					? this.convTableForward
					: this.convTableBackward
			);
			if(res != sel)
				this.insertText(ta, res);
		}
		else if(fe.contentEditable == "true") {
			var doc = fe.ownerDocument;

			var docURI = doc.documentURI;
			if(
				docURI.substr(0, 5) == "data:"
				&& docURI.indexOf("chrome://browser/skin/devtools/") != -1
			) {
				//~ todo: seems like we only can use paste from clipboard here...
				return;
			}

			var sel = doc.defaultView.getSelection();
			var rng = sel.rangeCount && sel.getRangeAt(0);
			var tmpNode;
			if(!rng || rng.collapsed) {
				if(!this.noSelBehavior || _subCall)
					return;
				if(this.noSelBehavior == 1) {
					var r = doc.createRange();
					r.selectNodeContents(fe);
					sel.removeAllRanges();
					sel.addRange(r);
					tmpNode = fe.cloneNode(true);
				}
				else {
					this.handleNoSel(fe);
					return;
				}
			}
			else {
				tmpNode = doc.createElementNS("http://www.w3.org/1999/xhtml", "div");
				tmpNode.appendChild(rng.cloneContents());
			}

			var orig = tmpNode.innerHTML;
			var convTable = this.inPrimaryLayout(tmpNode.textContent)
				? this.convTableForward
				: this.convTableBackward;

			var _this = this;
			var parseChildNodes = function(node) {
				if(Element.isInstance(node)) {
					var childNodes = node.childNodes;
					for(var i = childNodes.length - 1; i >= 0; --i)
						parseChildNodes(childNodes[i]);
				}
				else if(node.nodeType == node.TEXT_NODE) {
					var text = node.nodeValue;
					var newText = _this.switchKeybLayout(node.nodeValue, convTable);
					if(newText != text)
						node.parentNode.replaceChild(doc.createTextNode(newText), node);
				}
			}
			parseChildNodes(tmpNode);

			var res = tmpNode.innerHTML;
			if(res != orig)
				doc.execCommand("insertHTML", false, res);
		}
	},
	handleNoSel: function(node) {
		this.select(node);
		this.switchSelKeybLayout(true);
	},
	select: function(node) {
//		var e = this.noSelBehavior;
//		if(!e || typeof e != "object")
//			return;
//		var evt = node.ownerDocument.createEvent("KeyboardEvent");
//		evt.initKeyEvent(
//			"keypress", true /*bubbles*/, true /*cancelable*/, node.ownerDocument.defaultView,
//			e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
//			e.keyCode, e.charCode
//		);
//		node.dispatchEvent(evt);

	   var beh = this.noSelBehavior;
	   beh && node.ownerGlobal.docShell.doCommand("cmd_select" + beh);
	},
	beh2cmd: { // Ctrl_Shift_VK
		false_true_36: "cmd_selectLinePrevious", // Shift+Home
	},
	insertText: function(ta, text) {
		//var editor = ta.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor
		var editor = ta.editor
			.QueryInterface(Components.interfaces.nsIPlaintextEditor || Ci.nsIEditor);
		if(editor.flags & editor.eEditorReadonlyMask)
			return;

		var sTop = ta.scrollTop;
		var sHeight = ta.scrollHeight;
		var sLeft = ta.scrollLeft;
		// var sWidth = ta.scrollWidth;

		if(text)
			editor.insertText(text);
		else
			editor.deleteSelection(0, 0);

		ta.scrollTop = sTop + (ta.scrollHeight - sHeight);
		ta.scrollLeft = sLeft; // + (ta.scrollWidth - sWidth);
	}
}`);

Отсутствует

 

№124702-03-2024 02:34:07

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

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

Dumby пишет

Оказывается, что если вписан sub, код прогоняет через [for in] объект в который вписан sub.
То есть, и для ключей, упомянутых в этом регулярном выражении тоже создаётся (ненужный) элемент (как минимум <menuitem>)

Спасибо! Я делал так же: (обработать только объект), но результат разный:
for (key in o) { if (typeof o[key] != "object") continue; // Dumby
if (typeof o == "object") for (key in o){ // Dobrov


Dumby пишет

Всё потому, что у строки есть sub. Вот проверь с консоли: var {sub} = "bla-bla"; alert(sub);
Это будет — String.prototype.sub().

Исправил свой код менюшки и убрал имя переменной sub.
Но тогда js-код для var {sub} работает нелогично, ведь var {lab} = "bla-bla"; alert(lab); (и другие имена) возвращают «undefined» !

Отредактировано Dobrov (02-03-2024 02:48:48)

Отсутствует

 

№124803-03-2024 01:03:06

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 124.0

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

UserChromeFiles обнова https://github.com/VitaliyVstyle/Vitali … hromeFiles
На старых версиях [firefox] работать не будет т. к.
ESM, CSS3, Fluent (для локализации, пока добавленно три языка en-US, uk, ru)

Отсутствует

 

№124903-03-2024 01:54:42

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

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

Vitaliy V.
Спасибо! А одним архивом можно сделать? Или я не нашёл...:(

Отсутствует

 

№125003-03-2024 06:00:33

Viatcheslav
Участник
 
Группа: Members
Откуда: г. Бобруйск, Беларусь
Зарегистрирован: 23-11-2016
Сообщений: 320
UA: Firefox 115.0

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

xrun1 пишет

А одним архивом можно сделать? Или я не нашёл...:(

А он есть ;)
https://github.com/VitaliyVstyle/VitaliyVstyle.github.io/blob/main/UserChromeFiles/UserChromeFiles.zip

Отсутствует

 

Board footer

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