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

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

№190104-03-2025 00:52:05

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

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

egorsemenov06 пишет

в [firefox] 136.0 выдает вот такую ошибку
Error sanitizing historyFormDataAndDownloads TypeError: item is undefined

Ну, в 136, Object.keys(Sanitizer.items).join("\n");
(типа список возможностей) выдаёт

cache
cookies
offlineApps
history
formdata
downloads
sessions
siteSettings
openWindows
pluginData
browsingHistoryAndDownloads
cookiesAndStorage

Таким образом, наверно,
historyFormDataAndDownloads
browsingHistoryAndDownloads

Отсутствует

 

№190204-03-2025 08:34:20

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

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

Есть такой скрипт ucf_contextmenu_openwith.js:

Выделить код

Код:

(this.contextmenuopenwith = { //на основе forum.mozilla-russia.org/viewtopic.php?pid=809407#p809407
	_eventListeners: [],
	init(that) { var Hint = "Открыть выделенный текст или ссылку\nПравый клик | Shift - ссылка из буфера",
		selector = "#context-sep-selectall", // вставить пункты меню перед этим селектором
		attricon = true, // false: без иконок атрибут "image"
		submenu = false, /* подменю программ для ссылок

	name: 'Prefix или пусто|Имя', path: 'путь', Необязательно: icon: 'иконка',
	args: `опции через пробел "в двойных кавычках считаются одной"`,
	roll: аналог args, выполняется средним кликом (+Shift: адрес из буфера)
	hint: подсказка в строке меню для roll
	%OpenURI выделенный текст или URL страницы/ссылки */

		OS_linux = [
			{ name: 'Ссылку в |плеер VLC', path: '/usr/bin/vlc',
				icon: 'moz-icon://stock/vlc?size=menu'
			},
			{ name: 'Скачать в |Yt-dlp', path: '/usr/bin/konsole', //предпочтительно .mp4 hevc|h265|avc|h264 <=1080
				args: `--hold --workdir ~/Загрузки -e "yt-dlp -f %quotbv[height<=1080][ext=mp4][vcodec~='^(hevc|h265|avc|h264)']+ba[ext~='(aac|m4a)']/best[height<=1080][ext=mp4]/best[height<=1080]/best%quot %OpenURI"`,
				hint: 'скачать в FFmpeg',
				roll: `--hold --workdir ~/Загрузки -e "ffmpeg -i %OpenURI -c copy -f mp4 video.mp4"`,
				icon: 'moz-icon://stock/youtube-dl?size=menu'}
		],
		OS_win = [
			{	name: 'Ссылку в |плеер MPC-BE', path: 'D:\\[Programs]\\MPC-BlackEdition\\mpc-be64.exe',
				args: `"%OpenURI"`
			},
			{ name: 'Ссылку в |плеер PotPlayer', path: 'D:\\[Programs]\\PotPlayer\\PotPlayerMini64.exe',
				args: `"%OpenURI"`
			},
			{ name: 'Открыть в |Microsoft Edge', path: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', args: `"microsoft-edge:%OpenURI%OpenURI "`}
		],
		OS_macosx = [
			{	name: '|Видео загрузчик yt-dlp', path: '/usr/bin/osascript',
				args: `-e "tell app %quotTerminal%quot to activate do script %quotrun ytdlp '%OpenURI' || { yt-dlp '%OpenURI' && say сделано;}; exit%quot"`,
				hint: 'опции --downloader ffmpeg…',
				roll: `-e "tell app %quotTerminal%quot to activate do script %quotyt-dlp --downloader ffmpeg --hls-use-mpegts '%OpenURI' && say сделано; exit%quot"`,
				icon: 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4TC0AAAAvD8ADEA8QEfMfQlFt29T7MhRBFNGIJsqLYPhnqEJE/8P8772bd+qxBfOVCwIA'
			},
			{	name: 'Ссылку в |плеер MPV', path: '/usr/bin/osascript', //FIX only mpv
				args: `-e "tell app %quotTerminal%quot to do script %quotopen -b io.mpv '%OpenURI' --args '--ytdl-format=bestvideo[height<=?720][fps<=?30]+bestaudio/best[height<=?720][fps<=?30]'; exit%quot" -e "tell app %quotSystem Events%quot to set visible of process %quotTerminal%quot to false"`,
				hint: 'скачать книгу в Elib2Ebook',
				roll: `-e "tell app %quotTerminal%quot to do script %quotcd ${Downloadir()}; Elib2EbookCli --additional -f epub -u '%OpenURI' && say сделано; exit%quot"`,
				icon: 'moz-icon://file:///System/Applications/Automator.app?size=16'
			},
			{	name: 'Открыть в браузере |Safari', path: '/usr/bin/open',
				args: `-b com.apple.Safari -u "%OpenURI"`,
				icon: 'chrome://devtools/skin/images/browsers/safari.svg'},
		];
		try {var arrOS = eval('OS_'+ AppConstants.platform);} catch {return};
		if (!arrOS || !arrOS.length) return;
		var addListener = (...arr) => {
			var elm = arr[0];
			if (!elm) return;
			elm.addEventListener(...arr.slice(1));
			this._eventListeners.push(arr);
		};
		var readFromClipboard = (url = "") => {
			try {
				let trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
				trans.init(docShell.QueryInterface(Ci.nsILoadContext));
				trans.addDataFlavor("text/plain");
				let {clipboard} = Services, data = {};
				clipboard.getData(trans, clipboard.kGlobalClipboard);
				trans.getTransferData("text/plain", data);
				if (data.value)
					url = data.value.QueryInterface(Ci.nsISupportsString).data;
			} catch {}
			return url;
		};
		var getCurrentURL = (url = gBrowser.selectedBrowser.currentURI.displaySpec) => {
			try {
				let _url = ReaderMode.getOriginalUrl(url);
				if (_url)
					url = Services.io.newURI(_url).displaySpec;
			} catch {}
			return url;
		};
		var getURL = key => {
			return !key
			? gContextMenu?.linkURI?.displaySpec || getCurrentURL()
			: readFromClipboard();
		};
		var popup = document.querySelector("#contentAreaContextMenu");
		var create = e => {
			if (e.target != popup || gContextMenu.webExtBrowserType === "popup" ||
				(gContextMenu.isContentSelected || gContextMenu.onTextInput) && !gContextMenu.linkURL) return;
			popup.removeEventListener("popupshowing", create);
			this._eventListeners.shift();
			var contextsel = popup.querySelector(`:scope > ${selector}`) || popup.querySelector(":scope > menuseparator:last-of-type");
			var fragment = document.createDocumentFragment();
			if (arrOS.length == 1) submenu = false;
			var itemId = 0;
			arrOS.forEach(item => {
				let name = item.name.split('|'), {path, args, roll, hint} = item;
				if (!name || !path) return;
				if (submenu) name.shift();
				name = name.join('');
				if (hint) hint = '\nКолёсико: '+ hint;
				var icon = item.icon || `moz-icon://file://${path}?size=16`;
				let mitem = document.createXULElement("menuitem");
				mitem.id = `ucf-menu-open-with-${++itemId}`;
				mitem.className = "menuitem-iconic ucf-menu-open-with";
				mitem.setAttribute("label", `${name}`);
				mitem.apppath = path; mitem.roll = roll;
				mitem.tooltipText = Hint + (hint || "");
				mitem.appargs = args;
				if (attricon)
					mitem.setAttribute("image", icon);
				fragment.append(mitem);
				addListener(mitem, "command", function command(e) {
					try {
						let trg = e.currentTarget, args = trg.appargs, file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
						if (trg.roll && e.button == 1)
							args = trg.roll;
						file.initWithPath(trg.apppath);
						if (!file.exists()) return;
						if (file.isExecutable()) {
							let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
							process.init(file);
							if (args) {
								let openuri = false;
								args = args.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/).map(sp => {
									if (/%OpenURI/.test(sp)) {
										openuri = true;
										return sp.replace(/^["']+|["']+$/g, "").replace(/%quot/g, '"').replace(/%OpenURI/g, getURL(e.shiftKey || e.button == 2));
									}
									return sp.replace(/^["']+|["']+$/g, "").replace(/%quot/g, '"');
								});
								if (!openuri)
									args.push(getURL(e.shiftKey || e.button == 2));
							} else
								args = [getURL(e.shiftKey || e.button == 2)];
							process.runwAsync(args, args.length);
						} else
							file.launch();
					} catch {}
				});
			});
			var funcpopupshowing, funcpopuphiding;
			if (submenu) {
				let rootmenu = {};
				if (fragment.children.length) {
					rootmenu = document.createXULElement("menu");
					rootmenu.id = "ucf-menu-open-with-submenu";
					rootmenu.className = "menu-iconic ucf-menu-open-with";
					rootmenu.setAttribute("label", "Открыть ссылку в…");
					let mpopup = document.createXULElement("menupopup");
					mpopup.append(fragment);
					rootmenu.append(mpopup);
					contextsel.before(rootmenu);
				}
				funcpopupshowing = () => {
					rootmenu.hidden = false;
				};
				funcpopuphiding = () => {
					rootmenu.hidden = true;
				};
			} else {
				contextsel.before(fragment);
				funcpopupshowing = () => {
					for(let arr of this._eventListeners) {
						if (arr[2].name === "command")
							arr[0].hidden = false;
					}
				};
				funcpopuphiding = () => {
					for(let arr of this._eventListeners) {
						if (arr[2].name === "command")
							arr[0].hidden = true;
					}
				};
			}
			addListener(popup, "popupshowing", function popupshowing(e) {
				if (e.target != popup || gContextMenu.webExtBrowserType === "popup" ||
					(gContextMenu.isContentSelected || gContextMenu.onTextInput) && !gContextMenu.linkURL) return;
				funcpopupshowing();
			});
			addListener(popup, "popuphiding", function popuphiding(e) {
				if (e.target != popup) return;
				funcpopuphiding();
			});
		};
		addListener(popup, "popupshowing", create);
		setUnloadMap("contextmenuopenwith", this.destructor, this);
		function Downloadir(c = Ci.nsIFile){
			var d = Services.dirsvc.get("DfltDwnld",c);
			try {var d = Services.prefs.getComplexValue("browser.download.dir",c);} catch {}
			return d.path;
		}
	},
	destructor() {
		for(let arr of this._eventListeners)
			arr.shift().removeEventListener(...arr);
	}
}).init(this);

и возникла проблема с "Открыть в Microsoft Edge", например при открытии https://4pda.to/ ссылка передается в таком виде - https://4pda.to/https://4pda.to/

Можно это как-то поправить?

Отсутствует

 

№190304-03-2025 09:18:51

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

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

Northtech пишет

https://4pda.to/ ссылка передается в таком виде - https://4pda.to/https://4pda.to/

Ага, а если вместо прописанного
microsoft-edge:%OpenURI%OpenURI
написать
microsoft-edge:%OpenURI%OpenURI%OpenURI


то будет передаваться
microsoft-edge:https://4pda.to/https://4pda.to/https://4pda.to/

Отсутствует

 

№190404-03-2025 09:23:18

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 23-07-2024
Сообщений: 28
UA: Firefox 136.0

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

Dumby пишет
egorsemenov06 пишет

в [firefox] 136.0 выдает вот такую ошибку
Error sanitizing historyFormDataAndDownloads TypeError: item is undefined

Ну, в 136, Object.keys(Sanitizer.items).join("\n");
(типа список возможностей) выдаёт

cache
cookies
offlineApps
history
formdata
downloads
sessions
siteSettings
openWindows
pluginData
browsingHistoryAndDownloads
cookiesAndStorage

Таким образом, наверно,
historyFormDataAndDownloads
browsingHistoryAndDownloads

СПАСИБО БОЛЬШОЕ!!!!Работает!

Отсутствует

 

№190504-03-2025 16:57:58

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

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

Dumby
а слона то я и не заметил) спасибо.

Отсутствует

 

№190605-03-2025 15:46:46

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

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

green25
А Вы его подключали в UCF правильно?
№1645

Отсутствует

 

№190706-03-2025 14:33:17

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

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

Farby
Опять или снова отвалился код "Экспорт папки в HTML".
Вы уже помогали... раз и два.
custom_script.js

Экспорт папки в HTML

Выделить код

Код:

(async topic => {
  var imp = (m, n = m) => Cu.import(`resource://gre/modules/${m}.jsm`, {})[n];
  var exporter = {
    get dps() {
      delete this.dps;
      return this.dps = imp("DownloadPaths");
    },
    get exporter() {
      delete this.exporter;
      return this.exporter = imp("BookmarkHTMLUtils", "BookmarkExporter");
    },
    async export(popup) {
      var win = popup.ownerGlobal, tn = popup.triggerNode;
      var node, pu = win.PlacesUtils, bm = pu.bookmarks;

      if (tn.nodeName == "treechildren") node = popup._view.selectedNode;
      else if (tn.id == "OtherBookmarks")
        node = {bookmarkGuid: bm.unfiledGuid, title: tn.getAttribute("label")};
      else node = tn._placesNode || popup._view.result.root;

      var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
      fp.init(
        !("inIsolatedMozBrowser" in win.browsingContext.originAttributes)
        ? win.browsingContext
        : win, win.PlacesUIUtils.promptLocalization.formatValueSync("places-bookmarks-export"), fp.modeSave);
      fp.appendFilters(fp.filterHTML);
      fp.defaultString = (node.title ? this.dps.sanitize(node.title) : "untitled") + ".html";

      if (await new Promise(fp.open) == fp.returnCancel) return;

      var tree = await pu.promiseBookmarksTree(pu.getConcreteItemGuid(node), {includeItemIds: true});
      tree.title = bm.getLocalizedTitle(tree);
      var bookmarks = {children: [
        {root: "toolbarFolder"},
        {root: "unfiledBookmarksFolder"},
        {root: "bookmarksMenuFolder", children: [tree], guid: bm.menuGuid}
      ]};
      new this.exporter(bookmarks).exportToFile(fp.file.path);
    },
    observe(doc) {
      var popup = doc.querySelector("menupopup#placesContext");
      if (!popup) return;

      var menuitem = (doc.createXULElement || doc.createElement).call(doc, "menuitem");
      for(var args of Object.entries({
        label: "Экспорт папки в HTML",
        selection: "folder",
        "node-type": "folder",
        "selection-type": "single|none",
        id: "placesContext_exportFolder",
        oncommand: "exporter.export(parentNode);"
      }))
        menuitem.setAttribute(...args);

      menuitem.exporter = this;
      doc.getElementById("placesContext_openSeparator").before(menuitem);
    }
  };
  Services.obs.addObserver(exporter, topic);
  Services.obs.addObserver(function quit(s, t) {
    Services.obs.removeObserver(quit, t);
    Services.obs.removeObserver(exporter, topic);
  }, "quit-application-granted");
})("chrome-document-loaded");


P.S. Я помню, что сами Вы не пользуетесь UCF.

Отсутствует

 

№190806-03-2025 15:05:58

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

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

xrun1 пишет

P.S. Я помню, что сами Вы не пользуетесь UCF.

зато у меня есть лодырь от Dumby
И код выглядит так:

Экспорт папки в HTML

Выделить код

Код:

// skip 1st line
(async topic => {
	var imp = (m, n = m) => ChromeUtils.importESModule(`resource://gre/modules/${m}.sys.mjs`)[n];
	//var {_uc} = ChromeUtils.importESModule("chrome://userchromejs/content/userChrome.mjs");
	var exporter = {
		get dps() {
			delete this.dps;
			return this.dps = imp("DownloadPaths");
		},
		get exporter() {
			delete this.exporter;
			//return this.exporter = _uc.dbg.ref("BookmarkExporter", imp("BookmarkHTMLUtils").exportToFile);
			return this.exporter = UcfPrefs.dbg.ref("BookmarkExporter", imp("BookmarkHTMLUtils").exportToFile);
		},
		async export(popup) {
			var win = popup.ownerGlobal, tn = popup.triggerNode;
			var node, pu = win.PlacesUtils, bm = pu.bookmarks;

			if (tn.nodeName == "treechildren") node = popup._view.selectedNode;
			else if (tn.id == "OtherBookmarks")
				node = {bookmarkGuid: bm.unfiledGuid, title: tn.getAttribute("label")};
			else node = tn._placesNode || popup._view.result.root;

			var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
			// fp.init(win, win.PlacesUIUtils.getString("EnterExport"), fp.modeSave);
			fp.init(
				!("inIsolatedMozBrowser" in win.browsingContext.originAttributes)
				? win.browsingContext
				: win, win.PlacesUIUtils.promptLocalization.formatValueSync("places-bookmarks-export"), fp.modeSave);
			fp.appendFilters(fp.filterHTML);
			fp.defaultString = (node.title ? this.dps.sanitize(node.title) : "untitled") + ".html";

			if (await new Promise(fp.open) == fp.returnCancel) return;

			var tree = await pu.promiseBookmarksTree(pu.getConcreteItemGuid(node), {includeItemIds: true});
			tree.title = bm.getLocalizedTitle(tree);
			var bookmarks = {children: [
				{root: "toolbarFolder"},
				{root: "unfiledBookmarksFolder"},
				{root: "bookmarksMenuFolder", children: [tree], guid: bm.menuGuid}
			]};
			new this.exporter(bookmarks).exportToFile(fp.file.path);
		},
		observe(doc) {
			var popup = doc.querySelector("menupopup#placesContext");
			if (!popup) return;

			var menuitem = (doc.createXULElement || doc.createElement).call(doc, "menuitem");
			for(var args of Object.entries({
				label: "Экспорт папки в HTML",
				selection: "folder",
				"node-type": "folder",
				"selection-type": "single|none",
				id: "placesContext_exportFolder",
				//oncommand: "exporter.export(parentNode);"
			}))
				menuitem.setAttribute(...args);

			menuitem.exporter = this;
			menuitem.addEventListener("command", e => {
				e.target.exporter.export(e.target.parentNode);
			});
			doc.getElementById("placesContext_openSeparator").before(menuitem);
		}
	};
	Services.obs.addObserver(exporter, topic);
	Services.obs.addObserver(function quit(s, t) {
		Services.obs.removeObserver(quit, t);
		Services.obs.removeObserver(exporter, topic);
	}, "quit-application-granted");
})("chrome-document-loaded");


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

На форуме

 

№190906-03-2025 15:26:03

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

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

Farby
:beer:

Отсутствует

 

№191007-03-2025 00:14:34

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

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

Farby
Посмотрите, пожалуйста, ещё раз Async Run Applications 2021.9.7-mod_117+.
Новая версия не интересна. Здесь 3 кнопки, мне так удобнее. Настройки в расширении отвалились давно: есть и их видно, а изменить не получается. Но можно было руками поправить файл в профиле async_run_applications.json.
Теперь кнопок не видно, если вызвать настройки - пусто, хотя файл есть.
Можно что-то сделать или всё, кирдык?

Отсутствует

 

№191107-03-2025 11:40:09

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

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

Farby пишет

зато у меня есть лодырь от Dumby
И код выглядит так:
Экспорт папки в HTML

Плиз, поправьте для работы с Aris-t2. Сейчас пункт есть, диалог сохранения есть, но сохранение не происходит.

Отсутствует

 

№191207-03-2025 12:20:34

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

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

fuchsfan пишет

Плиз, поправьте для работы с Aris-t2.

Все остальные лоадеры свободны как мухи в самолёте, причина банальна больше нет Cu.inport. Вот что по этому поводу Dumby писсал.
Зато есть дебагер в UCF, когда Aris прикрутит, тогда можно посмотреть будет.


xrun1 пишет

Можно что-то сделать или всё, кирдык?

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

Отредактировано Farby (07-03-2025 14:08:39)


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

На форуме

 

№191307-03-2025 14:34:16

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

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

Farby пишет

берём тестируем отписываемся

Работает, даже настройки. Спасибо! :beer:
Dumby
Сломалась кнопка для боковой панели (второй спойлер), 4+ года работала. Можно поправить, привык?

Отредактировано xrun1 (07-03-2025 14:35:22)

Отсутствует

 

№191407-03-2025 21:17:39

Garalf
Участник
 
Группа: Members
Зарегистрирован: 19-09-2017
Сообщений: 345
UA: Firefox 136.0

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

Farby
Помогите, пожалуйста. Не получается запустить вашу кнопку Reload user{Chrome, Content}
https://forum.mozilla-russia.org/viewto … 97#p806797
Куда надо помещать код?

Отсутствует

 

№191508-03-2025 00:01:59

_zt
Забанен
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1696
UA: Firefox 128.0

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

Garalf
mjs - https://forum.mozilla-russia.org/viewto … 97#p806797

Выделить код

Код:

scriptsbackground: [ // В фоне [System Principal]
        { func: 'ChromeUtils.importESModule("chrome://user_chrome_files/content/путь/UCF_userChrome_Reloader.mjs")', },

Отредактировано _zt (08-03-2025 00:12:03)

Отсутствует

 

№191608-03-2025 15:09:17

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

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

xrun1 пишет

Сломалась кнопка для боковой панели (второй спойлер)

O, кнопочка мне понравилась, решил себе оставить

sidebar-button-toggle-state.uc.js

Выделить код

Код:

// ==UserScript==
// @name           Sidebar button Toggle state
// @namespace      sidebar-button@forum.mozilla-russia.org
// @description    sidebar button
// @include        main
// @author         Dumby
// @version        27-08-2020 00:22:15
// @homepageURL    https://forum.mozilla-russia.org/viewtopic.php?pid=784391#p784391
// ==/UserScript==

try {(lst => {
	var type = "MozBeforeInitialXULLayout", sidebar = document.getElementById("sidebar");
	sidebar.addEventListener(type, lst, true);
	document.addEventListener("unload", () => sidebar.removeEventListener(type, lst, true), {once: true});
})({
	handleEvent(e) {
		var parent = e.target.querySelector(":root:is(#bookmarksPanel,#history-panel) > #sidebar-search-container");
		parent && this.insert(parent);
	},
	insert(parent) {
		var df = parent.ownerGlobal.MozXULElement.parseXULToFragment(`
			<hbox>
				<toolbarbutton 
					id="sidebar-button-toggle-state"
					tooltiptext="ЛКМ: Закрыть все папки верхнего уровня&#xA;((Ctrl или Shift) и ЛКМ) или СКМ: Закрыть все папки&#xA;ПКМ: Открыть все папки"
				/>
			</hbox>
		`);
		var sidebarImg = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 48 48"><g><path d="M 2.438,0 C 1.087,0 0,1.088 0,2.438 V 45.56 C 0,46.91 1.087,48 2.438,48 H 45.56 C 46.91,48 48,46.91 48,45.56 V 2.438 C 48,1.088 46.91,0 45.56,0 Z" style="fill:%230078ad;fill-opacity:1;" /><path style="opacity:0.25;fill:%23000000;" d="M 5,11 V 39.5 L 13.5,48 H 45.5 C 47,47.9 47.9,47 48,45.5 V 13.6 L 43.4,9 10,8 Z"/><path style="fill:%23ffffff;" d="M 10.9,6 H 37.1 C 41.6,6 45,9.48 45,13.7 V 34.3 C 45,38.7 41.6,42 37.1,42 H 10.9 C 6.51,42 3,38.7 3,34.3 V 13.7 C 3.03,9.48 6.54,6.03 10.9,6 Z M 39.7,34.3 V 13.7 C 39.7,12.3 38.7,11.1 37.1,11.1 H 24 V 36.8 H 37.1 C 38.7,36.8 39.7,35.8 39.7,34.3 Z M 8.25,34.3 C 8.25,35.8 9.42,36.8 10.9,36.8 H 21.4 V 11.1 H 10.9 C 9.42,11.1 8.25,12.3 8.25,13.7 Z" /><path style="fill:%23ffffff;" d="M 12,16.3 H 17.7 C 18.4,16.3 19,15.7 19,15 19,14 18.4,13.4 17.7,13.4 H 12 C 11.2,13.4 10.6,14 10.6,15 10.6,15.7 11.2,16.3 12,16.3 Z M 12,21.8 H 17.7 C 18.4,21.8 19,21.3 19,20.5 19,19.6 18.4,19 17.7,19 H 12 C 11.2,19 10.6,19.6 10.6,20.5 10.6,21.3 11.2,21.8 12,21.8 Z M 14.9,27.4 H 17.7 C 18.4,27.4 19,26.8 19,26.1 19,25.1 18.4,24.6 17.7,24.6 H 14.9 C 14,24.6 13.4,25.1 13.4,26.1 13.4,26.8 14,27.4 14.9,27.4 Z" /></g></svg>';
		Services.io.getProtocolHandler("resource")
			.QueryInterface(Ci.nsIResProtocolHandler)
			.setSubstitution("sidebar-button-toggle-state", Services.io.newURI(sidebarImg));
		(this.insert = pn => {
			pn.prepend(pn.ownerDocument.importNode(df, true));
			var btn = pn.firstChild.firstChild;
			btn.toggleState = this.toggleState;
			btn.tree = pn.nextSibling;
			btn.style = "-moz-appearance: none !important; min-width: 2.5em !important; min-height: 2em !important";
			btn.style.listStyleImage = 'url("resource://sidebar-button-toggle-state")';
			btn.style.MozContextProperties = "fill";
			btn.style.setProperty("fill", "currentColor");
			btn.addEventListener("click", event => {event.target.toggleState(event);});
		})(parent);
	},
	toggleState(e) {
		if (this.start) return;
		this.start = true;

		var {view} = this.tree;
		var close = e.button < 2;
		var closeAll = e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey);

		var index = view.rowCount, i;

		if (closeAll) for(i = index; i >= 0; i--)
			view.isContainer(i) && view.isContainerOpen(i) && view.toggleOpenState(i);

		else for(i = 0; i < index; i++) {
			if (!view.isContainer(i) || view.isContainerOpen(i) != close) continue;

			view.toggleOpenState(i);
			index = view.rowCount;
			if (close) continue;

			var node = view._rows[i];
			if (node.type == node.RESULT_TYPE_QUERY) i += node.childCount;
		}
		this.start = false;
	}
});} catch(ex) {Cu.reportError(ex);}


как там говорят в UCF подключать в scriptschrome:


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

На форуме

 

№191708-03-2025 17:04:48

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

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

Farby пишет

sidebar-button-toggle-state.uc.js

Странное дело, только в этом скрипте в тултипе не работает перенос строки по \n :angry:

Отсутствует

 

№191808-03-2025 18:05:31

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

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

Farby
Работает, спасибо!
Поведение кнопки немого сломалось, давно уже. Не принципиально, конечно.
При закрытии ЛКМ или СКМ фокус улетает на позицию ниже. Т.е. если была панель закладок --> какая-то папка или закладка, фокус сместится на меню закладок. Если меню закладок --> какая-то папка или закладка --> фокус на другие закладки.
Если это сложно, и так сойдёт.))

Отсутствует

 

№191908-03-2025 18:12:10

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

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

fuchsfan пишет

Странное дело, только в этом скрипте в тултипе не работает перенос строки по \n :angry:

Либо вы не правильно задали вопрос, либо я чего-то не понимаю. В этом скрипте я не нахожу вхождения "\n"...
PS: Но parseXULToFragment не понимает "\n", ну так то так, на всякий случай.


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

На форуме

 

№192008-03-2025 19:24:32

_zt
Забанен
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1696
UA: Firefox 128.0

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

fuchsfan
А это?
&#xA;

Отсутствует

 

№192108-03-2025 19:36:14

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

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

_zt пишет

А это?
&#xA;

Оно же так и было в первоисточнике, не пашет, решил, что какой-то символ кракозябрнулся, заменил на \n. Но это уже в прошлом, т.к. не все опции работают, то сократил тултип до одной строки.

Отсутствует

 

№192208-03-2025 22:52:20

_zt
Забанен
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1696
UA: Firefox 128.0

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

fuchsfan
У меня работает.
85c65d278b6810448a2c9a9cda02de56.png
Но оно мне не надо, так как есть
3f842bdcbf765fb54a5978a4299f1ed5.png
Которые и в истории и в sidebartabs работают
Для вашей версии [firefox] скрипты AutoClose...
https://github.com/alice0775/userChrome … master/136

Отредактировано _zt (08-03-2025 22:54:44)

Отсутствует

 

№192309-03-2025 09:43:28

Garalf
Участник
 
Группа: Members
Зарегистрирован: 19-09-2017
Сообщений: 345
UA: Firefox 136.0

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

_zt

https://forum.mozilla-russia.org/viewto … 87#p812487

Не удалось запустить MJS-ку. Поясните пожалуйста, код запуска надо помещать
в custom_scripts.js?

Отсутствует

 

№192409-03-2025 10:43:27

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

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

Garalf пишет

Не удалось запустить MJS-ку.

Есть такая запись, не знаю, правильная или нет.
В папке Firefox использовать config.js с правками от Dumby для активации .JSM, .MJS, кажется, от 09.11.2023, ссылки, увы не имею (или добавить в существующий config.js, где уже имеются антиподписной код).
В папке \chrome\ создать папку \widget\ и в неё поместить файлы скриптов .JSM, .MJS. Их не нужно нигде дополнительно прописывать для активации.
Очистить startupCache.

Добавлено 09-03-2025 10:44:00

_zt пишет

Для вашей версии [firefox] скрипты AutoClose...

Спасибо.

Отредактировано fuchsfan (09-03-2025 10:44:00)

Отсутствует

 

№192509-03-2025 11:50:52

Inko7
Участник
 
Группа: Members
Зарегистрирован: 09-11-2009
Сообщений: 1010
UA: Firefox 136.0

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

С обновлением до FF136, обнаружил некоторые проблемки:
пришло время обносвить сам user_chrome_files на последнюю версию, старый категорически не захотел работать. Всё вроде прописал/подтянул, но скрипт SwitchKeyboardLayout не хочет работать.

F8_kbd_layout.js

Выделить код

Код:

// Назначить клавишу F8 для исправления раскладки введенного текста
// код SwitchKeyboardLayout в файле custom_script.js

try {(id => {
    var listener = {
        get obj() {
            var obj = document.getElementById(id);
            if (obj) obj = obj.linkedObj;
            else {
                obj = Cu.import("resource:///modules/CustomizableUI.jsm", {})
                    .gPalette.get(id);
                if (obj) obj = obj.implementation;
                else {
                    Services.console.logStringMessage(id + " not found");
                    return this.destroy() || {switch() {}};
                }
            }
            delete this.obj; return this.obj = obj;
        },
        handleEvent(e) {
            if (e.key != "F8" || e.ctrlKey || e.shiftKey || e.altKey || e.repeat)
                return;
            //e.preventDefault();
            //e.stopPropagation();
            this.obj.switch(document);
        },
        destroy: function destroy() {
            removeEventListener("keydown", this, true);
            removeEventListener("unload", destroy);
        }
    };
    addEventListener("keydown", listener, true);
    addEventListener("unload", listener.destroy);
})("SwitchKeyboardLayout");} catch(ex) {Cu.reportError(ex);}


kbd_layout.js

Выделить код

Код:

// Switch Keyboard Layout button (порт с СВ)

try {(keybUtils => CustomizableUI.createWidget({
    type: "custom",
    id: "SwitchKeyboardLayout",
    onBuild(doc) {
        var btn = doc.createXULElement("toolbarbutton");
        btn.id = this.id;
        btn.label = btn.tooltipText = "Switch Keyboard Layout";
        btn.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAk1BMVEX///8/Pz8BAQF8fHwJCQkCAgIJCQl8fHx9fX0AAABJSUkBAQENDQ0wMDBVVVUAAABra2t0dHR7e3thYWEBAQEAAAAAAAABAQEAAAAgICABAQEBAQH8/Pzw8PDp6en39/fj4+Pe3t41V9I/YeWKioqDg4N9fX0jRa8wUrVoaGhkhuxWeNx1dXVCZMhvb28kRqsqTL4KidXxAAAAHHRSTlMAAABndwAAAAA0blVZcm1naWhNa6hrcJ8AAKRU4jk/3gAAAHVJREFUeF6FyMUCwjAUBdEbaQupUMOjqMv/fx1dQN6yZ3aDcWnyw6ezoRWNYc15kqKQZCFlgTKQQwgllL/dn5f3+bPb+6P3CpWNw56srdCZOMzDmA61i8O9nKvRaHLVukEryFKIFtnkj7ENYxmNdd5v+5xj1BcJ/w9Kj6K7ZAAAAABJRU5ErkJggg==";

        btn.setAttribute("oncommand", "linkedObj.switch(document);");
        btn.className = "toolbarbutton-1 chromeclass-toolbar-additional";
        btn.linkedObj = this;
        return btn;
    },
    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;
    }
}))(`{
    //== Options
    noSelBehavior: { // Shift+Home
        ctrlKey:  false,
        altKey:   false,
        shiftKey: true,
        metaKey:  false,
        keyCode:  KeyEvent.DOM_VK_HOME,
        charCode: 0
    },
    // 0 - do nothing
    // 1 - convert all text
    // Or use object like following to simulate "keypress" event:

    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);
/*
            if(c in this.convTableForward)
                return true;
            if(c in this.convTableBackward)
                return false;
*/
            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 = new node.ownerGlobal.KeyboardEvent(
            "keypress", {bubbles: true, cancelable: true, ...e}
        );

        node.dispatchEvent(evt);
    },
*/

	if(ChromeUtils.domProcessChild.childID) {
            var cmd = this.beh2cmd[e.ctrlKey + "_" + e.shiftKey + "_" + e.keyCode];
            cmd && docShell.doCommand(cmd);
        }
        else node.dispatchEvent(new node.ownerGlobal.KeyboardEvent(
            "keypress", {bubbles: true, cancelable: true, ...e}
        ));
    },
    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);
    }
}`)} catch(ex) {Cu.reportError(ex);}


В консоли ошибка:

Uncaught TypeError: Cu.import is not a function
    get obj chrome://user_chrome_files/content/custom_scripts/win/F8_kbd_layout.js:10
    handleEvent chrome://user_chrome_files/content/custom_scripts/win/F8_kbd_layout.js:25

Dumby
помоги пожалуйста восстановить работу скрипта

Отсутствует

 

Board footer

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