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

Список ответов на каверзные вопросы можно получить в FAQ-разделе форума.

№1495110-08-2020 19:43:59

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

Re: Custom Buttons

Dumby
огромное спасибо
работает :rock:

Отсутствует

 

№1495211-08-2020 00:26:27

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 537
UA: Firefox 52.0

Re: Custom Buttons

Duche пишет

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

Duche, попробуй ещё вот что.


Замени эту строку:

Выделить код

Код:

canvas.style.cssText = "min-width: diapx; min-height: diapx; max-width: diapx; max-height: diapx".replace(/dia/g, dia);

на эту

Выделить код

Код:

canvas.style.cssText = "position: fixed !important; min-width: diapx; min-height: diapx; max-width: diapx; max-height: diapx".replace(/dia/g, dia);

«The Truth Is Out There»

Отсутствует

 

№1495311-08-2020 08:25:52

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 208
UA: unknown 0.0

Re: Custom Buttons

unter_officer пишет

Замени эту строку:

Не работает, закрывает другие кнопки справа , нет в контекстного меню для редактирования. Я так понимаю , тело часов закрывает звездочку где контекстное меню.

Отсутствует

 

№1495411-08-2020 11:37:58

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

Re: Custom Buttons

Dumby

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
    suc.charset = "utf-8";
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "Save_snapshot_to_html_alert";
    var notify = as.showAlertNotification.bind(
        as, null, "Страница сохранена на Рабочем столе", null, false, null, null, alertName
    );
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
    return (html, name) => {
        var file = desk.clone()
        file.append(name);
        html = suc.ConvertFromUnicode(html);
        var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
        stream.write(html, html.length);
        stream.close();
        notify();
        setTimeout(as.closeAlert, 2e3, alertName);
    }
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

var resolveURL = function (url, base) {
    try {
        var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
        var baseURI = ioService.newURI(base, null, null);
        var absURI = ioService.newURI(url, null, baseURI);
        return absURI.spec;
    } catch (e) {}
};

var getSelWin = function (w) {
    if (w.getSelection().toString()) return w;
    for (var i = 0, f, r; f = w.frames[i]; i++) {
        try {
            if (r = getSelWin(f)) return r;
        } catch(e) {}
    }
};
var encodeImg = function (src, obj) {
    var canvas, img, ret = src;
    if (/^https?:\/\//.test(src)) {
        canvas = doc.createElement('canvas');
        if (!obj || obj.nodeName.toLowerCase() != 'img') {
            img = doc.createElement('img');
            img.src = src;
        } else {
            img = obj;
        };
        if (img.complete) try{
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.getContext('2d').drawImage(img, 0, 0);
            ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png'));
        } catch (e) {};
        if (img != obj) img.src = 'about:blank';
    };
    return ret;
};
var toSrc = function (obj) {
    var strToSrc = function (str) {
        var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
        while (chr = str.charAt(i++)) {
            ret += meta[chr] || chr;
        };
        return '\x22' + ret + '\x22';
    },
    arrToSrc = function (arr) {
        var ret = [];
        for (var i = 0; i < arr.length; i++) {
            ret[i] = toSrc(arr[i]) || 'null';
        };
        return '[' + ret.join(',') + ']';
    },
    objToSrc = function (obj) {
        var val, ret = [];
        for (var prop in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, prop) && (val = toSrc(obj[prop]))) ret.push(strToSrc(prop) + ': ' + val);
        };
        return '{' + ret.join(',') + '}';
    };

    switch (Object.prototype.toString.call(obj).slice(8, -1)) {
        case 'Array': return arrToSrc(obj);
        case 'Boolean':
        case 'Function':
        case 'RegExp': return obj.toString();
        case 'Date': return 'new Date(' + obj.getTime() + ')';
        case 'Math': return 'Math';
        case 'Number': return isFinite(obj) ? String(obj) : 'null';
        case 'Object': return objToSrc(obj);
        case 'String': return strToSrc(obj);
        default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
    }
};

var mainWin = document.commandDispatcher.focusedWindow.top == content ? document.commandDispatcher.focusedWindow : content;
var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g;

if (selWin) {
    var rng = win.getSelection().getRangeAt(0);
    pEle = rng.commonAncestorContainer;
    ele = rng.cloneContents();
} else {
    pEle = doc.documentElement;
    ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true);
};
while (pEle) {
    if (pEle.nodeType == 1) {
        clone = pEle.cloneNode(false);
        clone.appendChild(ele);
        ele = clone;
    };
    pEle = pEle.parentNode
};
var sel = doc.createElement('div');
sel.appendChild(ele);

for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) {
    el = all[i];
    if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) {
        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
        return prev + encodeImg(url) + next;
    });
    switch (el.nodeName.toLowerCase()) {
        case 'link':
        case 'style':
        case 'script': el.parentNode.removeChild(el); break;
        case 'a': 
        case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break;
        case 'img':
        case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break;
        case 'audio':
        case 'video':
        case 'embed':
        case 'frame':
        case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break;
        case 'object': if (el.hasAttribute('data')) el.data = el.data; break;
        case 'form': if (el.hasAttribute('action')) el.action = el.action; break;
    }
};

var head = ele.insertBefore(doc.createElement('head'), ele.firstChild);
var meta = doc.createElement('meta');
meta.httpEquiv = 'content-type';
meta.content = 'text/html; charset=utf-8';
head.appendChild(meta);
var title = doc.getElementsByTagName('title')[0];
if (title) head.appendChild(title.cloneNode(true));

head.copyScript = function (unsafeWin) {
    if ('$' in unsafeWin) return;
    var f = doc.createElement('iframe');
    f.src = 'about:blank';
    f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');
    doc.documentElement.appendChild(f);
    var str, script = doc.createElement('script');
    script.type = 'text/javascript';
    for (var name in unsafeWin) {
        if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
        try {
            str = toSrc(unsafeWin[name]);
            if (!/\{\s*\[native code\]\s*\}/.test(str)) {
                script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
            }
        } catch (e) {};
    };
    f.parentNode.removeChild(f);
    if (script.childNodes.length) this.nextSibling.appendChild(script);
};
head.copyScript(win.wrappedJSObject || win);

head.copyStyle = function (s) {
    if (!s) return;
    var style = doc.createElement('style');
    style.type = 'text/css';
    if (s.media && s.media.mediaText) style.media = s.media.mediaText;
    try {
        for (var i = 0, rule; rule = s.cssRules[i]; i++) {
            if (rule.type != 3) {
                if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) {
                    var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
                        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
                        if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
                        return prev + url + next;
                    });
                    style.appendChild(doc.createTextNode(css + '\n'));
                }
            } else {
                this.copyStyle(rule.styleSheet);
            }
        }
    } catch(e) {
        if (s.ownerNode) style = s.ownerNode.cloneNode(false);
    };
    this.appendChild(style);
};
var sheets = doc.styleSheets;
for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]);
head.appendChild(doc.createTextNode('\n'));

var doctype = '', dt = doc.doctype;
if (dt && dt.name) {
    doctype += '<!DOCTYPE ' + dt.name;
    if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
    if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
    doctype += '>\n';
};
var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');
fileName += ("  " + new Date().toLocaleFormat("%d.%m.%Y. %H-%M-%S"));
if(!/\.html?$/.test(fileName))fileName += '.html';

saveToFile(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName);

Приветствую,
А можно чуть подправить, чтобы alert показывался секунд 5, и если по нему кликнуть - откроется сохраненная страница.
Спасибо

Отсутствует

 

№1495511-08-2020 12:55:17

sachka
Участник
 
Группа: Members
Зарегистрирован: 11-04-2018
Сообщений: 23
UA: Firefox 79.0

Re: Custom Buttons

Dumby

А можно сотворить такой фокус - сделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?

Отсутствует

 

№1495611-08-2020 13:43:31

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

Re: Custom Buttons

sachka пишет

сделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?

А поставить и убрать галочку неужели так сложно не вариант:

скрин
f5bc2c28a2ad.png

Отредактировано kokoss (11-08-2020 18:24:43)


Win7

Отсутствует

 

№1495711-08-2020 14:05:29

sachka
Участник
 
Группа: Members
Зарегистрирован: 11-04-2018
Сообщений: 23
UA: Firefox 79.0

Re: Custom Buttons

kokoss пишет

sachka пишетсделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?А поставить и убрать галочку неужели так сложно: скрин

одной кнопкой удобнее же

Отсутствует

 

№1495811-08-2020 14:27:39

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

Re: Custom Buttons

sachka
Можно ещё так, ПКМ на иконке:

скрин
ed2fe5b5176e.png


Win7

Отсутствует

 

№1495911-08-2020 14:35:17

sachka
Участник
 
Группа: Members
Зарегистрирован: 11-04-2018
Сообщений: 23
UA: Firefox 79.0

Re: Custom Buttons

kokoss пишет

sachkaМожно ещё так, ПКМ на иконке: скрин

Спасибо за совет конечно, но с такой кнопочкой все меньше лишних движений. Пусть бы была

Отсутствует

 

№1496011-08-2020 15:05:52

mokujin
Участник
 
Группа: Members
Зарегистрирован: 17-02-2017
Сообщений: 494
UA: unknown 0.0

Re: Custom Buttons

sachka пишет

Пусть бы была

Сделай сам. Узнай id пункта и запихни в Код, сделай кнопку:   

Выделить код

Код:

document.getElementById("id_пункта").click();

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

Отсутствует

 

№1496111-08-2020 16:43:38

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 537
UA: Firefox 52.0

Re: Custom Buttons

Duche пишет

Не работает

Сделаю последнюю попытку.
Если не получится, тогда не знаю, что ещё можно сделать.


Попробуйте вставить перед кодом часов (в инициализации) вот это:

Выделить код

Код:

self.type = "canvas";
if (!self.hasAttribute("initialized")) self.init = Function();

Далее из секции /*CODE*/ удалите this.leftclick(event); и перезапустите браузер.


P.S. По крайней мере у меня на [firefox] 78 ESR этот костыль сработал.

Отредактировано unter_officer (11-08-2020 16:44:40)


«The Truth Is Out There»

Отсутствует

 

№1496211-08-2020 18:00:58

sandro79
Участник
 
Группа: Members
Зарегистрирован: 15-11-2017
Сообщений: 1750
UA: Firefox 78.0

Re: Custom Buttons

kokoss пишет

sachka пишет

    сделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?
А поставить и убрать галочку неужели так сложно:
скрин

А неужели было так сложно открывать дилы "Топ сайтов" в новой вкладке по нажатию СКМ или через конт. меню? Вопрос риторический!

СКРИНЫ!!!
35b13f5efefc.pngi?id=0340f45e307ba6d0f9bd32890ab46310&n=13

Не надо вот этого выпендрёжного спама, неужто он не знает про ПКМ на иконке. Ну попросил человек - ну может ему так будет удобней.

Отсутствует

 

№1496311-08-2020 19:26:09

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 208
UA: unknown 0.0

Re: Custom Buttons

unter_officer пишет

78 ESR этот костыль сработал.

Примите искреннюю благодарность. Всё работает.

Отсутствует

 

№1496411-08-2020 19:56:58

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

Re: Custom Buttons

firepox пишет

А можно чуть подправить, чтобы alert показывался секунд 5, и если по нему кликнуть - откроется сохраненная страница.

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
    suc.charset = "utf-8";
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "Save_snapshot_to_html_alert";
    var file, id, obs = (s, topic) => {switch(topic) {
        case "alertshow": id = setTimeout(as.closeAlert, 5e3, alertName); break;
        case "alertfinished": id = file = null; break;
        case "alertclickcallback": clearTimeout(id);
            gBrowser.selectedTab = gBrowser.addTab(Services.io.newFileURI(file).spec);
    }};
    var notify = as.showAlertNotification.bind(
        as, null, "Страница сохранена на Рабочем столе", null, true, null, obs, alertName
    );
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
    return (html, name) => {
        file = desk.clone();
        file.append(name);
        html = suc.ConvertFromUnicode(html);
        var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
        stream.write(html, html.length);
        stream.close();
        notify();
    }
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

sachka пишет

А можно сотворить такой фокус - сделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?

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

Выделить код

Код:

WebExtensionPolicy.getByID("{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}").extension._backgroundPageFrameLoader.messageManager
	.loadFrameScript('data:,((p,n)=>p.set(n,!p.get(n)))(content.wrappedJSObject.prefs,"disableAll")', false);

Отсутствует

 

№1496511-08-2020 20:03:12

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

Re: Custom Buttons

Dumby
огромное спасибо

Отсутствует

 

№1496611-08-2020 20:05:19

sachka
Участник
 
Группа: Members
Зарегистрирован: 11-04-2018
Сообщений: 23
UA: Firefox 79.0

Re: Custom Buttons

Dumby пишет
firepox пишет

А можно чуть подправить, чтобы alert показывался секунд 5, и если по нему кликнуть - откроется сохраненная страница.

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
    suc.charset = "utf-8";
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "Save_snapshot_to_html_alert";
    var file, id, obs = (s, topic) => {switch(topic) {
        case "alertshow": id = setTimeout(as.closeAlert, 5e3, alertName); break;
        case "alertfinished": id = file = null; break;
        case "alertclickcallback": clearTimeout(id);
            gBrowser.selectedTab = gBrowser.addTab(Services.io.newFileURI(file).spec);
    }};
    var notify = as.showAlertNotification.bind(
        as, null, "Страница сохранена на Рабочем столе", null, true, null, obs, alertName
    );
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
    return (html, name) => {
        file = desk.clone();
        file.append(name);
        html = suc.ConvertFromUnicode(html);
        var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
        stream.write(html, html.length);
        stream.close();
        notify();
    }
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

sachka пишет

А можно сотворить такой фокус - сделать кнопку для включения\выключения всех стилей Stylus одной кнопкой?

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

Выделить код

Код:

WebExtensionPolicy.getByID("{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}").extension._backgroundPageFrameLoader.messageManager
	.loadFrameScript('data:,((p,n)=>p.set(n,!p.get(n)))(content.wrappedJSObject.prefs,"disableAll")', false);

O! Спасибо большое

Отсутствует

 

№1496711-08-2020 22:05:21

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

Re: Custom Buttons

sandro79 пишет

kokoss пишет

    Dumby
    Есть ли способ в about:newtab открывать дилы "Топ сайты" ЛКМ в новой вкладке  в  71 ?

За ссылку спасибо, а то сразу забыл добавил в закладки 61e02079e5fa.gif

Отредактировано kokoss (11-08-2020 22:09:33)


Win7

Отсутствует

 

№1496812-08-2020 01:09:21

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

Re: Custom Buttons

Dumby потестировал QuickSettings в Waterfox 2020.07.1 x64 Classic (пока не проверял в user_chrome_files от Виталия)
Пожелание: в новой QuickSettings при изменении настроек не закрывается меню опций.
Надо, чтобы нажал на кнопку, переключил галочку и меню закрылось. Так работал мой оригинальный код…


Вопрос по скриптам user_chrome_files от Виталия
Можно для Thunderbird сделать такой скрипт, чтобы одним кликом на письме спама добавить его адрес в фильтры сообщений в набор правил с именем SPAM ?
фильтр SPAM у меня выполняет действие: «Удалить сообщение» если поле Адрес содержит перечисленные адреса.
Можно автоматизировать эти несколько действий добавления адреса письма в фильтр ?
1) копировать адрес электронной почты письма (спама)
2) открыть фильтры сообщений. Выбрать правило с именем SPAM, нажать «Изменить»
3) добавить новое условие, вставив адрес письма (спама)
4) нажать «OK», закрыть окно фильтров…

Есть ли такой скрипт для Thunderbird, который делает это прямой правкой about:config ?

Отредактировано Dobrov (12-08-2020 01:50:32)

Отсутствует

 

№1496912-08-2020 09:43:13

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

Re: Custom Buttons

Dobrov пишет

пока не проверял в user_chrome_files от Виталия

Хмм, так в этом смысл задачи и был, ну пока там «(или)» не нарисовалось.

Надо, чтобы нажал на кнопку, переключил галочку и меню закрылось. Так работал мой оригинальный код…

Тогда зачем в коде пунктам меню проставляется атрибут closemenu=none ?


И нет, твой оригинальный код так не работает.
Там, по mouseup на пункте, проверяется его атрибут "{Popup, menuContext}.state",
и, по результату, идёт вызов метода на открытие или закрытие menupopup.
Затем, этому пункту ставится этот атрибут по результату вызова.
Таким образом, в общем случае, меню будет закрыто, если конкретный пункт
кликнут чётноё количество раз. Довольно странно, правда же?


Но, раз пожелание закрывающихся меню, хорошо, попробую модифицировать.
Вторая половина кода, на замену.

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

Выделить код

Код:

...
	return {
		label: "Quick toggle",
		id: "QuickToggleAboutConfigSettings",
		localized: false,
		image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB6klEQVQ4jZWTv2tUQRDHv8ntd28GLLQQfwS5VkuDSgRF/wlRiIiCQQQhhZ1VII1/wDUWkkLTBAsbC0FJYZGQ3NuZRcHYW6UQEQzoeXkW791xXh5CptodZr8z85kd4BBWRJwDgB5wyoCjh3mLbfK8C/ddW11XJlduNgYaeTFpvJWA0+P+BBx3Cf2sLEy5m4WrS8A0AGANaBUSrgKAKzdcY5k0PF4HJGm47NK6nSUMXOIXAEgSrrnG0oU/AGDKNb6qHe9c+Ms1lqbxqws/uoTfWVp3ksRll/DTJM6bcMWEn1KbDysBCW+zsnSNpWssTbg3PNf3uw7MuHDgym8uoW8aX496SxKXs7J0iTsFObcGRBfey8rShP1EXthSnDHhShJ0vM0H1uYiAKBSHWZqLYyDc+H7sSpeNlMX9l1jWWebEAgjgSxcbRRYB46YhCcVxH9bqDP3nbyUBB0XPk+Cjgnvj1qoqohvJqDtTUBdcGAmSzgIEQBM2R0fY/U41GPkwNpcTBKfmnDPNN4w4TOX+NnbfAQAWAKmXcMVAMgaNqrM1UfqkbMmrXkT/nGJO1XF4Xod8/0Ak4KcKzTe3AROjPs/AMdM2M8atk25a8IXAKYawTZZj5jNEvZN2TVldg3Ny/RfkYizALAFnByu819tzvCRWXKqTwAAAABJRU5ErkJggg==",
		onCreated(btn) {
			btn.setAttribute("image", this.image);
			var doc = btn.ownerDocument;

			btn.domParent = null;
			btn.popups = new btn.ownerGlobal.Array();
			this.createPopup(doc, btn, "primary", primary);
			this.createPopup(doc, btn, "secondary", secondary);

			btn.linkedObject = this;
			for(var type of ["command", "contextmenu"])
				btn.setAttribute("on" + type, `linkedObject.${type}(event)`);
		},
		createPopup(doc, btn, name, data) {
			var popup = doc.createElementNS(xul_ns, "menupopup");
			var prop = name + "Popup";
			btn.popups.push(btn[prop] = popup);
			popup.id = this.id + "-" + prop;
			popup.setAttribute("onpopupshowing", "parentNode.linkedObject.popupshowing(event.target)");
			for(var obj of data) popup.append(this.createElement(doc, obj));
			btn.append(popup);
		},
		createElement(doc, obj) {
			if (!obj) return doc.createElementNS(xul_ns, "menuseparator");
			var pref = doc.ownerGlobal.Object.create(null), node, img;
			for(var [key, val] of Object.entries(obj)) {
				if (key == "pref") {
					var [apref, lab, akey, ttt] = val;
					pref.pref = apref; pref.lab = lab || apref;
					if (akey) pref.key = akey;
					if (ttt) pref.ttt = ttt;
				}
				else if (key == "image") img = val;
				else if (key != "values") pref[key] = val;
			}
			var type = prefs.getPrefType(pref.pref);
			var pint = type == prefs.PREF_INT, inv = type == prefs.PREF_INVALID;
			if (inv && obj.values || pint || type == prefs.PREF_STRING) {
				node = doc.createElementNS(xul_ns, "menu");
				img && node.setAttribute("image", img);
				if (img || !pref.key) node.className = "menu-iconic"; // CE bug?
				node.append(doc.createElementNS(xul_ns, "menupopup"));
				pref.bool = false;
				var str = pint || (inv && typeof obj.values[0][0] == "number") ? "Int" : "String";
				pref.get = prefs[`get${str}Pref`];
				pref.set = prefs[`set${str}Pref`];
			} else {
				node = doc.createElementNS(xul_ns, "menuitem");
				node.setAttribute("type", "checkbox");
				pref.bool = true;
				pref.get = prefs.getBoolPref;
				pref.set = prefs.setBoolPref;
			}
			(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
			pref.key && node.setAttribute("accesskey", pref.key);
			pref.bool || this.createRadios(doc, obj.values, node.firstChild);
			return node;
		},
		upd(node) {
			var {pref} = node, def = false, user = false, val;
			if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
				var pn = pref.pref;
				try {val = db[pref.get.name](pn); def = true} catch(ex) {def = false;}
				var user = prefs.prefHasUserValue(pn);
				if (user) try {val = pref.get(pn, undefined);} catch(ex) {}
			}
			if (val == pref.val && def == pref.def && user == pref.user) return;
			pref.val = val; pref.def = def; pref.user = user;
			var exists = def || user;

			var ttt = exists ? val : "This preferences does not exist";
			if (ttt === "") ttt = "[ empty_string ]";
			if (pref.ttt) ttt += "\n" + pref.ttt;
			node.tooltipText = ttt;

			if (pref.bool) val
				? node.setAttribute("checked", true)
				: node.removeAttribute("checked");

			if ("userChoice" in pref) val == pref.userChoice
				? node.style.removeProperty("color")
				: node.style.setProperty("color", "maroon", "important")
			user
				? node.style.setProperty("font-weight", "bold", "important")
				: node.style.removeProperty("font-weight");

			var {lab} = pref;
			if (exists && !pref.bool) {
				if (val in pref.vals) var sfx = pref.vals[val] || val;
				else var sfx = user ? "Other" : "Default";
				lab += ` — "${sfx}"`;
			}
			node.setAttribute("label", lab);
		},
		createRadios(doc, vals, popup) {
			for(var arr of vals) {
				if (!arr) {
					popup.append(doc.createElementNS(xul_ns, "menuseparator"));
					continue;
				}
				var [val, lab, key, ttt] = arr;
				var menuitem = doc.createElementNS(xul_ns, "menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab);
				key && menuitem.setAttribute("accesskey", key);
				var tip = menuitem.val = val;
				if (ttt) tip += "\n" + ttt;
				menuitem.tooltipText = tip;
				popup.append(menuitem);
			}
		},
		openPopup(popup) {
			var btn = popup.parentNode;
			if (btn.domParent != btn.parentNode) {
				btn.domParent = btn.parentNode;
				var pos;
				if (btn.matches(".widget-overflow-list > :scope"))
					pos = "after_start";
				else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
					btn.closest("toolbar").getBoundingClientRect(), pos = width > height
						? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
						: `${win.innerWidth - right > left ? "end" : "start"}_before`;
				for(var p of btn.popups) p.setAttribute("position", pos);
			}
			popup.openPopup(btn);
		},
		maybeRestart(node, conf) {
			var msgRest = "Resart?", msgAbort = "The quit request has been canceled.";
			if (pv >= 77) {
				var title = node.closest("toolbarbutton").label;
				var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({
					domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW
				});
				var confirm = win => pp(win).confirm(title, msgRest);
				var alert = win => pp(win).alert(title, msgAbort);
			} else {
				var confirm = win => win.confirm(msgRest);
				var alert = win => win.alert(msgAbort);
			}
			return (this.mayBeRestart = (node, conf) => {
				var win = node.ownerGlobal;
				if (conf && !confirm(win)) return;
				if (win.BrowserUtils.restartApplication() === false) alert(win);
				else return true;
			})(node, conf);
		},
		regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
		maybeRe(node, cm) {
			var {pref} = node;
			if ("restart" in pref) {
				if (this.maybeRestart(node, pref.restart)) return;
			}
			else if (cm) node.ownerGlobal.closeMenus(node);
			if ("refresh" in pref) {
				var win = node.ownerGlobal;
				if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
					? win.BrowserReloadSkipCache() : win.BrowserReload();
			}
		},
		command(e) {
			var trg = e.target;
			if (trg.nodeName.startsWith("t"))
				return this.openPopup(trg.primaryPopup);

			var node = trg.closest("menu") || trg;
			var newVal = "pref" in trg ? !trg.pref.val : trg.val;
			if (newVal == node.pref.val) return;
			node.pref.set(node.pref.pref, newVal);
			this.maybeRe(node);
		},
		popupshowing(trg) {
			if (trg.id) {
				for(var node of trg.children)
					node.nodeName.endsWith("r") || this.upd(node);
				return;
			}
			var {val} = trg.closest("menu").pref;
			var checked = trg.querySelector("[checked]");
			if (checked) {
				if (checked.val == val) return;
				else checked.removeAttribute("checked");
			}
			for(var node of trg.children) if ("val" in node && node.val == val) {
				node.setAttribute("checked", true);
				break;
			}
		},
		contextmenu(e) {
			var trg = e.target;
			if (trg.nodeName.startsWith("t")) {
				if (e.ctrlKey || e.shiftKey) return;
				if (e.detail == 2) return trg.secondaryPopup.hidePopup();
				this.openPopup(trg.secondaryPopup);
			}
			else if ("pref" in trg && trg.pref.user)
				prefs.clearUserPref(trg.pref.pref),
				this.maybeRe(trg, true);
			e.preventDefault();
		}
	};
});

одним кликом на письме спама

Понятия не имею о чём речь.
Я просто не пользуюсь электронной почтой как таковой.

Отсутствует

 

№1497012-08-2020 12:31:43

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 78.0

Re: Custom Buttons

Dumby
Я проверил, в основном все работает.
   
Нельзя ли true-false в подменю (что бы все к единому стилю привести), и во всех подменю выделение НЕ дефолтных значений курсивом?
Что бы, заглянул в подменю и сразу понятно было, где дефолт, а где все остальное.  На мой взгляд так логичнее было бы.
   
А освободившееся место в корневом меню слева, которое под иконку, неплохо было бы использовать как индикатор userChoice.
(Я там видел цветовое выделение "maroon", но цвет у меня не работает.)

Отсутствует

 

№1497112-08-2020 14:47:07

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

Re: Custom Buttons

А есть такой код или Greasemonkey скрипт, который подсветит каждую русскую букву на странице ?
То есть выделит символы кириллицы цветом, отличным от фонового ?
В идеале надо выделять только слова, в которых есть и кириллица и латиница !
Так сделано в этом online-сервисе, но в нём проверяется только введённый текст, а не вся страница…

Причина: на форуме Arch-Linux тупо копировали код и он не работал из-за того, что в слове сonfig первая буква была русская…

Отредактировано Dobrov (13-08-2020 00:50:45)

Отсутствует

 

№1497212-08-2020 15:45:39

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

Re: Custom Buttons

Dumby по кнопке QuickSettings
А можно добавить действия на долгое нажатие кнопок мыши на кнопке QuickSettings ?
То есть удержание кнопок мыши более секунды…

Отсутствует

 

№1497313-08-2020 08:08:57

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

Re: Custom Buttons

_zt пишет

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

Если я ничего не упускаю, то для этого просто нет API, то есть
нет чего-то типа getDefaultPref(prefName) или isDefaultPref(prefName, prefValue)

Нельзя ли true-false в подменю (что бы все к единому стилю привести)
А освободившееся место в корневом меню слева, которое под иконку, неплохо было бы использовать как индикатор userChoice.
(Я там видел цветовое выделение "maroon", но цвет у меня не работает.)

Не работает "maroon" — значит, скорее всего, забито стилем, и тогда,
казалось бы, должно напрашиваться дописать в этот стиль что-то типа
menupopup[id^=QuickToggleAboutConfigSettings-] > [style*=maroon] > label {color: ...}


И, не совсем понятно про «индикатор userChoice», с одной стороны,
«освободившееся место» говорит о том, что нужен только для «true-false»,
с другой стороны, упомянут "maroon", а он применяется не только для «true-false».
Ладно, попробую так: если не задан "image" — значит индикатор, для всех.

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

Выделить код

Код:

...
	return {
		label: "Quick toggle",
		id: "QuickToggleAboutConfigSettings",
		localized: false,
		image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB6klEQVQ4jZWTv2tUQRDHv8ntd28GLLQQfwS5VkuDSgRF/wlRiIiCQQQhhZ1VII1/wDUWkkLTBAsbC0FJYZGQ3NuZRcHYW6UQEQzoeXkW791xXh5CptodZr8z85kd4BBWRJwDgB5wyoCjh3mLbfK8C/ddW11XJlduNgYaeTFpvJWA0+P+BBx3Cf2sLEy5m4WrS8A0AGANaBUSrgKAKzdcY5k0PF4HJGm47NK6nSUMXOIXAEgSrrnG0oU/AGDKNb6qHe9c+Ms1lqbxqws/uoTfWVp3ksRll/DTJM6bcMWEn1KbDysBCW+zsnSNpWssTbg3PNf3uw7MuHDgym8uoW8aX496SxKXs7J0iTsFObcGRBfey8rShP1EXthSnDHhShJ0vM0H1uYiAKBSHWZqLYyDc+H7sSpeNlMX9l1jWWebEAgjgSxcbRRYB46YhCcVxH9bqDP3nbyUBB0XPk+Cjgnvj1qoqohvJqDtTUBdcGAmSzgIEQBM2R0fY/U41GPkwNpcTBKfmnDPNN4w4TOX+NnbfAQAWAKmXcMVAMgaNqrM1UfqkbMmrXkT/nGJO1XF4Xod8/0Ak4KcKzTe3AROjPs/AMdM2M8atk25a8IXAKYawTZZj5jNEvZN2TVldg3Ny/RfkYizALAFnByu819tzvCRWXKqTwAAAABJRU5ErkJggg==",
		onCreated(btn) {
			btn.setAttribute("image", this.image);
			var doc = btn.ownerDocument;

			btn.btn = true;
			btn.domParent = null;
			btn.popups = new btn.ownerGlobal.Array();
			this.createPopup(doc, btn, "primary", primary);
			this.createPopup(doc, btn, "secondary", secondary);

			btn.linkedObject = this;
			for(var type of ["command", "contextmenu"])
				btn.setAttribute("on" + type, `linkedObject.${type}(event)`);
		},
		createPopup(doc, btn, name, data) {
			var popup = doc.createElementNS(xul_ns, "menupopup");
			var prop = name + "Popup";
			btn.popups.push(btn[prop] = popup);
			popup.id = this.id + "-" + prop;
			popup.setAttribute("onpopupshowing", "parentNode.linkedObject.popupshowing(event)");
			for(var obj of data) popup.append(this.createElement(doc, obj));
			btn.append(popup);
		},
		createElement(doc, obj) {
			if (!obj) return doc.createElementNS(xul_ns, "menuseparator");
			var pref = doc.ownerGlobal.Object.create(null), node, img;
			for(var [key, val] of Object.entries(obj)) {
				if (key == "pref") {
					var [apref, lab, akey, ttt] = val;
					pref.pref = apref; pref.lab = lab || apref;
					if (ttt) pref.ttt = ttt;
				}
				else if (key == "image") img = val, pref.img = true;
				else if (key != "values") pref[key] = val;
			}
			var type = prefs.getPrefType(pref.pref), str, bool;
			var pint = type == prefs.PREF_INT, inv = type == prefs.PREF_INVALID;
			if (inv && obj.values || pint || type == prefs.PREF_STRING)
				str = pint || (inv && typeof obj.values[0][0] == "number") ? "Int" : "String",
				pref.bool = false;
			else
				str = "Bool", pref.bool = true;
			pref.get = prefs[`get${str}Pref`];
			pref.set = prefs[`set${str}Pref`];

			node = doc.createElementNS(xul_ns, "menu");
			node.className = "menu-iconic";
			node.setAttribute("closemenu", "none");
			img && node.setAttribute("image", img);
			akey && node.setAttribute("accesskey", akey);
			(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
			this.createRadios(doc,
				pref.bool ? [[true, "true"], [false, "false"]] : obj.values,
				node.appendChild(doc.createElementNS(xul_ns, "menupopup"))
			);
			return node;
		},
		notUserChoiceImg: "chrome://browser/content/robot.ico",
		upd(node) {
			var {pref} = node, def = false, user = false, val;
			if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
				var pn = pref.pref;
				try {val = db[pref.get.name](pn); def = true} catch(ex) {def = false;}
				var user = prefs.prefHasUserValue(pn);
				if (user) try {val = pref.get(pn, undefined);} catch(ex) {}
			}
			if (val == pref.val && def == pref.def && user == pref.user) return;
			pref.val = val; pref.def = def; pref.user = user;
			var exists = def || user;

			var ttt = exists ? val : "This preferences does not exist";
			if (ttt === "") ttt = "[ empty_string ]";
			if (pref.ttt) ttt += "\n" + pref.ttt;
			node.tooltipText = ttt;

			if ("userChoice" in pref)
				if (val == pref.userChoice)
					node.style.removeProperty("color"),
					pref.img || node.removeAttribute("image");
				else
					node.style.setProperty("color", "maroon", "important"),
					pref.img || node.setAttribute("image", this.notUserChoiceImg);
			user
				? node.style.setProperty("font-weight", "bold", "important")
				: node.style.removeProperty("font-weight");

			var {lab} = pref;
			if (exists && !pref.bool) {
				if (val in pref.vals) var sfx = pref.vals[val] || val;
				else var sfx = user ? "Other" : "Default";
				lab += ` — "${sfx}"`;
			}
			node.setAttribute("label", lab);
		},
		createRadios(doc, vals, popup) {
			for(var arr of vals) {
				if (!arr) {
					popup.append(doc.createElementNS(xul_ns, "menuseparator"));
					continue;
				}
				var [val, lab, key, ttt] = arr;
				var menuitem = doc.createElementNS(xul_ns, "menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("closemenu", "none");
				menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab);
				key && menuitem.setAttribute("accesskey", key);
				var tip = menuitem.val = val;
				if (ttt) tip += "\n" + ttt;
				menuitem.tooltipText = tip;
				popup.append(menuitem);
			}
		},
		openPopup(popup) {
			var btn = popup.parentNode;
			if (btn.domParent != btn.parentNode) {
				btn.domParent = btn.parentNode;
				var pos;
				if (btn.matches(".widget-overflow-list > :scope"))
					pos = "after_start";
				else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
					btn.closest("toolbar").getBoundingClientRect(), pos = width > height
						? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
						: `${win.innerWidth - right > left ? "end" : "start"}_before`;
				for(var p of btn.popups) p.setAttribute("position", pos);
			}
			popup.openPopup(btn);
		},
		maybeRestart(node, conf) {
			var msgRest = "Resart?", msgAbort = "The quit request has been canceled.";
			if (pv >= 77) {
				var title = node.closest("toolbarbutton").label;
				var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({
					domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW
				});
				var confirm = win => pp(win).confirm(title, msgRest);
				var alert = win => pp(win).alert(title, msgAbort);
			} else {
				var confirm = win => win.confirm(msgRest);
				var alert = win => win.alert(msgAbort);
			}
			return (this.mayBeRestart = (node, conf) => {
				var win = node.ownerGlobal;
				if (conf && !confirm(win)) return;
				if (win.BrowserUtils.restartApplication() === false) alert(win);
				else return true;
			})(node, conf);
		},
		regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
		maybeRe(node, fe) {
			var {pref} = node;
			if ("restart" in pref) {
				if (this.maybeRestart(node, pref.restart)) return;
			}
			else this.popupshowing(fe, node.parentNode);
			if ("refresh" in pref) {
				var win = node.ownerGlobal;
				if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
					? win.BrowserReloadSkipCache() : win.BrowserReload();
			}
		},
		command(e) {
			var trg = e.target;
			if (trg.btn) return this.openPopup(trg.primaryPopup);

			var menu = trg.closest("menu"), newVal = trg.val;
			if (newVal != menu.pref.val)
				menu.pref.set(menu.pref.pref, newVal),
				this.maybeRe(menu, true);
		},
		popupshowing(e, trg = e.target) {
			if (trg.id) {
				for(var node of trg.children) {
					if (node.nodeName.endsWith("r")) continue;
					this.upd(node);
					!e && node.open && this.popupshowing(null, node.querySelector("menupopup"));
				}
				return;
			}
			var {val} = trg.closest("menu").pref;
			var checked = trg.querySelector("[checked]");
			if (checked) {
				if (checked.val == val) return;
				else checked.removeAttribute("checked");
			}
			for(var node of trg.children) if ("val" in node && node.val == val) {
				node.setAttribute("checked", true);
				break;
			}
		},
		contextmenu(e) {
			var trg = e.target;
			if (trg.btn) {
				if (e.ctrlKey || e.shiftKey) return;
				if (e.detail == 2) return trg.secondaryPopup.hidePopup();
				this.openPopup(trg.secondaryPopup);
			}
			else if ("pref" in trg && trg.pref.user)
				prefs.clearUserPref(trg.pref.pref),
				this.maybeRe(trg);
			e.preventDefault();
		}
	};
});

Dobrov пишет

А можно добавить действия на долгое нажатие кнопок мыши на кнопке QuickSettings ?
То есть удержание кнопок мыши более секунды…

Ууу, это довольно мозголомно, ещё глюков каких-нибудь завезу.
Ну рискни. Метод londPress там в конце, просто запись в консоль и алерт.

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

Выделить код

Код:

...
	return {
		label: "Quick toggle",
		id: "QuickToggleAboutConfigSettings",
		localized: false,
		image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB6klEQVQ4jZWTv2tUQRDHv8ntd28GLLQQfwS5VkuDSgRF/wlRiIiCQQQhhZ1VII1/wDUWkkLTBAsbC0FJYZGQ3NuZRcHYW6UQEQzoeXkW791xXh5CptodZr8z85kd4BBWRJwDgB5wyoCjh3mLbfK8C/ddW11XJlduNgYaeTFpvJWA0+P+BBx3Cf2sLEy5m4WrS8A0AGANaBUSrgKAKzdcY5k0PF4HJGm47NK6nSUMXOIXAEgSrrnG0oU/AGDKNb6qHe9c+Ms1lqbxqws/uoTfWVp3ksRll/DTJM6bcMWEn1KbDysBCW+zsnSNpWssTbg3PNf3uw7MuHDgym8uoW8aX496SxKXs7J0iTsFObcGRBfey8rShP1EXthSnDHhShJ0vM0H1uYiAKBSHWZqLYyDc+H7sSpeNlMX9l1jWWebEAgjgSxcbRRYB46YhCcVxH9bqDP3nbyUBB0XPk+Cjgnvj1qoqohvJqDtTUBdcGAmSzgIEQBM2R0fY/U41GPkwNpcTBKfmnDPNN4w4TOX+NnbfAQAWAKmXcMVAMgaNqrM1UfqkbMmrXkT/nGJO1XF4Xod8/0Ak4KcKzTe3AROjPs/AMdM2M8atk25a8IXAKYawTZZj5jNEvZN2TVldg3Ny/RfkYizALAFnByu819tzvCRWXKqTwAAAABJRU5ErkJggg==",
		onCreated(btn) {
			btn.setAttribute("image", this.image);
			var doc = btn.ownerDocument;

			btn.btn = true;
			btn.domParent = null;
			btn.popups = new btn.ownerGlobal.Array();
			this.createPopup(doc, btn, "primary", primary);
			this.createPopup(doc, btn, "secondary", secondary);

			btn.linkedObject = this;
			for(var type of ["command", "contextmenu", "mousedown"])
				btn.setAttribute("on" + type, `linkedObject.${type}(event)`);
		},
		createPopup(doc, btn, name, data) {
			var popup = doc.createElementNS(xul_ns, "menupopup");
			var prop = name + "Popup";
			btn.popups.push(btn[prop] = popup);
			popup.id = this.id + "-" + prop;
			popup.setAttribute("onpopupshowing", "parentNode.linkedObject.popupshowing(event.target)");
			for(var obj of data) popup.append(this.createElement(doc, obj));
			btn.append(popup);
		},
		createElement(doc, obj) {
			if (!obj) return doc.createElementNS(xul_ns, "menuseparator");
			var pref = doc.ownerGlobal.Object.create(null), node, img;
			for(var [key, val] of Object.entries(obj)) {
				if (key == "pref") {
					var [apref, lab, akey, ttt] = val;
					pref.pref = apref; pref.lab = lab || apref;
					if (akey) pref.key = akey;
					if (ttt) pref.ttt = ttt;
				}
				else if (key == "image") img = val;
				else if (key != "values") pref[key] = val;
			}
			var type = prefs.getPrefType(pref.pref);
			var pint = type == prefs.PREF_INT, inv = type == prefs.PREF_INVALID;
			if (inv && obj.values || pint || type == prefs.PREF_STRING) {
				node = doc.createElementNS(xul_ns, "menu");
				img && node.setAttribute("image", img);
				if (img || !pref.key) node.className = "menu-iconic"; // CE bug?
				node.append(doc.createElementNS(xul_ns, "menupopup"));
				pref.bool = false;
				var str = pint || (inv && typeof obj.values[0][0] == "number") ? "Int" : "String";
				pref.get = prefs[`get${str}Pref`];
				pref.set = prefs[`set${str}Pref`];
			} else {
				node = doc.createElementNS(xul_ns, "menuitem");
				node.setAttribute("type", "checkbox");
				pref.bool = true;
				pref.get = prefs.getBoolPref;
				pref.set = prefs.setBoolPref;
			}
			(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
			pref.key && node.setAttribute("accesskey", pref.key);
			pref.bool || this.createRadios(doc, obj.values, node.firstChild);
			return node;
		},
		upd(node) {
			var {pref} = node, def = false, user = false, val;
			if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
				var pn = pref.pref;
				try {val = db[pref.get.name](pn); def = true} catch(ex) {def = false;}
				var user = prefs.prefHasUserValue(pn);
				if (user) try {val = pref.get(pn, undefined);} catch(ex) {}
			}
			if (val == pref.val && def == pref.def && user == pref.user) return;
			pref.val = val; pref.def = def; pref.user = user;
			var exists = def || user;

			var ttt = exists ? val : "This preferences does not exist";
			if (ttt === "") ttt = "[ empty_string ]";
			if (pref.ttt) ttt += "\n" + pref.ttt;
			node.tooltipText = ttt;

			if (pref.bool) val
				? node.setAttribute("checked", true)
				: node.removeAttribute("checked");

			if ("userChoice" in pref) val == pref.userChoice
				? node.style.removeProperty("color")
				: node.style.setProperty("color", "maroon", "important")
			user
				? node.style.setProperty("font-weight", "bold", "important")
				: node.style.removeProperty("font-weight");

			var {lab} = pref;
			if (exists && !pref.bool) {
				if (val in pref.vals) var sfx = pref.vals[val] || val;
				else var sfx = user ? "Other" : "Default";
				lab += ` — "${sfx}"`;
			}
			node.setAttribute("label", lab);
		},
		createRadios(doc, vals, popup) {
			for(var arr of vals) {
				if (!arr) {
					popup.append(doc.createElementNS(xul_ns, "menuseparator"));
					continue;
				}
				var [val, lab, key, ttt] = arr;
				var menuitem = doc.createElementNS(xul_ns, "menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab);
				key && menuitem.setAttribute("accesskey", key);
				var tip = menuitem.val = val;
				if (ttt) tip += "\n" + ttt;
				menuitem.tooltipText = tip;
				popup.append(menuitem);
			}
		},
		openPopup(popup) {
			var btn = popup.parentNode;
			if (btn.domParent != btn.parentNode) {
				btn.domParent = btn.parentNode;
				var pos;
				if (btn.matches(".widget-overflow-list > :scope"))
					pos = "after_start";
				else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
					btn.closest("toolbar").getBoundingClientRect(), pos = width > height
						? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
						: `${win.innerWidth - right > left ? "end" : "start"}_before`;
				for(var p of btn.popups) p.setAttribute("position", pos);
			}
			popup.openPopup(btn);
		},
		maybeRestart(node, conf) {
			var msgRest = "Resart?", msgAbort = "The quit request has been canceled.";
			if (pv >= 77) {
				var title = node.closest("toolbarbutton").label;
				var pp = domWin => Services.prompt.wrappedJSObject.pickPrompter({
					domWin, modalType: Ci.nsIPrompt.MODAL_TYPE_WINDOW
				});
				var confirm = win => pp(win).confirm(title, msgRest);
				var alert = win => pp(win).alert(title, msgAbort);
			} else {
				var confirm = win => win.confirm(msgRest);
				var alert = win => win.alert(msgAbort);
			}
			return (this.mayBeRestart = (node, conf) => {
				var win = node.ownerGlobal;
				if (conf && !confirm(win)) return;
				if (win.BrowserUtils.restartApplication() === false) alert(win);
				else return true;
			})(node, conf);
		},
		regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
		maybeRe(node, cm) {
			var {pref} = node;
			if ("restart" in pref) {
				if (this.maybeRestart(node, pref.restart)) return;
			}
			else if (cm) node.ownerGlobal.closeMenus(node);
			if ("refresh" in pref) {
				var win = node.ownerGlobal;
				if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
					? win.BrowserReloadSkipCache() : win.BrowserReload();
			}
		},
		command(e) {
			var trg = e.target;
			if (trg.btn) return this.openPopup(trg.primaryPopup);

			var node = trg.closest("menu") || trg;
			var newVal = "pref" in trg ? !trg.pref.val : trg.val;
			if (newVal == node.pref.val) return;
			node.pref.set(node.pref.pref, newVal);
			this.maybeRe(node);
		},
		popupshowing(trg) {
			if (trg.id) {
				for(var node of trg.children)
					node.nodeName.endsWith("r") || this.upd(node);
				return;
			}
			var {val} = trg.closest("menu").pref;
			var checked = trg.querySelector("[checked]");
			if (checked) {
				if (checked.val == val) return;
				else checked.removeAttribute("checked");
			}
			for(var node of trg.children) if ("val" in node && node.val == val) {
				node.setAttribute("checked", true);
				break;
			}
		},
		contextmenu(e) {
			var trg = e.target;
			if (trg.btn) {
				if (e.ctrlKey || e.shiftKey) return;
				if (e.detail == 2) return trg.secondaryPopup.hidePopup();
				this.openPopup(trg.secondaryPopup);
			}
			else if ("pref" in trg && trg.pref.user)
				prefs.clearUserPref(trg.pref.pref),
				this.maybeRe(trg, true);
			e.preventDefault();
		},
		mousedown(e) {
			var reset = e => e.target.linkedObject = this;
			var id, lo = {command: reset, mousedown: reset};

			var lin = e.view.AppConstants.platform == "linux";
			var stop = e => reset(e) && e.preventDefault();

			lo.contextmenu = lin
				? e => e.ctrlKey || e.shiftKey ? dsp(e) : stop(e) : stop;
			var context = lin
				? e => e.button == 2 && e.type.endsWith("p") && this.contextmenu(e) : () => {};

			var dsp = (e, timeout) => {
				var trg = e.target;
				trg.onmouseup = trg.onmouseleave = null;
				if (timeout) return this.londPress(e);
				e.view.clearTimeout(id);
				reset(e);
				context(e);
			}
			(this.mousedown = e => {
				var trg = e.target;
				if (!trg.btn) return;
				trg.linkedObject = lo;
				trg.onmouseup = trg.onmouseleave = dsp;
				id = e.view.setTimeout(dsp, 1001, e, true);
			})(e);
		},
		londPress(e) {
			var msg = "QuickSettings\nLONG PRESS: e.button = " + e.button;
			Components.utils.reportError(msg);
			e.view.alert(msg);
		}
	};
});

Отсутствует

 

№1497413-08-2020 10:12:22

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

Re: Custom Buttons

Dumby
приветствую,
А можно сделать так, чтобы при нажатии кнопки -  открывался  нужный сайт и уже потом сохранялась страница?
спасибо

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
    suc.charset = "utf-8";
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "Save_snapshot_to_html_alert";
    var file, id, obs = (s, topic) => {switch(topic) {
        case "alertshow": id = setTimeout(as.closeAlert, 5e3, alertName); break;
        case "alertfinished": id = file = null; break;
        case "alertclickcallback": clearTimeout(id);
            gBrowser.selectedTab = gBrowser.addTab(Services.io.newFileURI(file).spec);
    }};
    var notify = as.showAlertNotification.bind(
        as, null, "Страница сохранена на Рабочем столе", null, true, null, obs, alertName
    );
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
    return (html, name) => {
        file = desk.clone();
        file.append(name);
        html = suc.ConvertFromUnicode(html);
        var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
        stream.write(html, html.length);
        stream.close();
        notify();
    }
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

var resolveURL = function (url, base) {
    try {
        var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
        var baseURI = ioService.newURI(base, null, null);
        var absURI = ioService.newURI(url, null, baseURI);
        return absURI.spec;
    } catch (e) {}
};

var getSelWin = function (w) {
    if (w.getSelection().toString()) return w;
    for (var i = 0, f, r; f = w.frames[i]; i++) {
        try {
            if (r = getSelWin(f)) return r;
        } catch(e) {}
    }
};
var encodeImg = function (src, obj) {
    var canvas, img, ret = src;
    if (/^https?:\/\//.test(src)) {
        canvas = doc.createElement('canvas');
        if (!obj || obj.nodeName.toLowerCase() != 'img') {
            img = doc.createElement('img');
            img.src = src;
        } else {
            img = obj;
        };
        if (img.complete) try{
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.getContext('2d').drawImage(img, 0, 0);
            ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png'));
        } catch (e) {};
        if (img != obj) img.src = 'about:blank';
    };
    return ret;
};
var toSrc = function (obj) {
    var strToSrc = function (str) {
        var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
        while (chr = str.charAt(i++)) {
            ret += meta[chr] || chr;
        };
        return '\x22' + ret + '\x22';
    },
    arrToSrc = function (arr) {
        var ret = [];
        for (var i = 0; i < arr.length; i++) {
            ret[i] = toSrc(arr[i]) || 'null';
        };
        return '[' + ret.join(',') + ']';
    },
    objToSrc = function (obj) {
        var val, ret = [];
        for (var prop in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, prop) && (val = toSrc(obj[prop]))) ret.push(strToSrc(prop) + ': ' + val);
        };
        return '{' + ret.join(',') + '}';
    };

    switch (Object.prototype.toString.call(obj).slice(8, -1)) {
        case 'Array': return arrToSrc(obj);
        case 'Boolean':
        case 'Function':
        case 'RegExp': return obj.toString();
        case 'Date': return 'new Date(' + obj.getTime() + ')';
        case 'Math': return 'Math';
        case 'Number': return isFinite(obj) ? String(obj) : 'null';
        case 'Object': return objToSrc(obj);
        case 'String': return strToSrc(obj);
        default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
    }
};

var mainWin = document.commandDispatcher.focusedWindow.top == content ? document.commandDispatcher.focusedWindow : content;
var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g;

if (selWin) {
    var rng = win.getSelection().getRangeAt(0);
    pEle = rng.commonAncestorContainer;
    ele = rng.cloneContents();
} else {
    pEle = doc.documentElement;
    ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true);
};
while (pEle) {
    if (pEle.nodeType == 1) {
        clone = pEle.cloneNode(false);
        clone.appendChild(ele);
        ele = clone;
    };
    pEle = pEle.parentNode
};
var sel = doc.createElement('div');
sel.appendChild(ele);

for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) {
    el = all[i];
    if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) {
        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
        return prev + encodeImg(url) + next;
    });
    switch (el.nodeName.toLowerCase()) {
        case 'link':
        case 'style':
        case 'script': el.parentNode.removeChild(el); break;
        case 'a': 
        case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break;
        case 'img':
        case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break;
        case 'audio':
        case 'video':
        case 'embed':
        case 'frame':
        case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break;
        case 'object': if (el.hasAttribute('data')) el.data = el.data; break;
        case 'form': if (el.hasAttribute('action')) el.action = el.action; break;
    }
};

var head = ele.insertBefore(doc.createElement('head'), ele.firstChild);
var meta = doc.createElement('meta');
meta.httpEquiv = 'content-type';
meta.content = 'text/html; charset=utf-8';
head.appendChild(meta);
var title = doc.getElementsByTagName('title')[0];
if (title) head.appendChild(title.cloneNode(true));

head.copyScript = function (unsafeWin) {
    if ('$' in unsafeWin) return;
    var f = doc.createElement('iframe');
    f.src = 'about:blank';
    f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');
    doc.documentElement.appendChild(f);
    var str, script = doc.createElement('script');
    script.type = 'text/javascript';
    for (var name in unsafeWin) {
        if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
        try {
            str = toSrc(unsafeWin[name]);
            if (!/\{\s*\[native code\]\s*\}/.test(str)) {
                script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
            }
        } catch (e) {};
    };
    f.parentNode.removeChild(f);
    if (script.childNodes.length) this.nextSibling.appendChild(script);
};
head.copyScript(win.wrappedJSObject || win);

head.copyStyle = function (s) {
    if (!s) return;
    var style = doc.createElement('style');
    style.type = 'text/css';
    if (s.media && s.media.mediaText) style.media = s.media.mediaText;
    try {
        for (var i = 0, rule; rule = s.cssRules[i]; i++) {
            if (rule.type != 3) {
                if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) {
                    var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
                        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
                        if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
                        return prev + url + next;
                    });
                    style.appendChild(doc.createTextNode(css + '\n'));
                }
            } else {
                this.copyStyle(rule.styleSheet);
            }
        }
    } catch(e) {
        if (s.ownerNode) style = s.ownerNode.cloneNode(false);
    };
    this.appendChild(style);
};
var sheets = doc.styleSheets;
for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]);
head.appendChild(doc.createTextNode('\n'));

var doctype = '', dt = doc.doctype;
if (dt && dt.name) {
    doctype += '<!DOCTYPE ' + dt.name;
    if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
    if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
    doctype += '>\n';
};
var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');
fileName += ("  " + new Date().toLocaleFormat("%d.%m.%Y. %H-%M-%S"));
if(!/\.html?$/.test(fileName))fileName += '.html';

saveToFile(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName);

пробовал в начало кода добавлять это:
gBrowser.selectedTab = gBrowser.addTab('http://site.ru');
Не работает)

Отсутствует

 

№1497513-08-2020 12:09:24

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

Re: Custom Buttons

Dumby - какой код QuickSettings самый актуальный ?
Я посмотрел, во втором коде для _zt , где метод londPress, тоже есть установка иконок для пунктов меню.
Хотелось бы совместить оба варианта - для _zt и для меня с методом londPress, они почему-то сильно различаются…
P.S. надо наверное выделить для кнопки отдельный пост ?


Dumby пишет

не совсем понятно про «индикатор userChoice», с одной стороны,«освободившееся место» говорит о том, что нужен только для «true-false»,с другой стороны, упомянут "maroon", а он применяется не только для «true-false»

если значение в userChoice совпадает с текущим в about:config, то пункту меню будет со стилем bold (но наверное вопрос был не про стиль?)


Dumby пишет

Ууу, это довольно мозголомно, ещё глюков каких-нибудь завезу.Ну рискни. Метод londPress там в конце, просто запись в консоль и алерт

Спасибо, в моём коде londPress тоже был, но через некоторое время начинал срабатывать как двойной клик.

Отредактировано Dobrov (13-08-2020 12:19:54)

Отсутствует

 

Board footer

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