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

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

№40115-07-2022 04:25:38

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

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

Dobrov
Не все пользуются версией с CustomStylesScripts.jsm и прочими scriptsbackground: [ // В фоне [System Principal]. Мне эта версия UCF непонятна, лично я на старой остался.

Отредактировано xrun1 (15-07-2022 04:27:15)

Отсутствует

 

№40215-07-2022 04:32:07

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

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

xrun1 пишет

Не все пользуются версией с CustomStylesScripts.jsm. Мне эта версия UCF непонятна, лично я на старой остался.

Дополнил шапку, добавил custom_script.js - скрипты добавлять здесь: (async () => { ["ucf_SessionManager.js"]. Процитирую скрипт из шапки:

Выделить код

Код:

// Этот скрипт можно использовать для создания кнопок с помощью CustomizableUI.createWidget
(async (scripts) => { // подключить внешние скрипты
  [['ucf_QuickToggle.js'], ['UCFTitleChangedChild.jsm', 'registerUCFTitleChanged'], ['Test.jsm']]
  .forEach(function(js) { try { if (/\.jsm$/i.test(js[0])) { // [скрипт js или jsm, инициализация]
        var obj = ChromeUtils.import(scripts + js[0]);
        js[1] && obj[js[1]]();
      } else Services.scriptloader.loadSubScript(scripts + js[0]);
    } catch(ex) {Cu.reportError(ex);}
  });
})('chrome://user_chrome_files/content/custom_scripts/');

/* вариант с отдельными скриптами:
(async () => { var loadscript = (name, funcName) => {
  try { var {href, pathname} = new URL(`chrome://user_chrome_files/content/custom_scripts/${name}`);
    if (/\.jsm$/i.test(pathname)) {
      var obj = ChromeUtils.import(href);
      funcName && obj[funcName]();
    } else
      Services.scriptloader.loadSubScript(href);
  }
  catch(ex) {Cu.reportError(ex);}
}
loadscript("ucf_aom-button.js");
loadscript("UCFTitleChangedChild.jsm", "registerUCFTitleChanged");
})();
*/
ez7pac пишет

Скачал этот профиль, посмотрел, почитал - слишком много разных фишек, многие мне ни о чем не говорят, другие мне просто не нужны.

Какие фишки непонятны? Описание есть в спойлере шапки и встроенной справке (спойлер "Полный список▼").
Сообщите, какие конкретно скрипты непонятны и я дополню описание.
.


Ещё можно убрать ненужные скрипты из CustomStylesScripts.jsm и CustomStylesScriptsChild.jsm, оставив базовый ucf_hookClicks.js и нужный вам ucf_SessionManager.js. Впрочем дополнительные скрипты требуют значительно меньше памяти, чем дополнения.

Отредактировано Dobrov (15-07-2022 05:37:18)

Отсутствует

 

№40315-07-2022 19:26:54

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1734
UA: Firefox 102.0

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

ez7pac
xrun1
Этот скрипт... вроде работает в версии UCF 2021-6-5 -> https://forum.mozilla-russia.org/viewto … 17#p797517, код под первым спойлером.


Add, добавить в user_chrome_files/custom_scripts/custom_script.js

Отредактировано kokoss (15-07-2022 20:02:14)


Win7

Отсутствует

 

№40415-07-2022 19:58:29

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 198
UA: Firefox 91.0

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

Dobrov пишет

Сообщите, какие конкретно скрипты непонятны и я дополню описание..

Да не то, чтобы непонятны, просто я мельком пробежался, сильно не вникал. Я ставлю обычно только то, что мне нужно и полезно на данный момент. Ставить пак, пусть и хороший, "шоб було" :D, ради одной фишки - не мое. Вот сейчас из всего списка меня заинтересовал только менеджер сессий. А перебирать пак, удаляя ненужное мне - это косяки, глюки, нервотрепка и т.п. Элементарно не хватит знаний.

kokoss пишет

Этот скрипт... вроде работает в версии UCF 2021-6-5 -> https://forum.mozilla-russia.org/viewto … 17#p797517, код под первым спойлером.

Спасибо. Но код - это хорошо, но еще бы знать куда его впихнуть и не накосячить при этом... :D
Я в принцип работы UCF не въезжаю вообще. userChrome, userContent - еще так, с пятое на десятое, и то нужно носом ткнуть - "вот этот код добавить вот сюда и не забудь вот эту запятую поставить". А UCF - это уже другой уровень.

Отсутствует

 

№40516-07-2022 03:13:10

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 198
UA: Firefox 91.0

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

kokoss пишет

Add, добавить в user_chrome_files/custom_scripts/custom_script.js

Только сейчас увидел ответ. И снова спасибо! Добавил, кнопка появилась, работает менеджер. Я извиняюсь, конечно, но возникли пара вопросов.
1. Работает только ручное сохранение или можно выставить в авто? Если можно, то как включить и как настроить периодичность?
2. Где хранятся сессии?

Отсутствует

 

№40616-07-2022 03:33:00

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

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

ez7pac пишет

1. Работает только ручное сохранение или можно выставить в авто? Если можно, то как включить и как настроить периодичность?
2. Где хранятся сессии?

Сесии храняться в «Профиль Firefox//chrome/simple_session_manager.json»
С авто-сохранением и таймером для него надо обращаться к Dumby, он этот скрипт делал.

Отсутствует

 

№40716-07-2022 14:16:43

ez7pac
Участник
 
Группа: Members
Откуда: Кубань
Зарегистрирован: 27-12-2015
Сообщений: 198
UA: Firefox 91.0

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

Dobrov, понял, спасибо.

Отсутствует

 

№40822-07-2022 05:51:36

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

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

Уважаемые гуру, подскажите, пожалуйста. Есть вот такой скрипт, прекрасно работает на 78. А на 101 не грузится меню с подключёнными стилями (остальное работает). Это реально поправить?

Отсутствует

 

№40922-07-2022 13:38:45

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

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

kazarin пишет

Пробуй, проверял на [firefox] 103, в консоли ошибок нет...

UserCSSLoader.uc.js

Выделить код

Код:

// ==UserScript==
// @name           UserCSSLoader
// @description    Stylish みたいなもの
// @namespace      http://d.hatena.ne.jp/Griever/
// @author         Griever
// @include        main
// @license        MIT License
// @compatibility  Firefox 4
// @charset        UTF-8
// @version        0.0.4改
// @startup        UCL.init();
// @note           0.0.4 Remove E4X
// @note           CSSEntry クラスを作った
// @note           スタイルのテスト機能を作り直した
// @note           ファイルが削除された場合 rebuild 時に CSS を解除しメニューを消すようにした
// @note           uc で読み込まれた .uc.css の再読み込みに仮対応
// ==/UserScript==

/****** 使い方 ******

chrome フォルダに CSS フォルダが作成されるのでそこに .css をぶち込むだけ。
ファイル名が "xul-" で始まる物、".as.css" で終わる物は AGENT_SHEET で、それ以外は USER_SHEET で読み込む。
ファイルの内容はチェックしないので @namespace 忘れに注意。

メニューバーに CSS メニューが追加される
メニューを左クリックすると ON/OFF
					中クリックするとメニューを閉じずに ON/OFF
					右クリックするとエディタで開く

エディタは "view_source.editor.path" に指定されているものを使う
フォルダは "UserCSSLoader.FOLDER" にパスを入れれば変更可能

 **** 説明終わり ****/

(function(){

let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
if (!window.Services)
	Cu.import("resource://gre/modules/Services.jsm");
// 起動時に他の窓がある(2窓目の)場合は抜ける
let list = Services.wm.getEnumerator("navigator:browser");
while(list.hasMoreElements()){ if(list.getNext() != window) return; }

if (window.UCL) {
	window.UCL.destroy();
	delete window.UCL;
}
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

window.UCL = {
	IN_TOOLMENU: false,	// true: ツールメニュー内、 false:メインメニューのヘルプの前
	USE_UC: "UC" in window,
	AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET,
	USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET,
	readCSS    : {},
	get disabled_list() {
		let obj = [];
		try {
			obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|");
		} catch(e) {}
		delete this.disabled_list;
		return this.disabled_list = obj;
	},
	get prefs() {
		delete this.prefs;
		return this.prefs = Services.prefs.getBranch("UserCSSLoader.")
	},
	get styleSheetServices(){
		delete this.styleSheetServices;
		return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
	},
	get FOLDER() {
		let aFolder;
		try {
			// UserCSSLoader.FOLDER があればそれを使う
			let folderPath = this.prefs.getCharPref("FOLDER");
			aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
			aFolder.initWithPath(folderPath);
		} catch (e) {
			aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
			aFolder.appendRelativePath("CSS");
		}
		if (!aFolder.exists() || !aFolder.isDirectory()) {
			aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0664);
		}
		delete this.FOLDER;
		return this.FOLDER = aFolder;
	},
	getFocusedWindow: function() {
		let win = document.commandDispatcher.focusedWindow;
		if (!win || win == window) win = content;
		return win;
	},
	init: function() {
		const cssmenu = $C("menu", {
			id: "usercssloader-menu",
			label: "CSS",
			accesskey: "C"
		});
		const menupopup = $C("menupopup", {
			id: "usercssloader-menupopup"
		});
		cssmenu.appendChild(menupopup);

		let menu = $C("menu", {
			label: "メニュ━━━(゚∀゚)━━━!!",
			accesskey: "C"
		});
		menupopup.appendChild(menu);
		let mp = $C("menupopup", { id: "usercssloader-submenupopup" });
		menu.appendChild(mp);
		mp.appendChild($C("menuitem", {
			label: "Rebuld",
			accesskey: "R",
			acceltext: "Alt + R",
			oncommand: "UCL.rebuild();"
		}));
		mp.appendChild($C("menuseparator"));
		mp.appendChild($C("menuitem", {
			label: "新規作成",
			accesskey: "N",
			oncommand: "UCL.create();"
		}));
		mp.appendChild($C("menuitem", {
			label: "CSS フォルダを開く",
			accesskey: "O",
			oncommand: "UCL.openFolder();"
		}));
		mp.appendChild($C("menuitem", {
			label: "userChrome.css を編集",
//			hidden: true,
			oncommand: "UCL.editUserCSS(\'userChrome.css\');"
		}));
		mp.appendChild($C("menuitem", {
			label: "userContent.css を編集",
//			hidden: true,
			oncommand: "UCL.editUserCSS(\'userContent.css\');"
		}));
		mp.appendChild($C("menuseparator"));
		mp.appendChild($C("menuitem", {
			label: "スタイルのテスト (Chrome)",
			id: "usercssloader-test-chrome",
			hidden: true,
			accesskey: "C",
			oncommand: "UCL.styleTest(window);"
		}));
		mp.appendChild($C("menuitem", {
			label: "スタイルのテスト (Webページ)",
			id: "usercssloader-test-content",
			hidden: true,
			accesskey: "W",
			oncommand: "UCL.styleTest();"
		}));
		mp.appendChild($C("menuitem", {
			label: "userstyles.org でスタイルを検索",
			accesskey: "S",
			oncommand: "UCL.searchStyle();"
		}));

		menu = $C("menu", {
			label: ".uc.css",
			accesskey: "U",
			hidden: !UCL.USE_UC
		});
		menupopup.appendChild(menu);
		mp = $C("menupopup", { id: "usercssloader-ucmenupopup" });
		menu.appendChild(mp);
		mp.appendChild($C("menuitem", {
			label: "Rebuild(.uc.js)",
			oncommand: "UCL.UCrebuild();"
		}));
		mp.appendChild($C("menuseparator", { id: "usercssloader-ucsepalator" }));

		if (this.IN_TOOLMENU) {
			$('menu_ToolsPopup').insertBefore(cssmenu, $('menu_preferences'));
		} else {
			$('main-menubar').insertBefore(cssmenu, $('helpMenu'));
		}

		$("mainKeyset").appendChild($C("key", {
			id: "usercssloader-rebuild-key",
			oncommand: "UCL.rebuild();",
			key: "R",
			modifiers: "alt",
		}));

		this.rebuild();
		this.initialized = true;
		if (UCL.USE_UC) {
			setTimeout(function() {
				UCL.UCcreateMenuitem();
			}, 1000);
		}
		window.addEventListener("unload", this, false);
	},
	uninit: function() {
		const dis = [];
		for (let x of Object.keys(this.readCSS)) {
			if (!this.readCSS[x].enabled)
				dis.push(x);
		}
		this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|")));
		window.removeEventListener("unload", this, false);
	},
	destroy: function() {
		var i = document.getElementById("usercssloader-menu");
		if (i) i.parentNode.removeChild(i);
		var i = document.getElementById("usercssloader-rebuild-key");
		if (i) i.parentNode.removeChild(i);
		this.uninit();
	},
	handleEvent: function(event) {
		switch(event.type){
			case "unload": this.uninit(); break;
		}
	},
	rebuild: function() {
		let ext = /\.css$/i;
		let not = /\.uc\.css/i;
		let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);

		while (files.hasMoreElements()) {
			let file = files.getNext().QueryInterface(Ci.nsIFile);
			if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
			let CSS = this.loadCSS(file);
			CSS.flag = true;
		}
		for (let leafName of Object.keys(this.readCSS)) {
			const CSS = this.readCSS[leafName];
			if (!CSS.flag) {
				CSS.enabled = false;
				delete this.readCSS[leafName];
			}
			delete CSS.flag;
			this.rebuildMenu(leafName);
		}
		if (this.initialized) {
			if (typeof(StatusPanel) !== "undefined")
				StatusPanel._label = "Rebuild しました";
			else
				XULBrowserWindow.statusTextField.label = "Rebuild しました";
		}
	},
	loadCSS: function(aFile) {
		var CSS = this.readCSS[aFile.leafName];
		if (!CSS) {
			CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
			if (this.disabled_list.indexOf(CSS.leafName) === -1) {
				CSS.enabled = true;
			}
		} else if (CSS.enabled) {
			CSS.enabled = true;
		}
		return CSS;
	},
	rebuildMenu: function(aLeafName) {
		var CSS = this.readCSS[aLeafName];
		var menuitem = document.getElementById("usercssloader-" + aLeafName);
		if (!CSS) {
			if (menuitem)
				menuitem.parentNode.removeChild(menuitem);
			return;
		}

		if (!menuitem) {
			menuitem = $C("menuitem", {
				label		: aLeafName,
				id			: "usercssloader-" + aLeafName,
				class		: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : "USER_SHEET"),
				type		: "checkbox",
				autocheck	: "false",
				oncommand	: "UCL.toggle('"+ aLeafName +"');",
				onclick		: "UCL.itemClick(event);"
			});
			document.getElementById("usercssloader-menupopup").appendChild(menuitem);
		}
		menuitem.setAttribute("checked", CSS.enabled);
	},
	toggle: function(aLeafName) {
		var CSS = this.readCSS[aLeafName];
		if (!CSS) return;
		CSS.enabled = !CSS.enabled;
		this.rebuildMenu(aLeafName);
	},
	itemClick: function(event) {
		if (event.button == 0) return;

		event.preventDefault();
		event.stopPropagation();
		let label = event.currentTarget.getAttribute("label");

		if (event.button == 1) {
			this.toggle(label);
		}
		else if (event.button == 2) {
			closeMenus(event.target);
			this.edit(this.getFileFromLeafName(label));
		}
	},
	getFileFromLeafName: function(aLeafName) {
		let f = this.FOLDER.clone();
		f.QueryInterface(Ci.nsIFile); // use appendRelativePath
		f.appendRelativePath(aLeafName);
		return f;
	},
	styleTest: function(aWindow) {
		aWindow || (aWindow = this.getFocusedWindow());
		new CSSTester(aWindow, function(tester){
			if (tester.saved)
				UCL.rebuild();
		});
	},
	searchStyle: function() {
		let word;
		try {
			word = gBrowser.currentURI.host;
		} catch {
			word = gBrowser.currentURI.spec;
		}
		let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
		openLinkIn("https://userstyles.org/styles/search/" + word, "tab", {
								private: false,
								inBackground: false,
								relatedToCurrent: true,
								triggeringPrincipal: systemPrincipal,
								});
	},
	openFolder: function() {
		this.FOLDER.launch();
	},
	editUserCSS: function(aLeafName) {
		let file = Services.dirsvc.get("UChrm", Ci.nsIFile);
		file.appendRelativePath(aLeafName);
		this.edit(file);
	},
	edit: function(aFile) {
		var editor = Services.prefs.getCharPref("view_source.editor.path");
		if (!editor) return alert("エディタのパスが未設定です。\n view_source.editor.path を設定してください");
		try {
			var UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
			UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8";
			var path = UI.ConvertFromUnicode(aFile.path);
			var app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
			app.initWithPath(editor);
			var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
			process.init(app);
			process.run(false, [path], 1);
		} catch (e) {}
	},
	create: function(aLeafName) {
		if (!aLeafName) aLeafName = prompt("ファイル名を入力してください", dateFormat(new Date(), "%Y_%m%d_%H%M%S"));
		if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
		if (!aLeafName || !/\S/.test(aLeafName)) return;
		if (!/\.css$/.test(aLeafName)) aLeafName += ".css";
		let file = this.getFileFromLeafName(aLeafName);
		this.edit(file);
	},
	UCrebuild: function() {
		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
		let query = "?" + new Date().getTime();
		Array.prototype.slice(document.styleSheets).forEach(function(css){
			if (!re.test(css.href)) return;
			if (css.ownerNode) {
				css.ownerNode.parentNode.removeChild(css.ownerNode);
			}
			let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"');
			document.insertBefore(pi, document.documentElement);
		});
		UCL.UCcreateMenuitem();
	},
	UCcreateMenuitem: function() {
		let sep = $("usercssloader-ucsepalator");
		let popup = sep.parentNode;
		if (sep.nextSibling) {
			let range = document.createRange();
			range.setStartAfter(sep);
			range.setEndAfter(popup.lastChild);
			range.deleteContents();
			range.detach();
		}

		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
		Array.prototype.slice(document.styleSheets).forEach(function(css) {
			if (!re.test(css.href)) return;
			let fileURL = decodeURIComponent(css.href).split("?")[0];
			let aLeafName = fileURL.split("/").pop();
			let m = $C("menuitem", {
				label		: aLeafName,
				tooltiptext	: fileURL,
				id			: "usercssloader-" + aLeafName,
				type		: "checkbox",
				autocheck	: "false",
				checked		: "true",
				oncommand	: "this.setAttribute('checked', !(this.css.disabled = !this.css.disabled));",
				onclick		: "UCL.UCItemClick(event);"
			});
			m.css = css;
			popup.appendChild(m);
		});
	},
	UCItemClick: function(event) {
		if (event.button == 0) return;
		event.preventDefault();
		event.stopPropagation();

		if (event.button == 1) {
			event.target.doCommand();
		}
		else if (event.button == 2) {
			closeMenus(event.target);
			let fileURL = event.currentTarget.getAttribute("tooltiptext");
			let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL);
			this.edit(file);
		}
	},
};

function CSSEntry(aFile) {
	this.path = aFile.path;
	this.leafName = aFile.leafName;
	this.lastModifiedTime = 1;
	this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ? 
		Ci.nsIStyleSheetService.AGENT_SHEET: 
		Ci.nsIStyleSheetService.USER_SHEET;
}
CSSEntry.prototype = {
	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
	_enabled: false,
	get enabled() {
		return this._enabled;
	},
	set enabled(isEnable) {
		var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
		aFile.initWithPath(this.path);
	
		var isExists = aFile.exists(); // ファイルが存在したら true
		var lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
		var isForced = this.lastModifiedTime != lastModifiedTime; // ファイルに変更があれば true

		var fileURL;
			try {
					fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile);
			} catch {
					fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
			}

		var uri = Services.io.newURI(fileURL, null, null);

		if (this.sss.sheetRegistered(uri, this.SHEET)) {
			// すでにこのファイルが読み込まれている場合
			if (!isEnable || !isExists) {
				this.sss.unregisterSheet(uri, this.SHEET);
			}
			else if (isForced) {
				// 解除後に登録し直す
				this.sss.unregisterSheet(uri, this.SHEET);
				this.sss.loadAndRegisterSheet(uri, this.SHEET);
			}
		} else {
			// このファイルは読み込まれていない
			if (isEnable && isExists) {
				this.sss.loadAndRegisterSheet(uri, this.SHEET);
			}
		}
		if (this.lastModifiedTime !== 1 && isEnable && isForced) {
			log(this.leafName + " の更新を確認しました。");
		}
		this.lastModifiedTime = lastModifiedTime;
		return this._enabled = isEnable;
	},
};

function CSSTester(aWindow, aCallback) {
	this.win = aWindow || window;
	this.doc = this.win.document;
	this.callback = aCallback;
	this.init();
}
CSSTester.prototype = {
	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
	preview_code: "",
	saved: false,
	init: function() {
		this.dialog = openDialog(
			"data:text/html;charset=utf8,"+encodeURIComponent('<!DOCTYPE HTML><html lang="ja"><head><title>CSSTester</title></head><body></body></html>'),
			"",
			"width=550,height=400,dialog=no");
		this.dialog.addEventListener("load", this, false);
	},
	destroy: function() {
		this.preview_end();
		this.dialog.removeEventListener("unload", this, false);
		this.previewButton.removeEventListener("click", this, false);
		this.saveButton.removeEventListener("click", this, false);
		this.closeButton.removeEventListener("click", this, false);
	},
	handleEvent: function(event) {
		switch(event.type) {
			case "click":
				if (event.button != 0) return;
				if (this.previewButton == event.currentTarget) {
					this.preview();
				}
				else if (this.saveButton == event.currentTarget) {
					this.save();
				}
				else if (this.closeButton == event.currentTarget) {
					this.dialog.close();
				}
				break;
			case "load":
				var doc = this.dialog.document;
				doc.body.innerHTML = '\
					<style type="text/css">\
						:not(input):not(select) { padding: 0px; margin: 0px; }\
						table { border-spacing: 0px; }\
						body, html, #main, #textarea { width: 100%; height: 100%; }\
						#textarea { font-family: monospace; }\
					</style>\
					<table id="main">\
						<tr height="100%">\
							<td colspan="4"><textarea id="textarea"></textarea></td>\
						</tr>\
						<tr height="40">\
							<td><input type="button" value="Preview" /></td>\
							<td><input type="button" value="Save" /></td>\
							<td width="80%"><span class="log"></span></td>\
							<td><input type="button" value="Close" /></td>\
						</tr>\
					</table>\
				';
				this.textbox = doc.querySelector("textarea");
				this.previewButton = doc.querySelector('input[value="Preview"]');
				this.saveButton = doc.querySelector('input[value="Save"]');
				this.closeButton = doc.querySelector('input[value="Close"]');
				this.logField = doc.querySelector('.log');

				var code = "@namespace url(" + this.doc.documentElement.namespaceURI + ");\n";
				code += this.win.location.protocol.indexOf("http") === 0?
					"@-moz-document domain(" + this.win.location.host + ") {\n\n\n\n}":
					"@-moz-document url(" + this.win.location.href + ") {\n\n\n\n}";
				this.textbox.value = code;
				this.dialog.addEventListener("unload", this, false);
				this.previewButton.addEventListener("click", this, false);
				this.saveButton.addEventListener("click", this, false);
				this.closeButton.addEventListener("click", this, false);

				this.textbox.focus();
				let p = this.textbox.value.length - 3;
				this.textbox.setSelectionRange(p, p);

				break;
			case "unload":
				this.destroy();
				this.callback(this);
				break;
		}
	},
	preview: function() {
		var code = this.textbox.value;
		if (!code || !/\:/.test(code))
			return;
		code = "data:text/css;charset=utf-8," + encodeURIComponent(this.textbox.value);
		if (code == this.preview_code)
			return;
		this.preview_end();
		var uri = Services.io.newURI(code, null, null);
		this.sss.loadAndRegisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET);
		this.preview_code = code;
		this.log("Preview");
	},
	preview_end: function() {
		if (this.preview_code) {
			let uri = Services.io.newURI(this.preview_code, null, null);
			this.sss.unregisterSheet(uri, Ci.nsIStyleSheetService.AGENT_SHEET);
			this.preview_code = "";
		}
	},
	save: function() {
		var data = this.textbox.value;
		if (!data) return;

		var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
		fp.init(window, "", Ci.nsIFilePicker.modeSave);
		fp.appendFilter("CSS Files","*.css");
		fp.defaultExtension = "css";
		if (window.UCL)
			fp.displayDirectory = UCL.FOLDER;
		var res = fp.show();
		if (res != fp.returnOK && res != fp.returnReplace) return;

		var suConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
		suConverter.charset = "UTF-8";
		data = suConverter.ConvertFromUnicode(data);
		var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
		foStream.init(fp.file, 0x02 | 0x08 | 0x20, 0664, 0);
		foStream.write(data, data.length);
		foStream.close();
		this.saved = true;
	},
	log: function() {
		this.logField.textContent = dateFormat(new Date(), "%H:%M:%S") + ": " + $A(arguments);
	}
};

UCL.init();

function $(id) { return document.getElementById(id); }
function $A(arr) { return Array.prototype.slice(arr); }
function $C(name, attr) {
	const el = document.createElementNS(XULNS, name);
	if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) });
	return el;
}
function dateFormat(date, format) {
	format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4));
	format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2));
	format = format.replace("%d", ("0" + date.getDay()).substr(-2));
	format = format.replace("%H", ("0" + date.getHours()).substr(-2));
	format = format.replace("%M", ("0" + date.getMinutes()).substr(-2));
	format = format.replace("%S", ("0" + date.getSeconds()).substr(-2));
	return format;
}

function log() { Application.console.log(Array.prototype.slice(arguments)); }

})();


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

Отсутствует

 

№41022-07-2022 23:24:10

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

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

Farby
Меню появилось, но стили не отключаются и не обновляются. Проверял на чистой 102 ESR.


UPD Скрипт заработал! Правда, запускается он каким-то извращённым способом: во-первых, ему нужен пустой (ну или запиканный звёздочками) userChrome.css. В принципе, он его и так игнорит, но ни в 78, ни в доквантумных версиях наличие записей там ему не мешало. А во-вторых, после редактирования userChrome.css обновить надо через кнопку Reload user{Chrome, Content}.css. Тогда он видит изменения и потом уже начинает нормально работать.

Спасибо, что починили, очень уж удобный скрипт, приходилось держать вместо него три кнопки, которые не охватывали полностью его функций:)

Отредактировано kazarin (24-07-2022 15:22:42)

Отсутствует

 

№41126-07-2022 16:26:44

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

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

egorsemenov06 пишет

посмотрите пожалуйста кнопку Save.В ней не работает функция "Сохранить значок веб-сайта"

Опять изменили аргументы в internalSave()

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

Выделить код

Код:

/*
if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15
	? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
	: (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);
*/
if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 16
	? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
	: internalSave.length == 15
		? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
			internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
		: (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
			internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);

Отсутствует

 

№41226-07-2022 19:37:03

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

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

Заметил, что если включить стили в настройках расширения - перестают работать клавиши вызова боковой панели (ctrl+B, ctrl+H). Это можно как-то починить? (на всякий случай выложил папку https://disk.yandex.ru/d/SCyAqLNnyxbTRw)

скрытый текст
uFscb0O.png


upd: виновник этого безобразия - auto_hide_sidebar.css

Отредактировано Northtech (29-01-2023 00:20:59)

Отсутствует

 

№41302-08-2022 10:52:53

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

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

egorsemenov06 пишет

не работает функция "Сохранить выделеный текст как txt фаил"

А, saveURL() тоже

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

Выделить код

Код:

…
	//var splice = saveURL.length == 10;
	var {length} = saveURL, splice = length > 9, l11 = length == 11;

…

		//splice && args.splice(5, 0, null);
		splice && args.splice(5, 0, null) && l11 && args.splice(1, 0, null);

Отредактировано Dumby (02-08-2022 11:25:53)

Отсутствует

 

№41402-08-2022 11:21:55

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

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

Dumby - получается, что теперь нужны два скрипта?
А может лучше проверять на версию FF, как infocatcher делает?
Тогда бы один скрипт работал на прежнем и новом Firefox…

Отсутствует

 

№41502-08-2022 11:26:24

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

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

Dobrov пишет

получается, что теперь нужны два скрипта?

О чём речь, позволь поинтересоваться?

Отсутствует

 

№41602-08-2022 11:28:56

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

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

о проверке версий:
например AppConstants.MOZ_APP_VERSION больше 102 -> выполняем один код, меньше -> другой прежний.


Это наверное поможет, если Опять изменили аргументы в internalSave()

Отредактировано Dobrov (02-08-2022 11:30:13)

Отсутствует

 

№41702-08-2022 11:40:15

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

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

Dobrov
То есть, речь об этой правке.
Тогда скажи на какой версии Firefox эта правка
сломала обратную совместимость, попробую посмотреть.

Отсутствует

 

№41802-08-2022 11:43:01

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

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

Dumby пишет

Тогда скажи на какой версии Firefox эта правка
сломала обратную совместимость, попробую посмотреть.

Не знаю, если новая правка работает на всех Firefox, начиная с 90, тогда ладно.


Я откатился на FF97, когда страницы стали непонятно тормозить и долго загружаться на FF102.

Отсутствует

 

№41904-08-2022 09:44:19

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

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

egorsemenov06 пишет

addDestructor is not defined

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


Но дело в другом (см. также).
Пока, можно добавить в код одну строку про "lazy".

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

Выделить код

Код:

…
	let g = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {});
	if("lazy" in g) g = g.lazy;

Отредактировано Dumby (04-08-2022 09:47:22)

Отсутствует

 

№42018-08-2022 22:43:30

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

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

Dobrov, уважаемый, можно вопрос по вашей кнопке Quick toggle for about:config preferences (Dobrov mod)?

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

Выделить код

Код:

window.SetDownloadDir = function (path, path_old) {
	path = window.convertFromUnicode("UTF-8", path); path_old = window.convertFromUnicode("UTF-8", path_old) || '';
	if ( path != path_old ) {
		cbu.setPrefs("browser.download.folderList", 2);
		cbu.setPrefs("browser.download.useDownloadDir", true);
		cbu.setPrefs("browser.download.dir", path);
	} return path;
};

window.PathToDownloadDir = function (change) { // null возврат папки загрузки true тоже + открыть папку загрузки 2 изменить папку загрузки - обзор. возврат папки загрузки раньше диалога выбора
// 	try { var path = Services.prefs.getComplexValue("browser.download.dir", Ci.nsISupportsString).data }
	try { var path = Services.downloads.userDownloadsDirectory.path }
	catch(e) { path = Services.downloads.defaultDownloadsDirectory.path };
	if ( change == true ) {
		var file = Services.dirsvc.get('ProfD', Ci.nsIFile);
		file.initWithPath(path);
		file.launch();
	}
	if (typeof change == 'string') path = window.SetDownloadDir(change, path); // изменить путь загрузок
	if (change == 2) {
		var fp = window.makeFilePicker();
		fp.init(window, "Выберите папку для загрузок!", 2);
		fp.open(re=> { if ( re == fp.returnOK ) return window.SetDownloadDir(fp.file.path, path) });
	} return path;
};

window.PathToDownloadFolder = function (change) { // Получить\Открыть (change=false)\Изменить путь к папке загрузки (change=true или текст)
	try { var path = Services.downloads.userDownloadsDirectory.path }
	catch(e) { path = Services.downloads.defaultDownloadsDirectory.path };
	if ( change == false ) {
		var file = Services.dirsvc.get('ProfD', Ci.nsIFile);
		file.initWithPath(path);
		file.launch();
	} if ( !change ) return path; // arg == undefined || arg == false
	var fp = window.makeFilePicker();
	fp.init(window, "Выберите папку для загрузок!", 2);
	fp.open(re=> {
		if ( re != fp.returnOK ) return;
		cbu.setPrefs("browser.download.folderList", 2);
		cbu.setPrefs("browser.download.useDownloadDir", true);
		cbu.setPrefs("browser.download.dir", window.convertFromUnicode("UTF-8", fp.file.path));
	})
};

window.Title = function (type) { // заголовок (без обрезки, если type не указан), домен (type <0)
	var title = (content.document.title || gBrowser.mCurrentTab.label);
	var host = (/about:/.test(gURLBar.value)) ? // ReaderView или страница about:…
		decodeURIComponent(gURLBar.value).replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,'') :
		gBrowser.currentURI.host;
	if (/^file:\/\//.test(gBrowser.currentURI.spec)) host = ''; // открыт локальный файл
	if ( !type ) return title; // заголовок
	if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/  /g,' ').substr(0, type).trim(); // ограничить длину имени
	if ( type < 0 ) return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns');
};


// Быстрое переключение параметров about:config от 24.07.2016 [FIX Dobrov]
// Изменить иконку при несоответствие любого параметра пользовательскому предпочтению (см. ниже)
// Иконка меняется только при изменении параметров через меню кнопки, либо после его открытия.

var s='CB.hasNotUserChoice', str = ' Быстрые настройки';
// str = 'profile: '+ OS.Constants.Path.profileDir;
str = str +'\n Правый клик: опции браузера';
str = str +'\n Держать: открыть about:config';
str = str +'\n\n Proxy(VPN): …порт: '+ cbu.getPrefs("network.proxy.http_port");
str = str +'\n '+ cbu.getPrefs("network.proxy.http");
this.tooltipText = str;
// str = str +'\n'+ OS.Constants.Path.libxul;
// str = str +'\n'+ OS.Constants.Path.homeDir;
// str = str +'\n'+ OS.Constants.Path.desktopDir;
// str = str +'\n'+ OS.Constants.Path.winAppDataDir; // undefined
// str = str +'\n'+ OS.Constants.Path.winLocalAppDataDir; // undefined
// str = str +'\n'+ OS.Constants.Path.winStartMenuProgsDir; // undefined
// str = str +'\n'+ OS.Constants.Path.winStartMenuProgsDir; // undefined
// str = str +'\n'+ OS.Constants.Path.macUserLibDir; // undefined
// str = str +'\n'+ OS.Constants.Path.macLocalApplicationsDir; // undefined

function toggleImage(){
	custombuttons.getPrefs(s) ? self.style.cssText = '' : self.style.cssText = 'filter: grayscale(100%)';
};
toggleImage();Services.prefs.addObserver(s,toggleImage,false);addDestructor(()=>Services.prefs.removeObserver(s,toggleImage));

var menuPopup = self.appendChild(document.createXULElement("menupopup"));
menuPopup.id='quick-aboutconfig-menupopup'; // для стиля в userChrome.css
var menuContext = self.appendChild(document.createXULElement("menupopup"));

// для действия Сохранить как… Web-страница будет в кодировке Win1251. на FF ниже 60 в GIT не видно выпадающего списка версий
var useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:78.0) Gecko/20100101 Firefox/78.0"; //,,,Firefox 78/MacOSX|||\
var useragent_name = "Firefox 78/MacOSX";

[
{nodeName:"menu", name:"Прокси (VPN)", pref:"network.proxy.type", refresh:"", image:"chrome://browser/skin/privatebrowsing-mask.png", userChoice:2, strValues:"0,,,отключен,,,0|||2,,,Автонастройка,,,2|||4,,,…для текущей сети,,,4|||5,,,Системный,,,5"},

{nodeName:"menu", name:"URL автонастройки", pref:"network.proxy.autoconfig_url", refresh:"", userChoice:"https://antizapret.prostovpn.org/proxy.pac", strValues:"https://antizapret.prostovpn.org/proxy.pac,,,АнтиЗапрет,,,1|||file:///etc/proxy.pac,,,.pac файл,,,2|||https://git.io/ac-anticensority-pac,,,ac-anticensority,,,3|||127.0.0.1,,,Отключен,,,0"},	//https://rebrand.ly/ac-anticensority
{nodeName:"checkbox", name:"режим 'Без прокси' при выходе", pref:"CB.Proxy.reset", userChoice:"false"},
{nodeName:"menuseparator"},
{nodeName:"menu", name:"Загружать шрифты Web", pref:"browser.display.use_document_fonts", strValues:"0,,,Выкл,,,|||1,,,Вкл,,,"},
{nodeName:"checkbox", name:"Выполнять скрипты Java", pref:"javascript.enabled", key:'j', userChoice:"true"},
{nodeName:"checkbox", name:"Сообщить о загрузке страницы", pref:"dom.enable_performance", userChoice:"false"},
{nodeName:"menuseparator"},
{nodeName:"checkbox", name:"автопроигрывание мультимедиа", pref:"media.autoplay.enabled", key:'m', userChoice:"true"},
{nodeName:"menuseparator"},
{nodeName:"menu", name:"User Agent", pref:"general.useragent.override", key:'u', refresh:"", userChoice: useragent, strValues: "\
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:100.0.1) Gecko/20100101 Firefox/101.0.1.0,,,Firefox 101.0.1/MacOSX|||\
Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727),,,MSIE 6.0/Windows|||\
Mozilla/5.0 (Linux; Android 7.0; PLUS Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36,,,Chrome61/Android7|||\
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30,,,Safari 6/MacOSX|||\
Mozilla/5.0 (Linux; Android 5.1.1; SM-G928X Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36,,,Samsung Galaxy S6|||\
Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73 (KHTML, like Gecko),,,Playstation 4|||\
Xbox (Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Xbox One (mobile)|||\
Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Microsoft Lumia 950|||\
Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; GT-I8350),,,Windows Phone|||\
Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html),,,GoogleBot|||\
,,,Пустое значение"},
// Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots),,,YandexBot|||\
// Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm),,,BingBot|||\
// Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp),,,YahooBot|||\
// Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html),,,BaiduspiderBot|||\
// ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com),,,AlexaCrawlerBot|||\
// DuckDuck bot/1.0; (+http://duckduckgo.com/duckduckbot.html),,,DuckDuckBot|||\
].forEach( (m)=> {
	CreateMenu(m, menuPopup); // какое меню создавать
});


[
{nodeName:"menu", name:"Куки", pref:"network.cookie.cookieBehavior", refresh:"", userChoice:"0", strValues:"0,,,Разрешить все сайты,,,|||2,,,Запретить все сайты,,,|||3,,,Сторонние посещённые сайты,,,|||1,,,Не принимать со сторонних сайтов,,,"},
{nodeName:"menu", name:"Загружать графику", pref:"permissions.default.image", refresh:"", userChoice:1, strValues:"1,,,Да|||3,,,Site only|||2,,,Нет"},
// 1,2,3; 1 разрешить изображения, 2 отключить; 3 изображения с основного веб-сайта, блокировать со сторонних (third-party) серверов
{nodeName:"menu", name:"Анимация изображений", pref:"image.animation_mode", key:'i', refresh:"", userChoice:"normal", strValues:"normal,,,вкл.,,,|||none,,,выкл.,,,"},
{nodeName:"checkbox", name:"OnLine видео  'dom.workers'", pref:"dom.workers.enabled", key:'w', userChoice:"true"},
{nodeName:"menuseparator"},
{nodeName:"checkbox", name:"Откл. дискового кэша", pref:"browser.cache.disk.enable", userChoice:"false"},
{nodeName:"checkbox", name:"Откл. кэша в оперативной памяти", pref:"browser.cache.memory.enable", userChoice:"false"},
{nodeName:"checkbox", name:"Локальное хранилище indexedDB", pref:"dom.indexedDB.enabled", key:'d', userChoice:"true"},
{nodeName:"checkbox", name:"Откл. локального хранилища", pref:"dom.storage.enabled", key:'s'},
{nodeName:"menuseparator"},
// {nodeName:"menu", name:"Back-story-cash [Tessssttt]", pref:"browser.sessionhistory.max_total_viewers", strValues:"0,,,0"},
// {nodeName:"menuseparator"},
{nodeName:"menu", name:"useragent.locale", pref:"general.useragent.locale", key:'l', restart:"", strValues:"en-US,,,English,,,e|||ru-RU,,,Рус (ru-RU),,,r|||ru,,,русский (ru),,,"},
{nodeName:"menu", name:"language", pref:"intl.accept_languages", strValues:"en-US, en;q=0.5,,,en-US, en;q=0.5,,,e|||en-US, en, ru-RU, ru,,,en-US, en, ru-RU, ru,,,r"},
{nodeName:"menu", name:"document_color_use", pref:"browser.display.document_color_use", key:'c', userChoice:"0", strValues:"0,,,Auto,,,0|||1,,,Always,,,1|||2,,,Never,,,2"},
{nodeName:"menuseparator"},
{nodeName:"checkbox", name:"В качестве реферера корень сайта", pref:"network.http.referer.spoofSource", userChoice:"true"},
{nodeName:"menu", name:"Вкл/Выкл Referer", pref:"network.http.sendRefererHeader", userChoice:"2", strValues:"0,,,0|||2,,,2"},
{nodeName:"menu", name:"referer.trimmingPolicy", pref:"network.http.referer.trimmingPolicy", strValues:"0,,,0|||2,,,2"},
{nodeName:"menuseparator"},
{nodeName:"checkbox", pref:"media.mediasource.enabled", userChoice:"true"},
{nodeName:"checkbox", pref:"media.peerconnection.enabled"},		//WebRTC false=off!
{nodeName:"checkbox", name:"Многопоточность вкладок (CPU)", pref:"browser.tabs.remote.autostart", restart:"", userChoice:"false"},	//about:support=Multiprocess Windows|forum.ru-board.com/topic.cgi?forum=5&topic=49695&start=0&limit=1&m=9#1
{nodeName:"menuseparator"},
// {nodeName:"checkbox", name:"On/Off useragentS", pref:"general.useragent.site_specific_overrides"},
// useragent +",,,"+ useragent_name +"|||\
].forEach( (m)=> {
	CreateMenu(m, menuContext); // контекстное меню
});


function CreateMenu(m, menuNew) {

	if (m.nodeName==="checkbox" || m.nodeName==="radio")
		var mItem = document.createXULElement('menuitem') // для checkbox, radio
	else
		var mItem = document.createXULElement(m.nodeName);

	var addCommand=''; // создать элементы меню

	if ("refresh" in m)	addCommand = ' BrowserReload();';
	if ("restart" in m)	addCommand = ' if (custombuttons.confirmBox(null, "Restart?", "Yes", "Cancel")) Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);';


	if ("image" in m) mItem.setAttribute('image', m.image);
	if ("name" in m) mItem.setAttribute('name', m.name);
	if ("pref" in m) {
		mItem.setAttribute('closemenu', 'none');
		mItem.setAttribute('oncontextmenu', 'event.preventDefault();custombuttons.clearPrefs("'+m.pref+'");'+ addCommand);
	}
	if ("key" in m) mItem.setAttribute('accesskey', m.key);

// тип radio не добавлен !!!
	if (m.nodeName==="checkbox") {

		mItem.setAttribute('type', 'checkbox');
		mItem.setAttribute('oncommand','custombuttons.setPrefs("'+m.pref+'",!custombuttons.getPrefs("'+m.pref+'"));if (event.shiftKey && event.keyCode==event.DOM_VK_RETURN){event.preventDefault();custombuttons.clearPrefs("'+m.pref+'")};'+addCommand);
	}
	// if (m.nodeName==="radio") {
	// 	if ("name" in m) mItem.setAttribute('label', m.name);
	// 	mItem.setAttribute('type', 'radio');
	// 	mItem.setAttribute('oncommand','custombuttons.setPrefs("'+m.pref+'",!custombuttons.getPrefs("'+m.pref+'"));'+addCommand);
	// }

	if (m.nodeName === "menu") {
		mItem.setAttribute('class', 'menu-iconic');
		var subMenu = mItem.appendChild(document.createXULElement("menupopup"));
	 for (var value of m.strValues.split('|||')) {
		var submItem = document.createXULElement("menuitem");
		var smVal = value.split(',,,')[0];
		var smValConv = convertFromUnicode("UTF-8", smVal);
		var smName = value.split(',,,')[1];
		var key = value.split(',,,')[2];
		key && submItem.setAttribute('accesskey', key);
		submItem.setAttribute('type', 'radio');
		submItem.setAttribute('label', smName);
		submItem.setAttribute('tooltiptext', smVal);
		submItem.setAttribute('closemenu', 'none');
		submItem.setAttribute('oncommand', 'try{custombuttons.setPrefs("'+ m.pref +'","'+ smValConv.replace(/\\/g,'\\\\')+'")}catch(e){Services.prefs.setIntPref("'+ m.pref +'","'+ smValConv +'")};'+ addCommand);
		subMenu.appendChild(submItem);
	 }
	}

	menuNew.appendChild(mItem);


// Листенеры отслеживания переключения параметров и устанавка соответствующих названий и чекбоксов для пунктов меню при открытии меню и кликах
 for (var type of ['command', 'popupshowing', 'contextmenu']) {
	addEventListener(type, (e)=> {
	 setTimeout(()=> {
		if ("pref" in m) {
			var val, def;
			def = Services.prefs.prefHasUserValue(m.pref);

			try {
				val = Services.prefs.getComplexValue(m.pref, Ci.nsISupportsString).data;
			} catch(e) {
				if (Services.prefs.getPrefType(m.pref) == 64) val = custombuttons.getPrefs(m.pref).toString();
				else val = custombuttons.getPrefs(m.pref);
			}
			def ? mItem.style.setProperty('font-weight', 'bold', 'important') : mItem.style.removeProperty('font-weight');
		}

		if (m.nodeName === 'checkbox') {
			mItem.setAttribute('checked', val);
			mItem.label = ( mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref );

			if ("userChoice" in m) { // отображение значения +' - "'+val+'"';
				try {var usrChc = (val.toString() === m.userChoice)} catch(e) {usrChc = false};
				mItem.setAttribute('user-choice', usrChc);
				usrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color', 'orangered', 'important');
			}
		}

		if (subMenu) {
			for (var smitem of subMenu.getElementsByTagName('menuitem')) {
				var smval = smitem.getAttribute('tooltiptext');
				smitem.setAttribute('checked', (val === smval) ? true : false);
			}
		}

		if (m.nodeName === "menu") {
			var vname;

			try {
				vname = subMenu.getElementsByAttribute('checked', 'true')[0].getAttribute('label');
			} catch(e) {
				if (!Services.prefs.prefHasUserValue(m.pref)) vname = 'Default';
				else vname = 'Other';
			}

			mItem.setAttribute('label', ( mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref ) +' - "'+ vname +'"');
			mItem.setAttribute('tooltiptext', val || 'This preferences has null value or does not exist.');

			if ("userChoice" in m) {
				var smUsrChc = (val === m.userChoice.toString());

				mItem.setAttribute('user-choice', smUsrChc);
				smUsrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color', 'orangered', 'important');
			}
		}

		if ("userChoice" in m) {
			var hasNotUserChoice = menuNew.getElementsByAttribute('user-choice', 'false')[0];

			custombuttons.setPrefs(s, hasNotUserChoice ? true : false);
		}
	 }, 0)
	}, false, menuNew)
 }

}; // End CreateMenu



// Конвертировать текст в юникод .............
function convertFromUnicode(charset,str) {var converter=Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset=charset;str=converter.ConvertFromUnicode(str);return str+converter.Finish();};

var switchOffProxy = { // Переключать на режим 'Без прокси' при закрытии браузера если это разрешено в 'about:config'
	observe: function(subject, topic, data) {
	if ( data == "shutdown" && cbu.getPrefs("CB.Proxy.reset") ) cbu.setPrefs("network.proxy.type",0);
	}
};
Services.obs.addObserver(switchOffProxy, "quit-application", false);

// nodeName: checkbox - для логических(boolean) параметров, menu - для целых(integer) и строковых(string). menuseparator - для разделителя.
// pref - параметр about:config.
// Параметры имеющие значения отличные от дефолтных - выделены жирным стилем текста.
// restart (задавать с пустым значением. т.е., restart: "") - перезапуск браузера (с подтверждением в диалоговом окне) после изменения параметра.
// key - задает accesskey - клавиши для быстрой навигации по меню.
// userChoice - задает предпочитаемое значение и если текущее значение с ним не совпадает, пункт меню/название меню помечаются красным цветом.
// Также можно установить предупреждающую иконку для таких пунктов. См. стиль в посте ккнопки. А также меняется иконка самой кнопки (см. выше).
// strValues - значения и отображаемое в меню название значения. Задавать для целых(integer) и строковых(string) параметров.
// Задается в виде: значение,,,название,,,accesskey|||значение2,,,название2,,,accesskey2|||значение3,,,название3 и т.д. (accesskey - задается опционально)
// Полное значение отображается в подсказках, при наведении на название подменю/пункт подменю.
// Для логических(boolean) - отображается сразу после самого параметра (значение true - также ставит галочку для него).
// ЛКМ по пунктам меню - переключает значения для логических(boolean) параметров,
// любая кнопка по пунктам в субменю - задает это значение для целых(integer) и строковых(string) параметров.
// Клавиатура: Enter - переключение параметра.
// Alt + M - открыть меню кнопки. (Сочетание можно сменить на свое. См. в конце кода)
// ПКМ по пунктам меню и названию субменю - сбрасывает значение параметра в дефолтное (сейчас перехватывается кликом по кнопке).
// Спецклавиша вызова контекстного меню / Shift+Enter - сброс в дефолтное значение (убрал это действие).

// Настройка функций кликов мыши для кнопки, учитывая долгое нажатие
	var longPress = false; // долгое нажатие
function handleEvent(event) {
  switch(event.type)
  {	case"mouseover": // можно обновлять tooltip кнопки
	  0
		// this.setAttribute('Popup.state', menuPopup.state); // состояние меню: открыто/скрыто
		// this.setAttribute('menuContext.state', menuContext.state); // состояние меню: открыто/скрыто
		break;
	case"mousedown":
		self.timer = setTimeout(()=> { // удержание
			if ( event.target.localName == "menuitem" ) return;
			longPress = true; // блокировка обычных кликов
			if ( event.button == 0 ) { // ЛКм Long
				window.switch_tab_url('about:config');
			} else if ( event.button == 2 ) { // ПКм Long
// 				setPathToDownloadFolder();
				window.switch_tab_url('about:preferences#content');
			} else if ( event.button == 1 ) { // СКм Long
				0
			}
		}, 500 );
		break;
	case"mouseup": // отжатие кнопки
		clearTimeout(self.timer); // сброс таймера долгих нажатий
		if ( longPress ) { longPress = false } // выполнялась команда долгих нажатий, сброс флага и выход
		else if ( event.button == 0 ) { // ЛКм
			if ( /open|showing/.test(this.getAttribute('Popup.state')) || /open|showing/.test(this.getAttribute('menuContext.state')) ) {// показать/скрыть меню, замена функции this._handleClick
				menuPopup.hidePopup();
				menuContext.hidePopup()
			} else
				menuPopup.openPopup(this,'after_start');
			if ( !/open|showing/.test(this.getAttribute('menuContext.state')) ) // показать/скрыть меню, замена функции this._handleClick
				this.setAttribute('Popup.state', menuPopup.state); // видимость Popup. выполнить также на "mouseover" ( или один раз глобально в конце handleEvent)
			 	this.setAttribute('menuContext.state', menuContext.state); // видимость Popup. выполнить также на "mouseover" ( или один раз глобально в конце handleEvent)
		} else if ( event.button == 2 && !event.altKey && !event.metaKey) { // ПКм
			if ( event.ctrlKey && event.shiftKey ) { // +Ctrl +Shift
				var host = gURLBar.inputField;
				var str = 'host ' + host + "\n" +
				decodeURIComponent(gBrowser.currentURI.spec) + "\n" +
				'+1 '+ window.Title(33) + "\n" +
				'=0 '+ window.Title(0) + "\n" +
				'-1 '+ decodeURIComponent(window.Title(-1)) + "\n";
// 				URLBarInput.value + '/n';
// 				gURLBar.mInputField;
				// window.show_tooltip(0, '', str, 5000);
			}
			if ( event.ctrlKey) { // +Ctrl
// 				window.SavSnapshot();
				var info = custombuttons.cbService.readFromClipboard();
// 				info = document.getElementById('tabbrowser-tabs').clientWidth;
//				info = gBrowser.tabs.clientWidth;
				window.statusTextField(info);
			} else if ( event.shiftKey) { // +Shift
				window.PathToDownloadFolder("/home");
			} else {
// 				window.switch_tab_url('about:config');
			if (/open|showing/.test(this.getAttribute('menuContext.state'))) // показать/скрыть меню, замена функции this._handleClick
				menuContext.hidePopup()
			else
				menuContext.openPopup(this,'after_start');
		 	this.setAttribute('menuContext.state', menuContext.state); // видимость Popup. выполнить также на "mouseover" ( или один раз глобально в конце handleEvent)
			}
			event.preventDefault();
			event.stopPropagation();
		} else if ( event.button == 1 ) { // СКм
			custombuttons.editButton(this); // Редактировать кнопку…
		}
		break;
	case"DOMMouseScroll": // ролик мыши над кнопкой
		event.detail > 0 ? FullZoom.reduce() : FullZoom.enlarge();
		break;
	case"contextmenu": // ПКм+Alt или Meta откроет контекстное меню
		menuContext.hidePopup();
		if(!event.altKey && !event.metaKey) event.preventDefault();	// event.stopPropagation();
		// break;
  }
// команды при выполнении любых событий
};
// var this_event = ["mousedown", "mouseup", "mouseover", "contextmenu", "draggesture", "DOMMouseScroll"]
var this_event = ["mousedown", "mouseup", "mouseover", "draggesture", "DOMMouseScroll"]
	.forEach((type)=> this.addEventListener(type, handleEvent, false));

// Горячие клавиши: действия. коды: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Constants_for_keyCode_value
addEventListener("keyup", (e)=>{
	if (e.altKey && !e.shiftKey && !e.ctrlKey && e.keyCode==77){ // сочетание клавиш Alt+M
		e.preventDefault();e.stopPropagation();
		menuPopup.showPopup(this,-1,-1,"popup","bottomleft","topleft");
	}
}, false,window);

// Блокировать контекстное меню при клике ПКМ, +Ctrl, +Shift
this.oncontextmenu = function(e) { if(e.button == 2 && !e.altKey && !e.metaKey) { e.preventDefault(); e.stopPropagation(); } };

// Листенер позволяющий сброс параметров с субменю по Shift + Enter // За код спасибо Dumby
// addEventListener("popupshown", {
// 	handleEvent: function(e) {
// 		this[e.type](e);
// 	},
// 	popupshown: function(e) {
// 		if (e.target != menuPopup) return;
// 		menuPopup.addEventListener("popuphidden", this, false);
// 		window.addEventListener("keydown", this, true);
// 	},
// 	popuphidden: function(e) {
// 		if (e.target != menuPopup) return;
// 		menuPopup.removeEventListener("popuphidden", this, false);
// 		window.removeEventListener("keydown", this, true);
// 	},
// 	popupshowing: function(e) {
// 		e.target.parentNode.removeEventListener("popupshowing", this, false);
// 		e.preventDefault();
// 	},
// 	get old() {
// 		delete this.old;
// 		this.e = new MouseEvent("contextmenu", {});
// 		return this.old = parseInt(Services.appinfo.platformVersion) < 25;
// 	},
// 	get prop() {
// 		delete this.prop;
// 		if ("key" in KeyboardEvent.prototype) this.prop = "key", this.val = "Enter";
// 		else this.prop = "keyCode", this.val = KeyboardEvent.DOM_VK_RETURN;
// 		return this.prop;
// 	},
// 	keydown: function(e) {
// 		if (!e.shiftKey || e.ctrlKey || e.altKey || e[this.prop] != this.val) return;
// 		var target = menuPopup.querySelector("menu[_moz-menuactive]:not([open])");
// 		if (!target) return;

// 		this.old ? target.addEventListener("popupshowing", this, false) : e.stopPropagation();
// 		target.dispatchEvent(this.e);
// 		menuPopup.dispatchEvent(this.e);
// 	}
// }, false, menuPopup);




// pref:"network.proxy.autoconfig_url", refresh:"", userChoice:"https://antizapret.prostovpn.org/proxy.pac", strValues:"https://antizapret.prostovpn.org/proxy.pac,,,АнтиЗапрет,,,1|||file:///etc/proxy.pac,,,.pac файл,,,2|||https://git.io/ac-anticensority-pac,,,ac-anticensority,,,3"},	//https://rebrand.ly/ac-anticensority

// {nodeName:"checkbox", pref:"xpinstall.signatures.required"},		//Check is compatibility
// {nodeName:"checkbox", pref:"browser.bookmarks.autoExportHTML"},		//BookmarksHtml [false=places.sqlite]
// {nodeName: "menu", pref: "CB.TEST", key: 't', userChoice: "C:\\Downloads\\TEST1", strValues: "C:\\Downloads\\TEST1,,,TEST1,,,1|||C:\\Downloads\\TEST2,,,TEST2,,,2"},

// var mPrefs = "network.proxy.autoconfig_url";


// }, 100);

// window.statusTextField(gBrowser.docShell.charset +' '+ m.value +'_'+ decodeURIComponent(window.hostname()));

// 			tmp = (self.image == imgFlashToPlayer || self.image == imgFlashMinimize ||  self.image == imgFlashMaximize);
// 			if(m.value.substring(0,9)=='videotopl')
// 				self.image = tmp ? imgFlashToPlayer : imgHTML5ToPlayer;



// 	Menu_n_TooltipTxts.forEach((m) => {
// 	// window.show_tooltip(0, '', m, 5000);

// 	var mItem = document.createXULElement("menuitem");
// 		if("radio" in m) {
// 			// 0
// 			// l = l + ( cbu.getPrefs(mPrefs) == m.value ) + '\n';
// 			mItem.setAttribute('checked', cbu.getPrefs(mPrefs) == m.value);
// 		}
// //		menuContext.appendChild(mItem);
// 	});


// mItem.getAttribute('name')
// mItem.setAttribute("type", "radio");

// mItem.setAttribute('label', ( mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref ) +' - "'+ vname +'"');
// mItem.setAttribute('tooltiptext', val || 'This preferences has null value or does not exist.');

// {nodeName:"checkbox", name:"Загружать графику", radio:"", pref:"permissions.default.image", refresh:"", userChoice:1, strValues:"1,,,On"},
// {nodeName:"checkbox", name:"не Загружать графику", radio:"", pref:"permissions.default.image", refresh:"", strValues:"2,,,Off"},


Код привёл, потому что тут на форуме было много вариаций, а мне нравится именно эта. Обычно у меня всегда включен по умолчанию Автонастройка - Антизапрет, и до этого никакие сайты на это не ругались. Но сегодня (вчера ещё всё было в порядке) forum.ru-board.com выдал: "Прокси-сервер отказывается принимать соединения". Поскольку ничего другогоу меня подключено не было, я отключил антизапрет, и форум загрузился. Почему он стал реагировать на кнопку, и можно ли это как-то поправить? Захожу часто, постоянно включать-отключать не радует.

Отсутствует

 

№42119-08-2022 02:21:38

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

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

kazarin - Антизапрет переодически не работает на некоторых сайтах - флибуста и прочие.
Для Антизапрета нужно установить два пункта меню: 1) Прокси - Антизапрет 2) Режим прокси - Автонастройка.
С виду код вроде рабочий, но советую обновить кнопку. Приведённый код сильно устарел - актуальный от апреля 2022 (требуется 2 скрипта: ucf_QuickToggle.js + глобальный ucf_hookClicks.js).


в моём профиле (в шапке темы) переключение прокси делается проще: долгий клик по Замку или кнопке Quick toggle.

Отсутствует

 

№42219-08-2022 23:37:17

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

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

Dobrov
Спасибо за ответ!
Поторопился я писать, сегодня уже всё грузится - наверно, на стороне форума были косяки.
Код рабочий и работает отлично, пользуюсь им уже давно и он очень нравится мне в том виде, что есть)) Посмотрел новую версию, это вообще совсем другой скрипт, с другими функциями, он её не заменит.

Отсутствует

 

№42327-08-2022 17:52:45

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

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

egorsemenov06
Тяп-ляп — папка long_left_click
Загружать из неё в сандбокс скрипт startup.js
Например

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

Выделить код

Код:

…
    scriptsbackground: [ // В фоне [System Principal]
        …
        { path: "long_left_click/startup.js" },


Настройки — about:llc
скрытый текст

Выделить код

Код:

data:application/x-zip-compressed;base64,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

Отсутствует

 

№42427-08-2022 19:27:54

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1734
UA: Firefox 104.0

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

Dumby пишет

Тяп-ляп — папка long_left_click
Загружать из неё в сандбокс скрипт startup.js
Например
скрытый текст

Настройки — about:llc
скрытый текст

Интересный вариант, запихнуть расширение в UCF :beer:

Отредактировано kokoss (27-08-2022 19:29:21)


Win7

Отсутствует

 

№42528-08-2022 23:50:10

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

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

egorsemenov06 пишет

в этот скрипт можно добавить стиль что бы иконкии были все на одном уровне

В скрипт? Это принципиально?
Просто может лучше добавить в стиль для менюшек первой строкой:
#ID menuitem,
где ID — id кнопки Save.

Отсутствует

 

Board footer

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