b0ttle
Спасибо, помогло
я у себя их просто уменьшил, чтобы не такие огромные были.
#titlebar-buttonbox > .titlebar-button, .titlebar-buttonbox > :-moz-any(.titlebar-min,.titlebar-max,.titlebar-close,.titlebar-restore), #minimize-button, #restore-button, #close-button {
margin: 0 !important;
padding: 4px 8px !important;
}
Всех с праздником, наступившим и наступающим!
Отредактировано Northtech (31-12-2023 19:39:18)
Отсутствует
в новой версии ucf_hookClicks.js пропадает блок кнопок закрытия окна (#minimize-button, #restore-button, #close-button).
Попробуй включить "Кнопки управления окна" в диалоге "Настройки UserChromeFiles"
Отсутствует
Отсутствует
egorsemenov06
Пробуйте..
// ==UserScript== // @name Browser search engine // @author Vitaliy V. // @include main // @shutdown window.contextsearch.destructor(); // @note https://forum.mozilla-russia.org/viewtopic.php?pid=780283#p780283 // ==/UserScript== (this.contextsearch = { topic: "browser-search-engine-modified", hide: "browser.search.hiddenOneOffs", defaultImg: "chrome://browser/skin/search-engine-placeholder.png", searchSelect: null, popup: null, init(that) { var searchSelect = this.searchSelect = document.querySelector("#context-searchselect"); if (!searchSelect) return; var popup = this.popup = searchSelect.closest("menupopup"); popup.addEventListener("popupshowing", this); that.unloadlisteners?.push("contextsearch"); }, destructor() { this.popup.removeEventListener("popupshowing", this); if (this.popupshowing == this.handler) { this.popup.removeEventListener("popuphidden", this); Services.obs.removeObserver(this, this.topic); Services.prefs.removeObserver(this.hide, this); } }, handleEvent(e) { this[e.type](e); }, popupshowing(e) { var popup = this.popup; var searchSelect = this.searchSelect; if (e.target != popup || searchSelect.hidden) return; var menu = document.createXULElement("menu"); menu.className = "menu-iconic"; var menupopup = document.createXULElement("menupopup"); menu.append(menupopup); menu.ePopup = menupopup; searchSelect.style.setProperty("display", "none", "important"); searchSelect.before(menu); menu.onclick = this.search.bind(this); this.handler = e => e.target != popup || (menu.hidden = searchSelect.hidden); this.handlerRebuild = e => this.handler(e) || this.rebuild(menu); this.popuphidden = ev => { if (ev.target != popup) return; menu.hidden = true; }; this.popup.addEventListener("popuphidden", this); this.rebuild(menu); }, getEngines() { var args = "hideOneOffButton" in Services.search.defaultEngine ? [e => !e.hideOneOffButton] : Object.defineProperty( [function(e) {return !this.includes(e.name);}], "1", { get: () => Services.prefs.getStringPref(this.hide)?.split(",") || [] } ); return (this.getEngines = async () => (await Services.search.getVisibleEngines()).filter(...args) )(); }, async rebuild(menu) { var de = Services.search.defaultEngine; de = de.wrappedJSObject || de; this.setAttrs(menu, de, `Искать в ${de.name} или в ...`); menu.ePopup.textContent = ""; for(let engine of await this.getEngines()) { if (engine == de) continue; var menuitem = document.createXULElement("menuitem"); menuitem.className = "menuitem-iconic"; this.setAttrs(menuitem, engine); menu.ePopup.append(menuitem); } this.popupshowing = this.handler; Services.obs.addObserver(this, this.topic, false); Services.prefs.addObserver(this.hide, this); }, setAttrs(node, engine, label = engine.name) { node.engine = engine; node.setAttribute("label", label); node.setAttribute("image", engine._iconURI ? engine._iconURI.spec : engine.iconURI ? engine.iconURI.spec : this.defaultImg); }, observe() { this.popupshowing = this.handlerRebuild; Services.obs.removeObserver(this, this.topic); Services.prefs.removeObserver(this.hide, this); }, search(e) { var {engine} = e.target; if (!engine) return; var searchSelect = this.searchSelect; var submission = engine.getSubmission( searchSelect.searchTerms, null, "contextmenu" ); if (submission) { let tab = gBrowser.addTab(submission.uri.spec, { postData: submission.postData, index: (gBrowser.selectedTab._tPos + 1), triggeringPrincipal: searchSelect.principal }); if (e.button == 0) gBrowser.selectedTab = tab; } var popup = this.popup; e.button != 1 && popup.state == "open" && popup.hidePopup(); } }).init(this);
Жизнь иногда такое выкидывает, что хочется подобрать...
Отсутствует
А с первой не поможите?
Это баг 1872673 - Remove 'console' export from Console.sys.mjs
То есть, дело не в коде кнопки, а в само́м UCF.
Но держать отладочный консольский стафф в кнопке постоянно
не требуется, можешь просто удалить console.log(req)
Однако, вернуть в укфский сандбокс консоль не помешает.
Я тут в user_chrome.js так переставлял
/* if ("defineLazyModuleGetters" in XPCOMUtils) XPCOMUtils.defineLazyModuleGetters(scope, { console: "resource://gre/modules/Console.jsm", AddonManager: "resource://gre/modules/AddonManager.jsm", AppConstants: "resource://gre/modules/AppConstants.jsm", E10SUtils: "resource://gre/modules/E10SUtils.jsm", FileUtils: "resource://gre/modules/FileUtils.jsm", OS: "resource://gre/modules/osfile.jsm", PlacesUtils: "resource://gre/modules/PlacesUtils.jsm", setTimeout: "resource://gre/modules/Timer.jsm", setTimeoutWithTarget: "resource://gre/modules/Timer.jsm", clearTimeout: "resource://gre/modules/Timer.jsm", setInterval: "resource://gre/modules/Timer.jsm", setIntervalWithTarget: "resource://gre/modules/Timer.jsm", clearInterval: "resource://gre/modules/Timer.jsm", }); */ var data = { AddonManager: null, AppConstants: null, E10SUtils: null, FileUtils: null, PlacesUtils: null, Timer: ["setTimeout", "setTimeoutWithTarget", "clearTimeout", "setInterval", "setIntervalWithTarget", "clearInterval"] }; var sfx, def, modules = {}; var vers = parseInt(Services.appinfo.platformVersion); if (vers <= 114) data.osfile = "OS"; if (vers <= 122) def = XPCOMUtils.defineLazyModuleGetters, sfx = "jsm", data.Console = "console"; else def = ChromeUtils.defineESModuleGetters, sfx = "sys.mjs", ChromeUtils.defineLazyGetter(scope, "console", () => Cu.getGlobalForObject(Cu).console.createInstance()); var set = (key, val) => modules[key] = `resource://gre/modules/${val}.${sfx}`; for(var key in data) { var val = data[key] || key; if (Array.isArray(val)) for(var str of val) set(str, key); else set(val, key); } def(scope, modules);
Отсутствует
В шапке бы поправить ссылку на рабочую - "Восстановить фавиконки закладок".
Похож чем-то, с тем что выше. Тоже рабочий, пользуюсь. ucf_contextsearch.js
Да они идентичны, с мелкими различиями в коде)
Отредактировано b0ttle (19-02-2024 21:44:24)
Отсутствует
В шапке бы поправить ссылку
На этом форуме нет шапок, есть только первый пост, посему это могут сделать либо создатель либо модератор...
Да они идентичны, с мелкими различиями в коде)
Если у вас все работает,
Тоже рабочий, пользуюсь. ucf_contextsearch.js
пользуйтесь... Речь шла про 1945 год, ой про 123 найди различия...
Отредактировано Farby (19-02-2024 22:22:14)
Жизнь иногда такое выкидывает, что хочется подобрать...
Отсутствует
Farby
Сорри, этот момент упустил. Вы его сами подправили, вроде разбирайтесь в коде?
Надеюсь, что обновят некоторые ссылки с первого поста, а так скорее затеряется.
Отредактировано b0ttle (19-02-2024 23:27:47)
Отсутствует
В шапке бы поправить ссылку на рабочую - "Восстановить фавиконки закладок".
Раз это не в скрипте проблема, шапку пока не менял.
Это баг 1872673 - Remove 'console' export from Console.sys.mjs
То есть, дело не в коде кнопки, а в само́м UCF.
Dumby - Благодарю!
Обновил на гитхабе chrome/user_chrome_files/user_chrome.js
в Demo-профиле - сборке полезных скриптов немного поправил:
user_chrome.js, UcfPrefs.jsm, ucf_UrlTooltip, ucf_contextmenuopenwith, ucf_contextsearch, ucf_hookClicks
Отсутствует
Раз это не в скрипте проблема
Кстати, скрипт под багом ходит (1552815).
Движуха там затихла, но в любой момент это дело могут пнуть,
и баг вывалится как "FIXED". Прикинь тогда разгребать.
.jsm
А вот и баг о временах и сроках.
Может завести какую-нибудь папку с любым условным названием типа «129».
Запилить на неё readme, мол здесь вам (пока) не что-то готовое,
но всего лишь WIP-полигон миграции JSM —> ESM.
Это я в том смысле, что время пока есть,
и «подстелить соломку», а не чтобы как «снег на голову».
Совместимость, разумеется, может и должна быть сброшена.
Отсутствует
.jsm
А вот и баг о временах и сроках.
когда JSM уберут, то UCF практически перестанет работать!
Я не осилю добавить ESM в UCF-user_chrome.js и в CustomStylesScripts.jsm загрузчик скриптов/стилей…
Отсутствует
Dobrov
есть возможность сделать в ucf_contextsearch.js открытие вкладки поиска фоном? Или зависящим от этой настройки: user_pref("browser.search.context.loadInBackground", true);
Отсутствует
есть возможность сделать в ucf_contextsearch.js открытие вкладки поиска фоном? Или зависящим от этой настройки: user_pref("browser.search.context.loadInBackground", true);
Поиск и так открывается в фоновой вкладке по клику правой кнопкой или колёсиком на любых строках меню и подменю.
Отредактировано Dobrov (29-02-2024 01:51:11)
Отсутствует
egorsemenov06
Я так понял. Когда накроется jsm, отвалится весь UCF. Куда Вы будете эти кнопки писать, если CustomStylesScripts.jsm не будет работать? Или пересаживаться на старую версию версию UCF?
Отредактировано xrun1 (29-02-2024 05:31:45)
Отсутствует
Dumby возникла хотелка для менюшки кнопки, которую я немного доработал.
это меню создаётся однократно и перед кликом на кнопке его не существует, т.е. однократно выполняется menu.render = this.render;
Нужно, чтоб менялись строки меню перед его открытием в зависимости от опций about:config и прочих проверок, например "Графика сайтов включена" вместо "Графика сайтов вкл/выкл"
Прошу доработать код, чтоб ключи «lab» могли быть с backticks-кавычками и текст мог обновляться перед каждым открытием меню:
lab: `${проверка условия ? "√ Да, всё OK" : "Х Нет"}`
(async id => { // by Dumby forum.mozilla-russia.org/viewtopic.php?pid=807581#p807581 MyMenu = { //массив команд пользователя, alt() клик правой кнопкой Pics: { lab: `Графика сайтов вкл/выкл | Right Click`, inf: 'текст обновляется перед открытием меню', cmd(){ var n = uc.pref(E.v) == 2; uc.pref(E.v, n ? 1 : 2); BrowserReload(); }, alt(){ /* для этих действий нужен ucf_hookClicks.js */}, }, "Прочие команды": { sep: 1, //сперва разделитель cmd(){console.log("OK");} }, } CustomizableUI.createWidget({ id: id, label: id, tooltiptext: id, localized: false, defaultArea: CustomizableUI.AREA_NAVBAR, onCreated(btn) { btn.style.setProperty("list-style-image", "url(chrome://branding/content/icon32.png)"); btn.type = "menu"; var doc = btn.ownerDocument, m = nn => doc.createXULElement(nn); var popup = m("menupopup"), menu = m("menuitem"); menu.m = m; menu.fill = this.fill; menu.render = this.render; popup.append(menu); btn.prepend(popup); }, render(){ var popup = this.parentNode; this.remove(); this.fill(MyMenu, popup); }, fill(o, popup){ if (typeof o == "object") for (key in o){ var {lab, sep, sub, cmd, alt, inf, img} = o[key]; var name = sub ? "menu" : "menuitem"; sep && popup.append(this.m("menuseparator")); var item = this.m(name); item.setAttribute("label", lab || key); //update при изменении настроек if (img) item.className = name +"-iconic", item.setAttribute("image",img); if (inf) item.tooltipText = inf; item.alt = alt; //cmd2 sub || cmd && item.setAttribute("oncommand", cmd.toString().replace(/cmd\(.*?\){/,'{var trg = event.target || event;')); /^(sub|sep|inf|lab|img)$/.test(key) || popup.append(item); sub && this.fill(o[key], item.appendChild(this.m("menupopup"))); } }, }); E = { v: "permissions.default.image" } window.uc = { //all ChromeOnly-scripts pref(key,set){ //или key = [key,default] if (!Array.isArray(key)) key = [key]; var t = prefs.getPrefType(key[0]), m = {b:"Bool",n:"Int",s:"String"}; t = m[t == 128 ? "b" : t == 64 ? "n" : t == 32 ? "s" : ""]; if (set == "get") return t; //тип опции if (!t) t = m[set != undefined ? (typeof set)[0] : (typeof key[1])[0]]; if (t) if (set != undefined) prefs[`set${t}Pref`](key[0],set) else set = prefs[`get${t}Pref`](...key); return set; } } })("ucf_test_menu");
Отсутствует
Ссылки кликабельны
Здесь можно переделать. Переименовать UcfTextToLinkActorChild.{ jsm —> mjs } и правки
/* moduleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.jsm", */ esModuleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.mjs"
В UcfTextToLinkActorChild.mjs
/* var EXPORTED_SYMBOLS = ["UcfTextToLinkActorChild"]; var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyGlobalGetters(this, ["NodeFilter", "Node"]); XPCOMUtils.defineLazyGetter(this, "excludedTags", () => { return new Set(["a","svg","canvas","applet","input","button","area","embed","noembed","frame","frameset","head","iframe","img","select","option","datalist","map","meta","noscript","video","audio","object","param","script","style","textarea","code"]); }); class UcfTextToLinkActorChild extends JSWindowActorChild { */ var excludedTags = Object.defineProperty({}, "has", { value: tag => (excludedTags = new Set([ "a","svg","canvas","applet","input","button","area","embed","noembed","frame","frameset","head","iframe","img", "select","option","datalist","map","meta","noscript","video","audio","object","param","script","style","textarea","code" ])).has(tag) }); export class UcfTextToLinkActorChild extends JSWindowActorChild {
переключение раскладки клавиатуры по F8
Для этого кода нужен дебаггер.
В UCF 3 вообще необходимо встраивать дебаггер,
не городить же в каждом скрипте, где он нужен, свой собственный.
Но, наверно, можно пробросить implementation из кода само́й кнопки,
однако, этот код не предоставлен.
special_widgets.js
Этот скрипт — часть UCF.
На первый взгляд, в данном контексте ему ничего не угрожает.
Наоборот, его скорее покрамсать хочется.
и еще одна
Здесь можно попробовать влепить что-нибудь такое,
тогда, надеюсь, не будет импорта никаких jsm'ок.
/* try { */ if(Components.interfaces.nsIWebTransportHash) { // random, Fx 123+ var func = function() { func = false; } var thread = Services.tm.currentThread; var meth = newDis ? "disable" : "enable"; addon[meth]({allowSystemAddons: true}).finally(func); while(func) thread.processNextEvent(true); } else try {
немного доработал
Ничего себе «немного». Как там задумана обработка
структуры MyMenu я сходу понять не могу, субменю вообще в примере нет.
Ну хорошо хоть вопрос не об этом.
Добавил туда var {prefs} = Services; и заработало.
Можно ввести ещё один ключ — upd
который будет представлять собой функцию,
которая перекроет метод render() для item'а.
Ключевое слово this в этой функции будет ссылаться на сам item.
Например, вместо lab и inf пишем:
upd() {
//var {uc, E} = this.ownerGlobal;
var val = uc.pref(E.v);
this.label = `${E.v} is ${val == 1 || val == 2 ? val : "not 1 and not 2"}`;
this.tooltipText = val;
},
Далее, учитываем новый ключ в var {lab, sep, sub, cmd, alt, inf, img, upd} = o[key];
И дописываем подмену после добавления item'а в popup:
/^(sub|sep|inf|lab|img)$/.test(key) || popup.append(item) || upd && (item.render = upd).call(item);
Однако, хоть lab и убран, код тогда всё равно проставляет вместо него label — key,
а upd() уже затем ставит свой. Это слегка нехорошо, но тут уж думай сам, или забей.
Отсутствует
Ничего себе «немного». Как там задумана обработка структуры MyMenu я сходу понять не могу, субменю вообще в примере нет.
Спасибо за помошь!
P.S. Массив вместе с субменю есть в ucf_hookClicks.js, вложенность любая.
Отсутствует
Массив вместе с субменю есть в ucf_hookClicks.js, вложенность любая.
Да, теперь чуть понятнее, наверно.
А то я думал, к чему это /^(sub|sep|inf|lab|img)$/.test(key)
Оказывается, что если вписан sub, код прогоняет через for in
объект в который вписан sub.
То есть, и для ключей, упомянутых в этом регулярном выражении
тоже создаётся (ненужный) элемент (как минимум <menuitem>)
и ему присваивается одноимённый атрибут "label".
Если значение ключа окажется строкой, то тогда создаётся не <menuitem>,
а <menu>, и создаётся <menupopup>, который добавляется к этому menu.
Всё потому, что у строки есть sub.
Вот проверь с консоли: var {sub} = "bla-bla"; alert(sub);
Это будет — String.prototype.sub().
Эти ненужные элементы можно посмотреть в консоли,
если добавить в конец метода fill() строку
if (!item.parentNode) console.log(item.outerHTML);
Вот чтобы всё это низачем-созданное добро
не попало в итоговую DOM-структуру и нужен этот regexp.
Может этого как-то избежать, типа
// fill(o, popup) { for (key in o) { var val = o[key]; if (typeof val != "object") continue; var {lab, sep, sub, cmd, alt, inf, img, upd} = val; sep && popup.append(this.m("menuseparator")); var name = sub ? "menu" : "menuitem"; var item = this.m(name); item.setAttribute("label", lab || key); if (img) item.className = name + "-iconic", item.setAttribute("image", img); item.alt = alt; //cmd2 if (inf) item.tooltipText = inf; sub || cmd && item.setAttribute("oncommand", cmd.toString().replace( /cmd\(.*?\){/, "{var trg = event.target || event;" )); popup.append(item); upd && (item.render = upd).call(item); sub && this.fill(val, item.appendChild(this.m("menupopup"))); } },
сделайте пожалуйста из этих 2-х
// Switch Keyboard Layout (async keybUtils => CustomizableUI.createWidget(({ localized: false, id: "SwitchKeyboardLayout", init() { this.label = this.tooltiptext = "Switch Keyboard Layout"; var args = ["keydown", e => { if (e.key != "F8" || e.ctrlKey || e.shiftKey || e.altKey || e.repeat) return; //e.preventDefault(); //e.stopPropagation(); this.switch(e.view.document); }, true]; var unload = e => e.target.ownerGlobal.removeEventListener(...args); var obs = win => { win.addEventListener(...args); win.addEventListener("unload", unload, {once: true}); } var topic = "browser-delayed-startup-finished"; Services.obs.addObserver(obs, topic); Services.obs.addObserver(function quit(s, t) { Services.obs.removeObserver(quit, t); Services.obs.removeObserver(obs, topic); }, "quit-application-granted"); return this; }, onCreated(btn) { btn.linkedObj = this; btn._handleClick = this.click; btn.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAk1BMVEX///8/Pz8BAQF8fHwJCQkCAgIJCQl8fHx9fX0AAABJSUkBAQENDQ0wMDBVVVUAAABra2t0dHR7e3thYWEBAQEAAAAAAAABAQEAAAAgICABAQEBAQH8/Pzw8PDp6en39/fj4+Pe3t41V9I/YeWKioqDg4N9fX0jRa8wUrVoaGhkhuxWeNx1dXVCZMhvb28kRqsqTL4KidXxAAAAHHRSTlMAAABndwAAAAA0blVZcm1naWhNa6hrcJ8AAKRU4jk/3gAAAHVJREFUeF6FyMUCwjAUBdEbaQupUMOjqMv/fx1dQN6yZ3aDcWnyw6ezoRWNYc15kqKQZCFlgTKQQwgllL/dn5f3+bPb+6P3CpWNw56srdCZOMzDmA61i8O9nKvRaHLVukEryFKIFtnkj7ENYxmNdd5v+5xj1BcJ/w9Kj6K7ZAAAAABJRU5ErkJggg=="; }, click() { this.linkedObj.switch(this.ownerDocument); }, switch(doc) { var br = doc.activeElement; br && br.localName == "browser" && br.isRemoteBrowser ? br.messageManager.loadFrameScript(this.url, false) : this.keybUtils.switchSelKeybLayout(); }, get url() { delete this.url; return this.url = `data:;charset=utf-8,(${ encodeURIComponent(keybUtils) }).switchSelKeybLayout()`; }, get keybUtils() { delete this.keybUtils; var def = "let{KeyEvent,HTMLInputElement,HTMLTextAreaElement}=Cu.getGlobalForObject(Services);"; var url = `data:;charset=utf-8,${def}%0Athis.keybUtils=${encodeURIComponent(keybUtils)}`; Services.scriptloader.loadSubScript(url, this); var {id} = this; this.keybUtils.getFocusedElement = function(_subCall, _focusFixed) { var window = Services.focus.activeWindow, {document} = window; var button = document.getElementById(id); if( !_focusFixed && "closeMenus" in window && document.commandDispatcher.focusedElement == button ) { window.closeMenus(button); window.setTimeout(function(_this) { _this.switchSelKeybLayout(_subCall, true); }, 0, this); return; } return document.commandDispatcher.focusedElement; } return this.keybUtils; } }).init()))(`{ //== Options noSelBehavior: "BeginLine", //"EndLine", //"All", //"Top", //"Bottom", //"PageUp", //"PageDown", // etc // falsy - do nothing // Or use string like following to call cmd_select{string} convTableForward: { // ru -> en "\\"": "@", ":": "^", ";": "$", "?": "&", ",": "?", "/": "|", ".": "/", "э": "'", "б": ",", "ю": ".", "Ж": ":", "ж": ";", "Б": "<", "Ю": ">", "Э": "\\"", "х": "[", "ъ": "]", "ё": "\`", "Х": "{", "Ъ": "}", "Ё": "~", "№": "#", "Ф": "A", "ф": "a", "И": "B", "и": "b", "С": "C", "с": "c", "В": "D", "в": "d", "У": "E", "у": "e", "А": "F", "а": "f", "П": "G", "п": "g", "Р": "H", "р": "h", "Ш": "I", "ш": "i", "О": "J", "о": "j", "Л": "K", "л": "k", "Д": "L", "д": "l", "Ь": "M", "ь": "m", "Т": "N", "т": "n", "Щ": "O", "щ": "o", "З": "P", "з": "p", "Й": "Q", "й": "q", "К": "R", "к": "r", "Ы": "S", "ы": "s", "Е": "T", "е": "t", "Г": "U", "г": "u", "М": "V", "м": "v", "Ц": "W", "ц": "w", "Ч": "X", "ч": "x", "Н": "Y", "н": "y", "Я": "Z", "я": "z", __proto__: null }, //== End of options get convTableBackward() { var ctb = { __proto__: null }; var ctf = this.convTableForward; for(var c in ctf) ctb[ctf[c]] = c; delete this.convTableBackward; return this.convTableBackward = ctb; }, inPrimaryLayout: function(s) { for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); var primary = c in this.convTableForward; if(primary ^ c in this.convTableBackward) return primary; } return false; }, switchKeybLayout: function(s, convTable) { var res = ""; for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); res += c in convTable ? convTable[c] : c; } return res; }, getFocusedElement: function() { return Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, {}); }, switchSelKeybLayout: function(_subCall, _focusFixed) { var fe = this.getFocusedElement(_subCall, _focusFixed); if(!fe) return; if(HTMLInputElement.isInstance(fe) || HTMLTextAreaElement.isInstance(fe)) { var ta = fe; try { var val = ta.value; var sel = val.substring(ta.selectionStart, ta.selectionEnd); } catch(e) { // Non-text HTMLInputElement return; } if(!sel && val && this.noSelBehavior && !_subCall) { if(this.noSelBehavior == 1) { ta.selectionStart = 0; ta.selectionEnd = val.length; sel = val; } else { this.handleNoSel(ta); return; } } if(!sel) return; var res = this.switchKeybLayout( sel, this.inPrimaryLayout(sel) ? this.convTableForward : this.convTableBackward ); if(res != sel) this.insertText(ta, res); } else if(fe.contentEditable == "true") { var doc = fe.ownerDocument; var docURI = doc.documentURI; if( docURI.substr(0, 5) == "data:" && docURI.indexOf("chrome://browser/skin/devtools/") != -1 ) { //~ todo: seems like we only can use paste from clipboard here... return; } var sel = doc.defaultView.getSelection(); var rng = sel.rangeCount && sel.getRangeAt(0); var tmpNode; if(!rng || rng.collapsed) { if(!this.noSelBehavior || _subCall) return; if(this.noSelBehavior == 1) { var r = doc.createRange(); r.selectNodeContents(fe); sel.removeAllRanges(); sel.addRange(r); tmpNode = fe.cloneNode(true); } else { this.handleNoSel(fe); return; } } else { tmpNode = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); tmpNode.appendChild(rng.cloneContents()); } var orig = tmpNode.innerHTML; var convTable = this.inPrimaryLayout(tmpNode.textContent) ? this.convTableForward : this.convTableBackward; var _this = this; var parseChildNodes = function(node) { if(Element.isInstance(node)) { var childNodes = node.childNodes; for(var i = childNodes.length - 1; i >= 0; --i) parseChildNodes(childNodes[i]); } else if(node.nodeType == node.TEXT_NODE) { var text = node.nodeValue; var newText = _this.switchKeybLayout(node.nodeValue, convTable); if(newText != text) node.parentNode.replaceChild(doc.createTextNode(newText), node); } } parseChildNodes(tmpNode); var res = tmpNode.innerHTML; if(res != orig) doc.execCommand("insertHTML", false, res); } }, handleNoSel: function(node) { this.select(node); this.switchSelKeybLayout(true); }, select: function(node) { // var e = this.noSelBehavior; // if(!e || typeof e != "object") // return; // var evt = node.ownerDocument.createEvent("KeyboardEvent"); // evt.initKeyEvent( // "keypress", true /*bubbles*/, true /*cancelable*/, node.ownerDocument.defaultView, // e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, // e.keyCode, e.charCode // ); // node.dispatchEvent(evt); var beh = this.noSelBehavior; beh && node.ownerGlobal.docShell.doCommand("cmd_select" + beh); }, beh2cmd: { // Ctrl_Shift_VK false_true_36: "cmd_selectLinePrevious", // Shift+Home }, insertText: function(ta, text) { //var editor = ta.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor var editor = ta.editor .QueryInterface(Components.interfaces.nsIPlaintextEditor || Ci.nsIEditor); if(editor.flags & editor.eEditorReadonlyMask) return; var sTop = ta.scrollTop; var sHeight = ta.scrollHeight; var sLeft = ta.scrollLeft; // var sWidth = ta.scrollWidth; if(text) editor.insertText(text); else editor.deleteSelection(0, 0); ta.scrollTop = sTop + (ta.scrollHeight - sHeight); ta.scrollLeft = sLeft; // + (ta.scrollWidth - sWidth); } }`);
Отсутствует
Оказывается, что если вписан sub, код прогоняет через [for in] объект в который вписан sub.
То есть, и для ключей, упомянутых в этом регулярном выражении тоже создаётся (ненужный) элемент (как минимум <menuitem>)
Спасибо! Я делал так же: (обработать только объект), но результат разный:
for (key in o) { if (typeof o[key] != "object") continue; // Dumby
if (typeof o == "object") for (key in o){ // Dobrov
Всё потому, что у строки есть sub. Вот проверь с консоли: var {sub} = "bla-bla"; alert(sub);
Это будет — String.prototype.sub().
Исправил свой код менюшки и убрал имя переменной sub.
Но тогда js-код для var {sub} работает нелогично, ведь var {lab} = "bla-bla"; alert(lab); (и другие имена) возвращают «undefined» !
Отредактировано Dobrov (02-03-2024 02:48:48)
Отсутствует
UserChromeFiles обнова https://github.com/VitaliyVstyle/Vitali … hromeFiles
На старых версиях работать не будет т. к.
ESM, CSS3, Fluent (для локализации, пока добавленно три языка en-US, uk, ru)
Отсутствует
А одним архивом можно сделать? Или я не нашёл...
А он есть
https://github.com/VitaliyVstyle/VitaliyVstyle.github.io/blob/main/UserChromeFiles/UserChromeFiles.zip
Отсутствует