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

Общайтесь со знакомыми и друзьями в нашем сообществе в Facebook.

№1695101-09-2023 10:11:09

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

Re: Custom Buttons

Dumby пишет

bootstrap-loader.js не зачищен от Services.jsm

Спасибю, за новый bootstrap-loader-mini.js
Правда я сам понять не могу почему у меня старый на 117`м работает :cool:


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

На форуме

 

№1695201-09-2023 10:29:14

vitalii201
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 679
UA: Firefox 117.0

Re: Custom Buttons

Dumby, спасибо!

Отредактировано vitalii201 (01-09-2023 13:37:33)

Отсутствует

 

№1695306-09-2023 14:36:50

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

Re: Custom Buttons

Dumby или Farby - гляньте скрипт "Жесты мыши"


На сайте vk.com действия выполняются только первый раз - копирование в буфер, открытие ссылки…
Потом только строка статуса показывает следующие жесты, но команды не выполняются. Жесты заработают, если обновить страницу - но второй и последующие не сработают…

ucf_mousedrag.js

Выделить код

Код:

(async win => ({ // UCF drag and go жесты мыши https://forum.mozilla-russia.org/viewtopic.php?pid=797234#p797234
	link: {
		L: {
			name: "Копировать ссылку в буфер обмена", cmd() {
				this.gClipboard.write(this.val);
				this.flash();
			}
		},
		U: {
			name: "Копировать текст ссылки в буфер", cmd() {
				this.gClipboard.write(this.txt);
				this.flash();
			}
		},
		R: {
			name: "Открыть ссылку в новой активной странице", cmd() {
				win.openUILinkIn(this.val, "tab", this.opts);
			}
		},
		D: {
			name: "Открыть ссылку в новой фоновой странице", cmd() {
				win.openUILinkIn(this.val, "tabshifted", this.opts);
			}
		}
	},
	text: {
		U: {
			name: "Поиск текста поисковиком по умолчанию в новой активной странице", cmd() {
				this.search("tab");
			}
		},
		D: {
			name: "Поиск текста поисковиком по умолчанию в новой фоновой странице", cmd() {
				this.search("tabshifted");
			}
		},
		L: {
			name: "Копировать текст в буфер обмена", cmd() {
				this.gClipboard.write(this.val);
				this.flash();
			}
		}
	},
	toStatus(txt) {
		win.StatusPanel._labelElement.value = win.StatusPanel._label = txt;
		win.StatusPanel.panel.removeAttribute("inactive");
	},
	gClipboard: {
		write(str, ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)) {
			(this.write = str => ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard))(str);
		}
	},
	flash(color = 'rgba(240,176,0,0.5)', sec = 250, id = 'urlbar-input-container') {
		id = win.document.getElementById(id); id.style.background = color;
		setTimeout(() => { id.style.removeProperty('background-color');}, sec);
	},
	search(where) {
		var engine = Services.search[`default${this.opts.private ? "Private" : ""}Engine`];
		var submission = engine.getSubmission(this.val, null, "");
		win.openUILinkIn(submission.uri.spec, where, {postData: submission.postData, ...this.opts});
	},
	opts: { //relatedToCurrent: true,
		triggeringPrincipal: Cu.getObjectPrincipal(this),
		get userContextId() {
			return parseInt(win.gBrowser.selectedBrowser.getAttribute("usercontextid"));
		},
		get private() {
			return win.PrivateBrowsingUtils.isWindowPrivate(win);
		}
	},
	dragstart(e) {
		win = e.view.windowRoot.ownerGlobal;
		//if (!win.gBrowser.currentURI.spec.startsWith("http")) return;
		if (!e.dataTransfer.mozItemCount || !win.gBrowser.selectedBrowser.matches(":hover"))
			return;

		var dt = e.dataTransfer;
		this.type = this.link;
		this.dir = this.val = "";
		var txt = dt.getData("text/plain");
		var url = dt.getData("text/x-moz-url-data");
		if (url)
			this.val = url, this.txt = dt.getData("text/x-moz-url").split("\n")[1];
		else if (!txt) return;
		try {
			this.val = new URL(txt.trim());
		} catch {
			this.val = txt;
			if (!this.textLinkRe.test(txt))
				this.type = this.text;
		}
		this.x = e.screenX; this.y = e.screenY;
		this.drag(true);
	},
	drag(init) {
		var meth = `${init ? "add" : "remove"}EventListener`;
		for(var type of this.events) win[meth](type, this, true);
		init || win.StatusPanel.panel.setAttribute("inactive", true);
	},
	events: ["dragover", "drop", "dragend"],
	dragover(e) {
		var {x, y} = this, cx = e.screenX, cy = e.screenY;
		var dx = cx - x, ax = Math.abs(dx), dy = cy - y, ay = Math.abs(dy);
		if (ax < 10 && ay < 10) return;

		this.x = cx; this.y = cy;
		var dir = ax > ay ? dx > 0 ? "R" : "L" : dy > 0 ? "D" : "U";
		if (this.dir.endsWith(dir)) return;

		dir = this.dir += dir;
		var obj = this.type[dir];
		var txt = `${obj ? "Ж" : "Неизвестный ж"}ест мыши: ${dir + (obj ? "  " + obj.name : "")}`;
		this.toStatus(txt);
	},
	dragend(e) {
		var dt = e.dataTransfer;
		this.drag();
		var obj = this.type[this.dir];
		if (!obj || dt.mozUserCancelled) return;

		var x = e.screenX, y = e.screenY;
		var wx = win.mozInnerScreenX, wy = win.mozInnerScreenY;
		x > wx && y > wy && x < wx + win.innerWidth && y < wy + win.innerHeight
			&& obj.cmd.call(this);
	},
	textLinkRe: /^([a-z]+:\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&amp;]*)?)?(#[a-z][a-z0-9_]*)?$|^custombutton:\/\/\S+$/,

	observe(w) {
		this.drop = () => this.drag();
		this.handleEvent = e => this[e.type](e);
		var unload = e => {
			var w = e.target.ownerGlobal;
			w.gBrowser.tabpanels.removeEventListener("dragstart", this, true);
			if (w == win) win = null;
		}
		(this.observe = w => {
			//if (!w.toolbar.visible) return;
			w.gBrowser.tabpanels.addEventListener("dragstart", this, true);
			w.addEventListener("unload", unload, {once: true});
		})(w);
	},
	init(topic, self) {
		delete this.init;
		Services.obs.addObserver(self = this, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(self, topic);
			Services.obs.removeObserver(quit, t);
		}, "quit-application-granted");
	}
}).init("browser-delayed-startup-finished"))();

Отсутствует

 

№1695406-09-2023 17:28:40

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

Re: Custom Buttons

..

Добавлено 06-09-2023 17:41:06
Dobrov
Почти все удалось починить, но поломал - "Копировать текст ссылки в буфер"
Что-то не так с этим

кодом

Выделить код

Код:

`
		var txt = dt.getData("text/plain");
		var url = dt.getData("text/x-moz-url-data");
		if (url)
			this.val = url, this.txt = dt.getData("text/x-moz-url").split("\n")[1];
		else if (!txt) return;
		try {
			this.val = new URL(txt.trim());
		} catch {
			this.val = txt;
			if (!this.textLinkRe.test(txt))
				this.type = this.text;


И я не понимаю что этим сказано..
ucf_mousedrag.js

Выделить код

Код:

// UCF drag and go жесты мыши https://forum.mozilla-russia.org/viewtopic.php?pid=806832#p806832
(async win => ({
	link: {
		L: {
			name: "Копировать ссылку в буфер обмена", cmd() {
				this.gClipboard.write(this.val);
				this.flash();
			}
		},
		U: {
			name: "Копировать текст ссылки в буфер", cmd() {
				this.gClipboard.write(this.txt);
				this.flash();
			}
		},
		R: {
			name: "Открыть ссылку в новой активной странице", cmd() {
				win.openTrustedLinkIn(this.val, "tab", this.opts);
			}
		},
		D: {
			name: "Открыть ссылку в новой фоновой странице", cmd() {
				win.openTrustedLinkIn(this.val, "tabshifted", this.opts);
			}
		}
	},
	text: {
		U: {
			name: "Поиск текста поисковиком по умолчанию в новой активной странице", cmd() {
				this.search("tab");
			}
		},
		D: {
			name: "Поиск текста поисковиком по умолчанию в новой фоновой странице", cmd() {
				this.search("tabshifted");
			}
		},
		L: {
			name: "Копировать текст в буфер обмена", cmd() {
				this.gClipboard.write(this.val);
				this.flash();
			}
		}
	},
	toStatus(txt) {
		win.StatusPanel._labelElement.value = win.StatusPanel._label = txt;
		win.StatusPanel.panel.removeAttribute("inactive");
	},
	gClipboard: {
		write(str, ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)) {
			(this.write = str => ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard))(str);
		}
	},
	flash(color = 'rgba(240,176,0,0.5)', sec = 250, id = 'urlbar-input-container') {
		id = win.document.getElementById(id); id.style.background = color;
		setTimeout(() => { id.style.removeProperty('background-color');}, sec);
	},
	search(where) {
		var engine = Services.search[`default${this.opts.private ? "Private" : ""}Engine`];
		var submission = engine.getSubmission(this.val, null, "");
		win.openTrustedLinkIn(submission.uri.spec, where, {postData: submission.postData, ...this.opts});
	},
	opts: { //relatedToCurrent: true,
		triggeringPrincipal: Cu.getObjectPrincipal(this),
		get userContextId() {
			return parseInt(win.gBrowser.selectedBrowser.getAttribute("usercontextid"));
		},
		get private() {
			return win.PrivateBrowsingUtils.isWindowPrivate(win);
		}
	},
	dragstart(e) {
		win = e.view.windowRoot.ownerGlobal;
		//if (!win.gBrowser.currentURI.spec.startsWith("http")) return;
		if (!e.dataTransfer.mozItemCount || !win.gBrowser.selectedBrowser.matches(":hover"))
			return;

		var dt = e.dataTransfer;
		this.type = this.link;
		this.dir = this.val = "";

		var url = dt.getData("text/x-moz-url-data");
		if (url) this.val = url;
		else {
		var txt = dt.getData("text/plain");
			if (txt) {
			this.val = txt;
				if (!this.textLinkRe.test(txt)) this.type = this.text;
			}
			else return;
		}
		this.x = e.screenX; this.y = e.screenY;
		this.drag(true);
	},
	drag(init) {
		var meth = `${init ? "add" : "remove"}EventListener`;
		for(var type of this.events) win[meth](type, this, true);
		init || win.StatusPanel.panel.setAttribute("inactive", true);
	},
	events: ["dragover", "drop", "dragend"],
	dragover(e) {
		var {x, y} = this, cx = e.screenX, cy = e.screenY;
		var dx = cx - x, ax = Math.abs(dx), dy = cy - y, ay = Math.abs(dy);
		if (ax < 10 && ay < 10) return;

		this.x = cx; this.y = cy;
		var dir = ax > ay ? dx > 0 ? "R" : "L" : dy > 0 ? "D" : "U";
		if (this.dir.endsWith(dir)) return;

		dir = this.dir += dir;
		var obj = this.type[dir];
		var txt = `${obj ? "Ж" : "Неизвестный ж"}ест мыши: ${dir + (obj ? "  " + obj.name : "")}`;
		this.toStatus(txt);
	},
	dragend(e) {
		var dt = e.dataTransfer;
		this.drag();
		var obj = this.type[this.dir];
		if (!obj || dt.mozUserCancelled) return;

		var x = e.screenX, y = e.screenY;
		var wx = win.mozInnerScreenX, wy = win.mozInnerScreenY;
		x > wx && y > wy && x < wx + win.innerWidth && y < wy + win.innerHeight
			&& obj.cmd.call(this);
	},
	textLinkRe: /^([a-z]+:\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&amp;]*)?)?(#[a-z][a-z0-9_]*)?$|^custombutton:\/\/\S+$/,

	observe(w) {
		this.drop = () => this.drag();
		this.handleEvent = e => this[e.type](e);
		var unload = e => {
			var w = e.target.ownerGlobal;
			w.gBrowser.tabpanels.removeEventListener("dragstart", this, true);
			if (w == win) win = null;
		}
		(this.observe = w => {
			//if (!w.toolbar.visible) return;
			w.gBrowser.tabpanels.addEventListener("dragstart", this, true);
			w.addEventListener("unload", unload, {once: true});
		})(w);
	},
	init(topic, self) {
		delete this.init;
		Services.obs.addObserver(self = this, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(self, topic);
			Services.obs.removeObserver(quit, t);
		}, "quit-application-granted");
	}
}).init("browser-delayed-startup-finished"))();


Может Dumby подскажет или сам перепишешь...

Отредактировано Farby (06-09-2023 17:41:06)


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

На форуме

 

№1695507-09-2023 02:11:56

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

Re: Custom Buttons

Farby пишет

Почти все удалось починить, но поломал - "Копировать текст ссылки в буфер"

Нет, всё также на сайте vk.com после первого жеста второй и следующие не выполняются. Проверял на чистом профиле в Firefox 115 + UCF.

Что-то не так с этим кодом

на других сайтах работает - запоминается имя ссылки в this.txt = dt.getData("text/x-moz-url").split("\n")[1]…
и если жест для копирования имени ссылки (у меня "U"), тогда вместо URL в буфере будет имя ссылки.

Отсутствует

 

№1695607-09-2023 09:35:57

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

Re: Custom Buttons

Ну тогда есть ещё вариант, правда китайской, но с пометкой от Dumby. На UCF должен работать.

ucf Drag & Go

Выделить код

Код:

// ==UserScript==
// @name            ucf Drag & Go
// @description     鼠标拖拽 Drag & Go,来自于 Mozilla-Russia 论坛,Ryan 修改自用
// @author          Ryan, Dumby
// @include         main
// @homepageURL     https://github.com/benzBrake/FirefoxCustomize/tree/master/userChromeJS
// @referenceURL    https://forum.mozilla-russia.org/viewtopic.php?pid=797234#p797234
// @onlyonce
// ==/UserScript==

(async win => ({
    debug: false,
    link: {
        U: {
            name: "Open Link new Tab", cmd(val) {
                win.openTrustedLinkIn(val, "tab", this.opts);
            }
        },
        R: {
            name: "Open Link new Tab in background", cmd(val) {
                win.openTrustedLinkIn(val, "tabshifted", this.opts);
            }
        },
        RD: {
            name: "Save As Link", cmd(val) {
                this.saveAs(val);
            }
        },
        L: {
            name: "Copy Link", cmd(val) {
                this.copyString(val);
            }
        },
        D: {
            name: "Open Link in Tab", cmd(val) {
                win.openTrustedLinkIn(val, "current", this.opts);
            }
        },
        LD: {
            name: "Similar Sites new Tab", cmd(val) {
                if (!val) return;
                var TERM = "https://www.similarsites.com/site/" + new URL(val).hostname.replace(/^www./, '');
                if (val)
                    win.openTrustedLinkIn(TERM, "tab", this.opts);
            }
        },
        "LD-Shift": {
            name: "Web history new Tab", cmd(val) {
                if (!val) return;
                var TERM = "https://web.archive.org/web/*/" + new URL(val).hostname.replace(/^www./, '');
                if (val)
                    win.openTrustedLinkIn(TERM, "tab", this.opts);
            }
        },
    },
    text: {
        U: {
            name: "Search text new Tab", cmd(val) {
                this.searchWithEngine(val, "tab", "@default");
            }
        },
        "U-Shift": {
            name: "Search text new Tab in background", cmd(val) {
                this.searchWithEngine(val, "tabshifted", "@default");
            }
        },
        R: {
            name: "Search text new Tab (Yandex)", cmd(val) {
                this.searchWithEngine(val, 'tab', 'Yandex');
            }
        },
        "R-Shift": {
            name: "Search text new Tab in background (Yandex)", cmd(val) {
                this.searchWithEngine(val, 'tabshifted', 'Yandex');
            }
        },
        RD: {
            name: "Save Text", cmd(val) {
                this.saveText(val);
            }
        },
        D: {
            name: "Search in site", cmd(val, event) {
                var currentPageUrl = event.originalTarget._urlMetaData['url'];
                var TERM = "site:" + new URL(currentPageUrl).hostname.replace(/^www./, '') + " " + val;
                if (val)
                    this.searchWithEngine(TERM, 'current', '@default');
            }
        },
        "D-Shift": {
            name: "Search in site in background", cmd(val, event) {
                var currentPageUrl = event.originalTarget._urlMetaData['url'];
                var TERM = "site:" + new URL(currentPageUrl).hostname.replace(/^www./, '') + " " + val;
                if (val)
                    this.searchWithEngine(TERM, 'tab', '@default');
            }
        },
        L: {
            name: "Copy Text", cmd(val) {
                this.copyString(val);
            }
        },
        LD: {
            name: "Cambridge Dictionary new Tab", cmd(val) {
                var TERM = "https://dictionary.cambridge.org/dictionary/english-russian/" + val;
                if (val)
                    win.openTrustedLinkIn(TERM, "tab", this.opts);
            }
        },
        "LD-Shift": {
            name: "Cambridge Dictionary new Tab in background", cmd(val) {
                var TERM = "https://dictionary.cambridge.org/dictionary/english-russian/" + val;
                if (val)
                    win.openTrustedLinkIn(TERM, "tabshifted", this.opts);
            }
        }
    },
    image: {
        U: {
            name: "Open Image", cmd() {
                win.openTrustedLinkIn(this.val, "tab", this.opts);
            }
        },
        R: {
            name: "Open Image in background", cmd() {
                win.openTrustedLinkIn(this.val, "tabshifted", this.opts);
            }
        },
        RD: {
            name: "Save Image", cmd(val) {
                this.saveAs(val);
            }
        },
        L: {
            name: "Copy Image Link", cmd(val) {
                this.copyString(val);
            }
        },
        LD: {
            name: "Search Image by Google", cmd(val) {
                var TERM = "https://www.google.com/searchbyimage?image_url=" + val;
                if (val)
                    win.openTrustedLinkIn(TERM, "tabshifted", this.opts);
            }
        },
        "LD-Shift": {
            name: "Search Image by Yandex", cmd(val) {
                var TERM = "https://yandex.com/images/search?source=collections&rpt=imageview&url=" + val;
                if (val)
                    win.openTrustedLinkIn(TERM, "tabshifted", this.opts);
            }
        },
    },
    searchWithEngine(val, where, engine, addToHistory) {
        val || (val = this.val);
        var engine = this.getEngineByName(engine);
        var submission = engine.getSubmission(val, null);
        win.openTrustedLinkIn(submission.uri.spec, where, { postData: submission.postData, ...this.opts });
        if (addToHistory) {
            this.updateSearchbarHistory(val);
        }
    },
    getEngineByName(aEngineName) {
        const UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
            createInstance(Ci.nsIScriptableUnicodeConverter);
        UI.charset = "UTF-8";
        const nsIBSS = Ci.nsIBrowserSearchService || Ci.nsISearchService;
        const searchService = Cc["@mozilla.org/browser/search-service;1"].getService(nsIBSS);
        if (aEngineName.toUpperCase() == "CURRENT") {
            var searchbar = this.searchbar;
            if (searchbar) return searchbar.currentEngine;
        } else {
            try {
                aEngineName = UI.ConvertToUnicode(aEngineName)
            } catch (e) { }
            var engine = searchService.getEngineByName(aEngineName);
            if (engine) return engine;
        }
        //Default
        return searchService.defaultEngine;
    },
    copyToSearchBar(searchText) {
        var searchbar = this.searchbar;
        if (!searchbar)
            return;
        searchbar.value = searchText;
    },
    updateSearchbarHistory(searchText) {
        this.copyToSearchBar(searchText);

        //var event = document.createEvent("UIEvents");
        //event.initUIEvent("input", true, true, window, 0);
        var searchbar = this.searchbar;
        //searchbar.dispatchEvent(event);
        if (typeof searchbar.FormHistory == "object") {
            if (searchText && !win.PrivateBrowsingUtils.isWindowPrivate(window)) {
                searchbar.FormHistory.update({
                    op: "bump",
                    fieldname: searchbar._textbox.getAttribute("autocompletesearchparam"),
                    value: searchText
                }, {
                    handleError: function (aError) {
                        Components.utils.reportError("Saving search to form history failed: " + aError.message);
                    }
                });
            }
        } else {
            if (searchText) {
                searchbar._textbox._formHistSvc
                    .addEntry(searchbar._textbox.getAttribute("autocompletesearchparam"),
                        searchText);
            }
        }
    },
    copyString(text) {
        const cs = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
        cs.copyString(text);
    },
    saveAs(aURL, aFileName, aReferrer, aSourceDocument, aContentType, aContentDisposition) {
        const { gBrowser, PrivateBrowsingUtils, internalSave, saveImageURL, saveURL } = win;
        let createContentPrincipal = Services.scriptSecurityManager.createContentPrincipal || Services.scriptSecurityManager.createCodebasePrincipal;
        let aPrincipal = createContentPrincipal(Services.io.newURI(aURL), {});
        let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser);
        const firefoxVer = parseFloat(Services.appinfo.version);
        const imageLinkRegExp = /(.+)\.(png|jpg|jpeg|gif|bmp)$/i;
        if (aReferrer instanceof HTMLDocument) {
            aReferrer = aReferrer.documentURIObject;
        } else if (typeof aReferrer == 'string') {
            aReferrer = Services.io.newURI(aReferrer);
        }
        if (firefoxVer >= 70) {
            let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(Ci.nsIReferrerInfo);
            referrerInfo.init(
                Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE,
                true,
                aReferrer
            );
            aReferrer = referrerInfo;
        }
        if (imageLinkRegExp.test(aURL) || /^image\//i.test(aContentType)) {
            if (firefoxVer >= 102.3) {
                let cookieJarSettings = gBrowser.selectedBrowser.cookieJarSettings;
                if (/^data:/.test(aURL)) {
                    internalSave(aURL, null, null, "index.png", aContentDisposition, aContentType, true, null, null, aReferrer, cookieJarSettings, aSourceDocument, false, null, isPrivate, aPrincipal);
                } else {
                    internalSave(aURL, null, null, null, aContentDisposition, aContentType, false, null, null, aReferrer, cookieJarSettings, aSourceDocument, false, null, isPrivate, aPrincipal);
                }
            } else if (firefoxVer >= 84) {
                let cookieJarSettings = gBrowser.selectedBrowser.cookieJarSettings;
                if (/^data:/.test(aURL)) {
                    internalSave(aURL, null, "index.png", aContentDisposition, aContentType, true, null, null, aReferrer, cookieJarSettings, aSourceDocument, false, null, isPrivate, aPrincipal);
                } else {
                    internalSave(aURL, null, null, aContentDisposition, aContentType, false, null, null, aReferrer, cookieJarSettings, aSourceDocument, false, null, isPrivate, aPrincipal);
                }
            } else if (firefoxVer >= 77) {
                if (/^data:/.test(aURL)) {
                    internalSave(aURL, null, "index.png", aContentDisposition, aContentType, true, null, null, aReferrer, aSourceDocument, false, null, isPrivate, aPrincipal);
                } else {
                    internalSave(aURL, null, null, aContentDisposition, aContentType, false, null, null, aReferrer, aSourceDocument, false, null, isPrivate, aPrincipal);
                }
            } else {
                if (/^data:/.test(aURL)) {
                    saveImageURL(aURL, "index.png", null, true, false, aReferrer, aSourceDocument, aContentType, aContentDisposition, isPrivate, aPrincipal);
                } else {
                    saveImageURL(aURL, null, null, false, false, aReferrer, aSourceDocument, aContentType, aContentDisposition, isPrivate, aPrincipal);
                }
            }
        } else {
            if (firefoxVer >= 102.3) {
                let cookieJarSettings = gBrowser.selectedBrowser.cookieJarSettings;
                saveURL(aURL, null, aFileName, null, true, false, aReferrer, cookieJarSettings, aSourceDocument, isPrivate, aPrincipal);
            } else if (firefoxVer >= 84) {
                let cookieJarSettings = gBrowser.selectedBrowser.cookieJarSettings;
                saveURL(aURL, aFileName, null, true, false, aReferrer, cookieJarSettings, aSourceDocument, isPrivate, aPrincipal);
            } else {
                saveURL(aURL, aFileName, null, true, false, aReferrer, aSourceDocument, isPrivate, aPrincipal);
            }
        }
    },
    saveText: async function saveText(text) {
        const { Cc, Ci, gBrowser } = win;;
        const { nsIFilePicker } = Ci;
        var fp = Cc['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
        fp.init(win, "Select a File", Ci.nsIFilePicker.modeSave);
        fp.appendFilters(nsIFilePicker.filterText);
        fp.defaultString = gBrowser.contentTitle.replace(/\s-\s.*/i, "").replace(/_[^\[\]【】]+$/, "") + '.txt';
        switch (await new Promise(resolve => { fp.open(rv => { resolve(rv); }); })) {
            case (nsIFilePicker.returnOK):
            case (nsIFilePicker.returnReplace):
                file = fp.file;
                break;
            case (nsIFilePicker.returnCancel):
            default:
                return null;
        }
        var strm = Cc["@mozilla.org/network/file-output-stream;1"]
            .createInstance(Ci.nsIFileOutputStream);
        var convert = Cc['@mozilla.org/intl/scriptableunicodeconverter']
            .getService(Ci.nsIScriptableUnicodeConverter);
        convert.charset = "UTF-8";
        ext = convert.ConvertFromUnicode(text);
        try {
            strm.init(file, 0x02 | 0x08 | 0x20, parseInt(664, 8), 0); // write, create, truncate
            strm.write(text, text.length);
            strm.flush();
        } catch (ex) {
            alert('failed:\n' + ex);
            file = null;
        }
        strm.close();

        return file;
    },
    getDroppedURL_Fixup: function getDroppedURL_Fixup(url) {
        if (!url) return null;
        if (/^h?.?.p(s?):(.+)$/i.test(url)) {
            url = "http" + RegExp.$1 + ':' + RegExp.$2;
            if (!RegExp.$2) return null;
        }
        try {
            url = Services.uriFixup.getFixupURIInfo(url, Services.uriFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP).preferredURI.spec;
            // valid urls don't contain spaces ' '; if we have a space it
            // isn't a valid url, or if it's a javascript: or data: url,
            // bail out
            if (!url ||
                !url.length ||
                url.indexOf(" ", 0) != -1 ||
                /^\s*javascript:/.test(url) ||
                /^\s*data:/.test(url) && !/^\s*data:image\//.test(url))
                return null;
            return url;
        } catch (e) {
            return null;
        }
    },
    printDataTransferTypes: function (e) {
        var dt = e.dataTransfer;
        console.info("print dataTransfer type:");
        var types = dt.types;
        for (var i = 0; i < types.length; i += 1) {
            console.info(types[i] + ": " + dt.getData(types[i]));
        }
    },
    opts: {
        //relatedToCurrent: true,
        triggeringPrincipal: Cu.getObjectPrincipal(this),
        get userContextId() {
            return parseInt(win.gBrowser.selectedBrowser.getAttribute("usercontextid"));
        },
        get private() {
            return win.PrivateBrowsingUtils.isWindowPrivate(win);
        }
    },
    dragstart(e) {
        win = e.view.windowRoot.ownerGlobal;
        //if (!win.gBrowser.currentURI.spec.startsWith("http")) return;
        if (!e.dataTransfer.mozItemCount || !win.gBrowser.selectedBrowser.matches(":hover"))
            return;

        if (this.debug)
            this.printDataTransferTypes(e);

        var dt = e.dataTransfer;
        this.type = this.link;
        this.dir = this.val = "";

        var url = dt.getData("text/x-moz-url-data");

        if (url) {
            this.val = url;
            if (this.imageLinkRe.test(url)) {
                this.type = this.image;
            } else {
                var promiseUrl = dt.getData("application/x-moz-file-promise-url");
                var dragHTML = dt.getData("text/html");
                var parser = new DOMParser();
                var doc = parser.parseFromString(dragHTML, "text/html");
                var onImage = doc.getRootNode().body?.firstElementChild?.tagName == "IMG" || doc.getRootNode().body?.firstElementChild.querySelectorAll("img").length;
                if (onImage && e.ctrlKey) {
                    // force to image type when ctrlKey is pressed
                    this.type = this.image;
                    this.val = promiseUrl;
                }
            }
        } else {
            var txt = dt.getData("text/plain");
            if (txt) {
                this.val = txt;
                if (false) {
                    // 未来加入特殊文本处理 比如网盘链接
                } else {
                    if (!this.textLinkRe.test(txt)) this.type = this.text;
                    if (this.imageLinkRe.test(txt)) this.type = this.image;
                }
            }
            else return;
        }
        this.x = e.screenX; this.y = e.screenY;
        this.drag(true);
    },
    drag(init) {
        var meth = `${init ? "add" : "remove"}EventListener`;
        for (var type of this.events) win[meth](type, this, true);
        init || win.StatusPanel.panel.setAttribute("inactive", true);
    },
    events: ["dragover", "drop", "dragend"],
    dragover(e) {
        var { x, y } = this, cx = e.screenX, cy = e.screenY;
        var dx = cx - x, ax = Math.abs(dx), dy = cy - y, ay = Math.abs(dy);
        if (ax < 10 && ay < 10) return;

        this.x = cx; this.y = cy;
        var dir = ax > ay ? dx > 0 ? "R" : "L" : dy > 0 ? "D" : "U";
        if (this.dir.endsWith(dir)) return;

        dir = this.dir += dir;
        var obj;
        if (e.shiftKey) {
            obj = this.type[dir + "-Shift"];
        } else {
            obj = this.type[dir];
        }

        var txt = `${obj ? "Mouse" : "Unknown"
            } Gesture: ${dir + (obj ? "  " + obj.name : "")}`;

        win.StatusPanel._labelElement.value = txt;
        win.StatusPanel.panel.removeAttribute("inactive");
    },
    dragend(e) {
        var dt = e.dataTransfer;
        this.drag();
        var obj;
        if (e.shiftKey) {
            obj = this.type[this.dir + "-Shift"];
        } else {
            obj = this.type[this.dir];
        }
        if (!obj || dt.mozUserCancelled) return;

        var x = e.screenX, y = e.screenY;
        var wx = win.mozInnerScreenX, wy = win.mozInnerScreenY;
        x > wx && y > wy && x < wx + win.innerWidth && y < wy + win.innerHeight
            && obj.cmd.call(this, this.val, e);
    },
    textLinkRe: /^([a-z]+:\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&amp;]*)?)?(#[a-z][a-z0-9_]*)?$|^custombutton:\/\/\S+$/,
    imageLinkRe: /(http)?s?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg|avif|webp))/,
    observe(w) {
        this.drop = () => this.drag();
        this.handleEvent = e => this[e.type](e);
        var unload = e => {
            var w = e.target.ownerGlobal;
            w.gBrowser.tabpanels.removeEventListener("dragstart", this, true);
            if (w == win) win = null;
        }
        (this.observe = w => {
            //if (!w.toolbar.visible) return;
            w.gBrowser.tabpanels.addEventListener("dragstart", this, true);
            w.addEventListener("unload", unload, { once: true });
        })(w);
    },
    init(topic, self) {
        delete this.init;
        Services.obs.addObserver(self = this, topic);
        Services.obs.addObserver(function quit(s, t) {
            Services.obs.removeObserver(self, topic);
            Services.obs.removeObserver(quit, t);
        }, "quit-application-granted");
    }
}).init("browser-delayed-startup-finished"))();


ЗЫ: зашел с этом на vk.com, но повторить пропадание не смог


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

На форуме

 

№1695707-09-2023 22:48:25

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 484
UA: Firefox 117.0

Re: Custom Buttons

Dumby на 117 опять сломался DOM Inspector. скажи пожалуйста у тебя на эту версию есть рабочий вариант?

Отсутствует

 

№1695808-09-2023 18:25:53

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

Re: Custom Buttons

Farby пишет

Что-то не так с этим

кодом

Выделить код

Код:

`
		var txt = dt.getData("text/plain");
		var url = dt.getData("text/x-moz-url-data");
		if (url)
			this.val = url, this.txt = dt.getData("text/x-moz-url").split("\n")[1];
		else if (!txt) return;
		try {
			this.val = new URL(txt.trim());
		} catch {
			this.val = txt;
			if (!this.textLinkRe.test(txt))
				this.type = this.text;

Там используется экземпляр URL как таковой,
но, по дороге, прицепили на него вызов строкового метода includes()
поэтому следует привести его к строке, например, new URL(txt.trim()).href


Dobrov пишет

на сайте vk.com

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


Andrey_Krropotkin пишет

у тебя на эту версию есть рабочий вариант?

У меня такой.

Отсутствует

 

№1695908-09-2023 21:10:47

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

Re: Custom Buttons

Dumby

У меня такой.

Спасибо, у меня уже тоже такой, ой то бишь поставил уже!!


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

На форуме

 

№1696009-09-2023 03:17:38

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 322
UA: Firefox 117.0

Re: Custom Buttons

Ребята, у меня не работает антиподписячий код.
Он же должен лежать в файле config.js?

ФФ обновился до 117.
Перестали работать все неподписанные приложения.
На старнице about:addons с установленными дополнениями на многих приложениях висит теперь красная табличка "Работа дополнения не была проверенна, поэтому оно было отключено."
А когда пытаюсь установить custom_buttons-0.0.7.0.0.32-fx-paxmod или custom_buttons-0.0.7.0.0.32-fx-bootstrap, то вылетает ошибка: "дополнение не может быть установленно так как оно по-видимуму, повреждено."

C:\Program Files\Mozilla firefox\defaults\pref\

config.js

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

Выделить код

Код:

//
try {(jsval => {
	var dbg, gref, genv = func => {
		var sandbox = new Cu.Sandbox(g, {freshCompartment: true});
		Cc["@mozilla.org/jsdebugger;1"].createInstance(Ci.IJSDebugger).addClass(sandbox);
		(dbg = new sandbox.Debugger()).addDebuggee(g);
		gref = dbg.makeGlobalObjectReference(g);
		return (genv = func => func && gref.makeDebuggeeValue(func).environment)(func);
	}
	var g = Cu.getGlobalForObject(jsval), o = g.Object, {freeze} = o, disleg;

	var lexp = () => lockPref("extensions.experiments.enabled", true);
	var MRS = "MOZ_REQUIRE_SIGNING", AC = "AppConstants", uac = `resource://gre/modules/${AC}.`;

	if (o.isFrozen(o)) { // Fx 102.0b7+
		lexp(); disleg = true; genv();

		dbg.onEnterFrame = frame => {
			var {script} = frame;
			try {if (!script.url.startsWith(uac)) return;} catch {return;}
			dbg.onEnterFrame = undefined;

			if (script.isModule) { // ESM, Fx 108+
				var env = frame.environment;
				frame.onPop = () => env.setVariable(AC, gref.makeDebuggeeValue(freeze(
					o.assign(new o(), env.getVariable(AC).unsafeDereference(), {[MRS]: false})
				)));
			}
			else { // JSM
				var nsvo = frame.this.unsafeDereference();
				nsvo.Object = {freeze(ac) {
					ac[MRS] = false;
					delete nsvo.Object;
					return freeze(ac);
				}};
			}
		}
	}
	else o.freeze = obj => {
		if (!Components.stack.caller.filename.startsWith(uac)) return freeze(obj);
		obj[MRS] = false;

		if ((disleg = "MOZ_ALLOW_ADDON_SIDELOAD" in obj)) lexp();
		else
			obj.MOZ_ALLOW_LEGACY_EXTENSIONS = true,
			lockPref("extensions.legacy.enabled", true);

		return (o.freeze = freeze)(obj);
	}
	lockPref("xpinstall.signatures.required", false);
	lockPref("extensions.langpacks.signatures.required", false);

	var useDbg = true, xpii = "resource://gre/modules/addons/XPIInstall.";
	if (Ci.nsINativeFileWatcherService) { // Fx < 100
		jsval = Cu.import(xpii + "jsm", {});
		var shouldVerify = jsval.shouldVerifySignedState;
		if (shouldVerify.length == 1)
			useDbg = false,
			jsval.shouldVerifySignedState = addon => !addon.id && shouldVerify(addon);
	}
	if (useDbg) { // Fx 99+
		try {var exp = ChromeUtils.importESModule(xpii + "sys.mjs");}
		catch {exp = g.ChromeUtils.import(xpii + "jsm");}
		jsval = o.assign({}, exp);

		var env = genv(jsval.XPIInstall.installTemporaryAddon);
		var ref = name => {try {return env.find(name).getVariable(name).unsafeDereference();} catch {}}
		jsval.XPIDatabase = (ref("lazy") || {}).XPIDatabase || ref("XPIDatabase");

		var proto = ref("Package").prototype;
		var verify = proto.verifySignedState;
		proto.verifySignedState = function(id) {
			return id ? {cert: null, signedState: undefined} : verify.apply(this, arguments);
		}
		dbg.removeAllDebuggees();
	}
	if (disleg) jsval.XPIDatabase.isDisabledLegacy = () => false;
})(
	"permitCPOWsInScope" in Cu ? Cu.import("resource://gre/modules/WebRequestCommon.jsm", {}) : Cu
);}
catch(ex) {Cu.reportError(ex);}


config-prefs.js

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

Выделить код

Код:

pref("general.config.obscure_value", 0);
pref("general.config.filename", "config.js");
pref("general.config.sandbox_enabled", false);


Папку startupCache в локальный каталоге, вычистил. СВ не работает.

Отредактировано leex (09-09-2023 03:18:48)

Отсутствует

 

№1696109-09-2023 17:57:13

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

Re: Custom Buttons

leex пишет

Ребята, у меня не работает антиподписячий код.

А попробуйте прочитать хотя-бы от сюда и далее...


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

На форуме

 

№1696209-09-2023 20:06:43

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 322
UA: Firefox 117.0

Re: Custom Buttons

Farby пишет

А попробуйте прочитать хотя-бы от сюда и далее...

Читал конечно же и это и далее.

Антиподписячий код надо брать здесь

Именно этот код.




Добавлено.

Вот я тупанул. Все заработало.
Файл config.js должен был лежать в C:\Program Files\Mozilla firefox.
У меня он был в C:\Program Files\Mozilla firefox\defaults\pref

Отредактировано leex (09-09-2023 21:03:53)

Отсутствует

 

№1696326-09-2023 22:03:08

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 484
UA: Firefox 118.0

Re: Custom Buttons

Может кто подправить

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

Выделить код

Код:

// Сплывающая подсказка у кнопки ....
(function() {
    var title = self.label + ":\n\n";
    var data = {
        memory: "Memory Cache:  ",
        disk: "Disk Cache:  ",
        offline: "Offline Cache:  "
    };
    function getSize(size) {
        if (!size) return size === 0 ? "0" : "?";
        for(var count = -1; size >= 1024; size /= 1024, count++);
        return size.toFixed(2).replace(/0+$/, "").replace(/\.$/, "") + " " + ("KMGT"[count] || "") + "B";
    }
    function setInf(tot, max, type, i) {
        var inf = getSize(tot) + " / " + getSize(max);
        var key = "browser.cache." + type + ".enable";
        if (!Services.prefs.getBoolPref(key)) inf += " (disabled)";
        self.tooltipText = self.tooltipText.replace(zws(i), inf);
    }
  
var zws = ind => "\u200B".repeat(++ind);
    var types = Object.keys(data);
  
var ttt = title + types.map((key, i) => data[key] + zws(i)).join("\n");
 
    
  // var context = Cu.import("", {}).Services.loadContextInfo.default;
 
    self.onmouseenter = function() {
        self.tooltipText = ttt;
        try {
            var entries = {};
            Services.cache.visitEntries({
                visitDevice: function(device, info) {entries[device] = info},
                visitEntry: function() {}
            });
            types.forEach(function(type, i) {
                var info = entries[type];
                setInf(info && info.totalSize, info && info.maximumSize, type, i)
            });
        } catch(ex) {
           Services.cache2 && types.forEach(function(type, i) {
               var func = function(aEntryCount, aConsumption, aCapacity, aDiskDirectory)
                         { setInf(aConsumption, aCapacity, type, i)};
               var storage = Services.cache2[(type == "offline" ? "app" : type) + "CacheStorage"](context, null);
               try { storage.asyncVisitStorage({onCacheStorageInfo: func}, false) } catch(ex) {};
            });
        }
    } ;
})();

Отсутствует

 

№1696428-09-2023 21:03:14

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

Re: Custom Buttons

Andrey_Krropotkin
appCacheStorage удалили ещё в Firefox 90.
Может так сойдёт

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

Выделить код

Код:

(() => {
	var format = size => {
		if (!size) return size === 0 ? "0" : "?";
		for(var count = -1; size >= 1024; size /= 1024, count++);
		return `${+size.toFixed(2)} ${"KMG"[count] || ""}B`;
	}
	var res, visitor = Object.create(null);
	visitor.onCacheStorageInfo = (e, consumption, capacity, f) => {
		var str = format(consumption) + " / " + format(capacity);
		var pref = `browser.cache.${f ? "disk" : "memory"}.enable`;
        	if (!Services.prefs.getBoolPref(pref)) str += " (disabled)";
        	res(str);
	}
	var getInf = type => {
		var storage = Services.cache2[type](null);
		return new Promise(resolve => {
			res = resolve;
			storage.asyncVisitStorage(visitor, false);
		});
	}
	self.onmouseenter = async () => self.tooltipText =
		`${self.label}:\n\nMemory Cache:  ${
			await getInf("memoryCacheStorage")
		}\nDisk Cache:  ${
			await getInf("diskCacheStorage")
		}`;
})();

Отсутствует

 

№1696530-09-2023 10:31:36

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 484
UA: Firefox 118.0

Re: Custom Buttons

Dumby спасибо все работает

Отсутствует

 

№1696601-10-2023 12:00:55

vending_machine
Участник
 
Группа: Members
Зарегистрирован: 10-01-2020
Сообщений: 549
UA: Firefox 115.0

Re: Custom Buttons

Перешёл с 102esr  на 115.3.1esr и перестала работать кнопка Двойным левым кликом на папке закладок добавлять закладку в папку закладок, от 06.06.2019

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

Выделить код

Код:

// Двойным левым кликом на папке закладок добавлять закладку в папку закладок, от 06.06.2019. ......................
addEventListener("dblclick", (e, targ = e.originalTarget)=> {     
   if ( e.button || !targ._placesNode || !PlacesUtils.nodeIsFolder(targ._placesNode) ) return;          
   
   var docTitle = gBrowser.selectedTab.label.substr(0, 50);
   var folderId = PlacesUtils.getConcreteItemId(targ._placesNode);
   var folderTitle = PlacesUtils.bookmarks.getItemTitle(folderId);
   var currentURI = Services.io.newURI(gBrowser.currentURI.spec, null, null);
   PlacesUtils.bookmarks.insertBookmark(folderId, currentURI, -1, docTitle);  

   // всплывающая подсказка ....
   var favicon = gBrowser.selectedTab.image || "chrome://global/skin/icons/Portrait.png";
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
   .showAlertNotification(favicon, "Добавил в папку " + folderTitle + ":", docTitle);

   setTimeout(()=> { document.getElementById("bookmarksMenuPopup").hidePopup() }, 50); 
});

Нет ли у кого рабочего варианта кнопки?
---------------
Так же интересует [CB]Undo Close Tabs, который тоже отвалился. Нет ли у кого его рабочего варианта?
Версия Сustom Buttons - крайняя.

Отсутствует

 

№1696701-10-2023 13:50:23

negodnik
 
 
Группа: Members
Зарегистрирован: 14-03-2013
Сообщений: 608
UA: Seamonkey 2.38
Веб-сайт

Re: Custom Buttons

> Нет ли у кого рабочего варианта кнопки?
У Вас есть — https://forum.mozilla-russia.org/viewto … 30#p805830

> Так же интересует [CB]Undo Close Tabs
1.Заменитьвсе .getClosedTabCount на .getClosedTabCountForWindow, .getClosedTabData на .getClosedTabDataForWindow
2.Иконки - https://forum.mozilla-russia.org/viewto … 39#p804539

Отсутствует

 

№1696801-10-2023 14:24:33

vending_machine
Участник
 
Группа: Members
Зарегистрирован: 10-01-2020
Сообщений: 549
UA: Firefox 115.0

Re: Custom Buttons

negodnik пишет

> Нет ли у кого рабочего варианта кнопки?
У Вас есть — https://forum.mozilla-russia.org/viewto … 30#p805830

> Так же интересует [CB]Undo Close Tabs
1.Заменитьвсе .getClosedTabCount на .getClosedTabCountForWindow, .getClosedTabData на .getClosedTabDataForWindow
2.Иконки - https://forum.mozilla-russia.org/viewto … 39#p804539

Спасибо.

Отсутствует

 

№1696907-10-2023 01:50:33

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

Re: Custom Buttons

На форуме есть сообщения, содержащие сжатый текст или архив.
При вставке в строку адреса скопированного кода открывается текст или страница, содержащая архив – data:text/html …… octet-stream;base64,……
В старой кнопке Save+ этого нет и на форуме не нашёл по фразе: octet-stream;base64
кстати, на Android в браузерах Chrome и Samsung Internet этот способ не работает.


Объясните, как сжать текст или архив в код, открываемый из адресной строки ?
И есть ли возможность уменьшить код, используя zip или другое сжатие для сохранения больших страниц ?

Отсутствует

 

№1697007-10-2023 02:29:29

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

Re: Custom Buttons

Dobrov
У меня есть кнопка Save. Не знаю, какая она - старая или новая, но с правками. Позволяет закодировать выделенный текст в 2 этапа.
1. Сохранить выделенный текст как txt файл.
2. Кодировать изображение(текст.файл) в base64

скриншот
Image001_2023-10-07_02-09.png

Я не знаю, работают ли в кнопке все пункты меню.
Кнопка загружается в custom_script.js таким кодом
скрытый текст

Выделить код

Код:

// Save.js https://forum.mozilla-russia.org/viewtopic.php?pid=781458#p781458
try {CustomizableUI.createWidget({
  id: "ucf-cbbtn-Save",
  tooltiptext: "Сохранить страницу,\nчасть, выделенное...",
  localized: false,
  get initCode() {
    delete this.initCode;
    return this.initCode = Cu.readUTF8URI(Services.io.newURI(
      "chrome://user_chrome_files/content/custom_scripts/cs/Save.js"
    ));
  },
  cbu: {
    types: {
      128: "Bool", boolean: "Bool",
      64: "Int", number: "Int",
      32: "String", string: "String"
    },
    getPrefs(pref) {
      try {
        return Services.prefs[`get${
          this.types[Services.prefs.getPrefType(pref)]
        }Pref`](pref);
      }
      catch {return null;}
    },
    setPrefs(pref, val) {
      Services.prefs[`set${this.types[typeof val]}Pref`](pref, val);
    }
  },
  gClipboard: {
    get ch() {
      delete this.ch;
      return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"]
        .getService(Ci.nsIClipboardHelper);
    },
    write(str) {
      this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard);
    }
  },
  custombuttonsUtils: {
    writeFile(path, data) {
      try {
        if (path.includes(":\\")) path = path.replace(/\//g, "\\");
        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        file.exists() && file.remove(false);

        var strm = Cc["@mozilla.org/network/file-output-stream;1"]
          .createInstance(Ci.nsIFileOutputStream);
        strm.init(file, 0x04 | 0x08, 420, 0);
        strm.write(data, data.length);
        strm.flush();
        strm.close();
      } catch(ex) {
        Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n"));
      }
    }
  },
  addDestructor(destructor, context) {
    this._destructors.push({destructor, context});
  },
  addEventListener(...args) {
    var trg = args[3];
    if (!trg) trg = args[3] = this.ownerGlobal;
    trg.addEventListener(...args);
    this._handlers.push(args);
  },

  onCreated(btn) {
    var win = btn.ownerGlobal;
    btn._handlers = new win.Array();
    btn._destructors = new win.Array();
    win.addEventListener("unload", this, {once: true});
    new win.Function(
      "self,_id,cbu,xhtmlns,addDestructor,addEventListener,gClipboard,custombuttonsUtils",
      this.initCode
    ).call(
      btn, btn, this.id, this.cbu,
      "http://www.w3.org/1999/xhtml",
      this.addDestructor.bind(btn),
      this.addEventListener.bind(btn),
      this.gClipboard, this.custombuttonsUtils
    );
  },
  handleEvent(e) {
    var btn = e.target.getElementById(this.id);
    for(var args of btn._handlers)
      args.pop().removeEventListener(...args);
    delete btn._handlers;
    for(var {destructor, context} of btn._destructors)
      try {destructor.call(context, "destructor");}
      catch(ex) {Cu.reportError(ex);}
    delete btn._destructors;
  }
});} catch(ex) {Cu.reportError(ex);}


Кнопка не влезает, следующим сообщением.

Добавлено 07-10-2023 02:43:40
Не влазит, форум пытается объединить сообщения. Save.js
Там есть одна правка, примерно по дате 17.04.23, ищите по строке /*
Надеюсь, сможете разобраться. Хотя я бы не рискнул. ;)

Отредактировано xrun1 (07-10-2023 02:43:40)

Отсутствует

 

№1697107-10-2023 03:34:37

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

Re: Custom Buttons

xrun1 - это всё не то, я спрашивал, как создать вот такой код, открываемый из строки адреса:

Выделить код

Код:

data:text/html;charset=utf-8,<!DOCTYPE html>%0A<html><head>%0A%09<title>Attributes Inspector (mod)</title>%0A%09<meta http-equiv="Content-Type" content="text/html; charset=utf-8">%0A%0A%09<script type="module">%0A%0A%09%09var url = "data:application/octet-stream;base64,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";%0A%0A%09%09var response = await fetch(url);%0A%09%09var stream = response.body.pipeThrough(new DecompressionStream("gzip"));%0A%09%09pre.append(await new Response(stream).text());%0A%0A%09</script>%0A%0A</head><body><pre id="pre"></pre></body></html>

Отсутствует

 

№1697208-10-2023 01:44:56

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

Re: Custom Buttons

Dobrov пишет

это всё не то

Да, в том примере, который приводил, текст кодируется data:text/plain;charset=utf-8;base64

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

Выделить код

Код:

fp.open(re=> { 
  if ( re != fp.returnOK ) return;
   var file = fp.file;
   var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
   inputStream.init(file, 0x01, 0600, 0);
   var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
   stream.setInputStream(inputStream);
   var encoded = btoa(stream.readBytes(stream.available()));
   var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file);
   var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded;
   gClipboard.write(dataURI);
   //Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Скопировал файл как base64");
    // стиль для изображение в всплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Запомнил изображение как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
});
};


и по размеру получается намного больше (23831 против 88913 знаков).

Отсутствует

 

№1697308-10-2023 09:29:05

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

Re: Custom Buttons

Dobrov пишет

как создать вот такой код, открываемый из строки адреса

Можно, например, запустить в окне код, который
возьмёт текст из буфера и вернёт в буфер подобный data-адрес.

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

Выделить код

Код:

(async () => {
	var format = "gzip";
	var title = "Attributes Inspector (mod)";
	//if ((title = prompt("title?", title)) == null) return;

	var text = await navigator.clipboard.readText();
	var stream = new Response(text).body.pipeThrough(new CompressionStream(format));

	var reader = new FileReader();
	var url = await new Promise(async resolve => {
		reader.onload = () => resolve(reader.result);
		reader.readAsDataURL(await new Response(stream).blob());
	});

	var html = `

<!DOCTYPE html>
<html><head>
	<title>${title}</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

	<script type="module">

		var url = "${url}";

		var response = await fetch(url);
		var stream = response.body.pipeThrough(new DecompressionStream("${format}"));
		pre.append(await new Response(stream).text());

	</script>

</head><body><pre id="pre"></pre></body></html>

	`
		.trim()
		//.replace(/#/g, "%23")
		.replace(/\n/g, "%0A")
		.replace(/\t/g, "%09");

	await navigator.clipboard.writeText(url = "data:text/html;charset=utf-8," + html);

	var tl = text.length, ul = url.length;
	alert(`was:\t${tl}\nnow:\t${ul}  ( ${Math.ceil(100 * ul / tl)}% of was )`);
	gBrowser.selectedTab = gBrowser.addTrustedTab(url);
})();


Compression Streams API


Имеет смысл для кода, размером в определённых пределах.
Большой всё равно на форум не влезет, а маленький станет только больше,
поскольку html-оболочка, плюс компрессору негде разгуляться,
а кодировка base64 увеличивает размер на треть.

Отсутствует

 

№1697423-10-2023 14:43:44

vending_machine
Участник
 
Группа: Members
Зарегистрирован: 10-01-2020
Сообщений: 549
UA: Firefox 115.0

Re: Custom Buttons

В кнопке (Двойным левым кликом на папке закладок добавлять закладку в папку закладок)
https://forum.mozilla-russia.org/viewto … 93#p803993 - №16807
при добавлении закладки её имя отражается без первых двух-трёх букв.

скрытый текст
1b99355d1d304a110403ca00fe118ec5.jpg

Нельзя ли это как-то поправить?

Отсутствует

 

№1697523-10-2023 19:58:40

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

Re: Custom Buttons

vending_machine пишет

Нельзя ли это как-то поправить?

Нет, это нельзя «поправить». Потому что это не дефект.
У Андрея в коде имя так и обрезалось. Так что это просто цитата.


Но можно изменить. Находишь строку
title: gBrowser.selectedTab.label.substr(3, 50)


И меняешь числа, например, на (0, 50)
Вобщем так, как нужно обрезать название активной вкладки.
Или совсем убрать .substr(…) если обрезка не требуется.

Отсутствует

 

Board footer

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