Dumby
Здравия! Сделайте пожалуйста что бы этот скрипт: https://forum.mozilla-russia.org/viewto … 03#p776503 работал в актуальных версиях [firefox] !


P,S, и только для открытия истории из журнала и боковой панели в новой вкладке.

kokoss
У меня нет userChrome.js, нужно железное обоснование (и ссылка),
почему именно userChrome.js, ведь у тебя есть UCF.


Недавно же sandro79 обращал наше внимание на то,
что в 96 отвалился ucf_wheretoopenlink.js. А отвалился он потому,
что Bug 1742801 «move whereToOpenLink and getRootEvent implementations into BrowserUtils».


Я тогда попытался набросать новый вариант, и вот теперь уже,
переделать под только Журнал (боковушка ведь тоже озаглавлена как Журнал).
Так что, если хочешь, попробуй (это в custom_script.js).

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

Выделить код

Код:

(async sel => {
	var trees = ["places", "historySidebar"];
	var url = "resource://gre/modules/BrowserUtils.jsm";
	var bu = ChromeUtils.import(url).BrowserUtils, {whereToOpenLink} = bu;

	bu.whereToOpenLink = function(e) {
		var res = whereToOpenLink.apply(bu, arguments);
		if (res != "current" || !Event.isInstance(e)) return res;
		try {
			var skip = true, trg = e.composedTarget, win = trg.ownerGlobal;
			var name = win.document.documentURIObject
				.QueryInterface(Ci.nsIURL).fileName.slice(0, -6);

			if (name == "browser")
				skip = win.gBrowser.selectedTab.isEmpty || !trg.closest(sel);

			else if (trees.includes(name))
				skip = (win.opener || win.windowRoot.ownerGlobal).gBrowser.selectedTab.isEmpty
					|| trg.closest("tree").selectedNode.itemId != -1;

			return skip ? res : "tab";
		}
		catch {return res;}
	}
})("#historyMenuPopup,#PanelUI-history");

Dumby
Класс, при чём работает и в старой версии UCF!!! Благодарю :beer:


Add, всё же придётся перейти на актуальную версию UCF, в ней этот скрипт работает правильно!

Dumby пишет

Так что, если хочешь, попробуй (это в custom_script.js)

Благодарю за замену для ucf_wheretoopenlink.js для 96+
Работает по журналу отлично: с окна библиотеки, с боковой панели, с меню бутерброда, с вкладки chrome://browser/content/places/places.xhtml, в общем везде где есть журнал.
Работает как с user_chrome_files, так и с этим комплектом - одинаково, что меня очень обрадовало. Надо будет ещё с этим комплектом потестить.
Dumby, ну сделайте пожалуйста подобный компактный (873 байт) скрипт для версий [firefox] < 96. По идее должен будет наверно и в 78 работать.
И огромноая благодарность Вам за кнопку «вывести на кнопку индикацию muted-состояния активной вкладки» Тоже забрал на замену, работает отлично!

sandro79 пишет

Работает как с user_chrome_files, так и с этим комплектом - одинаково, что меня очень обрадовало.

А меня это огорчает. Сколько раз было сказано,
что коды для для custom_script.js не следует совать в окна.
Но, видимо, это слишком сложная мысль.
Я даже не понимаю зачем это может понадобиться,
какой-то поиск приключений браузеру на ...

подобный компактный (873 байт) скрипт для версий [firefox] < 96

Кстати, в скрипте есть баг: в Библиотеке, в закладках,
в новой вкладке также открывается добро исторических кверей,
типа «Двадцать часто посещаемых», а это не есть Журнал.


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


Код для custom_script_win.js (вот его можно во всяких там комплектах проверять).
Набирал из-под 77, в 98 вроде тоже работает.

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

Выделить код

Код:

(async sel => {
	var wtol = whereToOpenLink;
	whereToOpenLink = function whereToOpenLink(e) {
		var res = wtol.apply(window, arguments);
		return res == "current" && !gBrowser.selectedTab.isEmpty &&
			Event.isInstance(e) && e.composedTarget.closest(sel) ? "tab" : res;
	}
	var puu = PlacesUIUtils, key = "openNodeWithEvent";
	if (puu[key].name.startsWith("b")) return;

	var bt = Object.create(puu), bwt = BrowserWindowTracker;
	bt._openNodeIn = (node, where, win) => {
		if (where == "current" && node.itemId == -1 &&
			!(win.opener || bwt.getTopWindow()).gBrowser.selectedTab.isEmpty
		)
			where = "tab";
		puu._openNodeIn(node, where, win);
	}
	puu[key] = puu[key].bind(bt);
})("#goPopup,#historyMenuPopup,#PanelUI-history");

Dumby пишет

А меня это огорчает. Сколько раз было сказано, что коды для для custom_script.js не следует совать в окна

Да, это я припоминаю, но как запасной вариант что ли, так то вроде нормально работает в классических комплектах, ну навскидку. Впредь буду осмотрительней.

типа «Двадцать часто посещаемых», а это не есть Журнал

Да это не страшно, мелочи, пусть как фича будет.

Код для custom_script_win.js (вот его можно во всяких там комплектах проверять)

Скрипт подключал в custom_script_win.js в 69 и 78, в 91 и 98 в CustomStylesScripts.jsm в scriptschrome: { // Для докум. окна браузера [ChromeOnly]
Везде всё проверил, вроде всё как надо, работает везде по журналу, ну по мне - получилось отлично.
В основном использую журнал из автоскрываемой боковой панели, с журнала панели меню и значка в виде часов, размещённого на панели меню.
Огромное Спасибо! :beer:

как сделать чтоб было как в Центе нажать правой кнопкой на ссылку и было чтоб Скопировать текст ссылки
5.1692165433.png

казявка
Уж не знаю что за Цент,
а для лисы как-то так, наверно

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

Выделить код

Код:

(async (id, url) => {
	if (location != url) return;
	var menuitem = document.createXULElement("menuitem");
	document.getElementById(id).after(menuitem);
	var hidden = () => !nsContextMenu.contentData.context.linkTextStr;	
	menuitem.hidden = true;
	menuitem.render = () => {
		if (hidden()) return;
		menuitem.hidden = false;
		menuitem.id = id + "text";
		menuitem.label = "Скопировать текст ссылки";
		menuitem.setAttribute("oncommand", "navigator.clipboard.writeText(gContextMenu.linkTextStr);");
		delete menuitem.render;
		menuitem.render();
		menuitem.render = () => menuitem.hidden = hidden();
	}
})("context-copylink", "chrome://browser/content/browser.xhtml");

Dumby
ВЫ волшебник! я неделю наверно  искал в гугле в яндексе как так сделать и не нашел и пришлось ставить расширение Copy Link Text - а ВЫ на коленке сделали мою мечту - кладу ВАМ в карман огромное БЛШ СПС!

Dumby пишет

а для лисы как-то так, наверно

Если этот скрипт прописать в userChrome.js от Aris-t2 или Endor8, то при каждом открытии главной консоли (Ctrl + Shift + J) такая ошибка:
Uncaught (in promise) TypeError: document.getElementById(...) is null
хотя это не мешает работе, т.е. текст ссылки копируется

6e73epo пишет

Uncaught (in promise) TypeError: document.getElementById(...) is null

Да, точно! userChrome же.
Следует проверять, что это именно документ окна браузера.
Я избалован UCF'ским custom_script_win.js, где такая проверка не требуется,
вот и вылетело из головы. Подправил.

@Dumby
Здравствуйте. У вас есть скрипт под ucf, добавляющий функцию открытия встроенного родного прогресса загрузки файла при старте загрузки, а не по ее окончании
https://forum.mozilla-russia.org/viewto … 32#p801732
В Firefox v115 он уже не работает, но я даже не об этом. Просьба адаптировать его, чтобы он работал в среде Aris-t2. Благодарю. Речь о встроенном окне загрузки в виде поп-апа, а не о классическом самостоятельном окне загрузки.

fuchsfan пишет

Здравствуйте. У вас есть скрипт под ucf, добавляющий функцию открытия встроенного родного прогресса загрузки файла при старте загрузки, а не по ее окончании
https://forum.mozilla-russia.org/viewto … 32#p801732
В Firefox v115 он уже не работает

Ну почему не работает, у меня работает!
:offtopic:

fuchsfan пишет

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

Почему у тебя в sandbox'е не работает я без понятия.
А в окно можно попробовать, например, так

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

Выделить код

Код:

(async (flag, url) => {
	if (location != url) return;
	await delayedStartupPromise;
	if (Downloads[flag]) return;
	Downloads[flag] = true;

	var bwt = BrowserWindowTracker;
	var show = function(download) {
		download.newDownloadNotified ||
		bwt.getTopWindow(this)?.DownloadsPanel.showPanel();
	};
	["PUBLIC", "PRIVATE"].forEach(async (type, ind) => {
		var view = Object.create(null);
		view.private = Boolean(ind);
		view.onDownloadChanged = show;
		(await Downloads.getList(Downloads[type])).addView(view);
	});
})("806555", "chrome://browser/content/browser.xhtml");

Dumby пишет

А в окно можно попробовать, например, так

Благодарю, работает как надо. И с Aris-t2, и с UCF...

leshiy_odessa пишет

Решил вернуть себе нижнюю панель по типа AddonBar.

Эта панель работает в v117, v118b7, v119a1. На пару строчек ниже есть эта же панель с кнопкой скрыть\показать панель. Здесь https://forum.ru-board.com/topic.cgi?fo … tart=220#4 еще одна работающая нижняя панель с очень маленьким кодом в 20 строк. Там же в шапке описание активации скриптов методом Aris-t2, при внимательном выполнении совершенно не вызывает трудностей, я бы удалил все и выполнил повторно.

fuchsfan пишет

Эта панель работает в v117, v118b7, v119a1. На пару строчек ниже есть эта же панель с кнопкой скрыть\показать панель.

А вы можете показать скриншот этой кнопки или написать где её искать?

fuchsfan пишет

я бы удалил все и выполнил повторно.

Дя я уже несколько раз всё перепроверял и переустанавливал. Есть подозрение что где-то конфликт.

leshiy_odessa пишет

А вы можете показать скриншот этой кнопки или написать где её искать?

Она сразу появилась в правом верхнем углу браузера, или смотрите в настройке панелей инструментов, и вытащить оттуда.
but.png

fuchsfan пишет

Она сразу появилась в правом верхнем углу браузера, или смотрите в настройке панелей инструментов, и вытащить оттуда.

Да спасибо, у меня только что заработало с кнопки Restart, а потом начал добавлять остальное. Где я ошибся так и не понял.
Спасибо за помощь.

update И снова всё пропало. :(

 
update2 Како-то ломаю синтаксис — userChrome.js

Dumby
Вроде на форуме нет темы по скриптам, подключаемых по методам
метод Aris-t2   метод xiaoxiaoflood   метод Endor8
Может нужно создать тему по этим методам.
Поэтому попрошу Вас здесь посмотреть скрипт ucf-mem-indicator.js
Он перестал работать в 115. Применяю метод Endor8 для загрузки скриптов.

скрытый текст
ucf-mem-indicator.js

Выделить код

Код:

(async id => ({

  delay: 2e3,

  val: "",
  init(topic, mm) {
    Services.obs.addObserver(mm = this, topic);
    Services.obs.addObserver(function quit(s, t) {
      this.timer?.cancel();
      Services.obs.removeObserver(mm, topic);
      Services.obs.removeObserver(quit, t);
    }, "quit-application-granted");
  },
  observe(win) {
    var df = win.MozXULElement.parseXULToFragment(
      `<hbox id="${id}" tooltiptext="${
        "ЛКМ: Минимизировать потребление памяти&#xA;ПКМ: about:performance&#xA;Ctrl+ПКМ: about:debugging#/runtime/this-firefox"
      }" onclick="event.button || ${
        "memoryMinimizationButton.doMinimize(event)"
      }"><label id="${id += "-label"}"/></hbox>`
    );
    this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    (this.observe = async win => {
      this.timer.cancel();
      await new Promise(ChromeUtils.idleDispatch);
      var clone = win.document.importNode(df, true);
      clone.firstChild.oncontextmenu = this.about;
      win.document.getElementById("star-button-box").after(clone);
      this.notify();
    })(win);
  },
  about(e) {
    var gb = e.view.gBrowser;
    gb.selectedTab = gb.addTrustedTab(`about:${
      e.ctrlKey ? "debugging#/runtime/this-firefox" : "performance"
    }`);
  },
  async notify() {
    var info = await ChromeUtils.requestProcInfo();
    var bytes = info.memory;
    for(var child of info.children) bytes += child.memory;
    this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT);

    var prev = this.val;
    if ((this.val = this.mgb(bytes)) != prev)
      for(var win of CustomizableUI.windows) {
        var lab = win.document.getElementById(id);
        if (lab) lab.value = this.val;
      }
  },
  mgb: bytes => bytes < 1073741824
    ? Math.round(bytes / 1048576) + "MB"
    : (bytes / 1073741824).toFixed(2) + "GB"
}).init("browser-delayed-startup-finished"))("ucf-mem-indicator");

Открыть папку Chrome, Profiles хоткеем

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

Выделить код

Код:

// OpenChromeFolder(Alt+C).uc.js

(function(win){
    function openChromeDirectory() {
      // Get the chrome directory.
      let currUChrm = Services.dirsvc.get("UChrm", Ci.nsIFile);
      let chromeDir = currUChrm.path;
      // Show the chrome directory.
      let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1","nsIFile", "initWithPath");
      new nsLocalFile(chromeDir).reveal();
    }
    if (typeof win.openChromeDirectory == 'undefined') {
        win.openChromeDirectory = openChromeDirectory;
        win.addEventListener('keydown', function(e) {
            if (e.altKey == true && e.keyCode == 67) {
                e.preventDefault();
                openChromeDirectory();
            }
        }, false);
    }
})(window);

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

Выделить код

Код:

// OpenProfileFolder(Alt+P).uc.js

(function(win){
    function openProfileDirectory() {
        Components.classes["@mozilla.org/file/directory_service;1"]
              .getService(Components.interfaces.nsIProperties)
              .get("ProfD", Components.interfaces.nsIFile)
              .launch();
    }
    if(typeof win.openProfileDirectory == 'undefined') {
        win.openProfileDirectory = openProfileDirectory;
        win.addEventListener('keydown', function(e) {
            if (e.altKey == true && e.keyCode == 80) {
                e.preventDefault();
                openProfileDirectory();
            }
        }, false);
    }
})(window);

rubel пишет

Dumby
Вроде на форуме нет темы по скриптам, подключаемых по методам
метод Aris-t2   метод xiaoxiaoflood   метод Endor8
Может нужно создать тему по этим методам.

А что по названию темы непонятно... ?!

rubel пишет

Применяю метод Endor8 для загрузки скриптов.

То есть, насколько могу судить, скрипты грузятся
в top-level окна документов с адресом с протоколом chrome://
и по событию "load".


В первом приближении, перерисовал так

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

Выделить код

Код:

location.href.endsWith("://browser/content/browser.xhtml") && (async id => {
	var g = Cu.getGlobalForObject(Cu);
	g[id] || Services.scriptloader.loadSubScript("data:charset=utf-8," + encodeURIComponent(`(${id => this[id] = {

		delay: 2e3,

		val: "",
		init(win) {
			var df = win.MozXULElement.parseXULToFragment(
				`<hbox id="${id}" tooltiptext="${
					"ЛКМ: Минимизировать потребление памяти&#xA;ПКМ: about:performance&#xA;Ctrl+ПКМ: about:debugging#/runtime/this-firefox"
				}" onclick="event.button || ${
					"memoryMinimizationButton.doMinimize()"
				}"><label id="${id += "-label"}"/></hbox>`
			);
			this.cui = win.CustomizableUI;
			var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
			this.next = timer.initWithCallback.bind(null, this, this.delay, timer.TYPE_ONE_SHOT);

			(this.init = win => {
				timer.cancel();
				var clone = win.document.importNode(df, true);
				clone.firstChild.oncontextmenu = this.about;
				win.document.getElementById("star-button-box").after(clone);
				this.notify();
			})(win);
		},
		about(e) {
			var gb = e.view.gBrowser;
			gb.selectedTab = gb.addTrustedTab(`about:${
				e.ctrlKey ? "debugging#/runtime/this-firefox" : "performance"
			}`);
		},
		async notify() {
			var info = await ChromeUtils.requestProcInfo();
			var bytes = info.memory;
			for(var child of info.children) bytes += child.memory;
			this.next();

			var prev = this.val;
			if ((this.val = this.mgb(bytes)) != prev)
				for(var win of this.cui.windows) {
					var lab = win.document.getElementById(id);
					if (lab) lab.value = this.val;
				}
		},
		mgb: bytes => bytes < 1073741824
			? Math.round(bytes / 1048576) + "MB"
			: (bytes / 1073741824).toFixed(2) + "GB"

	}})("${id}");`), g);

	g[id].init(window);
})("urlbar-memory-indicator");

Dumby
Огромное спасибо, работает превосходно. :)

Dumby, существует ли возможность на кнопке в onCommand: function(event) {...)  прописать команды, чтобы кнопка открывала определенный раздел реестра через запуск regedit? Просто ответьте да или нет.

Вит

Вит пишет

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

Эта боковая панель входит в состав UCF, выдирается ли она оттуда как самостоятельный скрипт, не знаю. Если у вас UCF не установлен, то вот вам боковая панель от Aris-t2 https://github.com/Aris-t2/CustomJSforF … ical.uc.js

Вит пишет

Не появляется, видимо из-за конфликта

У вас v115, видимо, вам нужна версия скрипта постарее https://github.com/Aris-t2/CustomJSforF … ical.uc.js. Та, что в посту выше, исправлена автором для v117 и выше. Оба скрипта на своих версиях активируются совершенно легко и без бубна.

6e73epo пишет

Dumby, существует ли возможность на кнопке в onCommand: function(event) {...)  прописать команды, чтобы кнопка открывала определенный раздел реестра через запуск regedit? Просто ответьте да или нет.

Ну, как сказать, вот состряпал тестовую кнопку, и мне открывает.


Если использовать launch(); то открывает
только с нуля, то есть когда regedit не запущен,
иначе просто активируется окно, в котором открыто то, что открыто.


А если прицепить ключ «/m», то открывает всегда, но всегда в новом окне.


Вобщем, ответ, скорее «да».

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

Выделить код

Код:

(async (regedit, file) => CustomizableUI.createWidget({
	id: "regedit-opener",
	label: "RegEdit",
	localized: false,
	onCreated(btn) {
		file = Services.dirsvc.get("WinD", Ci.nsIFile);
		file.append("regedit.exe");
		var img = "moz-icon:file://" + file.path;
		(this.onCreated = btn => btn.image = img)(btn);
	},
	onCommand() {

		var path = "Компьютер\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Mozilla";

		var wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(Ci.nsIWindowsRegKey);
		wrk.open(wrk.ROOT_KEY_CURRENT_USER, regedit, wrk.ACCESS_WRITE);
		wrk.writeStringValue("LastKey", path);

		//file.launch();

		var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
		process.init(file);
		process.runwAsync(["/m"], 1);
	}
}))("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit");

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

Совсем забыл про "WinD" и делал типа такого: Services.env.get("windir") + "\\regedit.exe". А вместо wrk.open и process.runwAsync прописывал соответственно излишнее wrk.create и process.run

Теперь по вашему коду:
Без проверки на окно пишет, что CustomizableUI не определен. А почему ошибок нет через try {} catch(e) {}? Получается, что при запуске браузера идет как минимум 2 обращения и какое-то из них с ошибкой, но мы ее не видим? Или еще как-то писали про возвращение promise и при try это происходит позже на этапе, когда уже CustomizableUI инициализирован?
Компьютер\\ можно убрать, это автоматом дописывается.
wrk.close() стоит добавить или нет необходимости?
Если runwAsync без аргументов, то правильней ([], 0) или (null, null)?

6e73epo пишет

Без проверки на окно пишет, что CustomizableUI не определен.

Ну, я-то, разумеется, в custom_script.js добавил.
Вызывать CustomizableUI.createWidget() следует только один раз,
поэтому в окнах такой код слегка неуместен.


Если нет выбора, то хотя бы следует проверять, что виджет уже создавался.
Типа флаг какой-нибудь куда-нибудь поставить, или, может проверять, что
CustomizableUI.getWidget(id).provider равно (или не равно) "api"


К тому же, если коде самого виджета есть что-то связанное с promise, какой-то async, то если
закрыть окно браузера в котором виджет создавался, то этот функционал перестанет работать.

А почему ошибок нет через try {} catch(e) {}? Получается, что при запуске браузера идет как минимум 2 обращения и какое-то из них с ошибкой, но мы ее не видим?

Видим мы ошибку, или не видим, зависит от того, что находится в блоке catch.
Если там что-то типа Cu.reportError(e) или console.error(e), то дожно быть видно.
А если блок catch пустой, то тогда неудивительно, на то он и try.


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

Или еще как-то писали про возвращение promise и при try это происходит позже на этапе, когда уже CustomizableUI инициализирован?

Нет, try никак не должен влиять. Да это и не важно.
Первый же инлайн скрипт в browser.xhtml подгружает скрипт browser.js
который устанавливает в окно кучу геттеров модулей, среди которых и CustomizableUI.


То есть, это ещё до события "DOMContentLoaded".
Не думаю, что существует какой-либо uc-загрузчик, который подгружает скрипты так рано.
Ноборот, дожидаются этого сбытия, или даже события "load".

Компьютер\\ можно убрать, это автоматом дописывается.

Хорошая находка.
Я-то просто написал по-аналогии с тем, что там увидел.

wrk.close() стоит добавить или нет необходимости?

О, кстати да, лучше добавить.

Если runwAsync без аргументов, то правильней ([], 0) или (null, null)?

Как правильней мне, конечно, не известно, но если метод принимает null
без негативных последствий, то и хорошо, не создаётся ненужный пустой массив.
(null, 0) выглядит логичней.
С другой стороны, если без аргументов, то почему бы не просто file.launch();
возможно, есть приемущество в асинхронном вызове, типа UI браузера не подвиснет,
пока он за файлом сходит, не знаю.

Dumby, благодарю за подробные ответы. Добавил проверку на окно, теперь ошибок нет. Думаю, что дополнительных проверок не требуется и виджет повторно не запустится, иначе будет ошибка нормализации. Дополнительных окон никогда не открываю.
Состряпал кнопку для открытия папки Roaming. Не знаю, правильно или нет, но работает и без ошибок. Иконки не нужны, т.к. вывожу кнопки на доп. панель в текстовом виде

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

Выделить код

Код:

// Import from userChrome.js
location.href.endsWith("://browser/content/browser.xhtml") && (async (file) => CustomizableUI.createWidget({
	id: "openfolder-roaming",
	label: "roaming",
	tooltiptext: "Open Users/./Roaming",
	localized: false,
	onCreated() {
		file = Services.dirsvc.get("XREUSysExt", Ci.nsIFile).parent.parent;
	},
	onCommand() {
		if (file.exists()) file.launch();
	}
}))();

6e73epo пишет

Состряпал кнопку для открытия папки Roaming. Не знаю, правильно или нет, но работает и без ошибок.

Возможно, стоит добавить, что вроде как есть свойство "AppData"
по которому Services.dirsvc.get() отдаст папку Roaming сразу,
и обращение к parent'ам не потребуется.


И добавить, что это всё, конечно, должно подходить для установленной версии,
но вот, например, у меня портабельные лисицы на libportable,
так вот там, ни "XREUSysExt", ни "AppData", да вообще почти ничего,
никакой папки Roaming в пути не содержат.


Насколько я вижу, остались только "Progs" (четыре раза parent) и "CookD" (три раза parent).
Ещё можно от "Home" прибавить AppData и Roaming.
Ну, это я в том смысле, что если стоит задача получить с такой лисицы именно «Users/./Roaming».

Dumby, в линуксе и маке вроде должны работать "XREUserNativeManifests" и "XRESysNativeManifests"

6e73epo пишет

в линуксе и маке

Об этих ничего не знаю.
Но попробовал сейчас на Debian, и показывает так:


XRESysNativeManifests —> /usr/lib/mozilla
XREUserNativeManifests —> /home/dumby/.mozilla


Мне это ни о чём не говорит :).

Dumby
А возможно ли приспособить скрипт SingleHTML.jsm в загрузчик метода Endor8 ?
Очень нужный скрипт.

paths — путь до папки со скриптами (.js, .jsm, mjs), в данном случае %Профиль%\chrome\widget\
content — хром-регистрация на эту папку, в данном случае chrome://widget/content/

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

Выделить код

Код:

// UCF In background [System Principal] by Dumby, tested FF 115+
(async topic => {
	let ucf = async doc => {
		try { (async (xpc, cui) => {
			let paths = ["chrome", "widget"], content = "widget";

			let {ChromeUtils, Services} = Cu.getGlobalForObject(Cu),
				imp = ChromeUtils.import, impESM = ChromeUtils.importESModule,
				{XPCOMUtils} = impESM(xpc), {CustomizableUI} = impESM(cui);
			let sb = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(),
				{wantComponents: true, sandboxName: "ucfBox", sandboxPrototype: globalThis,});
			Object.assign(sb, {Services, XPCOMUtils, CustomizableUI, ChromeUtils});
		
			XPCOMUtils.defineLazyGlobalGetters(sb, [
				"atob", "btoa", "crypto", "fetch", "Blob", "CSS", "CSSRule", "Document",
				"DOMException", "DOMParser", "Element", "Event", "File", "FileReader", "FormData",
				"Headers", "InspectorUtils", "Node", "NodeFilter", "PathUtils", "Range", "Selection",
				"TextDecoder", "TextEncoder", "URL", "URLSearchParams", "XMLHttpRequest", "XMLSerializer"
			]);
			let m = {console: "Console"};
			m.AddonManager = m.AppConstants = m.E10SUtils = m.FileUtils = m.PlacesUtils = false;
			for (let [key, val] of Object.entries(m)) m[key] = `resource://gre/modules/${val || key}.sys.mjs`;
			m.setTimeout = m.setTimeoutWithTarget = m.clearTimeout = m.setInterval
				= m.setIntervalWithTarget = m.clearInterval = "resource://gre/modules/Timer.sys.mjs";
			ChromeUtils.defineESModuleGetters(sb, m);

			let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
			paths.forEach(dir.append);
			let ams = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
			sb[Symbol()] = ams.registerChrome(Services.io.newFileURI(dir), [["content", content, paths.pop() + "/"]]);
		
			let re = /\.(m)?js(m)?$/, lss = Services.scriptloader.loadSubScript, prfx = `chrome://${content}/content/`;
			for(let {leafName} of dir.directoryEntries) if (re.test(leafName))
				try {RegExp.$1 ? impESM(prfx + leafName) : RegExp.$2 ? imp(prfx + leafName) : lss(prfx + leafName, sb);} catch(ex) {Cu.reportError(ex);}
		})("resource://gre/modules/XPCOMUtils.sys.mjs", "resource:///modules/CustomizableUI.sys.mjs");
		} catch(ex) {Cu.reportError(ex);}
	}
	if (Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).inSafeMode) return;
	let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
	obs.addObserver(ucf, topic, false);
	obs.addObserver(function quitucf(aDoc, qtopic) {
		obs.removeObserver(quitucf, qtopic);
		obs.removeObserver(ucf, topic);
	}, "quit-application-granted");
})("profile-after-change");

rubel, загрузчик Endor8 не рекомендую, а именно когда папка userChromeJS в core находится.

Farby пишет

Проще говоря закинул в папку и работает, но не забываем после изменения чистить startupCache

У меня из установленных 30 активировались 10, допускаю, что мог допустить ошибку.

6e73epo пишет

загрузчик Endor8 не рекомендую, а именно когда папка userChromeJS в core находится.

Чтобы "тупо" бекапить не только папку профиля, как все делают всю жизнь, но и папку core?

fuchsfan пишет

У меня из установленных 30 активировались 10, допускаю, что мог допустить ошибку.

Ну конечно у многих скриптов есть вызовы типа

Выделить код

Код:

chrome://user_chrome_files/content/custom_scripts/...

и в этом есть подвох! Надо менять на

Выделить код

Код:

chrome://widget/content/...

Farby
Ваш код я применил для файла System Principal.uc.js. Поместил его в папку со скриптами
D:\\Firefox 115.2.0esr\\Profiles\\chrome\\Scripts"
В папке chrome создал папку widget в неё поместил файл SingleHTML.jsm
Что еще нужно, растолкуйте, пожалуйста.
И что делать с кодом от Dumby ?

fuchsfan пишет

Чтобы "тупо" бекапить не только папку профиля, как все делают всю жизнь, но и папку core?

С загрузчиком Endor8 , хоть скрипты и работают, идут ошибки в главной консоли, не помогает даже проверка на окно. Их не видно, потому что  catch(e) пустой.

rubel
Не в папку со скриптами, а добавить в config.js который расположен рядом с firefox.exe

Farby

В папке chrome создал папку widget в неё поместил файл SingleHTML.jsm
Вот такой сейчас config.js

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

Выделить код

Код:

// config.js

try {
  Cu.importGlobalProperties(['PathUtils']);

  if (!Services.appinfo.inSafeMode) {
    let path = PathUtils.parent(PathUtils.xulLibraryPath);
    if (Services.appinfo.OS == 'Darwin') { // macOS
      path = PathUtils.join(PathUtils.parent(path), 'Resources');
    }
    var ucjsDirPath = PathUtils.join(path, 'userChromeJS');
    path = PathUtils.join(ucjsDirPath, 'main.js');
    const mainFileURI = PathUtils.toFileURI(path);
    Services.scriptloader.loadSubScript(mainFileURI, this, 'UTF-8');
  }
}
catch(e) {
  Cu.reportError(e);
}

// UCF In background [System Principal] by Dumby
(async topic => {
	let ucf = async doc => {
		try { (async (xpc, cui) => {
			let paths = ["chrome", "widget"], content = "widget";

			let {ChromeUtils, Services} = Cu.getGlobalForObject(Cu),
				imp = ChromeUtils.import, impESM = ChromeUtils.importESModule,
				{XPCOMUtils} = impESM(xpc), {CustomizableUI} = impESM(cui);
			let sb = Cu.Sandbox(Cu.getObjectPrincipal(this), {wantComponents: true, sandboxName: "ucfBox"});
			Object.assign(sb, {Services, XPCOMUtils, CustomizableUI, ChromeUtils});
		
			XPCOMUtils.defineLazyGlobalGetters(sb, [
				"atob", "btoa", "crypto", "fetch", "Blob", "CSS", "CSSRule", "Document",
				"DOMException", "DOMParser", "Element", "Event", "File", "FileReader",
				"FormData", "Headers", "InspectorUtils", "Node", "NodeFilter", "Range", "Selection",
				"TextDecoder", "TextEncoder", "URL", "URLSearchParams", "XMLHttpRequest", "XMLSerializer"
			]);
			let m = {console: "Console"};
			m.AddonManager = m.AppConstants = m.E10SUtils = m.FileUtils = m.PlacesUtils = false;
			for (let [key, val] of Object.entries(m)) m[key] = `resource://gre/modules/${val || key}.sys.jsm`;
			m.setTimeout = m.setTimeoutWithTarget = m.clearTimeout = m.setInterval
				= m.setIntervalWithTarget = m.clearInterval = "resource://gre/modules/Timer.sys.mjs";
			ChromeUtils.defineESModuleGetters(sb, m);

			let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
			paths.forEach(dir.append);
			let ams = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
			sb[Symbol()] = ams.registerChrome(Services.io.newFileURI(dir), [["content", content, paths.pop() + "/"]]);
		
			let re = /\.(m)?js(m)?$/, lss = Services.scriptloader.loadSubScript, prfx = `chrome://${content}/content/`;
			for(let {leafName} of dir.directoryEntries) if (re.test(leafName))
				try {RegExp.$1 ? impESM(prfx + leafName) : RegExp.$2 ? imp(prfx + leafName) : lss(prfx + leafName, sb);} catch(ex) {Cu.reportError(ex);}
		})("resource://gre/modules/XPCOMUtils.sys.mjs", "resource:///modules/CustomizableUI.sys.mjs");
		} catch(ex) {Cu.reportError(ex);}
	}
	if (Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).inSafeMode) return;
	let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
	obs.addObserver(ucf, topic, false);
	obs.addObserver(function quit(s, t) {
		obs.removeObserver(quit, t);
		obs.removeObserver(ucf, topic);
	}, "quit-application-granted");
})("profile-after-change");


Почистил startupCache, меню не появляется. Где ещё посмотреть ?

rubel пишет

Где ещё посмотреть ?

файл точно называется SingleHTML.jsm, а не как нибудь так SingleHTML.jsm.txt?
url: chrome://widget/content/SingleHTML.jsm открывается?

Farby

url: chrome://widget/content/SingleHTML.jsm открывается?

Сейчас открывается, но все равно меню не появляется.

rubel
В меню гамбургера точно нет?

Farby
Точно нет.

rubel
Тогда последняя догадка, код скрипта должен быть в кодировке utf-8
chrome://widget/content/SingleHTML.jsm должны читаться русские буквы.

Farby
Русские буквы читаются. Я же скачал этот файл у Доброва.

02-10-2023 15:17:31
Farby
Все заработало! Оказывается сейчас с  https://github.com/VicDobrov/UserChromeFiles/blob/main/profile_ucf_dobrov/chrome/user_chrome_files/custom_scripts/SingleHTML.jsm скачивается файл размером 159 кб. А раньше я качал этот файл размером 13 кб.
Вот он и заработал при замене. Спасибо Вам за помощь. Будут вопросы тогда задам.

Farby
Нет, этот скрипт нормально не работает.
Открываю  Firefox, открываю вкладку, на ней скрипт работает. Можно сохранить. Открываю вторую вкладку, на ней скрипт не работает.
Это поправимо ?

rubel пишет

скачивается файл размером 159 кб. А раньше я качал этот файл размером 13 кб.

SingleHTML.0.png

rubel пишет

Это поправимо ?

Да конечно, этот файл весит всего 11,9 KB, и его можно забрать здесь
Рекомендую, перезагрузить ваше устройство с полной переустановкой системы, на макос это делается так...

rubel пишет

Да, глючит этот скрипт с загрузкой метод Aris-t2  и метод Endor8, хотя в UCF работает прекрасно.

хотя рекомендую, хотя в UCF работает прекрасно

Видимо, UCF скрипты в неизменном виде нормально работать не будут.
Кроме того, один SingleHTML.jsm мало полезен! Из меню запускать скрипт неудобно.
Нужен ucf_hookClicks.js, чтобы сохранять страницы по клику на кнопке Загрузки или по сочетанию клавиш.


Farby пишет

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

Это шутка? Только винда требует перестановки при различных глюках системы. МакOS, также как Линукс, не имеет таких недостатков.

Farby

Да конечно, этот файл весит всего 11,9 KB, и его можно забрать здесь...

Его и использую сейчас.
Dobrov

Ясно. Может быть уважаемый Dumby поможет в этом вопросе. Подождем.

rubel - под [System Principal] есть много полезных .
Переделка UCF и CustomButtons скриптов под userChrome.js не гарантирует их правильную работу. Может лучше установить UCF ???

Dobrov
Дело в том, что UCF уже давно не обновляется автором. А искать его исправленную версию разными умельцами под новые выпуски Firefox тот ещё гемморой. Как то так.
Хотя я его использую на 91esr и на тестовой 115esr.

rubel пишет

Открываю  Firefox, открываю вкладку, на ней скрипт работает. Можно сохранить. Открываю вторую вкладку, на ней скрипт не работает.

Хмм :/, я вижу это. Слетает хром-регистрация.
Она и должна слетать, а чтобы не слетала нужно где-то сохранить на неё ссылку.
И так и сделано, ссылка добавлена в ucfBox, но это, почему-то, не помогает.


Перенёс ссылку из ucfBox'а в конфигский сандбокс, и теперь, вроде, не слетает.
Вобщем, попробуй заменить sb[Symbol()] на globalThis[Symbol()]

rubel пишет

Дело в том, что UCF уже давно не обновляется автором. А искать его исправленную версию разными умельцами под новые выпуски Firefox тот ещё гемморой.

UCF (по ссылке в родной теме) работает на версиях Firefox 78-118.
посмотрел код поддержки методов Aris-t2 и Endor8. По моему, их качество проигрывают по сравнению с UCF,
да и обновлялись они в 2018 году, а UCF на 2 года новее.

Dumby

Вобщем, попробуй заменить sb[Symbol()] на globalThis[Symbol()]

Заменил, теперь скрипт прекрасно заработал на всех открытых вкладках, как и в UCF !
Спасибо Вам за ваше внимание. :)
Dobrov
Вам тоже спасибо.

Dobrov пишет

посмотрел код поддержки методов Aris-t2 и Endor8. По моему, их качество проигрывают по сравнению с UCF,

Они просты, они работают, а ucf это целый комплекс, досконально разбирающихся в нем дай бог чтобы с десяток нашелся, вследствие чего при любом катаклизме все мольбы к Dumby, и в те моменты оба форума забиты постами, почему перестало работать.

Dobrov пишет

да и обновлялись они в 2018 году, а UCF на 2 года новее.

А нужны ли обновления ради обновлений? Aris-t2 держит руку на пульсе, свои скрипты регулярно обновляет, проблемы с ними и с активацией практически отсутствуют, в поддержании работоспособности при смене версий браузера практически не нуждается, вроде больше ничего и не надо. Скрипты этих двух товарищей очень популярны среди иноязычных пользователей, и они совсем ничего не знают о ucf, такое сложилось мнение.
В конечном счете у юзера есть альтернативный выбор, каждый возьмет, что его устроит.

Dumby
Вот здесь Вы мне помогли со скриптом google-translate.js.
Возможно ли его сделать для загрузчика метода Endor8.?
Сейчас в контекстном меню появляется пункт Перевод из буфера, да и он не работает.
977e376bb9c8c3671ee43b986758cdf6.png 
Код скрипта google-translate.js там .

Скрипт google-translate-loader.js у меня сейчас такой:

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

Выделить код

Код:

({
	async init() {
		await delayedStartupPromise;
		var code = Cu.readUTF8URI(Services.io.newURI(
			"chrome://scripts/google-translate.js"
		));
		var addEventListener = (...args) => {
			var trg = args[3];
			if (!trg) trg = args[3] = window;
			trg.addEventListener(...args);
			this.handlers.push(args);
		}
		new Function(
			"_id,xhtmlns,addDestructor,addEventListener,gClipboard", code
		).call(
			this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
			() => {}, addEventListener, {read: () => readFromClipboard()}
		);
		addEventListener("unload", this, {once: true});
	},
	handlers: [],
	handleEvent() {
		for(var args of this.handlers)
			args.pop().removeEventListener(...args);
		delete this.handlers;
	}
}).init();

Dumby, на счет urlbar-memory-indicator заметил, что в 117 звездочка была левее индикатора, как в 118.0 - не знаю, а в 118.0.1 уже правее, причем без разницы - after или before
win.document.getElementById("star-button-box").after(clone);
Пока поправил стилем

rubel пишет

Возможно ли его сделать для загрузчика метода Endor8.?
Сейчас в контекстном меню появляется пункт Перевод из буфера, да и он не работает.
Скрипт google-translate-loader.js у меня сейчас такой

Это что ещё такое: «chrome://scripts/google-translate.js»?
Даже если бы метод Endor8 содержал какую-то свою хром-регистрацию,
а он не содержит, то такой адрес просто невозможен сам по себе.
Да и зачем это вообще, можно ведь прямо из файла читать.


И, нужно говорить где у тебя эти файлы лежат и что прописано в userChrome.js
а то непонятно. Такой google-translate-loader.js работать не может,
но какой-то пункт появляется, значит google-translate.js в авто-папке лежит,
а это неправильно, нужно либо сменить расширение, либо положить в другую папку.


Ладно, вот совмещённый вариант. Не слишком оптимально, зато гадать не надо.

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

Выделить код

Код:

location.href.endsWith("://browser/content/browser.xhtml") && ({
	async init(func) {
		await delayedStartupPromise;
		var code = func.toString();
		code = code.slice(code.indexOf("{") + 1, -1).trim();

		var addEventListener = (...args) => {
			var trg = args[3];
			if (!trg) trg = args[3] = window;
			trg.addEventListener(...args);
			this.handlers.push(args);
		}
		new Function(
			"_id,xhtmlns,addDestructor,addEventListener,gClipboard,LOG", code
		).call(
			this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
			() => {}, addEventListener, {read: readFromClipboard}, Cu.reportError
		);
		window.addEventListener("unload", this, {once: true});
	},
	handlers: [],
	handleEvent() {
		for(var args of this.handlers)
			args.pop().removeEventListener(...args);
		delete this.handlers;
	}
}).init(() => {

	// Здесь код google-translate.js

});

Код скрипта google-translate.js там .

Там loadURI(url, торчит, надо заменить, например, на fixupAndLoadURIString(url,


Ещё вот этот кусок совсем какой-то левый, возможно так подойдёт

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

Выделить код

Код:

/*
((id, g) => addDestructor(reason => id in g && g[id].destroy(reason)) || id in g || ({
    actions: [{
        title: "Перевод из буфера",
        tooltip: "Перевод из буфера",
        iconURL: gticon,
     
        id: "TranslateBufer1",
        _insertBeforeActionID: "copyURL",
        
     // onCommand: (e, btn) => e.view.BrowserReloadOrDuplicate(e)
        onCommand: (e, btn) => ujs_google_translat('auto|ru')
    }],
    init() {
        g[id] = this;
        this.actions = this.actions.map(action => {
            action.extensionID = "custombuttons@xsms.org";
            return g.PageActions.addAction(new g.PageActions.Action(action));
        });
    },
    destroy(reason) {
        if (reason[5] != "e") return;
        delete g[id];
        for(var action of this.actions) action.remove();
    }
}).init())(
    "CBPageActionsMaker", Cu.import("resource:///modules/PageActions.jsm", {})
);
*/
(id => {
    var action = PageActions.actionForID(id);
    if (!action) {
        var obj = {id, iconURL: gticon, onCommand(e) {this[e.view.browsingContext.id]("auto|ru");}};
        obj.title = obj.tooltip = "Перевод из буфера";
        action = PageActions.addAction(new PageActions.Action(obj));
    }
    action[id = browsingContext.id] = ujs_google_translat;
    addEventListener("unload", () => delete action[id]);
})("TranslateBufer1");


Может ещё что-то вылезет, надо смотреть.
Кстати, перетаскивание окошка «Google Translate» показалось мне
слегка глюковатым, сделал такую замену
скрытый текст

Выделить код

Код:

/*
            var grabX = e.clientX, grabY = e.clientY, origX = parseInt(w.style.left), origY = parseInt(w.style.top);
            var mouseMove = function(ev){
                w.style.left = origX+ev.clientX-grabX+'px';
                w.style.top = origY+ev.clientY-grabY+'px';
            };
*/
            var st = w.style;
            var mouseMove = e => {
                st.top = parseInt(st.top) + e.movementY + "px";
                st.left = parseInt(st.left) + e.movementX + "px";
            }

6e73epo пишет

заметил, что в 117 звездочка была левее индикатора, как в 118.0 - не знаю, а в 118.0.1 уже правее

Странно, я попробовал на 117 добавить код в custom_script_win.js по событию "load",
и у меня звёздочка справа от индикатора.
Добавляется то всё правильно, а затем инициализируется модуль PageActions
и переставляет звёздочку в конец.


То есть, получается не по-задумке.
Можно попробовать подождать, пусть она сначала передобавится.

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

Выделить код

Код:

/*
			(this.init = win => {
*/
			(this.init = async win => {
				await win.delayedStartupPromise;

Dumby

Ладно, вот совмещённый вариант.

Все сделал как Вы сказали, сделал все правки, работает прекрасно.
В userChrome.js прописано так:

Выделить код

Код:

userChrome.import("scripts", "UChrm");

Поместил его в папку с остальными скриптами.
Огромное спасибо Вам за помощь !
Вот такой у меня сейчас google_translate.js

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

Выделить код

Код:

location.href.endsWith("://browser/content/browser.xhtml") && ({
	async init(func) {
		await delayedStartupPromise;
		var code = func.toString();
		code = code.slice(code.indexOf("{") + 1, -1).trim();

		var addEventListener = (...args) => {
			var trg = args[3];
			if (!trg) trg = args[3] = window;
			trg.addEventListener(...args);
			this.handlers.push(args);
		}
		new Function(
			"_id,xhtmlns,addDestructor,addEventListener,gClipboard,LOG", code
		).call(
			this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
			() => {}, addEventListener, {read: readFromClipboard}, Cu.reportError
		);
		window.addEventListener("unload", this, {once: true});
	},
	handlers: [],
	handleEvent() {
		for(var args of this.handlers)
			args.pop().removeEventListener(...args);
		delete this.handlers;
	}
}).init(() => {

	// Здесь код google-translate.js

//Google,
var langFrom_google_text = "auto";//авто
var langTo_google_text = "ru"; 

      
//Назначаем иконки
var mainicon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQtJREFUKM9VkSFOhFEQg799/CjEihWAwKDgIFwAyWHgLDjuAGfZgMCQDQkG8abtQ/z8u9A0k4rOTCez2u0GB0gCsLELbCuxLduJy0zAZgOQBBqQALEbtOQoyRgjSZLt9nOaJyf5K2zPjr01SWst8ermZtzd5euLhCQ2Y9iOHXssIvZYr1f39x/T87Ourtr7O3ZUyK6KlN5HVRaOqlxcNGACJKRItigdHFXpFdXoPVWRGmSac0suRYWUWhz7zt5/BXh65Pi6Hr7rI/IopZyqpSqldLsq9onPX3iabuHYr6o3pCVHP2Sa11nIzZdnMAmOSpyejiocVEhtjrwc15L5l4HVDgReCGTR+V9n/AAByma0J+vVwwAAAABJRU5ErkJggg==";
var gticon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADKElEQVR42p2TX2hTdxTHPzfJTW6T3qQmapvWabUbog+udp3kYeLQ4f6wiZQNtjlXHyZaBYe6TekYVGRQYexFscOtuD7UdWxzMtAXEbZStKIbDsaUCbVj9o8mTW+aNrlJbu5vJ8Ex2OMO/Lj87jnne873nO9PSyTV3tkAfYi5NhQ1MB1Ijc3ijN+D7CQh28YK+GHDMyxpjlJTkmAdQi5dWvOsUrYkGB5QC5Kcg/aFBxxqqycmcY38a/1yTqYgMw8ByfFKjtZ4V6myCeW8IApyfOw2155fw1DG4dOJJK1r45x5BPDUpZuMr2uXSuAvgBMQgOitjLJNn7iDSJP0rIJ35dt19TeGoi0Es1MMP72KFvm3+88phuYM3HCd3ObQizpa/cW7Kh020E0Tz1yOUxvjdIr7o6t/cLpkEJqZp7s5zN62ZewfnWLQ9VIIBqodBdI5tIbBG8oKhSAaJZDN8tpSP5+3L8eVgLbeAdKal7NH3mKL3FcOXCfV1ITjc7FLFrWZIlpt/4+qEA7hLRrCwk/RusOXu7ax8xHvGTkVgi/89As/T8ia9EUyghKOWSaYyqNx8oIiuEgcshetsooceibJinvTfNH1DpseD3LHSZE4eprs6k24NQaevI1fF8q5FJqv9xvlmFLdkKZlhb77E8TdIlFD54OOl3mzdXm1k+sP0jzbdwF7cRhsj8ysAWYnpYPeQfXPnn3JJG8/sZT+PW8gkuDbkWEiRh3b29dV/edujNE5dB4nHJSCUrQsTdP9mUKrCKHA5piHK+918quVp/VoD9W9uhGejNRx6+N9VZAmoTJZmhbK4vR7BGDPCQEQ/qU8R15aT2/Hi/R8PcyxyyMyVBmaXwIfPiTVf5yYHiF28ARpOyuqk3nJ4DV2HFc4SamUZ3vrGr7vPlitFNraQc4SzZZt6ptWMv3DAOdGrrGj7yvR+2KYr5A0BeCVAwqvBQuyMG+MTzp3cvj15/ivfXfzNq++/yFEIlD7GFjZ6uPRaE4oGuNQI68jIINJu0QbTFoadIJlL7lSgb8sxbSVEb8geUUVtkh55r50MY5Wec6jibV9/A9LjP7e9TdFQScjW9P1XAAAAABJRU5ErkJggg==";


function GetXmlHttpObject(){
         if (window.XMLHttpRequest){ return new XMLHttpRequest();}
         if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP");}
        return null;
        };

var lc = navigator.lastClick = {};
addEventListener("mouseup", e => {
    if (e.button) return;
    lc.X = e.screenX - mozInnerScreenX;
    lc.Y = e.screenY - mozInnerScreenY;
}, false, gBrowser.tabpanels || 1);

var createWindow = function(text, status, title, id, pos, size){
var win = window, doc = win.document, wId = 'ujs_window'+(id || ''), w = doc.getElementById(wId);
    var keyDown = function(e){if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode == 27)doc.getElementById(wId).closeWin()};
    if(w)w.closeWin();
    w = doc.createElementNS(xhtmlns, 'div');
     w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#eaeaea;padding-top:0px;border-radius:4px;box-shadow:0 0 15px rgba(0,0,0,.4);' : 'background:-o-skin("Window Skin");'));
    w.id = wId;
    w.closeWin = function(){
        doc.removeEventListener('keydown', keyDown, false);
        this.parentNode.removeChild(this);
    };
    w.addEle = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'div');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }
                else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };
     w.addEle1 = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'textarea');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };
    var img = doc.createElementNS(xhtmlns, 'div');
    img.setAttribute('style', 'display:block;float:right;width:16px;height:16px;padding:0;margin-top:2px;margin-right:1px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVR4Xm2SPUhbURTHfzfNJ4nU0Axx7CJCN2kQtIgVCtq6OdQuBUftWIQqFNsKDo6iHTqIqN3a0kklUKTS2AZrcOjioFtRjFWUfH+803cS9GHwB4dzcu75/+8L9xgaSEDbLXhaASzAyXAMn5/DHxwwjeJgKLRxd3Q0atxuLhGgWqmQmp9PJ7LZJ5Ow3WhQFweDG20LC1FfRwc3kUsm+T48fPIzl3s8VTdxxLt+/2FhdlZkc1MkmdR8Pba2ajlrz3z1+9OvIOaIfb7DwsSEyNKSyM6OSLksEo/rbw2ttadntV7Gnv3k86VfqskvmDzv7hZ580Zkelrk4kJqFIsii4satVrRs+rYmBQHBuRvS4u8g/fuCmDOz+HgAIWpKRgfh3AYhoZQ8Hqxjo4o9PdT3d1FcQEl8KoBnJ7C/j6KZkZGYG4OIhEUFed7erD29q69jGrd1qVBqcQVKgwEuMSEQhjtXRk4JvW/kM1i2WGMga4uzMoKBIOIfbNiolEC6+uU+/qQRALFA1QBlwVYxmBcLmhuxqytQSgEKu7t1dBavwKvbeINh/Has2IMqnXpem4bky6qWLdvZgaOj2FwEHNyoqG19vRMZ8jZs1+NOfsNcZS3EFvzeNL51laRe/dEYrFadsLpZeyZDx7P6QN4Btwx1OE1xO4HAquP2tsjAZ+Pm8gWi3xMpc6W8/kXPyAO/DM4oOsZa2pafdjZGXF7PAgOpXKZL4nE2XImcyUGMDSg63kbhgvgtYCq8+akIL4J3y7Fyn+DokZOnLlMyQAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
        title.onclick = e => {
        e.preventDefault();
        var url = e.target.href;
        // Здесь открываем url как хотим.
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
        doc.getElementById(wId).closeWin();    
    }
    var cnt = w.addEle1(text, 'display:block;border:1px solid #aaa;padding-bottom:3px;padding-left:3px;background-color:#fafcfe;color:#000;font:17px Times New Roman;width:310px;height:160px;overflow:auto;cursor:text;-moz-user-focus:normal;-moz-user-select:text;');
    cnt.contentEditable="true";
    cnt.context="contentAreaContextMenu";
    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
    w.addEventListener('mousedown', function(e){
        if(e.target == w){
            e.preventDefault();
            var st = w.style;
            var mouseMove = e => {
                st.top = parseInt(st.top) + e.movementY + "px";
                st.left = parseInt(st.left) + e.movementX + "px";
            }
            doc.addEventListener('mousemove', mouseMove, false);
            doc.addEventListener('mouseup', function(){doc.removeEventListener('mousemove', mouseMove, false)}, false);
        }
    }, false);
    doc.documentElement.appendChild(w);
  
    if(size){
        cnt.style.height = size.height;
        cnt.style.width = size.width;
    }
    else{
        for(var i = 3; i < 10; i++){
            if(cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth){
                cnt.style.height = 80*i+'px';
                cnt.style.width = 160*i+'px';
            }
            else break;
        }
    };

    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? doc.documentElement : doc.body;
    var mX = docEle.clientWidth-w.offsetWidth, mY = docEle.clientHeight-w.offsetHeight;
    if(mX < 0){cnt.style.width = parseInt(cnt.style.width)+mX+'px'; mX = 0};
    if(mY < 0){cnt.style.height = parseInt(cnt.style.height)+mY+'px'; mY =0};
    var hW = parseInt(w.offsetWidth/2);
    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
    w.style.visibility = 'visible';
    doc.addEventListener('keydown', keyDown, false);
    return w;
};

var getHash = function (txt) {
    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
    function sM(a) {
        var b;
        if (null !== yr)
            b = yr;
        else {
            b = wr(String.fromCharCode(84));
            var c = wr(String.fromCharCode(75));
            b = [b(), b()];
            b[1] = c();
            b = (yr = window[b.join(c())] || "") || ""
        }
        var d = wr(String.fromCharCode(116))
            , c = wr(String.fromCharCode(107))
            , d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var l = a.charCodeAt(g);
            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                e[f++] = l >> 18 | 240,
                e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                e[f++] = l >> 6 & 63 | 128),
                e[f++] = l & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++)
            a += e[f],
                a = xr(a, "+-a^+6");
        a = xr(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    }

    var yr = null;
    var wr = function(a) {
        return function() {
            return a
        }
    }
        , xr = function(a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2)
                , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
                , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    };

    return sM(txt);
};

//----------Перевести  текст  из буфера в окне Google------------
var ujs_google_translat = function (dir){
   var lng = 'ru';
   var txt = gClipboard.read(); 
   var l = dir.split('|');
   var encTxt = encodeURIComponent(txt);
   var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&ujs=gtt";
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                  //  result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();

                    createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
    };
};



//----------Перевести выделенный текст в окне Google------------
function ujs_google_translate (){
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
       // var url = 'https://translate.google.com/translate_a/single?client=t&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                   // result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    //status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + langTo_google_text.toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
     };
};


//----------Заменить текст переводом Google------------
function ujs_google_TexReplace() {
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    if (txt) {
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
       
           function gettransdata(){
           xmlhttp=GetXmlHttpObject();
           xmlhttp.onreadystatechange=stateChanged;
           xmlhttp.open('POST', url, true);
           xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
           xmlhttp.send('q=' + encodeURIComponent(txt));
        }
        function stateChanged() {
            
           if (xmlhttp.readyState == 4 ) {
           var result = '';
           var data = JSON.parse(xmlhttp.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
           for(var i = 0, n; n = data[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
        var msgName = _id + ":ReplaceSelectionRangeAt0";
        var url = "data:," + encodeURIComponent(
       `addMessageListener("${msgName}", function listener(msg) {
        removeMessageListener("${msgName}", listener);
        var win = {};
        Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
            .getFocusedElementForWindow(content, true, win);

        var sel = win.value.document.getSelection();
        if (sel.isCollapsed) return;
        var range = sel.getRangeAt(0);
        range.deleteContents();
        range.insertNode(range.createContextualFragment(msg.data));
    });`
);
function replace(tagString) {
    var mm = gBrowser.selectedBrowser.messageManager;
    mm.loadFrameScript(url, false);
    mm.sendAsyncMessage(msgName, tagString);
}
replace('<span>'+result+'</span>');
                }
        }  
        gettransdata();
    } 
};



//--------Перевести страницу с Google--------------
function ujs_googlePage_translate() {
   var urlt = gBrowser.currentURI.spec;  
   var url = "http://translate.google.com/translate?hl=ru&sl=auto&tl=ru&u="+ encodeURIComponent(urlt) + "&sandbox=1";
   gBrowser. fixupAndLoadURIString(url, {
   triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
});
};


//Контекстное меню для перевода из буфера-------------------------------------------  

(function () {
 if ( document.getElementById("TranslateBufer") ) return; 
 var contextMenu = document.getElementById("contentAreaContextMenu");  
 var Item = document.createXULElement("menuitem");
       Item.setAttribute("Id", "TranslateBufer");
       Item.setAttribute("label", "Перевод из буфера");
       Item.setAttribute("class", "menuitem-iconic");
       Item.setAttribute("image", mainicon);
       Item.addEventListener("command", function(){ujs_google_translat('auto|ru')}, false);

    contextMenu.insertBefore(Item, document.getElementById("context-viewpartialsource-selection") ); 
    addDestructor(function() { contextMenu.removeChild( Item ) });
 })();

  (id => {
    var action = PageActions.actionForID(id);
    if (!action) {
        var obj = {id, iconURL: gticon, onCommand(e) {this[e.view.browsingContext.id]("auto|ru");}};
        obj.title = obj.tooltip = "Перевод из буфера";
        action = PageActions.addAction(new PageActions.Action(obj));
    }
    action[id = browsingContext.id] = ujs_google_translat;
    addEventListener("unload", () => delete action[id]);
})("TranslateBufer1");

 //Контекстное меню для перевода страниц-------------------------------------------  

(function () {
 if ( document.getElementById("TranslatePage") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
  
    menu.id = "TranslatePage";
    menu.setAttribute("label", "Перевести страницу");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);
   
  contextMenu.insertBefore(menu, document.getElementById("context-viewsource") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) }); 

    var array = [
        {label:"Google", func: ujs_googlePage_translate, image:gticon},
        
        
        ];
        
   array.forEach(function( m ) {  
       if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );

       });
   
     addEventListener("popupshowing", function() {
     menu.hidden = gContextMenu.isTextSelected || gContextMenu.onImage || gContextMenu.onTextInput ; 
  }, true, contextMenu );
})();



 //Контекстное меню для перевода текста-------------------------------------------  
(function () {
 if ( document.getElementById("TranslateSelected") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
      
    menu.id = "TranslateSelected";
    menu.setAttribute("label", "Перевести выделенный текст");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);

  contextMenu.insertBefore(menu, document.getElementById("context-viewpartialsource-selection") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) });
     
    
  var array = [
        {label:"В окне Google", func: ujs_google_translate, image:gticon},
       
        { separator: ''},
        {label:"Заменить текст переводом Google", func: ujs_google_TexReplace, image:gticon},
        
        
        
              ];
  array.forEach(function( m ) {  
        if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );
       });
 
     addEventListener("popupshowing", function() {
     menu.hidden = !gContextMenu.isTextSelected; 
  }, false, contextMenu ); 
 })();


});

Dumby
А можно ли адаптировать кнопку Attributes_Inspector для загрузчика метода Endor8.?
Сейчас, если его поместить в папку со всеми скриптами и запустить браузер, то он сразу запускается и можно смотреть атрибуты. Кнопка не создается.

rubel пишет

Dumby
А можно ли адаптировать кнопку Attributes_Inspector для загрузчика метода Endor8.?
Сейчас, если его поместить в папку со всеми скриптами и запустить браузер, то он сразу запускается и можно смотреть атрибуты. Кнопка не создается.

Ну, например, переименовываешь его в AttributesInspector.txt (txt, не js),
и кладёшь рядом скрипт, который создаст кнопку.

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

Выделить код

Код:

(async (cui, id, self) => cui?.getWidget(id)?.provider != "api" && cui.createWidget(self = {
	id, label: "Attributes Inspector", localized: false,
	onCreated(btn) {
		btn._handleClick = this.click;
		btn.setAttribute("tooltiptext", this.label);
		btn.onmouseenter = btn.onmouseleave = this.onmouse;
		btn.image = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf///////////9EAKf/RACn/0QAp////////////0QAp///////////////////////RACn/0QAp/9EAKf/RACn////////////RACn/0QAp/9EAKf///////////9EAKf//////////////////////0QAp/9EAKf/RACn/0QAp////////////0QAp/9EAKf/RACn////////////RACn/0QAp////////////0QAp/9EAKf/RACn/0QAp/9EAKf///////////9EAKf/RACn/0QAp////////////0QAp/9EAKf///////////9EAKf/RACn/0QAp/9EAKf/RACn//////////////////////////////////////9EAKf/RACn////////////RACn/0QAp/9EAKf/RACn/0QAp///////////////////////////////////////RACn/0QAp////////////0QAp/9EAKf/RACn/0QAp/9EAKf///////////9EAKf/RACn/0QAp////////////0QAp/9EAKf///////////9EAKf/RACn/0QAp/9EAKf/RACn////////////RACn/0QAp/9EAKf///////////9EAKf/RACn////////////RACn/0QAp/9EAKf/RACn/0QAp/////////////////9EAKf/RACn////////////RACn/0QAp////////////0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/////////////////////////////////0QAp/9EAKf///////////9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf//////////////////////0QAp/9EAKf//////////////////////0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp////////////0QAp/9EAKf/RACn//////////////////////9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/RACn/0QAp/9EAKf/AACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQ==";
	},
	click() {
		(this._handleClick = new this.ownerGlobal.Function(self.code).bind(this))();
	},
	get code() {
		delete this.code;
		var file = Services.dirsvc.get("UChrm", Ci.nsIFile);
		["scripts", "AttributesInspector.txt"].forEach(file.append);
		return this.code = "this.focusedWindow && this.focusedWindow.focus();\n" + Cu.readUTF8File(file);
	},
	onmouse: e => e.target.focusedWindow = e.type.endsWith("r") && Services.wm.getMostRecentWindow(null)
}))(window.CustomizableUI, "AttributesInspector");


Кстати, тут есть чуть подправленный, надеюсь.

Dumby
Спасибо Вам за помощь. Все работает прекрасно с вашим Мод-вриантом AttributesInspector.
Ctrl+Shift+C - copy tooltip's contents тоже работает, а в старом не работало.

Dumby, теперь все норм при ожидании, звездочка относительно индикатора появляется там где нужно в зависимости от after или before.
Несколькими постами ранее обсуждался скрипт google_translate.js (userChrome загрузка) . Я переделал меню для перевода страниц в пункт меню и пару моментов не смог понять:
1. Строка с addDestructor. Комментировал ее и никаких негативных изменений или последствий визуально не увидел. При каких событиях они наступят?
2. Два addEventListener. true или false? Читал, но вникнуть не смог, наверное потому, что, меняя значени(е)(я), опять же не увидел никакой разницы

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

Выделить код

Код:

/** ------------------------- Пункт контекстного меню для перевода страниц ------------------------- **/
(function () {
	if (document.getElementById("TranslatePage")) return;
	var contextMenu = document.getElementById("contentAreaContextMenu");
	var Item = document.createXULElement("menuitem");
	Item.setAttribute("id", "TranslatePage");
	Item.setAttribute("label", "Translate Page");
	Item.setAttribute("class", "menuitem-iconic");
	Item.setAttribute("image", mainicon);
	Item.addEventListener("command", function() {ujs_googlePage_translate()}, false);

	contextMenu.insertBefore(Item, document.getElementById("context-viewsource"));
	addDestructor(function() {contextMenu.removeChild(Item)});

	contextMenu.addEventListener("popupshowing", function() {
		Item.hidden = document.getElementById("context-savepage").hidden
	}, false);
})();

Dumby
Еще касательно google_translate.js
В окне перевода в конец текста добавляются 3, 5, 6 пустых строчек. Такая же проблема была с оригинальным кодом для Custom Buttons, но одна из его модификаций НЕ добавляла пустые строчки https://forum.mozilla-russia.org/viewto … 96#p777296
Спасибо, если исправите это в нашем случае.
Up
Хм, обнаружился баг. Наличие в переводимом тексте символа стрелки влево < приводит к падению окна перевода. Проверить можно здесь https://malwaretips.com/threads/testing … st-1052718

Перенес в пост выше.

6e73epo пишет

Несколькими постами ранее обсуждался скрипт google_translate.js (userChrome загрузка) . Я переделал меню для перевода страниц в пункт меню и пару моментов не смог понять:
1. Строка с addDestructor. Комментировал ее и никаких негативных изменений или последствий визуально не увидел. При каких событиях они наступят?

Нет, никакой «скрипт» google_translate.js не обсуждался.
Это просто код для Custom Buttons кнопки.


Поскольку никакой перевод для меня не возможен,
было предложено чисто формальное решение — пишем оболочку,
некий симулятор CB-кнопки, которая добавляет недостающее,
то, что специфично этому расширению и на что расчитывает код.


Функция addDestructor() — одна из таких вещей.
Предназначена для зачистки от результатов предыдущего исполнения кода
при переинициализации кнопки, например, удалить добавленные пункты меню,
ведь будут созданы новые, а то иначе будет эффект размножения.


Скрипты для большинства загрузчиков не restartless, исполняются в окне только раз,
поэтому, в данном случае, на addDestructor() просто поставлена заглушка — пустая функция.

скрытый текст
new Function(
        "_id,xhtmlns,addDestructor,addEventListener,gClipboard,LOG", code
).call(
        this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
        () => {}, addEventListener, {read: readFromClipboard}, Cu.reportError
);

Так что ответ — ни при каких.
Если есть желание сделать небольшой шаг на пути переделки в настоящий скрипт,
то можно удалить все вызовы addDestructor()
и убрать его из оболочки, то есть то, что выделено болдом (вместе с последующей запятой, конечно).

2. Два addEventListener. true или false? Читал, но вникнуть не смог

Да я тоже не особо это понимаю.
Событие как-то спускается сверху вниз до цели, а затем поднимается обратно.
Если true, можно перехватить пораньше, и, например, вызвать e.stopPropagation().
Может ещё что-то, не знаю.
В приведённом отрывке true, вроде как, совсем никчему.


fuchsfan пишет

В окне перевода в конец текста

Ещё раз повторю, негде мне взять никакой текст.

но одна из его модификаций НЕ добавляла пустые строчки https://forum.mozilla-russia.org/viewto … 96#p777296

Насколько я вижу, для сплошного текста в окне перевода,
Андрей предложил заменить .replace(/\\n/g, "<br />")); на .replace(/\\n/g, "").replace(/\\r/g, ""));
Так что можешь попробовать.

Проверить можно

Как теперь, надеюсь, понятно, проверить можно, но не мне.
Если бы дал xhr.responseText, то, может быть, попробовал бы посмотреть.


Ну, типа воткнуть после if (xhr.readyState == 4 && xhr.status == 200) {
строку console.log(xhr.responseText); и забрать responseText с консоли.

Dumby пишет

строку console.log(xhr.responseText); и забрать responseText с консоли.

console.log плюс ошибки

Выделить код

Код:

[[["Когда переключатели \u003cswh\u003e и \u003cwdac\u003e","When \u003c SWH \u003e and \u003c WDAC \u003e switches are ON",null,null,3,null,null,[[null,"offline"]],[[["edbff5b2398eeca464de2caaf36a7a7e","efficient_models_2022q2.md"]]]],[null,null,"Kogda pereklyuchateli \u003cswh\u003e i \u003cwdac\u003e"]],null,"en",null,null,[["When \u003c SWH \u003e and \u003c WDAC \u003e switches are ON",null,[["Когда переключатели \u003cswh\u003e и \u003cwdac\u003e",0,true,false,[3],null,[[3]]],["Когда переключатели \u003cswh\u003e и \u003cwdac\u003e включены",0,true,false,[8]]],[[0,41]],"When \u003c SWH \u003e and \u003c WDAC \u003e switches are ON",0,0]],1,[],[["en"],null,[1],["en"]]] google-translate.uc.js:257:29
Выделить код

Код:

XML Parsing Error: mismatched tag. Expected: </wdac>.
Location: 
Line Number 1, Column 93:
chrome://browser/content/browser.xhtml : Unable to run script because scripts are blocked internally. 2
SyntaxError: An invalid or illegal string was specified google-translate.uc.js:70:13
    addEle1 chrome://chrome/content/jsx/google-translate.uc.js?1696864250457 line 31 > Function:70
    createWindow chrome://chrome/content/jsx/google-translate.uc.js?1696864250457 line 31 > Function:98
    onreadystatechange chrome://chrome/content/jsx/google-translate.uc.js?1696864250457 line 31 > Function:266

Dumby, благодарю, подчистил  от деструктора.


fuchsfan пишет

Хм, обнаружился баг. Наличие в переводимом тексте символа стрелки влево < приводит к падению окна перевода

Логично. Добавь перед созданием окна, что-то типа такого, а может Dumby подскажет куда правильнее вставить замену

result=result.replace(/</g, '&lt;');

fuchsfan пишет

Хм, обнаружился баг. Наличие в переводимом тексте символа стрелки влево < приводит к падению окна перевода.

Никогда не замечал раньше (просто не попадалось). Здесь так же.

6e73epo пишет

может Dumby подскажет куда правильнее вставить замену

Да я вообще не понимаю почему в коде на <textarea> устанавливается innerHTML
Гугл когда-нибудь отдаёт на запрос перевода простого текста что-нибудь HTML'ское?
Если нет, то почему бы не просто value, типа так

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

Выделить код

Код:

/*
     w.addEle1 = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'textarea');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };
*/

.......

/*
    var cnt = w.addEle1(text, 'display:block;border:1px solid #aaa;padding-bottom:3px;padding-left:3px;background-color:#fafcfe;color:#000;font:17px Times New Roman;width:310px;height:160px;overflow:auto;cursor:text;-moz-user-focus:normal;-moz-user-select:text;');
    cnt.contentEditable="true";
    cnt.context="contentAreaContextMenu";
*/
    var cnt = doc.createElement("textarea");
    cnt.style.cssText = `
        color: #000;
        width: 310px;
        height: 160px;
        outline: none;
        padding-left: 3px;
        padding-bottom: 3px;
        border: 1px solid #aaa;
        background-color: #fafcfe;
        font: 17px Times New Roman;
    `;
    if (text) cnt.value = text;
    w.append(cnt);


Но json responseText'а, который дал Farby, какой-то странный.
С него, в правленном окошке, отображается только
«Когда переключатели <swh> и <wdac>».
Причём, полный вариант в json есть, но не там, где код ожидает его собрать.

Dumby пишет

Если нет, то почему бы не просто value, типа так

После этих правок падения со стрелками < прекратились. Продублирую линк на тестовый пост, чтобы народ не искал долго https://malwaretips.com/threads/testing … st-1052718
Эх, остался один бич - пустые строки.

fuchsfan
Не пользуюсь userChrome.js, у меня UCF. Но внёс в свой скрипт последние правки. Если выделяю несколько абзацев, вылезает <br />
Вроде, раньше у меня такого не было или уже забыл... Скажите, у Вас также?

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

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

xrun1 пишет

Скажите, у Вас также?

Точно так, <br /> вылазит.

fuchsfan
Не знаю, правильно ли, но так этого нет.

Выделить код

Код:

//                                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
                                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));

UPD: Если у Вас этот код, там в 3-х местах поправить надо.

xrun1 пишет

Не знаю, правильно ли, но так этого нет.

Помогло, спасибо. До финального релиза скрипта совсем чуть-чуть :)

fuchsfan пишет

До финального релиза скрипта совсем чуть-чуть

Т.к. избавиться от пустых строк не получается, давайте считать текущее состояние скрипта финальным и прекратить дебаты :)

fuchsfan пишет

избавиться от пустых строк не получается

Так хоть пробовал?

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

Выделить код

Код:

/*
    if (text) cnt.value = text;
*/
    if (text) cnt.value = text.trimRight();

Dumby пишет

Так хоть пробовал?

Пробовал, эффекта не дает.

fuchsfan
Что же там за responseText такой?

Dumby, начальный размер окна 310 или 320 на 160. Пусть текст вписался идеально в 8 строк без пустых строк. Если на слово длиннее, то будет переполенние и размер окна станет 480х240. Сразу получаем 3-4 пустых строки + еще несколько, т.к. для текста требуется уже меньше 8 строк. Пробовал не так резко менять размер окна (с шагом 20, сохраняя пропорции), но все равно 1-3 пустых строки иногда присутствуют.

Dumby пишет

Что же там за responseText такой?

В таких вопросах я ничего не понимаю.

6e73epo пишет

(с шагом 20, сохраняя пропорции), но все равно 1-3 пустых строки иногда присутствуют.

Попробую это, если 1-3, да только иногда.

11-10-2023 14:15:48
Попробовал, ответ отрицательный, в основном 5-6 пустых строчек, редко-редко 1. Но ведь был же код для Custom Buttons, который не давал пустых строчек.

Dumby пишет

Что же там за responseText такой?

Это в варианте без ваших правок? Так окно падает даже если попытаться перевести только один символ '<' А вообще, не смотрел еще, по какой причине переводимая строка "When < SWH > and < WDAC > switches are ON" оказывается не на своем месте в массиве

6e73epo пишет

размер окна

Ааа! Речь не о каких не «пустых строках», а о размере <textarea>.
Ни за что бы не догадался.


Тут бы хорошо вообще весь разресайз переписать,
но это слишком сложно (в смысле для меня).


Но, наверно, можно попробовать сделать окончательную
подгонку уже под конец.
Тогда, на всякий случай, всё таки if (text) cnt.value = text.trim();
и, перед return w;

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

Выделить код

Код:

//
    if (text) {
        var st = cnt.style;
        var div = cnt.editor.rootElement;

        var range = new Range();
        range.selectNode(div.firstChild);
        var rect = range.getBoundingClientRect();

        let w = Math.ceil(rect.width);
        if (cnt.scrollTopMax) {
            if (!matchMedia("(-moz-overlay-scrollbars)").matches) // ???
                w += InspectorUtils.getChildrenForNode(div, true, false).at(-1).clientWidth;
        }
        else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";

        st.width = Math.max(200, w) + "px";
    }

Dumby пишет

Тут бы хорошо вообще весь разресайз переписать,

Я тоже пробовал, не смог. :) Отлично всё работает, спасибо.:beer:

скрытый текст
Image001_2023-10-12_13-29.png

Dumby пишет

Но, наверно, можно попробовать сделать окончательную
подгонку уже под конец.

Безусловно, лучше, чем с теми "пустыми строками", хотя у меня гарантированно появляется вертикальный скролл, в 1 строку, если текст короткий, или в несколько пикселей, если текст побольше.

12-10-2023 13:57:16
Причину выяснил, такое происходит при установке в css-стиле скрипта размера шрифта 24px и выше, при размере 22px скролл отсутствует. Может, это можно исправить?

fuchsfan пишет

происходит при установке в css-стиле скрипта размера шрифта 24px и выше

Поставил 24px, и действительно, вижу,
пояляется ненужный вертикальный скролл.


Как ни странно, у меня помогает в строке
else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";


заменить 1 на 2 (ну или сколько не жалко). Попробуй.

Dumby пишет

else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";

заменить 1 на 2 (ну или сколько не жалко).

Супер, помогло. Благодарю.
Ну все, похоже, что приплыли, типа Final :)

xrun1
У вас вот на этом скрине googletranslate переводит с русского на английский.
В моем google_translate.js вообще нет такой строки ну и нет перевода на английский.

Выделить код

Код:

var url = "http://translate.google.com/translate?u="+encodeURIComponent(urlt)+"&hl="+lng+"&langpair="+dir+"&tbb=1";

Все остальные правки с этой темы я сделал.Что нужно еще поправить, чтоб был перевод и на английский ?
google_translate.js для Aris-t2

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

Выделить код

Код:

location.href.endsWith("://browser/content/browser.xhtml") && ({
	async init(func) {
		await delayedStartupPromise;
		var code = func.toString();
		code = code.slice(code.indexOf("{") + 1, -1).trim();

		var addEventListener = (...args) => {
			var trg = args[3];
			if (!trg) trg = args[3] = window;
			trg.addEventListener(...args);
			this.handlers.push(args);
		}
		new Function(
			"_id,xhtmlns,addDestructor,addEventListener,gClipboard,LOG", code
		).call(
			this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
			() => {}, addEventListener, {read: readFromClipboard}, Cu.reportError
		);
		window.addEventListener("unload", this, {once: true});
	},
	handlers: [],
	handleEvent() {
		for(var args of this.handlers)
			args.pop().removeEventListener(...args);
		delete this.handlers;
	}
}).init(() => {

	// Здесь код google-translate.js

//Google,
var langFrom_google_text = "auto";//авто
var langTo_google_text = "ru"; 

      
//Назначаем иконки
var mainicon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQtJREFUKM9VkSFOhFEQg799/CjEihWAwKDgIFwAyWHgLDjuAGfZgMCQDQkG8abtQ/z8u9A0k4rOTCez2u0GB0gCsLELbCuxLduJy0zAZgOQBBqQALEbtOQoyRgjSZLt9nOaJyf5K2zPjr01SWst8ermZtzd5euLhCQ2Y9iOHXssIvZYr1f39x/T87Ourtr7O3ZUyK6KlN5HVRaOqlxcNGACJKRItigdHFXpFdXoPVWRGmSac0suRYWUWhz7zt5/BXh65Pi6Hr7rI/IopZyqpSqldLsq9onPX3iabuHYr6o3pCVHP2Sa11nIzZdnMAmOSpyejiocVEhtjrwc15L5l4HVDgReCGTR+V9n/AAByma0J+vVwwAAAABJRU5ErkJggg==";
var gticon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADKElEQVR42p2TX2hTdxTHPzfJTW6T3qQmapvWabUbog+udp3kYeLQ4f6wiZQNtjlXHyZaBYe6TekYVGRQYexFscOtuD7UdWxzMtAXEbZStKIbDsaUCbVj9o8mTW+aNrlJbu5vJ8Ex2OMO/Lj87jnne873nO9PSyTV3tkAfYi5NhQ1MB1Ijc3ijN+D7CQh28YK+GHDMyxpjlJTkmAdQi5dWvOsUrYkGB5QC5Kcg/aFBxxqqycmcY38a/1yTqYgMw8ByfFKjtZ4V6myCeW8IApyfOw2155fw1DG4dOJJK1r45x5BPDUpZuMr2uXSuAvgBMQgOitjLJNn7iDSJP0rIJ35dt19TeGoi0Es1MMP72KFvm3+88phuYM3HCd3ObQizpa/cW7Kh020E0Tz1yOUxvjdIr7o6t/cLpkEJqZp7s5zN62ZewfnWLQ9VIIBqodBdI5tIbBG8oKhSAaJZDN8tpSP5+3L8eVgLbeAdKal7NH3mKL3FcOXCfV1ITjc7FLFrWZIlpt/4+qEA7hLRrCwk/RusOXu7ax8xHvGTkVgi/89As/T8ia9EUyghKOWSaYyqNx8oIiuEgcshetsooceibJinvTfNH1DpseD3LHSZE4eprs6k24NQaevI1fF8q5FJqv9xvlmFLdkKZlhb77E8TdIlFD54OOl3mzdXm1k+sP0jzbdwF7cRhsj8ysAWYnpYPeQfXPnn3JJG8/sZT+PW8gkuDbkWEiRh3b29dV/edujNE5dB4nHJSCUrQsTdP9mUKrCKHA5piHK+918quVp/VoD9W9uhGejNRx6+N9VZAmoTJZmhbK4vR7BGDPCQEQ/qU8R15aT2/Hi/R8PcyxyyMyVBmaXwIfPiTVf5yYHiF28ARpOyuqk3nJ4DV2HFc4SamUZ3vrGr7vPlitFNraQc4SzZZt6ptWMv3DAOdGrrGj7yvR+2KYr5A0BeCVAwqvBQuyMG+MTzp3cvj15/ivfXfzNq++/yFEIlD7GFjZ6uPRaE4oGuNQI68jIINJu0QbTFoadIJlL7lSgb8sxbSVEb8geUUVtkh55r50MY5Wec6jibV9/A9LjP7e9TdFQScjW9P1XAAAAABJRU5ErkJggg==";


function GetXmlHttpObject(){
         if (window.XMLHttpRequest){ return new XMLHttpRequest();}
         if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP");}
        return null;
        };

var lc = navigator.lastClick = {};
addEventListener("mouseup", e => {
    if (e.button) return;
    lc.X = e.screenX - mozInnerScreenX;
    lc.Y = e.screenY - mozInnerScreenY;
}, false, gBrowser.tabpanels || 1);

var createWindow = function(text, status, title, id, pos, size){
var win = window, doc = win.document, wId = 'ujs_window'+(id || ''), w = doc.getElementById(wId);
    var keyDown = function(e){if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode == 27)doc.getElementById(wId).closeWin()};
    if(w)w.closeWin();
    w = doc.createElementNS(xhtmlns, 'div');
      w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#33343F;padding-top:0px;border-radius:4px;box-shadow:0 0 15px rgba(0,0,0,.4);' : 'background:-o-skin("Window Skin");'));
    w.id = wId;
    w.closeWin = function(){
        doc.removeEventListener('keydown', keyDown, false);
        this.parentNode.removeChild(this);
    };
    w.addEle = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'div');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }
                else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };

    var img = doc.createElementNS(xhtmlns, 'div');
    img.setAttribute('style', 'display:block;float:right;width:16px;height:16px;padding:0;margin-top:2px;margin-right:1px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVR4Xm2SPUhbURTHfzfNJ4nU0Axx7CJCN2kQtIgVCtq6OdQuBUftWIQqFNsKDo6iHTqIqN3a0kklUKTS2AZrcOjioFtRjFWUfH+803cS9GHwB4dzcu75/+8L9xgaSEDbLXhaASzAyXAMn5/DHxwwjeJgKLRxd3Q0atxuLhGgWqmQmp9PJ7LZJ5Ow3WhQFweDG20LC1FfRwc3kUsm+T48fPIzl3s8VTdxxLt+/2FhdlZkc1MkmdR8Pba2ajlrz3z1+9OvIOaIfb7DwsSEyNKSyM6OSLksEo/rbw2ttadntV7Gnv3k86VfqskvmDzv7hZ580Zkelrk4kJqFIsii4satVrRs+rYmBQHBuRvS4u8g/fuCmDOz+HgAIWpKRgfh3AYhoZQ8Hqxjo4o9PdT3d1FcQEl8KoBnJ7C/j6KZkZGYG4OIhEUFed7erD29q69jGrd1qVBqcQVKgwEuMSEQhjtXRk4JvW/kM1i2WGMga4uzMoKBIOIfbNiolEC6+uU+/qQRALFA1QBlwVYxmBcLmhuxqytQSgEKu7t1dBavwKvbeINh/Has2IMqnXpem4bky6qWLdvZgaOj2FwEHNyoqG19vRMZ8jZs1+NOfsNcZS3EFvzeNL51laRe/dEYrFadsLpZeyZDx7P6QN4Btwx1OE1xO4HAquP2tsjAZ+Pm8gWi3xMpc6W8/kXPyAO/DM4oOsZa2pafdjZGXF7PAgOpXKZL4nE2XImcyUGMDSg63kbhgvgtYCq8+akIL4J3y7Fyn+DokZOnLlMyQAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
        title.onclick = e => {
        e.preventDefault();
        var url = e.target.href;
        // Здесь открываем url как хотим.
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
        doc.getElementById(wId).closeWin();    
    }
    var cnt = doc.createElement("textarea");
    cnt.style.cssText = `
        color: #000;
        width: 310px;
        height: 160px;
        outline: none;
        padding-left: 3px;
        padding-bottom: 3px;
        border: 1px solid #aaa;
        background-color: #fafcfe;
        font: 17px Times New Roman;
    `;
    if (text) cnt.value = text.trim();
    w.append(cnt);
    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
    w.addEventListener('mousedown', function(e){
        if(e.target == w){
            e.preventDefault();
            var st = w.style;
            var mouseMove = e => {
                st.top = parseInt(st.top) + e.movementY + "px";
                st.left = parseInt(st.left) + e.movementX + "px";
            }
            doc.addEventListener('mousemove', mouseMove, false);
            doc.addEventListener('mouseup', function(){doc.removeEventListener('mousemove', mouseMove, false)}, false);
        }
    }, false);
    doc.documentElement.appendChild(w);
  
    if(size){
        cnt.style.height = size.height;
        cnt.style.width = size.width;
    }
    else{
        for(var i = 3; i < 10; i++){
            if(cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth){
                cnt.style.height = 80*i+'px';
                cnt.style.width = 160*i+'px';
            }
            else break;
        }
    };

    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? doc.documentElement : doc.body;
    var mX = docEle.clientWidth-w.offsetWidth, mY = docEle.clientHeight-w.offsetHeight;
    if(mX < 0){cnt.style.width = parseInt(cnt.style.width)+mX+'px'; mX = 0};
    if(mY < 0){cnt.style.height = parseInt(cnt.style.height)+mY+'px'; mY =0};
    var hW = parseInt(w.offsetWidth/2);
    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
    w.style.visibility = 'visible';
    doc.addEventListener('keydown', keyDown, false);
	if (text) {
        var st = cnt.style;
        var div = cnt.editor.rootElement;

        var range = new Range();
        range.selectNode(div.firstChild);
        var rect = range.getBoundingClientRect();

        let w = Math.ceil(rect.width);
        if (cnt.scrollTopMax) {
            if (!matchMedia("(-moz-overlay-scrollbars)").matches) // ???
                w += InspectorUtils.getChildrenForNode(div, true, false).at(-1).clientWidth;
        }
        else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";

        st.width = Math.max(200, w) + "px";
    }
    return w;
};

var getHash = function (txt) {
    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
    function sM(a) {
        var b;
        if (null !== yr)
            b = yr;
        else {
            b = wr(String.fromCharCode(84));
            var c = wr(String.fromCharCode(75));
            b = [b(), b()];
            b[1] = c();
            b = (yr = window[b.join(c())] || "") || ""
        }
        var d = wr(String.fromCharCode(116))
            , c = wr(String.fromCharCode(107))
            , d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var l = a.charCodeAt(g);
            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                e[f++] = l >> 18 | 240,
                e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                e[f++] = l >> 6 & 63 | 128),
                e[f++] = l & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++)
            a += e[f],
                a = xr(a, "+-a^+6");
        a = xr(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    }

    var yr = null;
    var wr = function(a) {
        return function() {
            return a
        }
    }
        , xr = function(a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2)
                , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
                , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    };

    return sM(txt);
};

//----------Перевести  текст  из буфера в окне Google------------
var ujs_google_translat = function (dir){
   var lng = 'ru';
   var txt = gClipboard.read(); 
   var l = dir.split('|');
   var encTxt = encodeURIComponent(txt);
   var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&ujs=gtt";
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                  //  result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();

                    createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
    };
};



//----------Перевести выделенный текст в окне Google------------
function ujs_google_translate (){
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
       // var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                   // result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    //status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + langTo_google_text.toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
     };
};


//----------Заменить текст переводом Google------------
function ujs_google_TexReplace() {
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    if (txt) {
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
       
           function gettransdata(){
           xmlhttp=GetXmlHttpObject();
           xmlhttp.onreadystatechange=stateChanged;
           xmlhttp.open('POST', url, true);
           xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
           xmlhttp.send('q=' + encodeURIComponent(txt));
        }
        function stateChanged() {
            
           if (xmlhttp.readyState == 4 ) {
           var result = '';
           var data = JSON.parse(xmlhttp.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
           for(var i = 0, n; n = data[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
        var msgName = _id + ":ReplaceSelectionRangeAt0";
        var url = "data:," + encodeURIComponent(
       `addMessageListener("${msgName}", function listener(msg) {
        removeMessageListener("${msgName}", listener);
        var win = {};
        Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
            .getFocusedElementForWindow(content, true, win);

        var sel = win.value.document.getSelection();
        if (sel.isCollapsed) return;
        var range = sel.getRangeAt(0);
        range.deleteContents();
        range.insertNode(range.createContextualFragment(msg.data));
    });`
);
function replace(tagString) {
    var mm = gBrowser.selectedBrowser.messageManager;
    mm.loadFrameScript(url, false);
    mm.sendAsyncMessage(msgName, tagString);
}
replace('<span>'+result+'</span>');
                }
        }  
        gettransdata();
    } 
};



//--------Перевести страницу с Google--------------
function ujs_googlePage_translate() {
   var urlt = gBrowser.currentURI.spec;  
   var url = "http://translate.google.com/translate?hl=ru&sl=auto&tl=ru&u="+ encodeURIComponent(urlt) + "&sandbox=1";
   gBrowser. fixupAndLoadURIString(url, {
   triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
});
};


//Контекстное меню для перевода из буфера-------------------------------------------  

(function () {
 if ( document.getElementById("TranslateBufer") ) return; 
 var contextMenu = document.getElementById("contentAreaContextMenu");  
 var Item = document.createXULElement("menuitem");
       Item.setAttribute("label", "Перевод из буфера");
       Item.setAttribute("class", "menuitem-iconic");
       Item.setAttribute("image", mainicon);
       Item.addEventListener("command", function(){ujs_google_translat('auto|ru')}, false);

    contextMenu.insertBefore(Item, document.getElementById("context-viewpartialsource-selection") ); 
    addDestructor(function() { contextMenu.removeChild( Item ) });
 })();

  

 //Контекстное меню для перевода страниц-------------------------------------------  

(function () {
 if ( document.getElementById("TranslatePage") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
  
    menu.id = "TranslatePage";
    menu.setAttribute("label", "Перевести страницу");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);
   
  contextMenu.insertBefore(menu, document.getElementById("context-viewsource") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) }); 

    var array = [
        {label:"Google", func: ujs_googlePage_translate, image:gticon},
        
        
        ];
        
   array.forEach(function( m ) {  
       if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );

       });
   
     addEventListener("popupshowing", function() {
     menu.hidden = gContextMenu.isTextSelected || gContextMenu.onImage || gContextMenu.onTextInput ; 
  }, true, contextMenu );
})();



 //Контекстное меню для перевода текста-------------------------------------------  
(function () {
 if ( document.getElementById("TranslateSelected") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
      
    menu.id = "TranslateSelected";
    menu.setAttribute("label", "Перевести выделенный текст");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);

  contextMenu.insertBefore(menu, document.getElementById("context-viewpartialsource-selection") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) });
     
    
  var array = [
        {label:"В окне Google", func: ujs_google_translate, image:gticon},
       
        { separator: ''},
        {label:"Заменить текст переводом Google", func: ujs_google_TexReplace, image:gticon},
        
        
        
              ];
  array.forEach(function( m ) {  
        if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );
       });
 
     addEventListener("popupshowing", function() {
     menu.hidden = !gContextMenu.isTextSelected; 
  }, false, contextMenu ); 
 })();


});

В проекте Floorp появился скрипт для создания QR Code на текущую загруженную страницу. Сам скрипт базируется на функционале QR Code Styling. Работу проверял в [firefox] 115+ с загрузчиком от Xiao

qr-code.uc.js

Выделить код

Код:

// ==UserScript==
// @name	QR Code Generate
// @author	Project Floorp
// @include	main
// @homepageURL	https://github.com/Floorp-Projects/Floorp-core/blob/main/browser/base/content/browser-pageActions.js
// @description Need QR Code Styling https://unpkg.com/qr-code-styling@1.5.0/lib/qr-code-styling.js \n Place "qr-code-styling.js" in same folder with this script
// ==/UserScript==
/* eslint-disable no-undef */
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

if (location.href.startsWith("chrome://browser/content/browser.x")) {

  let strlngs = {
    'en-US': {
      'qrcode-generate-page-action-title': 'Scan QR Code with your Phone',
      'qrcode-generate-page-action': 'Share this page with your phone',
      'qrcode-generate-page-action-dl': 'L+Click: Download QR Code',
    },
    'ru': {
      'qrcode-generate-page-action-title': 'Сканировать QR-код с помощью телефона.',
      'qrcode-generate-page-action': 'Отправить страницу на телефон.',
      'qrcode-generate-page-action-dl': 'ЛКМ: Скачать QR Code',
        },
  };
  function QRCodeGenerateL10n(strlng) {
    let LOCALE = strlngs[Services.locale.requestedLocales[0]]
      ? Services.locale.requestedLocales[0]
      : 'en-US';
    return (!strlng)
      ? ""
      : strlngs[LOCALE][strlng]
        ? strlngs[LOCALE][strlng]
        : "";
  }

  let QRCodeGeneratePageActionButton = window.MozXULElement.parseXULToFragment(`
  <hbox id="QRCodeGeneratePageAction" label="${QRCodeGenerateL10n('qrcode-generate-page-action')}"
    class="urlbar-page-action" tooltiptext="${QRCodeGenerateL10n('qrcode-generate-page-action')}"
    role="button" popup="qrcode-panel">
    <image id="QRCodeGeneratePageAction-image" class="urlbar-icon"
    style="list-style-image: url(data:image/svg+xml;base64,PCEtLSBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljCiAgIC0gTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpcwogICAtIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uIC0tPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDE2IDE2IiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9ImNvbnRleHQtZmlsbCIgZmlsbC1vcGFjaXR5PSJjb250ZXh0LWZpbGwtb3BhY2l0eSI+CiAgPHBhdGggZD0iTTguMjUgMTAuMzc1YS42MjUuNjI1IDAgMCAxLTEuMjUgMGwwLTguMzIzLTMuMzA4IDMuMzA5YS42MjYuNjI2IDAgMCAxLS44ODUtLjg4NUw3LjI4NSAwbC42ODEgMCA0LjQ3NyA0LjQ3NmEuNjI2LjYyNiAwIDAgMS0uODg1Ljg4NUw4LjI1IDIuMDUybDAgOC4zMjN6Ii8+CiAgPHBhdGggZD0iTTEyLjI1IDE1YTIgMiAwIDAgMCAyLTJsMC0xLjM3NWEuNjI1LjYyNSAwIDAgMC0xLjI1IDBsMCAxLjUyNS0uNi42LTkuNTUgMC0uNi0uNiAwLTEuNTI1YS42MjUuNjI1IDAgMCAwLTEuMjUgMEwxIDEzYTIgMiAwIDAgMCAyIDJsOS4yNSAweiIvPgo8L3N2Zz4K);"/>
    <panel id="qrcode-panel" type="arrow" position="bottomright topright" tooltiptext="${QRCodeGenerateL10n('qrcode-generate-page-action-dl')}" onpopupshowing="generateCurrentTabQRCode()" onclick="if (event.button == 0) generateCurrentTabQRCode(true)">
     <vbox id="qrcode-box">
      <vbox class="panel-header">
       <html:h1>
        <html:span>${QRCodeGenerateL10n('qrcode-generate-page-action-title')}</html:span>
       </html:h1>
      </vbox>
      <toolbarseparator/>
      <a href="">
        <vbox id="qrcode-img-vbox"/>
      </a>
     </vbox>
    </panel>
  </hbox>
  `);

  function generateCurrentTabQRCode(DL) {
    let QRcodeStyling = Services.io.newURI(Components.stack.filename).resolve("qr-code-styling.js");
    // Need QR Code Styling from https://unpkg.com/qr-code-styling@1.5.0/lib/qr-code-styling.js
    // Place "qr-code-styling.js" in same folder with this script
    Services.scriptloader.loadSubScript(QRcodeStyling, window);

    let currentTab = gBrowser.selectedTab;
    let currentTabURL = currentTab.linkedBrowser.currentURI.spec;

    const qrCode = new QRCodeStyling({
      width: 250,
      height: 250,
      type: "svg",
      data: currentTabURL,
      image: "chrome://branding/content/about-logo.svg",
      dotsOptions: {
          color: "#4267b2",
      },
      cornersSquareOptions: {
        type: "extra-rounded",
      },
      backgroundOptions: {
          color: "#e9ebee",
      },
      imageOptions: {
          crossOrigin: "anonymous",
          margin: 10
      }
    });

  //remove old qrcode
    let QRCodeBox = document.getElementById("qrcode-img-vbox");

    while (QRCodeBox.firstChild) {
      QRCodeBox.firstChild.remove();
    }

    qrCode.append(QRCodeBox);
    if (DL)
      qrCode.download({ name: currentTabURL.replace(/[:\\\/<>?*|&#="]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, ''), extension: "svg" });
  }

  SessionStore.promiseInitialized.then(() => {
    document.getElementById("star-button-box").before(QRCodeGeneratePageActionButton);
  });
}


и
qr-code-styling.js

Выделить код

Код:

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

или qr-code-styling.js


Оба скрипта должны лежать в одной папке.

rubel
У нас скрипты разные. Вы изначально начали пилить скрипт с контекстным меню. У меня такой вариант:

скрытый текст
Image001_2023-10-13_12-56.png

Если текст выделен на странице - переводится в окне, если выделения нет - переводится вся страница. Исходный язык определяется автоматически, перевод на русский или английский соответственно.
Попробуйте в своём скрипте заменить 2 строки: 257 и 258

Выделить код

Код:

xhr.send('q=' + encodeURIComponent(txt));
    };

таким кодом

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

Выделить код

Код:

xhr.send('q=' + encodeURIComponent(txt));
                    } else {
                        var urlt = gBrowser.currentURI.spec;
// Изменил строку ниже. Добавил параметр '&tl='+l[1] https://forum.mozilla-russia.org/viewtopic.php?pid=796999#p796999
                        var url = "http://translate.google.com/translate?u=" + encodeURIComponent(urlt) + '&tl=' + l[1] + "&hl=" + lng + "&langpair=" + dir + "&tbb=1";
                        var ctabpos = gBrowser.selectedTab._tPos +1;
                        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
                    };


Проверить не могу, не пользуюсь методом Aris-t2, а ставить муторно.

xrun1 пишет

внёс в свой скрипт последние правки. Если выделяю несколько абзацев, вылезает <br />

С абзацами: удалить замену, т.к. она уже не требуется .replace(/\\n/g, "<br />")
Для сплошного текста: заменять на пробел, а не на пусто .replace(/\\n/g, ' ')

xrun1
Заменил вашим кодом, не переводит.
3f4595a26d152086aca05e13638e8126.png 
Может еще что-то нужно сделать.?

6e73epo
Уже сделал.
rubel
У Вас там второй кусок подобный есть, не заметил. Попробуйте поиском в скрипте xhr.send('q=' + encodeURIComponent(txt));.
В исходном вашем это строки 292 и 293. Попробуйте там тоже заменить.

13-10-2023 15:21:46
Свой код для UCF выложил в соответствующей теме.

xrun1
Нет и это не помогло.

rubel
Тогда не знаю. Скрипты разные, а я разобраться не смогу. :(

Dumby
Если возможно, то помогите, пожалуйста с моим вопросом.
xrun1
Вам спасибо за внимание и правки скрипта. :)

rubel пишет

Dumby
Если возможно, то помогите, пожалуйста с моим вопросом.

Ну сколько раз повторять, что проверить мне такое негде.
Хочешь чтобы я что-то из пальца высосал? Хорошо.


Допустим, что речь о переводе выделенного текста в окошке «Google Translate».
Тогда, находишь строку function ujs_google_translate (){
и меняешь на function ujs_google_translate(langTo_google_text) {


Ну, и определяем пункты субменю

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

Выделить код

Код:

/*
        {label:"В окне Google", func: ujs_google_translate, image:gticon},
*/
        {label: "В окне Google на русский", func: () => ujs_google_translate("ru"), image: gticon},
        {label: "В окне Google на английский", func: () => ujs_google_translate("en"), image: gticon},

Dumby
Огромное Вам спасибо. Все заработало прекрасно.
Появился выбор языка перевода.
f2aa3ddd0cfddf216b6bd4fc14a12713.png 
Вот окончательный вариант скрипта google_translate.js для Aris-t2

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

Выделить код

Код:

location.href.endsWith("://browser/content/browser.xhtml") && ({
	async init(func) {
		await delayedStartupPromise;
		var code = func.toString();
		code = code.slice(code.indexOf("{") + 1, -1).trim();

		var addEventListener = (...args) => {
			var trg = args[3];
			if (!trg) trg = args[3] = window;
			trg.addEventListener(...args);
			this.handlers.push(args);
		}
		new Function(
			"_id,xhtmlns,addDestructor,addEventListener,gClipboard,LOG", code
		).call(
			this, "ucf-cbinit-google-translate", "http://www.w3.org/1999/xhtml",
			() => {}, addEventListener, {read: readFromClipboard}, Cu.reportError
		);
		window.addEventListener("unload", this, {once: true});
	},
	handlers: [],
	handleEvent() {
		for(var args of this.handlers)
			args.pop().removeEventListener(...args);
		delete this.handlers;
	}
}).init(() => {

	// Здесь код google-translate.js

//Google,
var langFrom_google_text = "auto";//авто
var langTo_google_text = "ru"; 

      
//Назначаем иконки
var mainicon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQtJREFUKM9VkSFOhFEQg799/CjEihWAwKDgIFwAyWHgLDjuAGfZgMCQDQkG8abtQ/z8u9A0k4rOTCez2u0GB0gCsLELbCuxLduJy0zAZgOQBBqQALEbtOQoyRgjSZLt9nOaJyf5K2zPjr01SWst8ermZtzd5euLhCQ2Y9iOHXssIvZYr1f39x/T87Ourtr7O3ZUyK6KlN5HVRaOqlxcNGACJKRItigdHFXpFdXoPVWRGmSac0suRYWUWhz7zt5/BXh65Pi6Hr7rI/IopZyqpSqldLsq9onPX3iabuHYr6o3pCVHP2Sa11nIzZdnMAmOSpyejiocVEhtjrwc15L5l4HVDgReCGTR+V9n/AAByma0J+vVwwAAAABJRU5ErkJggg==";
var gticon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADKElEQVR42p2TX2hTdxTHPzfJTW6T3qQmapvWabUbog+udp3kYeLQ4f6wiZQNtjlXHyZaBYe6TekYVGRQYexFscOtuD7UdWxzMtAXEbZStKIbDsaUCbVj9o8mTW+aNrlJbu5vJ8Ex2OMO/Lj87jnne873nO9PSyTV3tkAfYi5NhQ1MB1Ijc3ijN+D7CQh28YK+GHDMyxpjlJTkmAdQi5dWvOsUrYkGB5QC5Kcg/aFBxxqqycmcY38a/1yTqYgMw8ByfFKjtZ4V6myCeW8IApyfOw2155fw1DG4dOJJK1r45x5BPDUpZuMr2uXSuAvgBMQgOitjLJNn7iDSJP0rIJ35dt19TeGoi0Es1MMP72KFvm3+88phuYM3HCd3ObQizpa/cW7Kh020E0Tz1yOUxvjdIr7o6t/cLpkEJqZp7s5zN62ZewfnWLQ9VIIBqodBdI5tIbBG8oKhSAaJZDN8tpSP5+3L8eVgLbeAdKal7NH3mKL3FcOXCfV1ITjc7FLFrWZIlpt/4+qEA7hLRrCwk/RusOXu7ax8xHvGTkVgi/89As/T8ia9EUyghKOWSaYyqNx8oIiuEgcshetsooceibJinvTfNH1DpseD3LHSZE4eprs6k24NQaevI1fF8q5FJqv9xvlmFLdkKZlhb77E8TdIlFD54OOl3mzdXm1k+sP0jzbdwF7cRhsj8ysAWYnpYPeQfXPnn3JJG8/sZT+PW8gkuDbkWEiRh3b29dV/edujNE5dB4nHJSCUrQsTdP9mUKrCKHA5piHK+918quVp/VoD9W9uhGejNRx6+N9VZAmoTJZmhbK4vR7BGDPCQEQ/qU8R15aT2/Hi/R8PcyxyyMyVBmaXwIfPiTVf5yYHiF28ARpOyuqk3nJ4DV2HFc4SamUZ3vrGr7vPlitFNraQc4SzZZt6ptWMv3DAOdGrrGj7yvR+2KYr5A0BeCVAwqvBQuyMG+MTzp3cvj15/ivfXfzNq++/yFEIlD7GFjZ6uPRaE4oGuNQI68jIINJu0QbTFoadIJlL7lSgb8sxbSVEb8geUUVtkh55r50MY5Wec6jibV9/A9LjP7e9TdFQScjW9P1XAAAAABJRU5ErkJggg==";


function GetXmlHttpObject(){
         if (window.XMLHttpRequest){ return new XMLHttpRequest();}
         if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP");}
        return null;
        };

var lc = navigator.lastClick = {};
addEventListener("mouseup", e => {
    if (e.button) return;
    lc.X = e.screenX - mozInnerScreenX;
    lc.Y = e.screenY - mozInnerScreenY;
}, false, gBrowser.tabpanels || 1);

var createWindow = function(text, status, title, id, pos, size){
var win = window, doc = win.document, wId = 'ujs_window'+(id || ''), w = doc.getElementById(wId);
    var keyDown = function(e){if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode == 27)doc.getElementById(wId).closeWin()};
    if(w)w.closeWin();
    w = doc.createElementNS(xhtmlns, 'div');
      w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#33343F;padding-top:0px;border-radius:4px;box-shadow:0 0 15px rgba(0,0,0,.4);' : 'background:-o-skin("Window Skin");'));
    w.id = wId;
    w.closeWin = function(){
        doc.removeEventListener('keydown', keyDown, false);
        this.parentNode.removeChild(this);
    };
    w.addEle = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'div');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }
                else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };

    var img = doc.createElementNS(xhtmlns, 'div');
    img.setAttribute('style', 'display:block;float:right;width:16px;height:16px;padding:0;margin-top:2px;margin-right:1px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVR4Xm2SPUhbURTHfzfNJ4nU0Axx7CJCN2kQtIgVCtq6OdQuBUftWIQqFNsKDo6iHTqIqN3a0kklUKTS2AZrcOjioFtRjFWUfH+803cS9GHwB4dzcu75/+8L9xgaSEDbLXhaASzAyXAMn5/DHxwwjeJgKLRxd3Q0atxuLhGgWqmQmp9PJ7LZJ5Ow3WhQFweDG20LC1FfRwc3kUsm+T48fPIzl3s8VTdxxLt+/2FhdlZkc1MkmdR8Pba2ajlrz3z1+9OvIOaIfb7DwsSEyNKSyM6OSLksEo/rbw2ttadntV7Gnv3k86VfqskvmDzv7hZ580Zkelrk4kJqFIsii4satVrRs+rYmBQHBuRvS4u8g/fuCmDOz+HgAIWpKRgfh3AYhoZQ8Hqxjo4o9PdT3d1FcQEl8KoBnJ7C/j6KZkZGYG4OIhEUFed7erD29q69jGrd1qVBqcQVKgwEuMSEQhjtXRk4JvW/kM1i2WGMga4uzMoKBIOIfbNiolEC6+uU+/qQRALFA1QBlwVYxmBcLmhuxqytQSgEKu7t1dBavwKvbeINh/Has2IMqnXpem4bky6qWLdvZgaOj2FwEHNyoqG19vRMZ8jZs1+NOfsNcZS3EFvzeNL51laRe/dEYrFadsLpZeyZDx7P6QN4Btwx1OE1xO4HAquP2tsjAZ+Pm8gWi3xMpc6W8/kXPyAO/DM4oOsZa2pafdjZGXF7PAgOpXKZL4nE2XImcyUGMDSg63kbhgvgtYCq8+akIL4J3y7Fyn+DokZOnLlMyQAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
        title.onclick = e => {
        e.preventDefault();
        var url = e.target.href;
        // Здесь открываем url как хотим.
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
        doc.getElementById(wId).closeWin();    
    }
    var cnt = doc.createElement("textarea");
    cnt.style.cssText = `
        color: #000;
        width: 310px;
        height: 160px;
        outline: none;
        padding-left: 3px;
        padding-bottom: 3px;
        border: 1px solid #aaa;
        background-color: #fafcfe;
        font: 17px Times New Roman;
    `;
    if (text) cnt.value = text.trim();
    w.append(cnt);
    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
    w.addEventListener('mousedown', function(e){
        if(e.target == w){
            e.preventDefault();
            var st = w.style;
            var mouseMove = e => {
                st.top = parseInt(st.top) + e.movementY + "px";
                st.left = parseInt(st.left) + e.movementX + "px";
            }
            doc.addEventListener('mousemove', mouseMove, false);
            doc.addEventListener('mouseup', function(){doc.removeEventListener('mousemove', mouseMove, false)}, false);
        }
    }, false);
    doc.documentElement.appendChild(w);
  
    if(size){
        cnt.style.height = size.height;
        cnt.style.width = size.width;
    }
    else{
        for(var i = 3; i < 10; i++){
            if(cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth){
                cnt.style.height = 80*i+'px';
                cnt.style.width = 160*i+'px';
            }
            else break;
        }
    };

    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? doc.documentElement : doc.body;
    var mX = docEle.clientWidth-w.offsetWidth, mY = docEle.clientHeight-w.offsetHeight;
    if(mX < 0){cnt.style.width = parseInt(cnt.style.width)+mX+'px'; mX = 0};
    if(mY < 0){cnt.style.height = parseInt(cnt.style.height)+mY+'px'; mY =0};
    var hW = parseInt(w.offsetWidth/2);
    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
    w.style.visibility = 'visible';
    doc.addEventListener('keydown', keyDown, false);
	if (text) {
        var st = cnt.style;
        var div = cnt.editor.rootElement;

        var range = new Range();
        range.selectNode(div.firstChild);
        var rect = range.getBoundingClientRect();

        let w = Math.ceil(rect.width);
        if (cnt.scrollTopMax) {
            if (!matchMedia("(-moz-overlay-scrollbars)").matches) // ???
                w += InspectorUtils.getChildrenForNode(div, true, false).at(-1).clientWidth;
        }
        else st.height = Math.max(50, Math.ceil(rect.height) + 1) + "px";

        st.width = Math.max(200, w) + "px";
    }
    return w;
};

var getHash = function (txt) {
    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
    function sM(a) {
        var b;
        if (null !== yr)
            b = yr;
        else {
            b = wr(String.fromCharCode(84));
            var c = wr(String.fromCharCode(75));
            b = [b(), b()];
            b[1] = c();
            b = (yr = window[b.join(c())] || "") || ""
        }
        var d = wr(String.fromCharCode(116))
            , c = wr(String.fromCharCode(107))
            , d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var l = a.charCodeAt(g);
            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                e[f++] = l >> 18 | 240,
                e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                e[f++] = l >> 6 & 63 | 128),
                e[f++] = l & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++)
            a += e[f],
                a = xr(a, "+-a^+6");
        a = xr(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    }

    var yr = null;
    var wr = function(a) {
        return function() {
            return a
        }
    }
        , xr = function(a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2)
                , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
                , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    };

    return sM(txt);
};

//----------Перевести  текст  из буфера в окне Google------------
var ujs_google_translat = function (dir){
   var lng = 'ru';
   var txt = gClipboard.read(); 
   var l = dir.split('|');
   var encTxt = encodeURIComponent(txt);
   var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&ujs=gtt";
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                  //  result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();

                    createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
    };
};



//----------Перевести выделенный текст в окне Google------------
function ujs_google_translate(langTo_google_text) {
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
       // var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, ""));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                   // result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';
                    //status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + langTo_google_text.toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
     };
};


//----------Заменить текст переводом Google------------
function ujs_google_TexReplace() {
    var lng = 'ru';
    var txt = gContextMenu.selectionInfo.fullText;
    if (txt) {
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + langFrom_google_text + '&tl=' + langTo_google_text + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
       
           function gettransdata(){
           xmlhttp=GetXmlHttpObject();
           xmlhttp.onreadystatechange=stateChanged;
           xmlhttp.open('POST', url, true);
           xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
           xmlhttp.send('q=' + encodeURIComponent(txt));
        }
        function stateChanged() {
            
           if (xmlhttp.readyState == 4 ) {
           var result = '';
           var data = JSON.parse(xmlhttp.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0').replace(/\\n/g, "<br />"));
           for(var i = 0, n; n = data[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
        var msgName = _id + ":ReplaceSelectionRangeAt0";
        var url = "data:," + encodeURIComponent(
       `addMessageListener("${msgName}", function listener(msg) {
        removeMessageListener("${msgName}", listener);
        var win = {};
        Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
            .getFocusedElementForWindow(content, true, win);

        var sel = win.value.document.getSelection();
        if (sel.isCollapsed) return;
        var range = sel.getRangeAt(0);
        range.deleteContents();
        range.insertNode(range.createContextualFragment(msg.data));
    });`
);
function replace(tagString) {
    var mm = gBrowser.selectedBrowser.messageManager;
    mm.loadFrameScript(url, false);
    mm.sendAsyncMessage(msgName, tagString);
}
replace('<span>'+result+'</span>');
                }
        }  
        gettransdata();
    } 
};



//--------Перевести страницу с Google--------------
function ujs_googlePage_translate() {
   var urlt = gBrowser.currentURI.spec;  
   var url = "http://translate.google.com/translate?hl=ru&sl=auto&tl=ru&u="+ encodeURIComponent(urlt) + "&sandbox=1";
   gBrowser. fixupAndLoadURIString(url, {
   triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
});
};


//Контекстное меню для перевода из буфера-------------------------------------------  

(function () {
 if ( document.getElementById("TranslateBufer") ) return; 
 var contextMenu = document.getElementById("contentAreaContextMenu");  
 var Item = document.createXULElement("menuitem");
       Item.setAttribute("label", "Перевод из буфера");
       Item.setAttribute("class", "menuitem-iconic");
       Item.setAttribute("image", mainicon);
       Item.addEventListener("command", function(){ujs_google_translat('auto|ru')}, false);

    contextMenu.insertBefore(Item, document.getElementById("context-viewpartialsource-selection") ); 
    addDestructor(function() { contextMenu.removeChild( Item ) });
 })();

  

 //Контекстное меню для перевода страниц-------------------------------------------  

(function () {
 if ( document.getElementById("TranslatePage") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
  
    menu.id = "TranslatePage";
    menu.setAttribute("label", "Перевести страницу");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);
   
  contextMenu.insertBefore(menu, document.getElementById("context-viewsource") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) }); 

    var array = [
        {label:"Google", func: ujs_googlePage_translate, image:gticon},
        
        
        ];
        
   array.forEach(function( m ) {  
       if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );

       });
   
     addEventListener("popupshowing", function() {
     menu.hidden = gContextMenu.isTextSelected || gContextMenu.onImage || gContextMenu.onTextInput ; 
  }, true, contextMenu );
})();



 //Контекстное меню для перевода текста-------------------------------------------  
(function () {
 if ( document.getElementById("TranslateSelected") ) return; 
  
  var menu = document.createXULElement("menu");  
  var menuPopup = document.createXULElement("menupopup");
  var contextMenu = document.getElementById("contentAreaContextMenu");  
      
    menu.id = "TranslateSelected";
    menu.setAttribute("label", "Перевести выделенный текст");
    menu.setAttribute("class", "menu-iconic");
    menu.setAttribute("image", mainicon);

  contextMenu.insertBefore(menu, document.getElementById("context-viewpartialsource-selection") ); 
  menu.appendChild( menuPopup );
  addDestructor(function() { contextMenu.removeChild( menu ) });
     
    
  var array = [
        {label: "В окне Google на русский", func: () => ujs_google_translate("ru"), image: gticon},
        {label: "В окне Google на английский", func: () => ujs_google_translate("en"), image:gticon},
       
        { separator: ''},
        {label:"Заменить текст переводом Google", func: ujs_google_TexReplace, image:gticon},
        
        
        
              ];
  array.forEach(function( m ) {  
        if ( "separator" in m ) { menuPopup.appendChild( document.createXULElement("menuseparator") ); return };
       var mItem = document.createXULElement("menuitem");
       mItem.setAttribute("label", m.label);
       mItem.setAttribute("class", "menuitem-iconic");
       mItem.setAttribute("image", m.image);
       mItem.addEventListener("command", m.func, false);
       menuPopup.appendChild( mItem );
       });
 
     addEventListener("popupshowing", function() {
     menu.hidden = !gContextMenu.isTextSelected; 
  }, false, contextMenu ); 
 })();


});

Dumby, правильно ли я добавил сепаратор?

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

Выделить код

Код:

/** ------------------------- Пункт контекстного меню для перевода страниц ------------------------- **/
(function () {
	if (document.getElementById("TranslatePage")) return;
	var contextMenu = document.getElementById("contentAreaContextMenu");
	var Item = document.createXULElement("menuitem");
	var sep = document.createXULElement("menuseparator");

	Item.setAttribute("id", "TranslatePage");
	Item.setAttribute("label", "Translate Page");
	Item.setAttribute("class", "menuitem-iconic");
	Item.setAttribute("image", rusFlag);
	Item.addEventListener("command", function() {ujs_googlePage_translate()}, false);

	var cvs = document.getElementById("context-viewsource");

	contextMenu.insertBefore(Item, cvs);
	contextMenu.insertBefore(sep, cvs);
	contextMenu.addEventListener("popupshowing", function() {
		Item.hidden = sep.hidden = cvs.hidden;
	}, false);
})();

6e73epo
Правильно. Можно так: contextMenu.insertBefore(Item, cvs).after(sep);


Да и как вообще можно добавить сепаратор неправильно?
Если он не добавился, или добавился не туда, куда ожидалось,
то это сразу будет видно что неправильно.

Dumby, да просто без sep.hidden сепаратор двоился при первом вызове контекстного меню, в котором пункты скрыты
На скрине, который давал, меню выше затемнено, если буфер обмена пуст и наоборот. Ничего умнее, чем применение readFromClipboard()  - не нашел

Если кому-то как и мне требуется переводить выделенный текст или текст из буфера на английский только с русского, то можно автоматом определять исходный язык. Вызываю функцию с параметром auto|det, а в коде функции добавляю

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

Выделить код

Код:

if (l[1] === "det") {
	l[1] = "ru";
	var fCodeRus = String.fromCodePoint(1040);
	var lCodeRus = String.fromCodePoint(1103);
	for (var j = 0; j < txt.length && j < 20; j++) {
		if (txt[j] >= fCodeRus && txt[j] <= lCodeRus) {
			l[1] = "en";
			break;
		}
	}
};


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

Подскажите что подправить в google_translate.js для Aris-t2.
В контекстном меню страницы строки переводчика немного сместились вправо от иконки по сравнению с другими пунктами меню
Как бы их выровнять с другими пунктами меню. ?
989297a1f69fe2d0c5ade51a6a444ed9.png

Выровнял с другими пунктами меню этот код:

Выделить код

Код:

menupopup .menu-iconic-left {
    -moz-appearance: none !important;
    appearance: none !important;
    margin-inline-start: 0 !important;
    margin-inline-end: 3px !important;
    visibility: visible !important;
  
}

скрытый текст
1c30d38370a4374bad44f525eedd95a8.png 

Dumby пишет

Ааа! Речь не о каких не «пустых строках», а о размере <textarea>.
Тут бы хорошо вообще весь разресайз переписать

Вроде бы ничего сложного нет. Можно по детски. Начальный размер окна (320х160) оставляем без изменений, т.к. не очень приятно лицезреть, например, двухстрочную высоту. При переполнении плавно, с сохранением пропорций, в цикле увеличиваем ширину на 40 px, а высоту на 20 px до пропадания скролла, затем в цикле уменьшаем высоту до появления скролла, затем обратно увеличиваем высоту на 20 px и готово.
С учетом того, что скролл может остаться из-за нарушения форматирования текста, то можно увеличить высоту не на 20, а на 40 px, а затем уменьшить на 20px.

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

Выделить код

Код:

if(size) {
	cnt.style.height = size.height;
	cnt.style.width = size.width;
}
else {
	for (var i = 9; i < 33; i++) {
		if (cnt.scrollTopMax) {
			cnt.style.width = 40*i+'px';
			cnt.style.height = 20*i+'px';
		}
		else break;
	}
	if (i > 9) {
		var k = 0;
		while (!cnt.scrollTopMax) {
			cnt.style.height = parseInt(cnt.style.height)-20+'px';
			k++;
		}
		if (k) {
			cnt.style.height = parseInt(cnt.style.height)+40+'px';
		}
	}
};

// ну и ближе к концу, например после строки w.style.top ...

if (k) {
	cnt.style.height = parseInt(cnt.style.height)-20+'px';
}

6e73epo пишет

Код:

Попробовал я это чуть потестировать.
Фейк, конечно, в окошко просто проброшен выделенный текст,
таким, какой он есть, ну просто чтобы было на что смотреть.


И, вобщем-то, весьма неплохо,
в большинстве случаев, подгонка выглядит хорошо.


Впрочем, попалось и такое
Здесь ширина чуть великовата, как мне кажется
(это на странице about:license, где много всякого текста).

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

Выделить код

Код:

data:image/webp;base64,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


И, даже сподобился словить не ожидавшийся скролл.
Это надеюсь показать в следующем посту,
а то в один пост два таких скиншота не поместятся.

Dumby пишет

надеюсь показать в следующем посту

Ага, размечтался, — «Unable to merge post.»

21-10-2023 20:29:58
Во, с третьей попытки получилось

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

Выделить код

Код:

data:image/webp;base64,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

Dumby пишет

Фейк, конечно, в окошко просто проброшен выделенный текст,
таким, какой он есть, ну просто чтобы было на что смотреть.

Не понял, имеется ввиду без перевода?


Dumby пишет

ширина чуть великовата

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


Dumby пишет

И, даже сподобился словить не ожидавшийся скролл

Повторил, текст выглядит один в один как на скрине, вот только скролла не было и последняя строка видна


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

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

Выделить код

Код:

if (size) {
	cnt.style.height = size.height;
	cnt.style.width = size.width;
}
else {
	for (var i = 9; i < 33; i++) {
		if (cnt.scrollTopMax) {
			cnt.style.width = 40*i+'px';
			cnt.style.height = 20*i+'px';
		}
		else break;
	}
	if (i > 9) {
		cnt.style.height = cnt.editor.rootElement.childNodes[1].offsetTop-4+'px';
	}
};

6e73epo пишет

Не понял, имеется ввиду без перевода?

Да-да, выделенный текст, без перевода.

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

А, это <br> который идёт после текстовой ноды.
Довольно остроумно. И работает.


Но, вычитать четыре пикселя сразу было понятно,
что у меня не прокатит, скролл стопроцентно возникает.
Убрал этот вычет, но что-то не помогло.
А вот когда, наоборот, прибавил четыре пикселя — стало нормально.
Правда это у меня font так ещё и остался 24px от прошлых экспериментов.


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


А у тебя написано так, что если цикл не оборвался прямо сразу,
то высота в любом случае будет установлена, то есть она может и увеличиваться.
И это хорошо, если там чуть-чуть не хватает до пропадания скролла,
но если скролла много, тогда, в результате дальнейшей подгонки,
окошко станет в высоту по всей высоте окна браузера.


Вобщем, даже не знаю, как здесь лучше, как должно быть.
Просто отмечу, что небольшое отличие в таком случае может присутствовать.

Dumby, благодарю, уже сам заметил, что весь цикл может отработать, а скролл остаться, поэтому добавил условие i > 9 && !cnt.scrollTopMax и теперь все ок.


Этот _moz_dirty идеально работает при размере шрифта 17, который как раз меня устраивает, а для большинства размеров offsetTop с плавающим значением. Конечно, можно под определенный размер все настроить, но мне не требуется.


Теперь единственное, что меня не устраивает, это когда при еще не наступившем событии "mouseup" для navigator.lastClick, окошко перевода появляется в правом нижнем углу окна документа браузера, а хочется, чтобы ближе к центру.

6e73epo пишет

Теперь единственное, что меня не устраивает, это когда при еще не наступившем событии "mouseup" для navigator.lastClick, окошко перевода появляется в правом нижнем углу окна документа браузера, а хочется, чтобы ближе к центру.

Функция createWindow() в коде всегда вызывается с аргументом pos
как navigator.lastClick (и, кстати, никогда с аргументом size),
значит pos это гарантированно объект, и это проверять не требуется.


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

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

Выделить код

Код:

/*
    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
*/
    var {X, Y} = pos, U = X == undefined;
    w.style.left = (U ? mX/2 : X < mX + hW ? X > hW ? X - hW : 0 : mX) + "px";
    w.style.top  = (U ? mY/2 : Y + 10 < mY ? Y + 10 : mY) + "px";

6e73epo пишет

работает при размере шрифта 17…… Конечно, можно под определенный размер все настроить…

API браузера - почти операционная система, неужели нет способа подгонки окна под произвольный текст (про HTML с графикой уж молчу) ???
Печально, что баги google-translate.js так долго (c 04-10-2023) победить не получается!


Dumby пишет

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

А если у кого-нибудь на планшете с нестандартным DPI или просто на Линуксе/MacOS размер окна не совпадёт?
Придётся логарифмы ещё добавлять или систему уравнений ! :)

Dumby пишет

Надеюсь ничего не испортил

Да вроде все ок. Спасибо.


Dobrov пишет

API браузера - почти операционная система, неужели нет способа подгонки окна под произвольный текст (про HTML с графикой уж молчу) ???

Когда текст еще не вписан? Вряд ли это возможно или будет крайне сложно. Даже при уже вписанном тексте при разных способах подгонки, получаются разные результаты, т.е. при одних и тех же размерах окна (например 400х200) в одном случае будет скролл, в другом - нет, а в третьем тоже нет, но с пустой строкой.


Так что в итоге, на случай если буду использовать размер шрифта отличный от 17, переделал все под способ Dumby с небольшой модификацией

Dumby, поисковик яндекса с результатами поиска. При наведении мыши на ссылки мы видим реальные адреса, но стоит только вызвать контекстное меню, как адрес меняется на редирект, либо добавляется хвост.
Что бы вы посоветовали (без реализации) для избавления от такого изменения, с учетом, что реализация будет выполняться из консоли страницы?

6e73epo

Remove_Fake_Links, но это user.js скрипт

Dumby
Помогите, пожалуйста, сделать скрипт cookiesPermissions.js для загрузчика метода Aris-t2.
В userChrome.js прописано так:

Выделить код

Код:

userChrome.import("scripts", "UChrm");

Farby, как и ожидалось, Remove_Fake_Links не работает, если включены скрипты статистики яндекса

6e73epo пишет

Что бы вы посоветовали

К сожалению, ничего.
У меня странный FF78 с запрещёнными скриптами, куками, и всё такое прочее.
Там даже сам «поисковик яндекса с результатами поиска» просто не возможен.


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


rubel пишет

Помогите, пожалуйста, сделать скрипт cookiesPermissions.js для загрузчика метода Aris-t2.

Что значит «сделать скрипт cookiesPermissions.js»?
Скрипт вполне себе (как-то) сделан, но под CB,
а значит расчитан на (уже) существующую кнопку.


Если нужен скрипт, который такую кнопку создаст,
то клади в scripts рядом с ним что-то типа такого,
а у самого cookiesPermissions.js смени расширение на .txt
чтобы был не для исполнения загрузчиком, а для чтения скриптом.

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

Выделить код

Код:

window.__SSi == "window0" && CustomizableUI.createWidget({
	id: "CookiesPermissions",
	label: "Cookies Permissions",
	localized: false,
	onCreated(btn) {
		var u = Services.io.newURI;
		var code = Cu.readUTF8URI(u(
			u(Components.stack.filename).resolve("cookiesPermissions.txt")
		)).replace(
			'Components.utils.import("resource://gre/modules/Services.jsm", {})',
			"Cu.getGlobalForObject(Cu)"
		);
		var del = function() {
			this.previousSibling.remove();
			this.remove();
		};
		(this.onCreated = btn => {
			btn.defaultContextId = "toolbar-context-menu";
			var win = btn.ownerGlobal;
			var wdp = new win.DOMParser();
			var parser = class {
				parseFromString(...args) {
					var doc = wdp.parseFromSafeString(...args);
					doc.documentElement.lastChild.appendChild = del;
					return doc;
				}
			}
			win.setTimeout(() => new win.Function("DOMParser", code).call(btn, parser), 50);
		})(btn);
	}
});

Dumby

Если нужен скрипт, который такую кнопку создаст...

ОК. Спасибо. Прекрасно работает. :)

Dumby, можете попробовать во втором приближении перерисовать так, чтобы очистка памяти по левому клику мыши работала без наличия кнопки memoryMinimizationButton, без notifications, статус инфо и прочего мусора, требующегося для сборщиков мусора и без обсервера? Все это у меня отключено в параметрах. Достаточно так, но как на клик прописать?

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

Выделить код

Код:

function doMemMinimize() {
	var gMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
	gMgr.minimizeMemoryUsage(() => {});
}


Вопрос решен. Одной строкой прописал и заработало

6e73epo пишет

Вопрос решен. Одной строкой прописал и заработало

Куда именно добавить, после какой строки?

fuchsfan, "memoryMinimizationButton.doMinimize()" заменил на
"Cc['@mozilla.org/memory-reporter-manager;1'].getService(Ci.nsIMemoryReporterManager).minimizeMemoryUsage(() => {})"
и не знаю, есть ли негативные последствия сего действия

Dumby

Уж не знаю что за Цент,а для лисы как-то так

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

Выделить код

Код:

(async (id, url) => {
	if (location != url) return;
	var menuitem = document.createXULElement("menuitem");
	document.getElementById(id).after(menuitem);
	var hidden = () => !nsContextMenu.contentData.context.linkTextStr;	
	menuitem.hidden = true;
	menuitem.render = () => {
		if (hidden()) return;
		menuitem.hidden = false;
		menuitem.id = id + "text";
		menuitem.label = "Скопировать текст ссылки";
		menuitem.setAttribute("oncommand", "navigator.clipboard.writeText(gContextMenu.linkTextStr);");
		delete menuitem.render;
		menuitem.render();
		menuitem.render = () => menuitem.hidden = hidden();
	}
})("context-copylink", "chrome://browser/content/browser.xhtml");

Возможно ли как-то переделать код для работы вот с этим загрузчиком?

Злой Буратино пишет

Возможно ли как-то переделать код для работы вот с этим загрузчиком?

Ух ты, как там всего навёрнуто!
Но, ничего, создал папку utils, а в ней «three files» :D руками.
И, рядом, папку JS, в которую положил test.uc.js с приведённым кодом.


И пункт контекстного меню страниц «Скопировать текст ссылки»
на ссылках появился, и копирует.
Таким образом, на первый взгляд, никакая переделка не требуется.

Dumby пишет

Ух ты, как там всего навёрнуто!

В описании так: начиная с версии «0.8» fx-autoconfig несовместим с Firefox ESR 102
Непонятно, с какой минимальной версии Firefox этот загрузчик скриптов работает ?

Странно, но не работает.
Либо неправильно понял... У меня в папке utils лежат файлы chrome.manifest, boot.sys.mjs, fs.sys.mjs, utils.sys.mjs. В папке JS (не подпапка, а папка этого же уровня, что и utils) лежат скрипты *.uc.js и, собственно, ваш скрипт. Все работают, ваш не хочет :D
Fx 115.0.4 ESR
ЧЯДНТ?

Dobrov пишет

В описании так: начиная с версии «0.8» fx-autoconfig несовместим с Firefox ESR 102

Ну правильно, там вызов метода, который импортирует ES-модуль,
а это специально выкинули из 102, чтоб не повадно было.

Непонятно, с какой минимальной версии Firefox этот загрузчик скриптов работает ?

Мне-то откуда ведомо, я его сегодня первый раз попробовал развернуть.
Рыться в кодах в поисках самого слабого звена — желания нет.
Заниматься бинарным поиском по-факту от 103 до 121 — тоже неохота.


Злой Буратино пишет

ЧЯДНТ?

Не знаю, и не могу знать.
Можно высказать странное предположение, что скрипт не в кодировке UTF-8.
Есть ли в консоли что-то типа «Caused by: SyntaxError: bad trailing UTF-8 byte 0xCA doesn't match the pattern 0b10xxxxxx»?


Нет, ну не обязательно чтобы только именно в UTF-8,
можно и в ANSI, но тогда и вместо "Скопировать текст ссылки"
придётся писать что-нибудь такое:
"\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0442\u0435\u043A\u0441\u0442 \u0441\u0441\u044B\u043B\u043A\u0438"

Dumby пишет

Можно высказать странное предположение, что скрипт не в кодировке UTF-8.

Бинго! :)
Спасибо, всё работает.

Dumby, попробовал сохранить страницу с поисковыми результатами яндекса, но в оффлайн режиме скрипты статистики не работают. Да и не беда. Я все равно такие скрипты не разрешаю, а без них победить прослушку можной одной строкой из консоли или букмарклета.
Однако, решил автоматизировать, но через скрипт, загружаемый из UserChrome.js, получить доступ к странице яндекса, наверное, не реально, да и ставить одно из обезьяних расширений из-за одного скрипта тоже не хотелось.
Добавил к скрипту манифест, упаковал в xpi, установил. Доступ к функциям страницы был получен малой кровью (wrappedJSObject). И все работает как надо

Dumby пишет

Ух ты, как там всего навёрнуто!

:beer: давно смотрю как загрузчик от ксяо раскорячило, ой продвинул MrOtherGuy

Farby
Посмотрел Ваш измененный пост и попробовал заменить в своем config.js на ваш новый код.
SingleHTML.jsm перестал работать как надо.

rubel пишет

Посмотрел Ваш

Так Вам

Dumby пишет

Перенёс ссылку из ucfBox'а в конфигский сандбокс, и теперь, вроде, не слетает.
Вобщем, попробуй заменить sb[Symbol()] на globalThis[Symbol()]

Уже давно расписал что надо сделать если у Вас не работает...

Здравствуйте.
На некоторых сайтах при закрытии страницы всплывает сообщение "Уйти со страницы" которое не позволяет закрыть вкладку не нажав соответствующую кнопку в предупреждении.

Например здесь: https://www.zbrushcentral.com/t/pendant/434810

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

leex
В about:config - dom.disable_beforeunload = true
userChrome.js тут не причём .

А можно закрыть вкладку повторным нажатием, но не окно.

AlAvis пишет

leex
В about:config - dom.disable_beforeunload = true
userChrome.js тут не причём .


Благодарю!
Сработало.

Народ привет.
Не совсем по Firefox, как перенести этот js скрипт, чтобы работал на Vivaldi?

Надо, чтобы в Vivaldi, можно было закрывать вкладку, если кликать по ней правым кликом мышки
Vivaldi, как и Firefox, тоже поддерживает js скрипты.

Выделить код

Код:

/* Firefox userChrome script
 * Right-clicking on tab button to close tab
 * Shift + right-clicking to popup menu
 * Tested on Firefox 91
 * Author: garywill (https://garywill.github.io)
 */

// ==UserScript==
// @include         main
// ==/UserScript==

console.log("right_click_close_tab.js");

(() => {

    gBrowser.tabContainer.addEventListener("TabOpen", eventTabAdded, false);
    function eventTabAdded(event) {
        var tab = event.target;
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    }
    
    
    function onTabEvent(event) {
        //console.log(event.type);
        if (event.button != 2 || event.shiftKey  ) 
            return;
            
        event.preventDefault();
        event.stopPropagation();
        
        if (event.type == 'click')
            gBrowser.removeTab(this, {animate: true});
    }
    
    gBrowser.tabContainer.querySelectorAll('tab').forEach( function(tab, index) {
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    });
    
})();
Nich пишет

Не совсем по Firefox, как перенести этот js скрипт, чтобы работал на Vivaldi?

К сожалению для вас спешу огорчить, это низкоуровневый скрипт, который исполнятся на уровне ядра [firefox]

gBrowser

Выделить код

Код:

// ==UserScript==
// @include         main
// ==/UserScript==


директива означает что, этот скрипт загружаться раньше чем вы увидели что [firefox] загрузился, что касается chromium подобных сущностей, рекомендую обратить внимание на приставку Version.dll, попробуйте уговорить умельцев создать загрузчик на уровне ядра Chromium

О кстати

https://github.com/Bush2021/chrome_plus
Features

    Double-click to close tab.
    Right-click to close tab. (Hold Shift to show the original menu.)
    Preserve the last tab (prevents the browser from closing when the last tab is closed; clicking the close button will not work.)
    Use the mouse wheel to switch tabs when hovering over the tab bar.
    Use the mouse wheel to switch tabs when holding the right mouse button.
    Create new tab to opens the contents entered in address bar. (Can be configured to open in foreground or background.)
    Create new tab to opens bookmarks. (Can be configured to open in foreground or background.)
    Disable the above two features when the current tab is a new tab.
    Customize hotkeys to quickly hide the browser window (boss key).
    Customize hotkeys to translate web page.
    Portable design: the program is placed in the App directory, and data is stored in the Data directory (incompatible with the original data; you can reinstall the system or change computers without losing data).
    Allow configuration of features using ini files.
    Allow custom Chromium startup parameters.


Вообще-то там это заявлено из коробки

Nich пишет

Vivaldi, как и Firefox, тоже поддерживает js скрипты.

когда увидите фразу

Firefox userChrome script

сразу проходите мимо, это не про Chromium Clones...

Nich пишет

Народ привет.
Не совсем по Firefox, как перенести этот js скрипт, чтобы работал на Vivaldi?

Надо, чтобы в Vivaldi, можно было закрывать вкладку, если кликать по ней правым кликом мышки
Vivaldi, как и Firefox, тоже поддерживает js скрипты.

Выделить код

Код:

/* Firefox userChrome script
 * Right-clicking on tab button to close tab
 * Shift + right-clicking to popup menu
 * Tested on Firefox 91
 * Author: garywill (https://garywill.github.io)
 */

// ==UserScript==
// @include         main
// ==/UserScript==

console.log("right_click_close_tab.js");

(() => {

    gBrowser.tabContainer.addEventListener("TabOpen", eventTabAdded, false);
    function eventTabAdded(event) {
        var tab = event.target;
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    }
    
    
    function onTabEvent(event) {
        //console.log(event.type);
        if (event.button != 2 || event.shiftKey  ) 
            return;
            
        event.preventDefault();
        event.stopPropagation();
        
        if (event.type == 'click')
            gBrowser.removeTab(this, {animate: true});
    }
    
    gBrowser.tabContainer.querySelectorAll('tab').forEach( function(tab, index) {
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    });
    
})();

https://github.com/benzBrake/VivaldiMods/blob/main/chrome/userChromeJS/rightClickTabToClose.ac.js

brake пишет
Nich пишет

Народ привет.
Не совсем по Firefox, как перенести этот js скрипт, чтобы работал на Vivaldi?

Надо, чтобы в Vivaldi, можно было закрывать вкладку, если кликать по ней правым кликом мышки
Vivaldi, как и Firefox, тоже поддерживает js скрипты.

Выделить код

Код:

/* Firefox userChrome script
 * Right-clicking on tab button to close tab
 * Shift + right-clicking to popup menu
 * Tested on Firefox 91
 * Author: garywill (https://garywill.github.io)
 */

// ==UserScript==
// @include         main
// ==/UserScript==

console.log("right_click_close_tab.js");

(() => {

    gBrowser.tabContainer.addEventListener("TabOpen", eventTabAdded, false);
    function eventTabAdded(event) {
        var tab = event.target;
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    }
    
    
    function onTabEvent(event) {
        //console.log(event.type);
        if (event.button != 2 || event.shiftKey  ) 
            return;
            
        event.preventDefault();
        event.stopPropagation();
        
        if (event.type == 'click')
            gBrowser.removeTab(this, {animate: true});
    }
    
    gBrowser.tabContainer.querySelectorAll('tab').forEach( function(tab, index) {
        tab.addEventListener('click', onTabEvent);
        tab.addEventListener('contextmenu', onTabEvent);
    });
    
})();

https://github.com/benzBrake/VivaldiMods/blob/main/chrome/userChromeJS/rightClickTabToClose.ac.js


Очень благодарю!

Ещё хотел спросить, вот у меня в Firefox, js скрипт активирует вкладку при наведении на нее, но не работает тогда выбор выделение вкладок, сбивается фокус, може есть какое нибудь решение?

Этот скрипт работал из config.js пока AboutNewTab.jsm не превратился в AboutNewTab.sys.mjs. Может кому-то не слабо переделать?

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

Выделить код

Код:

try {
  Cu.import("resource:///modules/AboutNewTab.jsm");

  if (AboutNewTab.newTabURL === "about:newtab") AboutNewTab.newTabURL = "about:blank";
} catch(e) {Cu.reportError(e)};

6e73epo
Эээ...


Cu.import("resource:///modules/AboutNewTab.jsm");
let {AboutNewTab} = ChromeUtils.importESModule("resource:///modules/AboutNewTab.sys.mjs");

Dumby
Спасибо. Делал также, но вместо ChromeUtils указывал Cu и получал: Cu.importESModule is not a function. Ну и зачем-то  полез искать решение в Cu.getGlobalForObject(Cu)

6e73epo пишет

вместо ChromeUtils указывал Cu

Cu.import("….jsm") и сейчас работает,
надо было только забрать AboutNewTab с того, что он возвращает.


Код, видимо, был сделан ещё во времена, когда этот метод
устанавливал экстортное добро прямо в глобальный объект.
Но он давно уже этого не делает.


Однако, ChromeUtils.importESModule() — это мейнстрим,
а Cu.import() подлежит удалению, надо полагать в 129.

зачем-то  полез искать решение в Cu.getGlobalForObject(Cu)

ChromeUtils был добавлен в конфигский сандбокс с Firefox 101+
А если бы не был добавлен, то правильно полез,
туда за ним слазить прямо напрашивается.

6e73epo

Dumby пишет

Но он давно уже этого не делает.

Похоже, здесь я совравши.
Подорвался проверить, в 125.0.1 запускаю с консоли


console.log(window.ProcessType);
Cu.import("resource://gre/modules/ProcessType.jsm");
console.log(window.ProcessType);


Первый лог — undefined
Второй лог — уже Object {...}


Тогда вернул Cu.import("resource:///modules/AboutNewTab.jsm");
Рестарт, и по Ctrl+T открывается about:blank


Я был уверен, что фичу выпилили, блин, всё надо проверять.
Осталось только непонятно, почему у тебя перестало работать.

Dumby
Вернул по старому и ошибок нет, а раньше была AboutNewTab is not defined. Теперь уже не знаю почему. Может Cu.import проходил с задержкой. Долго экспериментировал в стилях для установки фонового локального изображения для blanktab.html и about:blank. В итоге оставил только для blanktab.html.