Dumby
Переключиться на последнюю используемую вкладку? Это не то
gBrowser.tabContainer.advanceSelectedTab(-1, true);
Можно и обойтись,но
Есть аддон, но как в код предупереждение запихать?
} else if (event.button == 1) {
[...gtBrowser.tabs].forEach((tab)=> gtBrowser.removeTab(tab));
Отредактировано ВВП (22-05-2021 20:01:32)
Отсутствует
1) Если tooltip картики есть, то нужно сохранять картинку с именем всплывающей подсказки.
Без понятия как в этой концепции сохранения такое сделать.
Подсунуть имя в internalSave() — не прокатит.
Ну, вот, разве что отслеживать загрузки и переименовывать.
2) на двойной клик мыши надо "повесить" другую полезную функцию на твоё усмотрение. Желательно поиск дубликата этой картинки в Яндекс.
Это типа надо какую-то вкладку открыть?
Добавил такое, там, в конце, dblclick(win, imgURL) {}
А какой адрес открывать — сам смотри.
var EXPORTED_SYMBOLS = ["MouseImgSaverChild", "MouseImgSaverParent"]; // сохранить картинку — перетащив вправо; колёсиком var u = {get it() { delete this.it; return this.it = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools); }}; for(let name of ["E10SUtils", "PrivateBrowsingUtils"]) ChromeUtils.defineModuleGetter(u, name, `resource://gre/modules/${name}.jsm`); class MouseImgSaverChild extends JSWindowActorChild { handleEvent(e) { // клики мышью if (e.button > 1) return; // только ЛКМ, СКМ var trg = e.explicitOriginalTarget; trg.nodeType == Node.ELEMENT_NODE && trg instanceof Ci.nsIImageLoadingContent && this[e.type](trg, e); } handleDragEvent(e) { this[e.type](e); } dragstart(trg, e) { this.trg = trg; this.x = e.screenX; this.y = e.screenY; this.drag("add"); this.handleEvent = this.handleDragEvent; this.checkTextLinkyTool(trg.ownerDocument); } events = ["dragover", "drop", "dragend"]; drag(meth = (delete this.handleEvent, delete this.trg, "remove")) { meth += "EventListener"; var win = this.contentWindow; for(var type of this.events) win[meth](type, this, true); } drop() { this.drag(); } dragover(e) { var {x, y} = this, cx = e.screenX, cy = e.screenY, dx = cx - x, ax = Math.abs(dx), ay = Math.abs(cy - y); if (ax < 10 && ay < 10) return; if (dx < 0 || ax < ay) return this.drag(); this.x = cx; this.y = cy; } dragend(e) { var dt = e.dataTransfer, {trg} = this; this.drag(); dt.mozUserCancelled || this.send(trg, e.screenX); } auxclick(trg) { // клик СКМ trg.matches(":any-link :scope") || this.send(trg); } dblclick(trg) { // ЛКМ trg.matches(":any-link :scope") || this.sendAsyncMessage("dblclick", (trg.currentRequestFinalURI || uri).spec); } send(trg, sx) { var uri = trg.currentURI; if (!uri) return; var doc = trg.ownerDocument; var cookieJarSettings = u.E10SUtils .serializeCookieJarSettings(doc.cookieJarSettings); var referrerInfo = Cc["@mozilla.org/referrer-info;1"] .createInstance(Ci.nsIReferrerInfo); referrerInfo.initWithElement(trg); referrerInfo = u.E10SUtils.serializeReferrerInfo(referrerInfo); var contentType = null, contentDisposition = null; try { var props = u.it.getImgCacheForDocument(doc).findEntryProperties(uri, doc); var cs = Ci.nsISupportsCString; try {contentType = props.get("type", cs).data;} catch {} try {contentDisposition = props.get("content-disposition", cs).data;} catch {} } catch {} this.sendAsyncMessage("", { title: trg.closest("[title]")?.title, url: (trg.currentRequestFinalURI || uri).spec, contentType, referrerInfo, cookieJarSettings, contentDisposition, sx, isPrivate: u.PrivateBrowsingUtils.isContentWindowPrivate(trg.ownerGlobal) }); } checkTextLinkyTool(doc) { if (doc.title || !doc.documentURI.startsWith("moz-extension:")) return; var lab = doc.querySelector("body > label#lblFrom:first-child")?.textContent; if (lab) doc.title = lab.slice(0, lab.lastIndexOf("(")); } } if (!ChromeUtils.domProcessChild.childID) { ChromeUtils.registerWindowActor("MouseImgSaver", { allFrames: true, parent: {moduleURI: __URI__}, messageManagerGroups: ["browsers"], child: {moduleURI: __URI__, events: {auxclick: {capture: true}, dblclick: {capture: true}, dragstart: {capture: true}}} }); var wref, titles = Object.create(null); var data = Object.assign(Object.create(null), { "browser.download.dir": {type: "String", get set() { var win = wref.get(), {prefs, dirsvc} = win.Services var {DownloadPaths, FileUtils} = win; var map = val => DownloadPaths.sanitize(val); win.Downloads.getList(win.Downloads.ALL).then(list => list.addView({ onDownloadChanged(download) { if (!download.stopped) return; var {url} = download.source, title = titles[url]; if (!title) return; delete titles[url]; if (!download.succeeded) return; var file = FileUtils.File(download.target.path), {leafName} = file; var ext = leafName.slice(leafName.lastIndexOf(".")); var newName = map(title) + ext, {parent} = file; var newFile = parent.clone(); newFile.append(newName); try { newFile.createUnique(file.NORMAL_FILE_TYPE, file.permissions); file.renameTo(parent, newFile.leafName); download.target.path = newFile.path; download.refresh(); } catch {} } })); Object.defineProperty(this, "set", {get() { try {var dir = prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {var dir = dirsvc.get("DfltDwnld", Ci.nsIFile);} var arr = prefs.getStringPref("ucf_save.dirs", "_Web||_Images|0").split('|').slice(2, 4); // [Загрузки]/папки ucf_save/файл arr[1] = (arr[1]) ? wref.get().gBrowser.selectedTab.label.slice(0, 64).replace(/ \| Форум Mozilla Россия$| — Mozilla Firefox|[\\\/?*\"'`]+/g,'').replace(/\s+/g,' ').replace(/[|<>]+/g,'_').replace(/:/g,'։').trim() : ""; // имя вкладки arr.map(map).forEach(dir.append); // ucf_save.dirs: путь для html|имя или домен|папка графики|имя вкладки dir.exists() && dir.isDirectory() || dir.create(dir.DIRECTORY_TYPE, 0o777); // создать папку, если не существует… return dir.path; }}); return this.set; }}, "browser.download.folderList": {type: "Int", set: 2}, "browser.download.useDownloadDir": {type: "Bool", set: true} }); var MouseImgSaverParent = class extends JSWindowActorParent { receiveMessage(msg) { var win = msg.target.browsingContext.topChromeWindow; var {name} = msg; if (name) return this[name](win, msg.data); var {url, contentType, contentDisposition, sx, title, isPrivate, referrerInfo, cookieJarSettings} = msg.data; if (sx && sx > win.mozInnerScreenX + win.innerWidth) return; if (title) titles[url] = title; wref = Cu.getWeakReference(win); var p = win.Services.prefs; for(var pref in data) { var obj = data[pref], meth = `et${obj.type}Pref`; obj.val = p.prefHasUserValue(pref) ? p["g" + meth](pref) : null; p["s" + meth](pref, obj.set); } try {win.internalSave( url, null, // document null, // file name contentDisposition, contentType, false, // do not bypass the cache null, // filepicker title key null, // chosen data u.E10SUtils.deserializeReferrerInfo(referrerInfo), u.E10SUtils.deserializeCookieJarSettings(cookieJarSettings), win.document, // initiating doc true, // skip prompt for where to save null, // cache key isPrivate, win.document.nodePrincipal );} finally { for(var pref in data) data[pref].val === null ? p.clearUserPref(pref) : p[`set${data[pref].type}Pref`](pref, data[pref].val); } } dblclick(win, imgURL) { var url = "data:text/plain;charset=utf-8," + encodeURIComponent( "Поиск дубликата этой картинки в Яндекс.\n\n" + imgURL ); var gb = win.gBrowser; var index = gb.selectedTab._tPos + 1; gb.selectedTab = gb.addTrustedTab(url, {index}); } } }
Я получаю ошибку: e.view is undefined
Ну так Services.wm.getMostRecentWindow("navigator:browser")
это и есть окно (window), назови win и используй вместо e.view
как проверить наличие файла? chrome://user_chrome_files/content/Help.html
Можно "HEAD" запрос отправить, или попытаться прочитать,
или не как url, а напрямую как файл в профиле, или так
var url = "chrome://user_chrome_files/content/Help.html"; var exists = Cc["@mozilla.org/chrome/chrome-registry;1"] .getService(Ci.nsIXULChromeRegistry) .convertChromeURL(Services.io.newURI(url)) .QueryInterface(Ci.nsIFileURL).file.exists(); alert(exists);
Как показать текст в строке статуса в течении 5 секунд ? (строка, которая появляется при наведении на ссылку)
Уже спрашивал. Может имеется в виду приколотить,
чтобы за эти 5 секунд браузер там ничего другого не показывал?
function showInStatusPanel(str) { if (StatusPanel.update.tid) clearTimeout(StatusPanel.update.tid); else { var {update} = StatusPanel; StatusPanel.update = () => {}; StatusPanel.update.ret = () => { StatusPanel.update = update; StatusPanel.update(); } } StatusPanel.update.tid = setTimeout(StatusPanel.update.ret, 5000); StatusPanel._label = str; } showInStatusPanel(Math.random());
как без использования add…Listener получить данные от FrameScript-функции
В большинстве случаев FrameScript исполняется в другом процессе, так что — никак.
Даже если что-нибудь придумать, то это будет ни сколько не лучше, чем с использованием add…Listener.
из FrameScript не работает gBrowser
FrameScript исполняется в объекте ContentFrameMessageManager,
глобальный объект для него — тот же, что и у JSM'ок процесса.
Никакого gBrowser'а там нет, gBrowser — это объект окна browser.xhtml,
и, если в этом процессе его ещё можно там получить, то в другом — получать просто нечего.
Выделенный текст, кстати, можно через clipboard взять, если содержимое буфера
не большая ценность, а текст, если в нём был, затем назад вернуть.
alert(document.querySelector('textarea[name="req_message"]').value);
alert(document.location);
Как можно свободно обращаться к элементам DOM?
В многопроцессном Firefox — никак.
Переключиться на последнюю используемую вкладку?
Не уверен, что есть «последняя используемая вкладка».
Но вот, наверно, всё, к чему можно прицепиться без специального отслеживающего кода.
gBrowser.selectedTab = Array.from(gBrowser.tabs).reduce((prev, curr) => curr.closing || curr.selected || curr._notselectedsinceload !== false || curr.lastAccessed < prev.lastAccessed ? prev : curr , {});
Есть аддон, но как в код предупереждение запихать?
Это Flip Close Tab? Services.prompt.confirm() чем не угодил?
… } else if (event.button == 1) { if (Services.prompt.confirm(null, "Title", "Message")) [...gtBrowser.tabs].forEach((tab)=> gtBrowser.removeTab(tab));
Отсутствует
Dumby
Класс!
Это Flip Close Tab?
Ну,да. Так а на черта оно, если кнопка теперь так же работает.
/*Initialization Code*/ this.onclick = this.oncontextmenu = function(event) { if (event.button == 1) { if (custombuttons.confirmBox(null, "Вниманиее ! Закрыть все вкладки!", "Да", "Отмена") ) { [...gBrowser.tabs].forEach((tab)=> gBrowser.removeTab(tab)); } } if(event.button == 0 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ gBrowser.removeTab(gBrowser.selectedTab); } if(event.button == 2 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey){ gBrowser.selectedTab = Array.from(gBrowser.tabs).reduce((prev, curr) => curr.closing || curr.selected || curr._notselectedsinceload !== false || curr.lastAccessed < prev.lastAccessed ? prev : curr , {}); } }; this.oncontextmenu =e=> { e.button && !e.ctrlKey && e.preventDefault() }; this.tooltipText = "ЛКМ: Закрыть вкладку\nСКМ: Закрыть все вкладки \nПКМ: Переключиться на послед. вкладку";
А , вот :hover на кнопку стилем можно делать? Чтоб при этом иконка кнопки другая стала...
Отредактировано ВВП (23-05-2021 00:23:44)
Отсутствует
Dumby - спасибо, доработал всё, что мог! и свёл в демо-профиль все наработки - тестируйте!
Есть проблема - делаю СКМ LongClick и при отпускании кнопки ошибка: Uncaught TypeError: linkedObject.auxclick is not a function
Dumby - проверь пожалуйста скрипт переключения настроек либо отдельно, либо скачав расширенный профиль.
эта ошибка не влияет на работу кнопки, но я её не смог устранить !
8 кнопок (из них 4 в боковой панели) упрощают использование браузера:
Некоторые возможности кнопок (наведите мышь на кнопку для подсказки):
1) стандартная кнопка Меню:
Правый клик: ⇲ Свернуть окно
…Alt Персонализация\n
Колёсико: Закрыть браузер`
2) штатная Кнопка «Загрузки»
Колёсико: Сохранить (выделенный текст) как файл .txt
…Shift Сайт: графика Вкл/Выкл
ПКМ: Сохранить (выделенный текст) как единый .html
…Shift Обзор папки «Загрузки»
Alt⇧S сохранить страницу как единый .html (встроенным кодом или расширением SingleFile)
3) Избранное - боковые панели, управление опциями…
ПКМ меню переключения скрытых опций, …держать секунду - Справка, …+Alt Опции about:config
ЛКМ - Боковая панель: Журнал, …держать секунду - Вкл/Выкл proxy Антизапрет,
…+Shift - ★ Библиотека закладки, …+Alt - Пипетка: захват цвета
Колёсико: Zoom Текст/Страница, …держать: Консоль браузера
Значки в строках меню опций: ⟳ Обновить страницу, ↯ запрос Перезапуска браузера
4) Восстановить закрытые вкладки/Окна
5) Настройка расширений позволяет отключить скрытые дополнения.
6) ★ в строке адреса - Колёсико: Плитки быстрого доступа,
Правый клик - восстановить закрытую вкладку
…+Alt Перевод выделенного текста | Сайта, …+Shift Яндекс: поиск выдел.текста | Перевод сайта
…) ещё 8 кнопок упрощают использование и настройку браузера.
Отсутствует
не смог устранить
Это надо какой-нибудь auxclick() сюда вписать
… //var id, lo = {command: reset, mousedown: reset}; var id, lo = {command: reset, mousedown: reset, auxclick: e => e.button != 1 || reset(e)};
А , вот :hover на кнопку стилем можно делать? Чтоб при этом иконка кнопки другая стала...
#custombuttons-button25:hover > image { list-style-image: none !important; object-position: 16px 0px !important; background-position: center !important; background-repeat: no-repeat !important; background-image: url(chrome://browser/content/robot.ico) !important; }
Отсутствует
Это надо какой-нибудь auxclick() сюда вписать
Спасибо! Отличная и оперативная помощь! Осталась хотелка по кнопке Чтения…
Будет время, посмотри мой демо-профиль браузера, расширенный необходимым (по моему мнению за 3 месяца отладки) набором функций.
Dumby - может сделаешь обзор возможностей твоего профиля Firefox - какие там есть навороты за столько лет (с 2012 года на форуме) ?
Отсутствует
Dumby
Облажался ... Теперь класс ! Стиль на "справку" и все. Класс!
list-style-image: none !important;
object-position: 20px 0px !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-image: url("chrome://global/skin/icons/index.png") !important;}
}
Отсутствует
Как открыть обычное окно с заданным адресом и размерами?
Отсутствует
Нужно перетаскиванием влево/вправо сохранить в «Загрузки» без запроса рисунок или ссылку на файл.
Расширения не работают из режима чтения. Поискал и не нашёл такой скрипт для user_chrome_files. Наверняка такой код на форуме есть?
Dumby - подскажи, как сохранить ссылку на файл перетаскиванием скриптом UCF?
Отсутствует
Dumby
Есть код. масштаб на все. на конкретную страницу никак? К, примеру , на about:addons
Отсутствует
3) масштаб с отображением процентов на кнопке
Отображение масштаба на бэйдже кнопки что ли,
типа как у кнопок, которые создаёт Firefox для WebExtensions?
«Очки» — эпический комбайн, неудобовместительный в голове,
приступить можно, но как оно сложится — непонятно вообще.
Есть код. масштаб на все. на конкретную страницу никак? К, примеру , на about:addons
((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("about:addons", 2.4);
Отсутствует
Dumby
Хорошо, но не очень. Сброс или регулировка масштаба и все, только перезапуск нужен. А Стилем никак? Или тот код подрихтовать?
Нельзя ли в настройках запретить запоминать zoom для кажной страницы?
Поставим вопрос по другому: onclick="FullZoom.reset(); FullZoom.resetScalingZoom();" - это клик по масштабу в browser.xhtml , а мне надо такой код:
FullZoom.reset(); (function(val) { var cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(Ci.nsIContentPrefService2); cps2.setGlobal(window.FullZoom.name, val, Cu.createLoadContext()); })(1.15); ((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("about:addons", 1.09); ((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("https://hdrezka-ag.com/", 1.21); ((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("https://kinokrad.co/", 1.21); ((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("https://bigcinema.tv/", 1.21); ((url, val) => FullZoom._cps2.set( FullZoom._cps2.extractDomain(url), FullZoom.name, val, Cu.createLoadContext() ))("https://filmix.ac/", 1.21);
Рихтовать сам browser.xhtml - не прошло , как решить проблему ?
Отредактировано ВВП (02-06-2021 11:37:26)
Отсутствует
Я переключил в about:config настройку browser.urlbar.openintab = true
Все адреса из адресной строки открываются в новых вкладках. Мне это удобно.
А можно сделать, чтобы, если я вставляю в адресную строку алиас закладки, и если эта закладка - букмарклет (код начинается с javascript:), то она открывалась бы в текущей?
Отсутствует
Поставим вопрос по другому: onclick="FullZoom.reset(); FullZoom.resetScalingZoom();" - это клик по масштабу в browser.xhtml , а мне надо такой код
Рихтовать сам browser.xhtml - не прошло , как решить проблему ?
В смысле код в сам атрибут "onclick" вписать?
Тогда его надо сериализировать под это дело.
Вот, например, код — полный сброс, и установка твоего добра:
(lc => { var {_cps2, name} = FullZoom; _cps2.removeByName(name, lc, {handleCompletion() { _cps2.setGlobal(name, 1.15, lc); for(var [url, zoom] of Object.entries({ "about:addons": 1.09, "hdrezka-ag.com": 1.21, "kinokrad.co": 1.21, "bigcinema.tv": 1.21, "filmix.ac": 1.21, })) _cps2.set(_cps2.extractDomain(url), name, zoom, lc); }}); })(Cu.createLoadContext());
(lc => {
	var {_cps2, name} = FullZoom;
	_cps2.removeByName(name, lc, {handleCompletion() {
		_cps2.setGlobal(name, 1.15, lc);
		for(var [url, zoom] of Object.entries({

			"about:addons": 1.09,
			"hdrezka-ag.com": 1.21,
			"kinokrad.co": 1.21,
			"bigcinema.tv": 1.21,
			"filmix.ac": 1.21,
		}))
			_cps2.set(_cps2.extractDomain(url), name, zoom, lc);
	}});
})(Cu.createLoadContext());
А можно сделать, чтобы, если я вставляю в адресную строку алиас закладки, и если эта закладка - букмарклет (код начинается с javascript:), то она открывалась бы в текущей?
Не уверен, но можно попробовать подсунуть свой gURLBar._whereToOpen()
(key => { var wto = gURLBar[key]; gURLBar[key] = function() { try { var {keyword, url} = this._resultForCurrentValue.payload; if (keyword && url.startsWith("javascript:")) return "current"; } catch {} return wto.apply(this, arguments); } addDestructor(() => delete gURLBar[key]); })("_whereToOpen");
Отсутствует
Отсутствует
Dumby
Осваиваю 89. Есть две проблемы: Поиск из контекста (все поисковики сразу) Помнится в schemas ритовали , но теперь никак.
И второе, не могу загасить Ctrl+ клик по папке с закладками и все они открываются...Как прибить это?
И код не работает : Теперь в browser-places.js все не так. и рихтануть не получается...
xulStore.setValue(
doc, "PersonalToolbar", "collapsed", "true"
);
Отредактировано ВВП (04-06-2021 21:37:50)
Отсутствует
Поиск из контекста (все поисковики сразу) Помнится в schemas ритовали , но теперь никак.
Рихтовали не schemas, а ext-search.js
И рихтовка в Firefox 89 работает. Там только это убрали (баг),
что совершенно не важно.
не могу загасить Ctrl+ клик по папке с закладками и все они открываются...Как прибить это?
Для папок в Панели закладок, Меню, ...
%FOX%\browser\omni.ja\chrome\browser\content\browser\browser-places.js
/* // Only handle middle-click or left-click with modifiers. let modifKey; if (AppConstants.platform == "macosx") { modifKey = aEvent.metaKey || aEvent.shiftKey; } else { modifKey = aEvent.ctrlKey || aEvent.shiftKey; } if (aEvent.button == 2 || (aEvent.button == 0 && !modifKey)) { return; } */ // Only handle middle-click or left-click with shift. if (aEvent.button == 2 || (aEvent.button == 0 && !aEvent.shiftKey)) { return; }
/* // right-clicks are not handled here if (event.button == 2) { return; } */ // right-clicks and left-clicks with ctrl-only are not handled here if (event.button == 2 || (event.button == 0 && event.ctrlKey && !event.shiftKey && !event.altKey)) { return; } ..... /* let metaKey = AppConstants.platform === "macosx" ? event.metaKey : event.ctrlKey; let modifKey = metaKey || event.shiftKey; */ let modifKey = event.shiftKey;
xulStore.setValue(
doc, "PersonalToolbar", "collapsed", "true"
);
Так #PersonalToolbar теперь же под настройкой
browser.toolbars.bookmarks.visibility
Отсутствует
что-то я прям аж перепугался с выходом 89 ан, нет, поставил ночнушку, которая будет следующим релизом ЕСР, втулил в неё CB + UCF и все основополагающие, самые главные, просто величайшие и, без преувеличения, глобальные, кнопки заработали спокойно и легко. до стилей с изменением фейса доберусь может быть в бетке, это не такие важнейшие функции как кнопки. так что спасибо Dumby, Infocatcher и всем-всем причастным за еще больше года спокойной жизни
Отсутствует
Dumby
Вы когда то вешали минимизацию памяти на ЛКМ по ucf-mem-indicator. Вы не могли бы еще по ПКМ добавить открытие about:performance, а по Ctrl+ПКМ открытие about:debugging#/runtime/this-firefox? Хотелось бы иметь быстрый доступ к этим страницам без лишних кнопок.
Отсутствует
_zt
Вариант
/* win.document.getElementById("star-button-box") .after(win.document.importNode(df, true)); this.notify(); })(win); }, */ 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" }`); },
Отсутствует