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

Многие проблемы быстрее решаются поиском по форуму и чтением FAQ, чем созданием новой темы и томительным ожиданием ответа.

№120123-11-2023 21:18:29

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

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

all
В общем, в config.js заработал. Всем спасибо.

Отсутствует

 

№120226-11-2023 16:22:09

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

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

Нельзя тут как-то добавить PanelUI-menu-button, чтобы он тоже мог переноситься? Пробовал, что-то не выходит. И что за кнопка alltabs-button, все время забываю?

config.js

Выделить код

Код:

// https://forum.mozilla-russia.org/viewtopic.php?pid=806232#p806232 806233#p806233
// установить для кнопок #alltabs-button и #unified-extensions-button атрибут "removable" как "true"
(async topic => {
	var obs = doc => {
		doc.getElementById("alltabs-button")?.setAttribute("removable", true);
		doc.getElementById("unified-extensions-button")?.setAttribute("removable", true);
		doc.getElementById("PanelUI-menu-button")?.setAttribute("removable", true);
	}
	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");
})("chrome-document-interactive");


upd: fuchsfan, a точно;) Спасибо.

Отредактировано b0ttle (26-11-2023 21:11:23)

Отсутствует

 

№120326-11-2023 17:56:56

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 121.0

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

b0ttle пишет

И что за кнопка alltabs-button, все время забываю?

Видимо, это кропка справа сверху в виде стрелки вниз ˅, при клике на ней покажет список открытых табов.

Отсутствует

 

№120428-11-2023 09:29:38

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

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

Скрипт перехвата кликов-нажатий ucf_hookClicks.js — небольшие добработки и устранение ошибок:


1) Вернул сочетания кнопок мыши на вкладках и кнопке «Новая вкладка» — описание во всплывающих подсказках.
2) разблокировка перемещения #unified-extensions-button
3) добавлена команда alt в Меню пользователя. На строке «Закладка первая/последняя» клик правой кнопкой откроет последнюю ссылку.
В блоке «Menu = [{…» cmd имеет приоритет и сработает на клик колёсика или левой кнопки.
для alt возможны любые клики + управляющие клавиши (cmd при этом лучше убрать), пример есть в Mouse = {…B[6]…256 … btn.alt(btn)
4) Меню пользователя открывается колёсиком по кнопке «Быстрые опции» и правым кликом мыши на кнопке «Расширения» unified-extensions-button


В ucf_hookClicks треть объёма занимают блоки данных, которые можно менять «под себя»
Keys: нажатия клавиш, Menu: команды пользователя, Mouse: клики мыши, Setup быстрые опции.

Отредактировано Dobrov (28-11-2023 10:40:05)

Отсутствует

 

№120528-11-2023 15:32:28

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

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

Dobrov. Интересно сделано "настройки UCF", в плане тултипа.
upd: Dumby, круто. Спасибо.

Отредактировано b0ttle (30-11-2023 14:36:56)

Отсутствует

 

№120630-11-2023 11:56:36

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

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

Прошу прощения, я тут отсутствовал какое-то время.


egorsemenov06 пишет

Dumby посмотрите пожалуйста код кнопки в ней тусклая иконка если svg.context-properties.content.enabled стоит в false

Конкретный цвет можно прямо в SVG'шке указать, там, где stroke


А если надо чтобы context-properties подхватывались,
то можно сменить протокол

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

Выделить код

Код:

/*
                bt.image = img;
*/
                var subst = this.id + "-svg-image";
                Services.io.getProtocolHandler("resource")
                    .QueryInterface(Ci.nsIResProtocolHandler)
                    .setSubstitution(subst, Services.io.newURI(img));
                var url = `resource://${subst}/`;
                (this.onCreated = btn => btn.image = url)(bt);

b0ttle пишет

Нельзя тут как-то добавить PanelUI-menu-button, чтобы он тоже мог переноситься?

Эта кнопка не сама по себе, а в составе родительского <toolbaritem>'а,
наверно лучше их не разлучать.
А сам toolbaritem находится за пределами кастомизационных зон,
поэтому только просто устанавливать ему атрибут "removable" бесполезно.


Можно попробовать регистрировать его как "custom" виджет,
а вместо создания подсовывать существующий.
Типа в custom_script.js

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

Выделить код

Код:

(async id => CustomizableUI.createWidget({
	id,
	type: "custom",
	localized: false,
	defaultArea: CustomizableUI.AREA_NAVBAR,
	onBuild(doc) {
		var item = doc.getElementById(id);
		item.setAttribute("removable", true);
		return item;
	}
}))("PanelUI-button");

Отсутствует

 

№120730-11-2023 18:18:36

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

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

Скрипт ucf_hookClicks.js — изменил меню пользователя, чтобы проще подключать команды, устранил пару ошибок.
Справка по жестам мыши создаётся автоматически в ucf_mousedrag.js, и добавленные вами жесты тоже видны:
Меню пользователя > Правый клик по строке "Краткая справка | Жесты мыши"


обновлены скрипты: ucf_hookClicks.js ucf_mousedrag.js SingleHTML.jsm ClickPicSave.jsm и файлы профиля: prefs.js custom_styles_all_user.css userChrome.css userChrome_macosx.css
Firefox-Menu-Expert.png
Dumby - с возвращением!

Отредактировано Dobrov (30-11-2023 18:35:29)

Отсутствует

 

№120802-12-2023 06:09:03

iG0R
Участник
 
Группа: Members
Зарегистрирован: 15-08-2015
Сообщений: 48
UA: Firefox 120.0

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

Dobrov
Доброго времени суток.
Возможно ли убрать лишнюю разграничительную линию (на скриншоте), которая появляется при работе ucf_contextsearch.js?

Extra-line-when-running-ucf-contextsearch-js.png

Отсутствует

 

№120902-12-2023 06:52:31

iG0R
Участник
 
Группа: Members
Зарегистрирован: 15-08-2015
Сообщений: 48
UA: Firefox 120.0

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

Dobrov
И еще один вопрос.
Подскажите, от чего зависит стиль начертания шрифта (обычный, наклонный) и его цвет в быстрых настройках ucf_hookClicks.js?
Например, я добавил свой пункт "Unblock addons.mozilla.org"

Выделить код

Код:

pref: ["privacy.resistFingerprinting.block_mozAddonManager","Unblock addons.mozilla.org",,"Enables scripts & addons to run on the addons.mozilla.org page"], Def3el: true, refresh: true,
keys: [[true, "Unblock"], [false, "Block (default)"]]

он один в один повторяет "Выполнять скрипты Java"

Выделить код

Код:

pref: ["javascript.enabled", "Выполнять скрипты Java",,"Поддержка интерактивных сайтов, рекламы\nтакже разрешает действия горячих клавиш"], Def3el: true, refresh: true,
keys: [[true, "Да"], [false, "Нет"]]

но у моего пункта, почему-то, стиль шрифта наклонный, в отличие пункта с обычным шрифтом у "Выполнять скрипты Java".

Differences-in-menu-items-fonts-in-ucf-hook-Clicks-js.png

Отсутствует

 

№121002-12-2023 13:16:20

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

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

iG0R

custom_styles_all_user.css

Выделить код

Код:

#frame-sep{display:none!important;} //#context-sep-selectall


Выберите что-то одно. Подсмотреть id можно через Attributes-Inspector, судя по тому, что у вас ucf_hookClicks.js. Там идет отдельным файлом Attributes-Inspector.js, а код кнопка уже встроена в ucf_hookClicks.js. Есть способ без ничего, Ctrl+Alt+Shift+I > pick. Тема "настройка внешнего вида". Насчет другого, не в курсе. Может потом посмотрю.

Отсутствует

 

№121102-12-2023 13:23:57

iG0R
Участник
 
Группа: Members
Зарегистрирован: 15-08-2015
Сообщений: 48
UA: Firefox 120.0

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

b0ttle
Спасибо.
Я это уже сделал через userChrome.css

Выделить код

Код:

#context-sep-selectall {
	display: none !important;
}

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

Отсутствует

 

№121202-12-2023 13:36:58

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

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

iG0R. Так не бывает) Как это, без лишних движений?
У меня обычный шрифт, может не так вписали?

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

Выделить код

Код:

Setup = [
{
	pref: ["privacy.resistFingerprinting.block_mozAddonManager","Unblock addons.mozilla.org",,"Enables scripts & addons to run on the addons.mozilla.org page"], Def3el: true, refresh: true,
	keys: [[true, "Unblock"], [false, "Block (default)"]]
},null,
{ // быстрые настройки. есть Def3el: несовпадения выделяются
	pref: ["dom.disable_open_during_load", "Всплывающие окна"], Def3el: true, Yellow: false,
	keys: [[true, "Блокировать"], [false, "Разрешить"]],

Отредактировано b0ttle (02-12-2023 13:44:09)

Отсутствует

 

№121302-12-2023 13:46:37

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

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

iG0R пишет

Подскажите, от чего зависит стиль начертания шрифта (обычный, наклонный) и его цвет в быстрых настройках ucf_hookClicks.js?

Иконка зелёная или серая и шрифт обычный - значит опция в значении по-умолчанию, для вашей настройки это false.
Цвет других иконок задаётся для каждой строки подменю, например Blue ставлю, если опция изменена, но не критично. Пример всех цветов в строке: "Режим прокси"
если в pref:…… прописано значение для "Def3el", то текст будет красным, если опция не равна Def3el и не по-умолчанию. В новой версии скрипта вместо красного шрифта будет красный ореол текста.


По двойному разделителю в менюшке поиска не знаю, у меня на разных профилях этого нет.

Отредактировано Dobrov (02-12-2023 19:29:43)

Отсутствует

 

№121406-12-2023 16:33:30

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

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

Dumby, здравствуйте.
Может есть у Вас мысли, которые можно записать в виде скрипта. Но с начала немного о прошлом, есть три расширения в которых есть такой функционал это DownThemAll, Download Manager (S3) и совсем старинное Preserve Download Modification Timestamp. Все они умеют сохранять дату создания (брать дату с сервера) у скачиваемых файлов и присваивать конечному (скаченному). Даже существует по этому поводу Bug 733954, ему уже 12 лет. Так вот есть ли такая возможность реализовать для UCF?
-
Real UA: Mozilla/5.0 (Windows NT 10.0; Win64; x64;  rv:109.0) Gecko/20100101 Firefox/115.0


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

На форуме

 

№121507-12-2023 10:09:20

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

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

Farby пишет

умеют сохранять дату создания (брать дату с сервера) у скачиваемых файлов и присваивать конечному (скаченному)

В смысле присваивать как дату изменения?
Вроде как лиса не умееет присваивать файлам дату (именно) создания.


Я посмотрел как это сделано в S3, и, если правильно понял,
то там что-то типа такого (весьма упрощённый набросок),
но тестировать это мне особо негде.


В custom_script.js

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

Выделить код

Код:

(async (url, ...cc) => {
	var re = /^.*\//;
	var f = Components.Constructor(...cc);
	var setLastModified = (file, date) => {
		if (file.exists()) file.lastModifiedTime = date;
	}
	var {Downloads} = ChromeUtils.importESModule(url);
	(await Downloads.getList(Downloads.ALL)).addView({
		onDownloadChanged(download) {
			if (download.succeeded) try {
				var date = new Date(download.saver.entityID.replace(re, ""));
				+date && setTimeout(setLastModified, 2e3, f(download.target.path), date);
			}
			//catch(ex) {console.error(ex);}
			catch {}
		}
	});
})(
	"resource://gre/modules/Downloads.sys.mjs",
	"@mozilla.org/file/local;1", "nsIFile", "initWithPath"
);

Отсутствует

 

№121607-12-2023 12:32:35

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

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

Dumby
Большое спасибо, то что нужно :beer:. Теперь можно выключить S3 :D


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

На форуме

 

№121707-12-2023 15:44:30

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

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

Сделал отдельный скрипт на основе кнопки от Dumby «Быстрые опции about:config»: (меньше оригинала + некоторые улучшения)


Dumby, раз ты на связи, вот мои Хотелки и Проблемы к скрипту Быстрые опции:
1) сделать ввод значения текущей опции вручную через диалог ввода. Например в UserAgent > при клике по строке: "ваши данные…" нужно открыть диалог, где вводим нужные данные аналогично уже вшитым в другие строки этого подменю. После ввода или перезапуска браузера при открытии этого подменю строка "ваши данные…" должна быть выбрана флажком. Такой ввод данных пользователя нужен не для одной опции, а для многих: например в строке «Загрузки» нужна строка своих настроек…


2) надо, чтобы radio-строка подменю была выбрана (с флажком), если опция сброшена и отсутствует.
сделал костыль: pref.undef = [val,str] для pref: pref,lab,key,hint,[val,str],code
костыль делает строку меню такой: "Заголовок - str", но radio-строка подменю остаётся не выбранной.


3) при клике по родительской строке меню открывать эту опцию в about:config – функция about_config прилагается.
Это работает в ucf_hookClicks.js, но не пашет в этом коде, т.к. e.target определяется как кнопка, а не как текущая строка меню.


4) оригинальная кнопка "Быстрое переключение опций about:config" содержала два контекстных меню.
Прошу убрать код для нескольких меню: popups, popupshowing… (может попроще код станет).
Второе UserMenu другого формата и должно быть независимым, чтобы вызываться над разными кнопками.
0) странноcти кода – добавлял функцию switchTab через запятую в разной последовательности, но не
работает: ua = …}, switchTab = … Без запятой пашет: строка UserMenu не выдаст ошибку: no switchTab…

«Быстрые опции about:config» (не совместим с Custom Buttons)

Выделить код

Код:

/* Быстрые настройки меню опций about:config. Колёсико, Лев+Shift не закрывать
	Опция изменена: курсив; Цвет = ключ, по-умолчанию серый, иначе Red
	есть Def3el: несовпадения выделяются красной обводкой текста
	refresh=true ⟳ перечитать без кэша, restart=false ↯ без запроса 
pref: pref,lab,key,hint,[val,str],code | keys:val,lab,dat,+hint,code | icon:значок

	предыдущее значение: menu.pref.val
	Новое: newVal и trg.val данные
	trg.label метка keys:
*/

(async id =>{ var {prefs} = Services, db = prefs.getDefaultBranch("");
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;
}
Icon = (c = '0c0')=>"data:image/svg+xml;charset=utf-8,<svg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'><defs><linearGradient id='a' x1='16' x2='16' y1='32' gradientUnits='userSpaceOnUse'><stop stop-color='%23"+ c +"'/><stop stop-color='%23fff' offset='.8'/></linearGradient><linearGradient id='b' x2='32' y1='16' gradientTransform='matrix(1 0 0 1 2 2)'><stop stop-opacity='.5'/></linearGradient></defs><circle cx='16' cy='16' r='15' fill='url(%23a)' stroke='url(%23b)' stroke-width='2'/></svg>";
about_config = (filter) => { //на опцию
	if (gURLBar.value.startsWith("about:config")) switchTab(gURLBar.value);
	var setFilter = (e,input = (e?.target || window.content.document).getElementById("about-config-search")) => {	try {
		if (e || input.value != filter) input.setUserInput(filter);} catch{}
	},
	found = window.switchToTabHavingURI("about:config",true, {relatedToCurrent: true,
		triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
	if (found) setFilter(null,window);
	else gBrowser.selectedBrowser.addEventListener("pageshow",setFilter, {once: true});
};
ua = (real = false, ua_my = "general.useragent.override")=>{ //текущий или вшитый ЮзерАгент
	ttt = Pref(ua_my); prefs.clearUserPref(ua_my);
	ua = Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).userAgent; //костыль
	ttt && Pref(ua_my, ttt);
	ttt ||= ua;
	if (real) ttt = ua;
	return ttt;
}
switchTab = (url = 'about:config', go)=>{ //открыть вкладку | закрыть её | выбрать
	for(var tab of gBrowser.visibleTabs)
		if (tab.linkedBrowser.currentURI.spec == url)
			{go ? gBrowser.selectedTab = tab : gBrowser.removeTab(tab); return;}
	gBrowser.addTrustedTab(url);
	gBrowser.selectedTab = gBrowser.visibleTabs[gBrowser.visibleTabs.length -1];
}
var uar = ua(true), //real ЮзерАгент
fonts = arr => arr.map(n => [(n == arr[arr.length-1] ? null : n), n]), //array с вложениями
serif = fonts("Arial|Roboto|Cantarell|Segoe UI|Cambria|Calibri".split('|')),
sans = [["Times","Times"], ...serif],
hints = new Map([ //опция отсутствует ? вернуть строку
	["general.useragent.override", "UserAgent"]]);

UserMenu = { //массив команд пользователя, alt() клик правой кнопкой
	"Настройки профайлера": {
		cmd(){switchTab('about:profiling')}
	},
	DwDir: {lab: `папка Загрузки`,
		cmd(){
			Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(),Cu.reportError)},
		img: "chrome://devtools/skin/images/folder.svg"
	},
}
AboutCfg = [{
	pref: ["dom.disable_open_during_load", "Всплывающие окна"], Def3el: true, Yellow: false,
	keys: [[true, "Блокировать"], [false, "Разрешить"]],
},null,{
	pref: ["extensions.user_chrome_files.savedirs", "Загрузки",,'Пути сохранения Страниц и Графики\nСинтаксис «_Html/subdir|_Pics/subdir»\nsubdir: пусто | 0 заголовок | 1 домен',
		["", "всё в общей папке"]],
	Blue: "_Web|1|_Images|0", Gray: "",
	keys: [
		["_Сайты||_Фото|0", "_Сайты|_Фото/имя…"],
		["_Web|1|_Images|0", "_Web/сайт|_Images/имя"],
		["Сайт||Фото|", "ваши данные…",,"ключ в about:config", `console.log("введите ваши данные…")`]]
},{
	pref: ["general.useragent.override", "User Agent",,"Изменяет вид сайта", [uar,"встроенный"]],
		refresh: true, Def3el: uar,
	keys: [
	["Windows", "ваши данные…",,,`console.log("введите ваши данные…")`],
	["Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Chrome 118 Win10"],
	["Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12 Version/12.16", "Opera12 W8"],
	["Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "GoogleBot"],
	[uar, "по-умолчанию"]] //родной ЮзерАгент
}];

CustomizableUI.createWidget({ defaultArea: CustomizableUI.AREA_NAVBAR,
	label: "Журнал, Меню опций", localized: false, id: id,
	onCreated(btn) {
		btn.setAttribute("image", "chrome://devtools/skin/images/settings.svg");
		var doc = btn.ownerDocument, m = nn => doc.createXULElement(nn);
		btn.domParent = null;
		btn.popups = new btn.ownerGlobal.Array();
		this.createPopup(doc, btn, "config", AboutCfg);
		btn.linkedObject = this;
		for(var type of ["contextmenu", "command"])
			btn.setAttribute("on"+ type, `linkedObject.${type}(event)`);
		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(UserMenu, 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);
		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\(.*?\)/,''));
		/^(sub|sep|inf|lab|img)$/.test(key) || popup.append(item);
		sub && this.fill(o[key], item.appendChild(this.m("menupopup")));
	}},
	createPopup(doc, btn, prop, data) {
		var popup = doc.createXULElement("menupopup");
		btn.popups.push(btn[prop] = popup);
		popup.id = this.id +"-"+ prop;
		for (var type of ["popupshowing"])
			popup.setAttribute("on"+ type, `parentNode.linkedObject.${type}(event)`);
		for(var obj of data) popup.append(this.createElement(doc, obj));
		btn.append(popup);
	},
	createElement(doc, obj) { //pref
		if (!obj) return doc.createXULElement("menuseparator");
		var pref = doc.ownerGlobal.Object.create(null), node, bool, img;
		for(var [key, val] of Object.entries(obj)) {
			if (key == "pref") {
				var [apref, lab, akey, hint, undef, code] = val; //строка меню
				pref.pref = apref; pref.lab = lab || apref;
				if (hint) {
					if (RegExp(/\p{L}/,'u').test(hint[0]) && (hint[0] === hint[0].toUpperCase()))
						hint = '\n'+ hint;
					pref.hint = hint;
				}
				if (undef) pref.undef = undef; //если не массив: undef || undef == ""
				if (code) pref.code = code;
			}
			else if (key == "icon") img = val, pref.img = true;
			else if (key != "keys") pref[key] = val;
			else pref.hasVals = true;
		}
		var t = prefs.getPrefType(pref.pref), m = {b: "Bool", n: "Int", s: "String"};
		var str = m[t == prefs.PREF_INVALID ? obj.keys ? (typeof obj.keys[0][0])[0] : "b" : t == prefs.PREF_BOOL ? "b" : t == prefs.PREF_INT ? "n" : "s"]; //String по-умолчанию
		pref.get = prefs[`get${str}Pref`];
		var map, set = prefs[`set${str}Pref`];
		if (pref.hasVals) {
			for(var [val,,,,code] of obj.keys)
				code && (map || (map = new Map())).set(val, code);
			if (map) pref.set = (key, val) => {
				set(key, val);
				map.has(val) && eval(map.get(val)); //код2 если pref изменён
			}
		}
		if (!map) pref.set = set;
		node = doc.createXULElement("menu");
		node.className = "menu-iconic";
		img && node.setAttribute("image", img);
		akey && node.setAttribute("accesskey", akey);
		(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
		this.createRadios(doc,
			str.startsWith("B") && !pref.hasVals ? [[true, "true"], [false, "false"]] : obj.keys,
			node.appendChild(doc.createXULElement("menupopup"))
		);
		if ("Def3el" in obj) pref.noAlt = !("Yellow" in obj);
		return node;
	},
	createRadios(doc, vals, popup) {
		for(var arr of vals) {
			var [val, lab, key, hint] = arr;
			var menuitem = doc.createXULElement("menuitem");
			with (menuitem)
				setAttribute("type","radio"), setAttribute("closemenu","none"), setAttribute("label", popup.parentNode.pref.vals[val] = lab), key && setAttribute("accesskey", key);
			var tip = menuitem.val = val === "" ? "[ пустая строка ]" : val;
			if (hint) tip += "\n" + hint;
			menuitem.tooltipText = `${tip != undefined ? tip + "\n\n" : ""}клик с Shift блокирует авто-закрытие`;
			popup.append(menuitem);
		}
	},
	regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
	upd(node) {
		var {pref} = node, def = false, user = false, val; //если опция не найдена
		if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
			try {
				val = pref.defVal = db[pref.get.name](pref.pref); def = true; //опция по-умолчанию получена
			} catch {def = false}
			user = prefs.prefHasUserValue(pref.pref);
			if (user) try {val = pref.get(pref.pref, undefined);} catch {}
		}
		if (val == pref.val && def == pref.def && user == pref.user) return;
		pref.val = val; pref.def = def; pref.user = user;
		var exists = def || user;
		if (!exists && pref.undef) //опции нет ? вернуть default
			val = pref.undef[0];
		var hint = hints.get(pref.pref);
		hint ||= val != undefined ? val : "Эта опция не указана";
		if (hint === "") hint = "[ пустая строка ]";
		hint += "\n" + pref.pref;
		if (pref.hint) hint += "\n"+ pref.hint;
		node.tooltipText = hint; //+ текст
		var img = Icon("999"), alt = "Yellow" in pref && val == pref.Yellow, clr = "Gray" in pref && val == pref.Gray, blu = "Blue" in pref && val == pref.Blue;
		if (blu) img = Icon("a0f");
		if (alt) img = Icon("f80");
		if ("Def3el" in pref)
			if (val == pref.Def3el)
				img = Icon(), node.style.removeProperty('filter');
			else if (val != pref.defVal) {
				if (!alt && !clr && !blu)
					img = Icon("f26"); // Red
				node.style.filter = "drop-shadow(1px 1px 1px #B8F)";
			}
		pref.img || node.setAttribute("image", img); //нет Def3el ? серый
		user
			? node.style.setProperty("font-style", "italic", "important")
			: node.style.removeProperty("font-style");
		var {lab} = pref;
		if (exists && pref.hasVals) {
			if (val in pref.vals) var sfx = pref.vals[val] || val;
			else var sfx = user ? "другое" : "по-умолчанию";
			lab += ` ${"restart" in pref ? "↯-" : "refresh" in pref ? "-⟳" : "—"} ${sfx}`;
		}
		lab = exists ? lab : '['+ lab + `${"restart" in pref ? " ↯" : "refresh" in pref ? " ⟳" : ""}` +']'+ `${pref.undef ? " - "+ pref.undef[1] : ""}`;
		node.setAttribute("label", lab); //имя = [имя] если преф не существует
	},
	openPopup(popup) {
		var btn = popup.parentNode;
		if (btn.domParent != btn.parentNode) {
			btn.domParent = btn.parentNode;
			if (btn.matches(".widget-overflow-list > :scope"))
				var pos = "after_start";
			else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
				btn.closest("toolbar").getBoundingClientRect(), pos = width > height
					? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
					: `${win.innerWidth - right > left ? "end" : "start"}_before`;
			for(var p of btn.popups) p.setAttribute("position", pos);
		}
		popup.openPopup(btn);
	},
	maybeRestart(node, conf) {
		if (conf && !Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) return;
		var cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
		Services.obs.notifyObservers(cancel, "quit-application-requested", "restart");
		return cancel.data ? Services.prompt.alert(null, this.label, "Запрос на выход отменён.") : this.restart();
	},
	async restart() {
		var meth = Services.appinfo.inSafeMode ? "restartInSafeMode" : "quit";
		Services.startup[meth](Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
	},
	maybeRe(node, fe) {
		var {pref} = node;
		if ("restart" in pref) {
			if (this.maybeRestart(node, pref.restart)) return;
		}
		else this.popupshowing(fe, node.parentNode);
		if ("refresh" in pref) {
			var win = node.ownerGlobal;
			if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
				? win.BrowserReloadSkipCache() : win.BrowserReload();}
	},
	maybeClosePopup(e, trg) {
		(e.shiftKey || e.button == 1) || trg.parentNode.hidePopup();
	},
	popupshowing(e, trg = e.target) {
		if (trg.state == "closed") return;
		if (trg.id) {
			for(var node of trg.children) {
				if (node.nodeName.endsWith("r")) continue;
				this.upd(node);
				!e && node.open && this.popupshowing(null, node.querySelector("menupopup"));
			} return;
		}
		var {pref} = trg.closest("menu"), findChecked = true;
		var findDef = "defVal" in pref;
		var checked = trg.querySelector("[checked]");
		if (checked) {
			if (checked.val == pref.val) {
				if (findDef) findChecked = false;
				else return;
			}
			else checked.removeAttribute("checked");
		}
		if (findDef) {
			var def = trg.querySelector("menuitem:not([style*=font-style]");
			if (def)
				if (def.val == pref.defVal) {
					if (findChecked) findDef = false;
					else return;
				}
				else def.style.setProperty("font-style","italic","important");
		}
		for(var node of trg.children)
			if ("val" in node) {
				if (!pref.val && pref.val != "" && pref.undef)
					pref.val = pref.undef[0]; //опции нет ? вернуть default
				if (findChecked && node.val == pref.val) {
					node.setAttribute("checked", true);
					if (findDef) findChecked = false;
					else break;
				}
				if (findDef && node.val == pref.defVal) {
					node.style.removeProperty("font-style");
					if (findChecked) findDef = false;
					else break;
				}
			}
	},
	command(e, trg = e.target) { //LMB
		if (trg.id == id) {
			if (trg.config.state != "open")
				trg.menupopup.openPopup(trg, "after_start")
			else
				console.log("Здесь нужен переход на опцию about:config");
			return;
		}
		var menu = trg.closest("menu"), newVal = trg.val;
		if (!menu || !menu.pref) return;
		this.maybeClosePopup(e, menu);
		menu.pref.code && eval(menu.pref.code); //run1
		if (newVal != menu.pref.val)
			menu.pref.set(menu.pref.pref, newVal), this.maybeRe(menu, true);
	},
	contextmenu(e, trg = e.target) { //RMB
		if ((trg.id == id) && (!e.ctrlKey && !e.altKey && !e.shiftKey))
			if (trg.config.state != "open")
				this.openPopup(trg.config);
			else
			  trg.config.hidePopup();
		else if ("pref" in trg) {
			this.maybeClosePopup(e, trg);
			if (trg.pref.user)
				prefs.clearUserPref(trg.pref.pref), this.maybeRe(trg);
			trg.pref.code && eval(trg.pref.code); //run
		}
		e.preventDefault();
	}
});
})("ucf_AboutConfig");

Отсутствует

 

№121810-12-2023 19:48:49

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

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

Dobrov пишет

1) сделать ввод значения текущей опции вручную через диалог ввода. Например в UserAgent > при клике по строке: "ваши данные…" нужно открыть диалог, где вводим нужные данные аналогично уже вшитым в другие строки этого подменю. После ввода или перезапуска браузера при открытии этого подменю строка "ваши данные…" должна быть выбрана флажком.

Попробовал это записать, но как-бы слегка снаружи.
Задержка, и, если ничего не выбрано и преф имеет пользовательское значение,
тогда выбираем строку "ваши данные…".


Врезка в createRadios() перед строкой popup.append(menuitem);
добавляем lab == "ваши данные…" && this.asInput(menuitem, val);


дополнительный стафф в объект

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

Выделить код

Код:

//
	asInput(menuitem, val) {
		menuitem.ttsfx = (menuitem.ittt = menuitem.tooltipText)
			.slice(String(menuitem.ival = val).length);
		menuitem.linkedObject = this;
		menuitem.setAttribute("oncommand", "linkedObject.input(event)");
		menuitem.render = this.renderInputOnce;
	},
	input(e) {
		e.stopImmediatePropagation();
		var trg = e.target, {pref} = trg.parentNode.parentNode;
		var res = {value: trg.tt ? pref.val : trg.ival};

		if (Services.prompt.prompt(
			null, `Введите значение (${pref.isInt ? "целое" : "строка"})`, pref.pref, res, null, {}
		)) {
			if (pref.isInt) {
				// from old about:config
				var val = res.value | 0;
				if (val != res.value - 0) return Services.prompt.alert(
					null, "Недействительное значение", 
					"Введённый вами текст не является числом."
				);
			}
			else val = res.value;
			pref.set(pref.pref, val);
		}
	},
	renderInputOnce() {
		delete this.render;
		this.render();
		var {pref} = this.parentNode.parentNode;
		pref.isInt = pref.get.name[3] == "I";
		if (!("val" in pref)) try {pref.val = pref.get(pref.pref);} catch {}

		this.linkedObject.hookUncheck(this); // for Shif+Click outside
		(this.render = this.linkedObject.renderInput).call(this);
	},
	hookUncheck(menuitem) {
		var rtt = function() {
			this.tt = false;
			this.tooltipText = this.ittt;
		}
		var desc = {configurable: true, enumerable: true, value(attr) {
			this.ownerGlobal.Element.prototype.removeAttribute.call(this, attr);
			attr.startsWith("c") && this.popup.state.startsWith("o") && this.parentNode.rtt();
		}};
		(this.hookUncheck = menuitem => {
			menuitem.rtt = rtt;
			var box = menuitem.firstChild;
			box.popup = menuitem.parentNode;
			menuitem.ownerGlobal.Object.defineProperty(box, "removeAttribute", desc);
		})(menuitem);
	},
	get renderInput() {
		delete this.renderInput;
		return this.renderInput = Cu.getGlobalForObject(Cu).eval(`(${async function() {
			await new Promise(this.ownerGlobal.requestAnimationFrame);

			var popup = this.parentNode, menu = popup.parentNode;
			menu.hasAttribute("_moz-menuactive") || this.linkedObject.popupshowing(null, popup, false); // force

			var checked = popup.querySelector("[checked]");
			var {pref} = menu, checkedThis = checked == this;

			if (checked && !checkedThis || !pref.user) return this.tt && this.rtt();

			this.tt = true;
			this.tooltipText = pref.val + this.ttsfx;
			if (checkedThis) return;

			menu.label = menu.label.replace(/другое$/, this.label);
			this.setAttribute("checked", true);
		}})`);
	},


и чуть модифицировать popupshowing()
чтобы была возможность пропустить проверку state
скрытый текст

Выделить код

Код:

/*
	popupshowing(e, trg = e.target) {
		if (trg.state == "closed") return;
*/
	popupshowing(e, trg = e.target, checkstate = true) {
		if (checkstate && trg.state == "closed") return;

2) надо, чтобы radio-строка подменю была выбрана (с флажком), если опция сброшена и отсутствует.
сделал костыль: pref.undef = [val,str] для pref: pref,lab,key,hint,[val,str],code
костыль делает строку меню такой: "Заголовок - str", но radio-строка подменю остаётся не выбранной.

Не понял. Какая radio-строка остаётся не выбранной?


Вот для extensions.user_chrome_files.savedirs есть pref.undef
и есть три radio-строки, но ни одна из них
не подходит быть выбранной если преф отсутствует.


И, даже если бы подходящая radio-строка была,
то что должно было бы происходить при её активации кликом?

3) при клике по родительской строке меню открывать эту опцию в about:config – функция about_config прилагается.
Это работает в ucf_hookClicks.js, но не пашет в этом коде, т.к. e.target определяется как кнопка, а не как текущая строка меню.

У себя вижу, что на кликнутое ссылается e.explicitOriginalTarget

4) оригинальная кнопка "Быстрое переключение опций about:config" содержала два контекстных меню.
Прошу убрать код для нескольких меню: popups, popupshowing… (может попроще код станет).

Да нет, особо попроще код не станет. В popupshowing здесь менять нечего,
а popups — да, не используется, можно почистить

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

Выделить код

Код:

....
		//btn.popups = new btn.ownerGlobal.Array();
....
		//btn.popups.push(btn[prop] = popup);
		btn[prop] = popup;
....
			//for(var p of btn.popups) p.setAttribute("position", pos);
			btn.config.setAttribute("position", pos);

0) странноcти кода – добавлял функцию switchTab через запятую в разной последовательности, но не
работает: ua = …}, switchTab = … Без запятой пашет: строка UserMenu не выдаст ошибку: no switchTab…

Я добавил запятую как написано, и у меня всё работает.
Запятая, в данном случае, это оператор множественного вычисления,
она что есть, что нет.


А вот если перед ua добавить var
то запятая станет частью var-синтаксиса
и switchTab перестанет быть глобальной переменной.
То есть, из атрибута "oncommand" его видно не будет.

Отсутствует

 

№121915-12-2023 17:46:47

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

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

Можно в ucf_aom-button.js как-то добавить функцию, как у unified_extensions_button, чтобы при клике вылазило окно, не настройки? Можно эти дополнения с меню, отдельно выделять используя тот шарик с цветом. Во, или на ПКМ посадить unified_extensions_button, а саму кнопку скрыть.

Отредактировано b0ttle (15-12-2023 17:55:26)

Отсутствует

 

№122016-12-2023 05:48:28

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

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

b0ttle пишет

Можно эти дополнения с меню, отдельно выделять используя тот шарик с цветом.

Не понял, нужен скриншот или подробные разьяснения.
Сделал, но пока не публиковал (ucf_hookClicks.js в процессе отладки):
Дополнения к меню опций от Dumby (работает, но переделываю по-своему, ещё изменю формат Setup = [{…)
Меню пользователя и прочие клики для unified_extensions_button работают и на старой кнопке Расширений "add-ons-button"


b0ttle пишет

Можно в ucf_aom-button.js как-то добавить функцию, как у unified_extensions_button, чтобы при клике вылазило окно, не настройки?

Вообще-то удобнее иконку скрипта ucf_aom-button.js убрать, а на правый клик unified_extensions_button назначить меню управления расширениями от ucf_aom-button (но не разбирался, как в этом скрипте привязать клики по меню, открытому из другой кнопки).

Отредактировано Dobrov (16-12-2023 06:30:12)

Отсутствует

 

№122116-12-2023 12:15:14

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

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

 

Отредактировано b0ttle (29-12-2023 15:22:52)

Отсутствует

 

№122216-12-2023 15:37:58

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

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

 

Отредактировано b0ttle (29-12-2023 15:23:02)

Отсутствует

 

№122317-12-2023 19:00:50

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

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

b0ttle пишет

попап таких расширений как ublock, tampermonkey, про это меню имелось ввиду, чтобы вместо двух кнопок была одна.

Нет, менюшки расширений не рассматриваются, и я не проверял их открытие над другой кнопкой, если кнопка расширения не закреплена на панели инструментов.
Правым кликом на unified-extensions-button открывается меню пользовательских команд (отлажу скрипт и для "add-ons-button" это меню добавлю)

Отсутствует

 

№122431-12-2023 13:27:12

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

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

Обновил скрипта перехвата кликов-нажатий ucf_hookClicks.js — исправил ошибки несрабатывания некоторых команд пользовательского меню по клику из кнопок.


Cкрипт сохранения страниц SingleHTML.jsm исправлена связка Путь сохранения <-> установка пути из Опций быстрых настроек.


Всех с наступающим праздником!

Отсутствует

 

№122531-12-2023 15:23:29

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

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

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

Отсутствует

 

Board footer

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