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

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

№7626-08-2019 20:23:23

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin
Я обычно и в других темах тоже вижу, просто не всегда есть время на осмысленные ответы.

Andrey_Krropotkin пишет

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

На удивление не все еще отломали. У меня было опасение, что дублирование command/oncommand (от загружаемого оверлея в старых версиях и дописанное вручную) может привести к дублирующейся отработке команд, но, вроде (как минимум, в Firefox 52 и 56), работает нормально.
Добавил, спасибо: https://github.com/Infocatcher/Custom_B … a2ec1e4d2d

Заодно оживил в новых версиях: https://github.com/Infocatcher/Custom_B … fd057a0614


Andrey_Krropotkin пишет

Не решенным осталось еще, что не работает кнопка "Внешний редактор", вообще не как не реагирует.
Может Вы все таки посмотрите, ну просто без кнопки, такое чувство, что что-то не хватает.

Я не пользуюсь... В самых новых – и вовсе редактирование поломало, я открытием во вкладке спасаюсь. Dumby, насколько я помню, тоже говорил, что не пользуется...


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№7726-08-2019 21:44:51

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

Re: [CB]Attributes Inspector (для разработчиков)

Да-да, не пользуюсь, и Source Editor'ом тоже.
Не потому, что нехорош, а просто не пользуюсь.

Открытие внешнего редактора показалось мне
настолько простым, что думал Андрей подкумекает
это если не в тот же день, то на следующий.
Я просто дописал в начало метода initWindow()

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


И, ещё «See also» нарисовался:
Bug 1566457 - Loaders summer cleanup
То есть, предположительно, так
скрытый текст


Выделить код

Код:

            window.edit_button = function edit_button() {
                var panel = document.getElementById(
                    "custombuttons-editbutton-tabbox"
                ).tabpanels.selectedPanel;
                if (/sourceEditor-(.+)/.test(panel.id))
                    panel = document.getElementById(RegExp.$1);
                if (panel.localName == "cbeditor")
                    window.edittarget(panel);
            }

Отсутствует

 

№7826-08-2019 22:00:21

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

Re: [CB]Attributes Inspector (для разработчиков)

Infocatcher и Dumby спасибо и вот еще по этому коду вопрос (может только у меня - не знаю): неправильно работает выделение в URL кнопки, Имя, Изображение. Текст мышкой не выделяется (или как у меня двойной дубль-клик), но если нажать в контекстном меню после этого копировать или выделить все и копировать, то текст нормально копируется (т.е. не видно полосы выделения текста).

Отредактировано Andrey_Krropotkin (26-08-2019 22:11:56)

Отсутствует

 

№7927-08-2019 18:44:46

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

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

(может только у меня - не знаю)

Подтвержаю, у меня на Win7 выделенное там тоже не подсвечивается фоном.
И, я тебе в начало метода initWindow() добавить посоветовал,
нет, в конец, конечно же.

Выделение можно стилем задать, а кодом — ничего лучше не придумал,
тоже в конец метода initWindow()

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


Выделить код

Код:

            if(this.platformVersion >= 68) (function(events, win) {
                var listener = function(e) {
                    if(e.type == "unload") return destroy();
                    var sheets = win.document.styleSheets;
                    for(var ind = sheets.length - 1; ind; ind--) {
                        var sheet = sheets.item(ind);
                        if(sheet.href != "resource://devtools/client/themes/common.css")
                            continue;
                        destroy();
                        for(let ind = 0, len = sheet.cssRules.length; ind < len; ind++) {
                            var rule = sheet.cssRules.item(ind);
                            if(rule.selectorText && rule.selectorText == "::selection")
                                return sheet.deleteRule(ind);
                        }
                    }
                }
                var destroy = function() {
                    events.forEach(function(type) {
                        win.removeEventListener(type, listener, false);
                    });
                }
                events.forEach(function(type) {
                    win.addEventListener(type, listener, false);
                });
            })(["mousedown", "keydown", "unload"], window);

Отсутствует

 

№8027-08-2019 20:44:40

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

Re: [CB]Attributes Inspector (для разработчиков)

Dumby спасибо, теперь вообще комфортнее стало.

Отсутствует

 

№8113-09-2019 20:21:55

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

Re: [CB]Attributes Inspector (для разработчиков)

Dumby есть ещё маленький такой момент, у Infocatcher есть ещё кнопка редактировать во вкладке, при совместной работе с  Source Editor-ом на 68 проблем не было, и в редакторе и во вкладке все было одинаково, на 69, Source Editor работает только в редакторе, а во вкладке как обычно, т. е. Source Editor не применяется, посмотри пожалуйста. В какой из этих двух кнопках где-то неисправность не знаю.

Отсутствует

 

№8214-09-2019 12:42:52

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

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

В какой из этих двух кнопках где-то неисправность не знаю.

В коде Source Editor'а поиск:
isBrowserWindow: function(window) {

Как только увидишь — всё сразу станет ясно.

Отсутствует

 

№8314-09-2019 13:27:08

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

Re: [CB]Attributes Inspector (для разработчиков)

Dumby спасибо, слона и не заметил, заменил, все работает.

Отсутствует

 

№8430-11-2019 15:35:28

Garalf
Участник
 
Группа: Members
Зарегистрирован: 19-09-2017
Сообщений: 235
UA: Firefox 72.0

Re: [CB]Attributes Inspector (для разработчиков)

В 71 перестал работать, также как и dom inspector

Отредактировано Garalf (30-11-2019 15:38:30)

Отсутствует

 

№8506-12-2019 20:37:57

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Garalf пишет

В 71 перестал работать, также как и dom inspector

DOM Inspector и правда снова отвалился...
А вот Attributes Inspector, на первый взгляд, живой:

ntiWJv7.png

mqUnF2d.png

Что конкретно не работает и что пишет в консоль (Ctrl+Shift+J)?


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№8606-12-2019 21:08:09

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

Re: [CB]Attributes Inspector (для разработчиков)

Garalf пишет

В 71 перестал работать

В [firefox] 71 работает!

Отредактировано kokoss (06-12-2019 21:09:10)

Отсутствует

 

№8706-12-2019 22:24:58

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

Re: [CB]Attributes Inspector (для разработчиков)

Да и в 73, на данный момент, работает.

А DOMi, ну давайте попробую скинуть.

DOMi-7.0.{4a1-5}-fx.js


Выделить код

Код:

// DOMi-7.0.{4a1-5}-fx.js
(async re => {
    var gzip = "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";

    var sel = "Select";
    try {sel = Services.strings.createBundle("chrome://global/locale/commonDialogs.properties")
        .GetStringFromName(sel);} catch(ex) {}
    var picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
    picker.init(window, sel + " DOMi 7.0.4a1", picker.modeOpen);
    picker.appendFilter(null, "dom_inspector-7.0.4a1-fx-*.xpi");
    await new Promise(resolve => picker.open(resolve));
    var {file} = picker; if (!file) return;
    var ln = file.leafName;
    if (!re.test(ln)) return alert("???\n" + ln);
    var {fileURL} = picker;

    var xpi = file.parent.clone();
    xpi.append(ln = ln.replace("4a1-", "5-"));
    file.copyTo(file.parent, ln);

    var obs = {}, data;
    var td = new TextDecoder(), te = new TextEncoder();
    var scs = Cc["@mozilla.org/streamConverters;1"].getService(Ci.nsIStreamConverterService);
    var sis = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
    var sl =  Cc["@mozilla.org/network/stream-loader;1"].createInstance(Ci.nsIStreamLoader);

    sis.data = atob(gzip);
    obs.onStreamComplete = (a, b, c, d, result) => data = td.decode(new Uint8Array(result));
    sl.init(obs);
    var converter = scs.asyncConvertData("gzip", "uncompressed", sl, null);

    converter.onStartRequest(null, null);
    var args = [null, null, sis, 0, sis.data.length];
    if (converter.onDataAvailable.length == 4) args.shift();
    converter.onDataAvailable(...args);
    converter.onStopRequest(null, null, null);

    var zw = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
    var mt = Date.now() * 1000, cp = zw.COMPRESSION_DEFAULT;
    var bootstrap = ln.includes("bootstrap");
    var prefix = "jar:" + fileURL.spec + "!/";
    var lr = /^¦(?:\d+)?$/, sep1 = "£", sep2 = "¥";

    zw.open(xpi, 0x04); // PR_RDWR
    for(var item of data.split(sep1)) {
        var [entry, val] = item.split(sep2);
        if (bootstrap && (entry == "manifest.json" || entry == "startup.jsm")) continue;
        if (val == "+") {
            zw.addEntryDirectory(entry, mt, false); continue;
        }
        if (zw.hasEntry(entry)) {
            if (val.includes("¦")) {
                var lines = val.split("\n");
                var oldLines = (await (await fetch(prefix + entry)).text()).split("\n");

                lines.forEach((line, ind) => {
                    if (lr.test(line)) lines[ind] = oldLines[
                        line.length == 1 ? ind : +line.slice(1)
                    ];
                });
                val = lines.join("\n");
            }
            zw.removeEntry(entry, false);
            if (val == "-") continue;
        }
        var stream = Cc["@mozilla.org/io/string-input-stream;1"]
            .createInstance(Ci.nsISupportsCString);
        stream.data = String.fromCharCode(...new Uint8Array(te.encode(val)));
        zw.addEntryStream(entry, mt, cp, stream, false);
        stream.close();
    }
    zw.close(); xpi.reveal();
})(
    /^dom_inspector-7\.0\.4a1-fx-(?:paxmod|bootstrap)\.xpi$/
);

Отсутствует

 

№8816-12-2019 11:59:38

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

Re: [CB]Attributes Inspector (для разработчиков)

Infocatcher, Dumby в кнопке для 71 версии

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


Выдает
скрытый текст
TypeError: btn is null button.js:187:4
destroyWindow chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button58@init line 1 > Function:187
    observe chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button58@init line 1 > Function:205

В кнопке
скрытый текст


при редактировании во вкладке выдает
скрытый текст
ecurityError: The operation is insecure. button.js:219
    initWindow chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button57@init line 1 > Function:219
    handleEvent chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button57@init line 1 > Function:835

Просто при редактировании работает, но выдает
SecurityError: The operation is insecure. button.js:219
    initWindow chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button57@init line 1 > Function:219
    handleEvent chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button57@init line 1 > Function:835
И последннее в кнопке
скрытый текст


не создается кнопка рядом с текущей
Не могли бы Вы глянуть?

Выделить код

Код:

// https://github.com/Infocatcher/Custom_Buttons/tree/master/CB_Editor_Toggle_on_Top
// (c) Infocatcher 2012-2015
// version 0.1.11 - 2015-06-04
 // Hotkey: Ctrl+T 

const watcherId = "customButtonsToggleOnTop_" + this.id;
var {Components} = window; // Prevent garbage collection in Firefox 3.6 and older
var storage = (function() {
    if(!("Services" in window)) // Firefox 3.6 and older
        return Application.storage;
    var global = Components.utils.import("resource://gre/modules/Services.jsm", {});
    var ns = "_cbEditorToggleOnTopStorage";
    var storage = global[ns] || (global[ns] = Components.utils.getGlobalForObject(global).Object.create(null));
    return {
        get: function(key, defaultVal) {
            if(key in storage)
                return storage[key];
            return defaultVal;
        },
        set: function(key, val) {
            if(key === null)
                delete storage[key];
            else
                storage[key] = val;
        }
    };
})();
var watcher = storage.get(watcherId, null);
if(!watcher) {
    watcher = {
        btnPos: 0, // 0 - at top right window corner, 1 - at end of tabs, 2 - before dialog buttons spacer
        btnStyle: "toolbarbutton", // "button" or "toolbarbutton"
        btnChecked: true, // use "checked" style: true or false
         // http://www.iconfinder.com/icondetails/12276/16/gps_location_pin_icon
        icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AgNBjAx4SevkwAAAjxJREFUKM+FUk1oE0EU/mZnRU0U6cFLIT1KKkkNpIcSWwUvVty2l142hZpDoQcPgYQKQkUEz6V6sHgR/KGQQwleQg/xEKRRsIEmga4NoZa2oRGKpJaWmp2Z52UX12Dxg4838+D73ps3jzUYQycIgDc7l0oNAkgqpZ4n5uc/NgHsEEHDKZB/X5OJRGJcSplemJ6+6SZPFStvJ0Ta4eEhTNMcE0I8fDsxcQsAdPwHc6nUoBRCOz4+Rr1eR39//+18Pn/h/cjIGea+eS6VegLgKoBfRPRdKbXGOf8GIBmPx8cty0Kz2YTf74ff70cmkynpNSIAwP7+/t2ZmZnowcGBPDo6+rm1tdWo1Wo7pmnesSwLtm2jWCx+EkJwKSUnoln2wWnv9eTkMBE9TafT0b29PbTbbXDO0Wq1YNs2lpaWVpVSj8ZyuWXhaPg953CtXK6v9fVtr6ys9A4NDXU3Gg24JoVC4fPJycnjsVxu2TtMzgCUAVQAUKVSrwDtzc3NQCQS6d7d3XU7EK1W62twY+ML84i1N4zB5TvgYrVaPTs1NRXNZDKlrq4u+Hw+BAKBy1LK6zYA2xE+6/gqzhgbXl9fnw+FQrPBYPCHlBKjo6NRIjpPRD3kEdbcJWGMgTF2Y3Fx8UE4HE4yxl70WtYCEc1ms9kS51wDcM4r/FOS87BhGK90XTc0TeNuPgggFosNG4axOjAw8PJKxwIxAD26rt9XShWVUtvOWosO2h1RAJAMwCUAPseInGG6UTlm6l/8DZ+nFuAjSdH0AAAAAElFTkSuQmCC",
        iconPinned: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AgNBjIpwH1VRwAAAgdJREFUKM+FkkFoU0EQhr/dtxFSquLBS8CAICISQci1oBWLKaaINL300psXDxH0ItSD4L21UKgUxV4aWnKyiIGaQwio2IQ0PQQpBaEhoaEk0dSQNsnb9WAepg+LPwz/7DD/7O7MiJIQuGEAV3QIiNowV4f0HlA0BskJsI8fo75YLHIEjw3ccIInivVxX1IqcXFu7l4Lnhq4BaD4P4Y6INsHB+zlcpwfH7+zG48PavCIvj8/B64CRxoqXdg8Bd+BqG9xMVJNpaiUy5zxehkcGCC2uppV28Y44rs3V1aCFIt2p15v/MzlSj/S6eKlmZnRairFoW2zmUx+boHVBsvAtEj+fV5Iw4vbS0tBe2uLw04H2+ulUy5zaNu8X17OdOGZgkTX3TADCRumP0xNZY3fz6/9fSr5PNVGg6/x+BfdE/Y3wxJAHtj6wzt5aHsSiQv+4WFfbWcHu9VCeDzdRq32DdgQfZMQom9JjDGngcn19fWF2shI9vrYWNBqNjFCND8mk+8MTDq5s65RWUKIUKFQmA0EAtP3pawdra0xGokE0dqrwe8kvgS2e1cjpURKORyLxTaUUg+UUuciUvIWQq8hU5uYMPOQmQcuu7fAsqxr4XD4jVIqLKW0nPgV4AmEFiDzCF65hQLwK6Ueaq0/aa13e2vddVnHxV3AFsBZYKBXyPSa6bDuFdP/st/BfOD54p3eIQAAAABJRU5ErkJggg==",

        boxId: "cbToggleOnTopBox",
        btnId: "cbToggleOnTopButton",
        onTopAttr: "cbOnTop",
        naAttr: "cbOnTopNA",
        styleId: "cbToggleOnTopStyle",
        get btnTip() {
            var locale = (function() {
                if("Services" in window && "locale" in Services) {
                    var locales = Services.locale.requestedLocales // Firefox 64+
                        || Services.locale.getRequestedLocales && Services.locale.getRequestedLocales();
                    if(locales)
                        return locales[0];
                }
                var prefs = "Services" in window && Services.prefs
                    || Components.classes["@mozilla.org/preferences-service;1"]
                        .getService(Components.interfaces.nsIPrefBranch);
                function pref(name, type) {
                    return prefs.getPrefType(name) != prefs.PREF_INVALID ? prefs["get" + type + "Pref"](name) : undefined;
                }
                if(!pref("intl.locale.matchOS", "Bool")) { // Also see https://bugzilla.mozilla.org/show_bug.cgi?id=1414390
                    var locale = pref("general.useragent.locale", "Char");
                    if(locale && locale.substr(0, 9) != "chrome://")
                        return locale;
                }
                return Components.classes["@mozilla.org/chrome/chrome-registry;1"]
                    .getService(Components.interfaces.nsIXULChromeRegistry)
                    .getSelectedLocale("global");
            })().match(/^[a-z]*/)[0];
            if(locale == "ru")
                return "Поверх всех окон (Ctrl+T)";
            return "Always on top (Ctrl+T)";
        },

        REASON_STARTUP: 1,
        REASON_SHUTDOWN: 2,
        REASON_WINDOW_LOADED: 3,
        REASON_WINDOW_CLOSED: 4,

        get obs() {
            delete this.obs;
            return this.obs = Components.classes["@mozilla.org/observer-service;1"]
                .getService(Components.interfaces.nsIObserverService);
        },
        get ww() {
            delete this.ww;
            return this.ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                .getService(Components.interfaces.nsIWindowWatcher);
        },
        get wm() {
            delete this.wm;
            return this.wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                .getService(Components.interfaces.nsIWindowMediator);
        },
        init: function(reason) {
            this.obs.addObserver(this, "quit-application-granted", false);
            var ws = this.wm.getEnumerator(null);
            while(ws.hasMoreElements())
                this.initWindow(ws.getNext(), reason);
            this.ww.registerNotification(this);
        },
        destroy: function(reason) {
            this.obs.removeObserver(this, "quit-application-granted");
            var ws = this.wm.getEnumerator(null);
            while(ws.hasMoreElements())
                this.destroyWindow(ws.getNext(), reason);
            this.ww.unregisterNotification(this);
        },
        initWindow: function(window, reason) {
            if(!this.isTargetWindow(window))
                return;
            window.addEventListener("keypress", this, true);
            if(this.hasSizeModeChangeEvent)
                window.addEventListener("sizemodechange", this, false);
            else {
                window.addEventListener("resize", this, false); // Can detect only maximize/restore
                this.legacySizeModeChange(window);
            }

            var document = window.document;
            this.removeStyle(document);
            this.addStyle(document);
            var box = document.getElementById(this.boxId);
            box && box.parentNode.removeChild(box);
            box = document.createXULElement("hbox");
            box.id = this.boxId;
            var btn = document.createXULElement(this.btnStyle);
            btn.id = this.btnId;
            if(this.btnChecked) {
                btn.setAttribute("type", "checkbox");
                btn.setAttribute("autoCheck", "false");
            }
            btn.tooltipText = this.btnTip;
            btn.addEventListener("command", this, false);
            box.appendChild(btn);
            switch(this.btnPos) {
                default:
                    box.setAttribute("cbOnTopFloat", "true");
                    document.documentElement.appendChild(box);
                break;
                case 1:
                    box.setAttribute("align", "right");
                    let tabbox = document.getElementById("custombuttons-editbutton-tabbox");
                    let tabs = tabbox.getElementsByTagName("tabs")[0];
                    tabs.parentNode.insertBefore(box, tabs);
                    box.style.marginBottom = -btn.boxObject.height + "px";
                break;
                case 2:
                    box.setAttribute("align", "center");
                    let btnBox = document.documentElement.getButton("accept").parentNode;
                    let insPos = btnBox.firstChild;
                    for(let node = insPos; node; node = node.nextSibling) {
                        if(node.localName == "spacer") {
                            insPos = node;
                            break;
                        }
                    }
                    btnBox.insertBefore(box, insPos);
            }
            this.checkWindowStatus(window, box);
        },
        destroyWindow: function(window, reason) {
            if(reason == this.REASON_WINDOW_CLOSED)
                window.removeEventListener("DOMContentLoaded", this, false); // Window can be closed before DOMContentLoaded
            if(!this.isTargetWindow(window))
                return;
            window.removeEventListener("keypress", this, true);
            if(this.hasSizeModeChangeEvent)
                window.removeEventListener("sizemodechange", this, false);
            else
                window.removeEventListener("resize", this, false);
            var document = window.document;
            var btn = document.getElementById(this.btnId);
            btn.removeEventListener("command", this, false);
            if(reason == this.REASON_SHUTDOWN) {
                let box = btn.parentNode;
                box.parentNode.removeChild(box);
                this.removeStyle(document);
                let xulWin = this.getXulWin(window);
                xulWin.zLevel = xulWin.normalZ;
            }
        },
        isTargetWindow: function(window) {
            return window.location.href.substr(0, 41) == "chrome://custombuttons/content/editor.xul";
        },
        observe: function(subject, topic, data) {
            if(topic == "quit-application-granted")
                this.destroy();
            else if(topic == "domwindowopened")
                subject.addEventListener("DOMContentLoaded", this, false);
            else if(topic == "domwindowclosed")
                this.destroyWindow(subject, this.REASON_WINDOW_CLOSED);
        },
        handleEvent: function(e) {
            var trg = e.originalTarget || e.target;
            var window;
            switch(e.type) {
                case "DOMContentLoaded":
                    window = trg.defaultView;
                    window.removeEventListener("DOMContentLoaded", this, false);
                    this.initWindow(window, this.REASON_WINDOW_LOADED);
                break;
                case "keypress":
                    if(
                        !(
                            (e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey
                            && String.fromCharCode(e.charCode).toLowerCase() == "t"
                        )
                    )
                        break;
                    e.preventDefault();
                    e.stopPropagation();
                case "command":
                    window = trg.ownerDocument.defaultView.top;
                    this.toggleOnTop(window);
                break;
                case "sizemodechange":
                case "resize":
                    window = trg;
                    this.checkWindowStatus(window);
            }
        },
        get hasSizeModeChangeEvent() {
            var appinfo = "Services" in window && Services.appinfo;
            delete this.hasSizeModeChangeEvent;
            return this.hasSizeModeChangeEvent = appinfo && (
                appinfo.name == "Pale Moon"
                || parseFloat(appinfo.platformVersion) >= 8
            );
        },
        legacySizeModeChange: function(window) {
            var lastState = window.windowState;
            window.setInterval(function(window, _this) {
                var state = window.windowState;
                if(state != lastState)
                    _this.checkWindowStatus(window);
                lastState = state;
            }, 150, window, this);
        },
        checkWindowStatus: function(window, box) {
            if(!box)
                box = window.document.getElementById(this.boxId);
            var na = String(window.windowState != window.STATE_NORMAL);
            if(box.getAttribute(this.naAttr) == na)
                return;
            box.setAttribute(this.naAttr, na);
            //LOG("Set n/a: " + na);
            this.setOnTop(box.firstChild);
        },
        addStyle: function(document) {
            var style = '\
                %box%[cbOnTopFloat] {\n\
                    position: fixed !important;\n\
                    top: 0 !important;\n\
                    right: 0 !important;\n\
                }\n\
                %btn%, %btn% * {\n\
                    margin: 0 !important;\n\
                    padding: 0 !important;\n\
                }\n\
                %btn% > .button-box > .button-icon {\n\
                    margin: -3px -1px !important;\n\
                }\n\
                toolbarbutton%btn% {\n\
                    padding: 0 2px !important;\n\
                }\n\
                %btn% {\n\
                    position: relative !important;\n\
                    z-index: 2147483647 !important;\n\
                    list-style-image: url("%icon%") !important;\n\
                    -moz-user-focus: ignore !important;\n\
                    min-height: 0 !important;\n\
                    min-width: 0 !important;\n\
                }\n\
                %btn%[%onTopAttr%="true"] {\n\
                    list-style-image: url("%iconPinned%") !important;\n\
                }\n\
                %box%[%naAttr%="true"] image {\n\
                    opacity: 0.75 !important;\n\
                }'
                .replace(/%box%/g, "#" + this.boxId)
                .replace(/%btn%/g, "#" + this.btnId)
                .replace(/%onTopAttr%/g, this.onTopAttr)
                .replace(/%icon%/g, this.icon)
                .replace(/%iconPinned%/g, this.iconPinned)
                .replace(/%naAttr%/g, this.naAttr);

            document.insertBefore(document.createProcessingInstruction(
                "xml-stylesheet",
                'id="' + this.styleId + '" href="' + "data:text/css,"
                    + encodeURIComponent(style) + '" type="text/css"'
            ), document.documentElement);
        },
        removeStyle: function(document) {
            var mark = 'id="' + this.styleId + '"';
            for(var child = document.documentElement; child = child.previousSibling; ) {
                if(
                    child.nodeType == child.PROCESSING_INSTRUCTION_NODE
                    && child.data.substr(0, mark.length) == mark
                ) {
                    document.removeChild(child);
                    break;
                }
            }
        },
        getXulWin: function(window) {
            return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                .getInterface(Components.interfaces.nsIWebNavigation)
                .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                .treeOwner
                .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                .getInterface(Components.interfaces.nsIXULWindow);
        },
        
        setOnTop: function(btn, toggle) {
            var document = btn.ownerDocument;
            var root = document.documentElement;
            var onTop = root.getAttribute(this.onTopAttr) == "true";
            var xs = Components. classes ["@mozilla.org/xul/xulstore;1"].
        getService (Components. interfaces. nsIXULStore);
            if(toggle) {
                onTop = !onTop;
                root.setAttribute(this.onTopAttr, onTop);
                if(root.id) {
                    if (!("persist" in document)) {
                    if (!("persist" in xs))
            xs = ChromeUtils. import ("resource://gre/modules/Services.jsm"). Services. xulStore;

                document.persist = function (id, attrr){ 
                
            var node = document. getElementById (root.id);
            if (node) xs. persist (root.id, this.onTopAttr);
                 } 
                         
                    }    
                }
            }
            
            else if(!onTop) // Just opened or restored window always have zLevel == normalZ
                return;
            var window = document.defaultView;
            var state = window.windowState;
            var restore = onTop && state == window.STATE_MINIMIZED;
            if(restore || state == window.STATE_NORMAL) {
                if(restore)
                    onTop = false;
                let xulWin = this.getXulWin(window);
                xulWin.zLevel = onTop ? xulWin.raisedZ : xulWin.normalZ;
            }
            this.checkButton(btn, onTop);
        },
        toggleOnTop: function(window) {
            this.setOnTop(window.document.getElementById(this.btnId), true);
        },
        checkButton: function(btn, onTop) {
            btn.setAttribute(this.onTopAttr, onTop);
            this.btnChecked && btn.setAttribute("checked", onTop);
        }
    };
    storage.set(watcherId, watcher);
    watcher.init(watcher.REASON_STARTUP);
}
function destructor(reason) {
    if(reason == "update" || reason == "delete") {
        watcher.destroy(watcher.REASON_SHUTDOWN);
        storage.set(watcherId, null);
    }
}
if(
    typeof addDestructor == "function" // Custom Buttons 0.0.5.6pre4+
    && addDestructor != ("addDestructor" in window && window.addDestructor)
)
    addDestructor(destructor, this);
else
    this.onDestroy = destructor;

Отредактировано Andrey_Krropotkin (16-12-2019 12:52:47)

Отсутствует

 

№8917-12-2019 19:46:20

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

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

CB_Editor_Toggle_on_Top

Эта та кнопка, которой я пользуюсь сам, и там много чего уже накопилось.
Всё собирался написать Infocatcher'у, но так и не собрался.
А теперь уже страшно даже и подумать, там целый трактат нужен,
и далеко не всё и обосновать бы смог.
Давай скопирую у себя из 73, но следует понимать, что это будет
гораздо хуже, чем если бы правил сам Автор, так что просто на всякий случай.

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


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


для Add_New_Buttons_After_This_Button


Выделить код

Код:

// https://forum.mozilla-russia.org/viewtopic.php?id=56040
// http://infocatcher.ucoz.net/js/cb/cbEditorToggleOnTop.js
// https://github.com/Infocatcher/Custom_Buttons/tree/master/CB_Editor_Toggle_on_Top

// Custom Buttons Editor: Toggle on Top button for Custom Buttons
// (code for "initialization" section)

// (c) Infocatcher 2012-2015
// version 0.1.11 - 2015-06-04

// Hotkey: Ctrl+T

const watcherId = "customButtonsToggleOnTop_" + this.id;
var {Components} = window; // Prevent garbage collection in Firefox 3.6 and older
var storage = (function() {
    if(!("Services" in window)) // Firefox 3.6 and older
        return Application.storage;
    // Simple replacement for Application.storage
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1090880
    //var global = Components.utils.getGlobalForObject(Services);
    // Ensure, that we have global object (because window.Services may be overwritten)
    var global = Components.utils.import("resource://gre/modules/Services.jsm", {});
    var ns = "_cbEditorToggleOnTopStorage";
    // Note: Firefox 57+ returns NonSyntacticVariablesObject w/o .Object property
    var storage = global[ns] || (global[ns] = Components.utils.getGlobalForObject(global).Object.create(null));
    return {
        get: function(key, defaultVal) {
            if(key in storage)
                return storage[key];
            return defaultVal;
        },
        set: function(key, val) {
            if(key === null)
                delete storage[key];
            else
                storage[key] = val;
        }
    };
})();
var watcher = storage.get(watcherId, null);
if(!watcher) {
    watcher = {
        btnPos: 0, // 0 - at top right window corner, 1 - at end of tabs, 2 - before dialog buttons spacer
        btnStyle: "button", // "button" or "toolbarbutton"
        btnChecked: true, // use "checked" style: true or false

        // Fogue icons, http://p.yusukekamiyamane.com/
        // http://www.iconfinder.com/icondetails/12276/16/gps_location_pin_icon
        icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AgNBjAx4SevkwAAAjxJREFUKM+FUk1oE0EU/mZnRU0U6cFLIT1KKkkNpIcSWwUvVty2l142hZpDoQcPgYQKQkUEz6V6sHgR/KGQQwleQg/xEKRRsIEmga4NoZa2oRGKpJaWmp2Z52UX12Dxg4838+D73ps3jzUYQycIgDc7l0oNAkgqpZ4n5uc/NgHsEEHDKZB/X5OJRGJcSplemJ6+6SZPFStvJ0Ta4eEhTNMcE0I8fDsxcQsAdPwHc6nUoBRCOz4+Rr1eR39//+18Pn/h/cjIGea+eS6VegLgKoBfRPRdKbXGOf8GIBmPx8cty0Kz2YTf74ff70cmkynpNSIAwP7+/t2ZmZnowcGBPDo6+rm1tdWo1Wo7pmnesSwLtm2jWCx+EkJwKSUnoln2wWnv9eTkMBE9TafT0b29PbTbbXDO0Wq1YNs2lpaWVpVSj8ZyuWXhaPg953CtXK6v9fVtr6ys9A4NDXU3Gg24JoVC4fPJycnjsVxu2TtMzgCUAVQAUKVSrwDtzc3NQCQS6d7d3XU7EK1W62twY+ML84i1N4zB5TvgYrVaPTs1NRXNZDKlrq4u+Hw+BAKBy1LK6zYA2xE+6/gqzhgbXl9fnw+FQrPBYPCHlBKjo6NRIjpPRD3kEdbcJWGMgTF2Y3Fx8UE4HE4yxl70WtYCEc1ms9kS51wDcM4r/FOS87BhGK90XTc0TeNuPgggFosNG4axOjAw8PJKxwIxAD26rt9XShWVUtvOWosO2h1RAJAMwCUAPseInGG6UTlm6l/8DZ+nFuAjSdH0AAAAAElFTkSuQmCC",
        iconPinned: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AgNBjIpwH1VRwAAAgdJREFUKM+FkkFoU0EQhr/dtxFSquLBS8CAICISQci1oBWLKaaINL300psXDxH0ItSD4L21UKgUxV4aWnKyiIGaQwio2IQ0PQQpBaEhoaEk0dSQNsnb9WAepg+LPwz/7DD/7O7MiJIQuGEAV3QIiNowV4f0HlA0BskJsI8fo75YLHIEjw3ccIInivVxX1IqcXFu7l4Lnhq4BaD4P4Y6INsHB+zlcpwfH7+zG48PavCIvj8/B64CRxoqXdg8Bd+BqG9xMVJNpaiUy5zxehkcGCC2uppV28Y44rs3V1aCFIt2p15v/MzlSj/S6eKlmZnRairFoW2zmUx+boHVBsvAtEj+fV5Iw4vbS0tBe2uLw04H2+ulUy5zaNu8X17OdOGZgkTX3TADCRumP0xNZY3fz6/9fSr5PNVGg6/x+BfdE/Y3wxJAHtj6wzt5aHsSiQv+4WFfbWcHu9VCeDzdRq32DdgQfZMQom9JjDGngcn19fWF2shI9vrYWNBqNjFCND8mk+8MTDq5s65RWUKIUKFQmA0EAtP3pawdra0xGokE0dqrwe8kvgS2e1cjpURKORyLxTaUUg+UUuciUvIWQq8hU5uYMPOQmQcuu7fAsqxr4XD4jVIqLKW0nPgV4AmEFiDzCF65hQLwK6Ueaq0/aa13e2vddVnHxV3AFsBZYKBXyPSa6bDuFdP/st/BfOD54p3eIQAAAABJRU5ErkJggg==",

        boxId: "cbToggleOnTopBox",
        btnId: "cbToggleOnTopButton",
        onTopAttr: "cbOnTop",
        naAttr: "cbOnTopNA",
        styleId: "cbToggleOnTopStyle",
        get btnTip() {
            var locale = (function() {
                if("Services" in window && "locale" in Services) {
                    var locales = Services.locale.requestedLocales // Firefox 64+
                        || Services.locale.getRequestedLocales && Services.locale.getRequestedLocales();
                    if(locales)
                        return locales[0];
                }
                var prefs = "Services" in window && Services.prefs
                    || Components.classes["@mozilla.org/preferences-service;1"]
                        .getService(Components.interfaces.nsIPrefBranch);
                function pref(name, type) {
                    return prefs.getPrefType(name) != prefs.PREF_INVALID ? prefs["get" + type + "Pref"](name) : undefined;
                }
                if(!pref("intl.locale.matchOS", "Bool")) { // Also see https://bugzilla.mozilla.org/show_bug.cgi?id=1414390
                    var locale = pref("general.useragent.locale", "Char");
                    if(locale && locale.substr(0, 9) != "chrome://")
                        return locale;
                }
                return Components.classes["@mozilla.org/chrome/chrome-registry;1"]
                    .getService(Components.interfaces.nsIXULChromeRegistry)
                    .getSelectedLocale("global");
            })().match(/^[a-z]*/)[0];
            if(locale == "ru")
                return "Поверх всех окон (Ctrl+T)";
            return "Always on top (Ctrl+T)";
        },

        REASON_STARTUP: 1,
        REASON_SHUTDOWN: 2,
        REASON_WINDOW_LOADED: 3,
        REASON_WINDOW_CLOSED: 4,

        get obs() {
            delete this.obs;
            return this.obs = Components.classes["@mozilla.org/observer-service;1"]
                .getService(Components.interfaces.nsIObserverService);
        },
        get ww() {
            delete this.ww;
            return this.ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                .getService(Components.interfaces.nsIWindowWatcher);
        },
        get wm() {
            delete this.wm;
            return this.wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                .getService(Components.interfaces.nsIWindowMediator);
        },
        init: function(reason) {
            this.obs.addObserver(this, "quit-application-granted", false);
            var ws = this.wm.getEnumerator(null);
            while(ws.hasMoreElements())
                this.initWindow(ws.getNext(), reason);
            this.ww.registerNotification(this);
        },
        destroy: function(reason) {
            this.obs.removeObserver(this, "quit-application-granted");
            var ws = this.wm.getEnumerator(null);
            while(ws.hasMoreElements())
                this.destroyWindow(ws.getNext(), reason);
            this.ww.unregisterNotification(this);
        },
        checkOnTopAttr: function(window) {
            if(this.version < 71)
                return this.checkOnTopAttr = function() {}
            var attr = this.onTopAttr;
            var id = window.document.documentElement.id;
            var xs = Cu.import("resource://gre/modules/Services.jsm", {})
                .Services.xulStore;
            (this.checkOnTopAttr = function(window) {
                var de = window.document.documentElement;
                if(de.hasAttribute(attr))
                    return;
                var url = window.location.href;
                if(xs.hasValue(url, id, attr))
                    de.setAttribute(attr, xs.getValue(url, id, attr));
            })(window);
        },
        initWindow: function(window, reason) {
            if(!this.isTargetWindow(window))
                return;
            window.addEventListener("keypress", this, true);
            if(this.hasSizeModeChangeEvent)
                window.addEventListener("sizemodechange", this, false);
            else {
                window.addEventListener("resize", this, false); // Can detect only maximize/restore
                this.legacySizeModeChange(window);
            }
            this.checkOnTopAttr(window);

            var document = window.document;
            this.removeStyle(document);
            this.addStyle(document);
            var box = document.getElementById(this.boxId);
            box && box.parentNode.removeChild(box);
            box = document.createElementNS(xulns, "hbox");
            box.id = this.boxId;
            var btn = document.createElementNS(xulns, this.btnStyle);
            btn.id = this.btnId;
            if(this.btnChecked) {
                btn.setAttribute("type", "checkbox");
                btn.setAttribute("autoCheck", "false");
            }
            btn.tooltipText = this.btnTip;
            btn.addEventListener("command", this, false);
            box.appendChild(btn);
            switch(this.btnPos) {
                default:
                    box.setAttribute("cbOnTopFloat", "true");
                    document.documentElement.appendChild(box);
                break;
                case 1:
                    box.setAttribute("align", "right");
                    let tabbox = document.getElementById("custombuttons-editbutton-tabbox");
                    let tabs = tabbox.getElementsByTagName("tabs")[0];
                    tabs.parentNode.insertBefore(box, tabs);
                    box.style.marginBottom = -(btn.boxObject || btn.getBoundingClientRect()).height + "px";

                break;
                case 2:
                    box.setAttribute("align", "center");
                    let btnBox = document.documentElement.getButton("accept").parentNode;
                    let insPos = btnBox.firstChild;
                    for(let node = insPos; node; node = node.nextSibling) {
                        if(node.localName == "spacer") {
                            insPos = node;
                            break;
                        }
                    }
                    btnBox.insertBefore(box, insPos);
            }
            this.checkWindowStatus(window, box);
            //this.setOnTop(btn);
        },
        destroyWindow: function(window, reason) {
            if(reason == this.REASON_WINDOW_CLOSED)
                window.removeEventListener("DOMContentLoaded", this, false); // Window can be closed before DOMContentLoaded
            if(!this.isTargetWindow(window))
                return;
            window.removeEventListener("keypress", this, true);
            if(this.hasSizeModeChangeEvent)
                window.removeEventListener("sizemodechange", this, false);
            else
                window.removeEventListener("resize", this, false);
            var document = window.document;
            var btn = this.shadow(document).getElementById(this.btnId);

            btn.removeEventListener("command", this, false);
            if(reason == this.REASON_SHUTDOWN) {
                let box = btn.parentNode;
                box.parentNode.removeChild(box);
                this.removeStyle(document);
                let xulWin = this.getXulWin(window);
                xulWin.zLevel = xulWin.normalZ;
            }
        },
        isTargetWindow: function(window) {
            return window.location.href.substr(0, 41) == "chrome://custombuttons/content/editor.xul";
        },
        observe: function(subject, topic, data) {
            if(topic == "quit-application-granted")
                this.destroy();
            else if(topic == "domwindowopened")
                subject.addEventListener("DOMContentLoaded", this, false);
            else if(topic == "domwindowclosed")
                this.destroyWindow(subject, this.REASON_WINDOW_CLOSED);
        },
        handleEvent: function(e) {
            var trg = e.originalTarget || e.target;
            var window;
            switch(e.type) {
                case "DOMContentLoaded":
                    window = trg.defaultView;
                    window.removeEventListener("DOMContentLoaded", this, false);
                    this.initWindow(window, this.REASON_WINDOW_LOADED);
                break;
                case "keypress":
                    if(
                        !(
                            (e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey
                            && String.fromCharCode(e.charCode).toLowerCase() == "t"
                        )
                    )
                        break;
                    e.preventDefault();
                    e.stopPropagation();
                case "command":
                    window = trg.ownerDocument.defaultView.top;
                    this.toggleOnTop(window);
                break;
                case "sizemodechange":
                case "resize":
                    window = trg;
                    this.checkWindowStatus(window);
            }
        },
        version: 0,
        get hasSizeModeChangeEvent() {
            var appinfo = "Services" in window && Services.appinfo;
            delete this.hasSizeModeChangeEvent;
            return this.hasSizeModeChangeEvent = appinfo && (
                appinfo.name == "Pale Moon"
                || (this.version = parseFloat(appinfo.platformVersion)) >= 8
            );
        },
        legacySizeModeChange: function(window) {
            var lastState = window.windowState;
            window.setInterval(function(window, _this) {
                var state = window.windowState;
                if(state != lastState)
                    _this.checkWindowStatus(window);
                lastState = state;
            }, 150, window, this);
        },
        checkWindowStatus: function(window, box) {
            if(!box)
                box = this.shadow(window.document).getElementById(this.boxId);
            var na = String(window.windowState != window.STATE_NORMAL);
            if(box.getAttribute(this.naAttr) == na)
                return;
            box.setAttribute(this.naAttr, na);
            //LOG("Set n/a: " + na);
            this.setOnTop(box.firstChild);
        },
        addStyle: function(document) {
            var style = '\
                %box%[cbOnTopFloat] {\n\
                    display: block !important;\n\
                    position: fixed !important;\n\
                    top: 0 !important;\n\
                    right: 0 !important;\n\
                }\n\
                %btn%, %btn% * {\n\
                    margin: 0 !important;\n\
                    padding: 0 !important;\n\
                }\n\
                %btn% > .button-box > .button-icon {\n\
                    margin: -3px -1px !important;\n\
                }\n\
                toolbarbutton%btn% {\n\
                    padding: 0 2px !important;\n\
                }\n\
                %btn% {\n\
                    position: relative !important;\n\
                    z-index: 2147483647 !important;\n\
                    list-style-image: url("%icon%") !important;\n\
                    -moz-user-focus: ignore !important;\n\
                    min-height: 0 !important;\n\
                    min-width: 0 !important;\n\
                }\n\
                %btn%[%onTopAttr%="true"] {\n\
                    list-style-image: url("%iconPinned%") !important;\n\
                }\n\
                %box%[%naAttr%="true"] image {\n\
                    opacity: 0.75 !important;\n\
                }'
                .replace(/%box%/g, "#" + this.boxId)
                .replace(/%btn%/g, "#" + this.btnId)
                .replace(/%onTopAttr%/g, this.onTopAttr)
                .replace(/%icon%/g, this.icon)
                .replace(/%iconPinned%/g, this.iconPinned)
                .replace(/%naAttr%/g, this.naAttr);

            if(this.shadow(document, style))
                return;
            document.insertBefore(document.createProcessingInstruction(
                "xml-stylesheet",
                'id="' + this.styleId + '" href="' + "data:text/css,"
                    + encodeURIComponent(style) + '" type="text/css"'
            ), document.documentElement);
        },
        removeStyle: function(document) {
            if(this.shadow(document, false))
                return;
            var mark = 'id="' + this.styleId + '"';
            for(var child = document.documentElement; child = child.previousSibling; ) {
                if(
                    child.nodeType == child.PROCESSING_INSTRUCTION_NODE
                    && child.data.substr(0, mark.length) == mark
                ) {
                    document.removeChild(child);
                    break;
                }
            }
        },
        shadow: function(document, arg) {
            var sr = document.documentElement.shadowRoot;
            if(this.btnPos != 2 || !sr)
                return (this.shadow = function(document, arg) {
                    return arg === undefined ? document : false;
                })(document, arg);

            if(arg === undefined)
                return sr;
            var st = sr.querySelector("style"), id = this.styleId;
            if(arg) {
                st.append(arg);
                st.lastChild[id] = true;
            }
            else {
                var tn = Array.from(st.childNodes).find(function(node) {
                    return id in node;
                });
                tn && tn.remove();
            }
            return true;
        },
        getXulWin: function(window) {
            return (
                    window.docShell && window.docShell instanceof Components.interfaces.nsIDocShell
                        ? window.docShell
                        : window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                            .getInterface(Components.interfaces.nsIWebNavigation)
                            .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                )
                    .treeOwner
                    .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                    .getInterface(Components.interfaces.nsIXULWindow || Ci.nsIAppWindow);
        },
        setOnTop: function(btn, toggle) {
            var document = btn.ownerDocument;
            var root = document.documentElement;
            var onTop = root.getAttribute(this.onTopAttr) == "true";
            if(toggle) {
                onTop = !onTop;
                root.setAttribute(this.onTopAttr, onTop);
                if(root.id) {
                    if("persist" in document)
                        document.persist(root.id, this.onTopAttr);
                    else // Firefox 63+
                        Services.xulStore.persist(root, this.onTopAttr);
                }
            }
            else if(!onTop) // Just opened or restored window always have zLevel == normalZ
                return;
            var window = document.defaultView;
            var state = window.windowState;
            // Strange glitches with minimized "raisedZ" window...
            var restore = onTop && state == window.STATE_MINIMIZED;
            if(restore || state == window.STATE_NORMAL) {
                if(restore)
                    onTop = false;
                let xulWin = this.getXulWin(window);
                xulWin.zLevel = onTop ? xulWin.raisedZ : xulWin.normalZ;
                //LOG("Set on top: " + onTop);
            }
            this.checkButton(btn, onTop);
        },
        toggleOnTop: function(window) {
            this.setOnTop(this.shadow(window.document).getElementById(this.btnId), true);
        },
        checkButton: function(btn, onTop) {
            btn.setAttribute(this.onTopAttr, onTop);
            this.btnChecked && btn.setAttribute("checked", onTop);
        }
    };
    storage.set(watcherId, watcher);
    watcher.init(watcher.REASON_STARTUP);
}
function destructor(reason) {
    if(reason == "update" || reason == "delete") {
        watcher.destroy(watcher.REASON_SHUTDOWN);
        storage.set(watcherId, null);
    }
}
if(
    typeof addDestructor == "function" // Custom Buttons 0.0.5.6pre4+
    && addDestructor != ("addDestructor" in window && window.addDestructor)
)
    addDestructor(destructor, this);
else
    this.onDestroy = destructor;

Отсутствует

 

№9017-12-2019 20:01:12

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

Re: [CB]Attributes Inspector (для разработчиков)

Dumby да все работает, спасибо.

Отсутствует

 

№9119-12-2019 00:10:15

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Dumby
О! Спасибо!
Начал потихоньку внедрять: https://github.com/Infocatcher/Custom_B … 6e8a3ad252, пока только Toggle on Top (и то частично).

Добавлено 19-12-2019 00:11:24
P.S. И отдельное спасибо за оживленный DOMi – попробовать успел, но не отписался...

Отредактировано Infocatcher (19-12-2019 00:11:24)


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№9206-01-2020 16:28:39

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

Re: [CB]Attributes Inspector (для разработчиков)

Infocatcher
Насчёт Source Editor'а и Firefox 73.
В нелокализированной версии покромсали editMenuOverlay.dtd
и там вместо <popupset>'а образуется <parsererror>, длиннющий такой,
больше двадцати тысяч пикселей.

По всему коду лазать не стал, записал всё про контекстное меню
отдельным блоком в if, а существующее задвинул в else.
Получилось не очень, «Найти ещё раз» находит не следующее,
а перескакивает через одно.

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


Но я не об этом.

Лисе сделали XUL content type лоботомию, и теперь
документ CB-редактора это XMLDocument :usch:.
Скрипты не исполняются и кустомэлементщина окно игнорирует.
Приходится подгружать скриптлоадером вручную.

И вот здесь нарисовалась какая-то нестыковка.
При попытке открыть окно редактора, браузер зависает, грузит процессор,
и Windows дописывает ему в заголовок своё «(Не отвечает)».
Причём, если открыть во вкладке, то такого не происходит.

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

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


P.S. Да, DOMi тоже ведь .xul
dom_inspector-7.0.6-fx-paxmod.xpi
dom_inspector-7.0.6-fx-bootstrap.xpi

Выделить код

Код:

            var SourceEditor = window.SourceEditor;

            if(this.platformVersion >= 73) {
                var psXUL = '<popupset id="sourceEditorPopupset">\
                    <linkset>\
                        <html:link rel="localization" href="toolkit/global/textActions.ftl" />\
                    </linkset>\
                    <menupopup id="sourceEditorContext"\
                        onpopupshowing="popupHandler(event.target)"\
                        oncommand="popupHandler(event.target)">\
\
                        <menuitem id="menu_undo" data-l10n-id="text-action-undo" />\
                        <menuitem id="menu_redo" data-l10n-id="text-action-redo" />\
                        <menuseparator/>\
                        <menuitem id="menu_cut" data-l10n-id="text-action-cut" />\
                        <menuitem id="menu_copy" data-l10n-id="text-action-copy" />\
                        <menuitem id="menu_paste" data-l10n-id="text-action-paste" />\
                        <menuitem id="menu_delete" data-l10n-id="text-action-delete" />\
                        <menuseparator/>\
                        <menuitem id="menu_selectAll" data-l10n-id="text-action-select-all" />\
                        <menuseparator/>\
                        <menuitem id="menu_find" label="&findCmd.label;" accesskey="&findCmd.accesskey;" />\
                        <menuitem id="menu_findAgain" label="&findAgainCmd.label;" accesskey="&findAgainCmd.accesskey;" />\
                        <menuseparator/>\
                        <menuitem id="se-menu-gotoLine" label="&gotoLineCmd.label;"\
                            accesskey="&gotoLineCmd.accesskey;" key="key_gotoLine" />\
                    </menupopup>\
                </popupset>';
                var ps = window.MozXULElement.parseXULToFragment(psXUL, [
                    "chrome://global/locale/editMenuOverlay.dtd",
                    "chrome://devtools/locale/sourceeditor.dtd"
                ]);
                if(!this.popupHandler) {
                    var commands = {module: {}};
                    ps.querySelectorAll("menuitem").forEach(function(menuitem) {
                        commands[menuitem.id] = menuitem.id.replace(/^(se-)?menu./, "cmd_");
                    });
                    Services.scriptloader.loadSubScript(
                        "resource://devtools/client/shared/sourceeditor/editor-commands-controller.js", commands
                    );
                    var createController = function(editor) {
                        var res = editor.popupCmdController = commands.createController(editor);
                        res.docShell = editor.container.contentWindow.docShell;
                        return res;
                    }
                    var getObj = function(cmd, controller) {
                        return controller.supportsCommand(cmd) ? controller: controller.docShell;
                    }
                    var setDisabled = function(menuitem) {
                        var cmd = commands[menuitem.id];
                        menuitem.disabled = !getObj(cmd, this).isCommandEnabled(cmd);
                    }
                    this.popupHandler = function(node) {
                        var ed = node.ownerDocument.activeElement.contentWindow.editor;
                        var controller = ed.popupCmdController || createController(ed);
                        var cmd = commands[node.id];
                        if(cmd) getObj(cmd, controller).doCommand(cmd);
                        else node.menuitems.forEach(setDisabled, controller);
                    }
                }
                var popup = ps.querySelector("menupopup");
                popup.menuitems = popup.querySelectorAll("menuitem");
                popup.popupHandler = this.popupHandler;

            } else {
                // See view-source:chrome://browser/content/devtools/scratchpad.xul
                // + view-source:chrome://browser/content/devtools/source-editor-overlay.xul
                var psXUL = (isCodeMirror

                // .......
            }
            document.documentElement.appendChild(ps);

Отсутствует

 

№9307-01-2020 23:08:25

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Dumby пишет

При попытке открыть окно редактора, браузер зависает, грузит процессор,
и Windows дописывает ему в заголовок своё «(Не отвечает)».
Причём, если открыть во вкладке, то такого не происходит.

Упс.
Я попробовал поиграться, еще помогает
Но на глаз все равно есть задержка (хотя она и от самого CodeMirror'а).
И еще перестает зависать после замены "DOMContentLoaded" -> "load", так что я пока такую распорку воткнул.


А с меню надо бы еще посмотреть, куда и как доотламывать будут. Хотя, наверное, это еще локализации не обновились. :sick:
Меня особенно удивили постоянные перепиливания бедного Eyedropper'а без каких бы то ни было приростов в возможностях: https://github.com/Infocatcher/Custom_B … 1358-L1397 А вы, друзья, как ни садитесь...

Выделить код

Код:

            if(!again && !isFrame && window.document.contentType == "text/xml") { // Firefox 73+
                //window.setTimeout(function(_this) {
                //    _this.initWindow(window, reason, isFrame, true);
                //}, 0, this);
                Services.tm.mainThread.dispatch(function() {
                    this.initWindow(window, reason, isFrame, true);
                }.bind(this), Components.interfaces.nsIThread.DISPATCH_NORMAL);
                return;
            }

Отредактировано Infocatcher (07-01-2020 23:09:15)


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№9408-01-2020 19:03:39

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

Re: [CB]Attributes Inspector (для разработчиков)

Infocatcher на 72 обновил кнопки с вашей страницы:
1. Undo Close Tabs - работает нормально, но показывает ошибку для
var label = document.getAnonymousElementByAttribute(tip, "class", "tooltip-label");  - document.getAnonymousElementByAttribute is not a function
2. Check for Addons Updates (использую в составе Toggle Restartless Add-ons) - постоянно крутится и выдает ошибку inProgress is null для btn.tooltipText = inProgress.getAttribute("value");
3. Source Editor - version 0.1.0a10 - 2019-12-25 работает нормально, но показывает ошибку - InvalidAccessError: A parameter or an operation is not supported by the underlying object для  for(var j = 0, len = sheet.cssRules.length; j < len; ++j)

Отредактировано Andrey_Krropotkin (08-01-2020 19:08:53)

Отсутствует

 

№9508-01-2020 23:20:00

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

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

3. Source Editor - version 0.1.0a10 - 2019-12-25 работает нормально, но показывает ошибку - InvalidAccessError: A parameter or an operation is not supported by the underlying object для  for(var j = 0, len = sheet.cssRules.length; j < len; ++j)

Там таймаут надо поднимать.
Или вот, ещё вариант. Вроде работает (как идея).

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


Выделить код

Код:

                        css("resource://devtools/client/themes/variables.css");
                        css("resource://devtools/client/themes/common.css");
                        css("chrome://devtools/skin/tooltips.css");
                        if(this.platformVersion >= 68) {
                            var eKey = "styleSheetChangeEventsEnabled";
                            var notVal = !document[eKey];
                            if(notVal)
                                document[eKey] = true;
                            document.addEventListener("StyleSheetApplicableStateChanged", function change(e) {
                                var sheet = e.stylesheet;
                                if(sheet.href != "resource://devtools/client/themes/common.css")
                                    return;
                                document.removeEventListener(e.type, change);
                                if(notVal && document[eKey])
                                    document[eKey] = false;
                                for(var i = 0, len = sheet.cssRules.length; i < len; ++i)
                                    if(sheet.cssRules[i].selectorText == "::selection") {
                                        sheet.deleteRule(i);
                                        break;
                                    }
                            });
                        }

Отсутствует

 

№9609-01-2020 00:08:58

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

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

1. Undo Close Tabs - работает нормально, но показывает ошибку для
var label = document.getAnonymousElementByAttribute(tip, "class", "tooltip-label");  - document.getAnonymousElementByAttribute is not a function

Решаемая в этом месте кода проблема с тултипом,
наверно уже давно потеряла актуальность после этого:
Bug 1461798 - Migrate <tooltip> away from XBL

Может так

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


Выделить код

Код:

        //if(this.appVersion >= 61) {
        if(this.appVersion <= 63 && this.appVersion >= 61) {

Отсутствует

 

№9709-01-2020 00:14:38

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Andrey_Krropotkin пишет

1. Undo Close Tabs - работает нормально, но показывает ошибку для
var label = document.getAnonymousElementByAttribute(tip, "class", "tooltip-label");  - document.getAnonymousElementByAttribute is not a function

(Долго я писал, да...)
Вроде, распорка эта больше и не требуется... отключил: https://github.com/Infocatcher/Custom_B … 63b9ee2fe2

Andrey_Krropotkin пишет

2. Check for Addons Updates (использую в составе Toggle Restartless Add-ons) - постоянно крутится и выдает ошибку inProgress is null для btn.tooltipText = inProgress.getAttribute("value");

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

Какой-то неработающий черновик


Выделить код

Код:

--- a/checkForAddonsUpdates.js
+++ b/checkForAddonsUpdates.js
@@ -169,8 +169,6 @@
     }
 
     progressIcon.loading();
-    var inProgress = $("updates-progress");
-    btn.tooltipText = inProgress.getAttribute("value");
 
     var origIcon = tab.image;
     tab.image = image;
@@ -180,12 +178,36 @@
     if(!updEnabled)
         Services.prefs.setBoolPref(updEnabledPref, true);
 
-    var notFound = $("updates-noneFound");
-    var updated = $("updates-installed");
+    var fu = $("cmd_findAllUpdates");
+    if(!fu) { // Firefox 72+
+        var win = doc.defaultView;
+        var vb = doc.getElementById("html-view-browser");
+        if(!vb) {
+            win.setTimeout(processAddonsTab, 20, win);
+            return;
+        }
+        var vbDoc = vb.contentDocument;
+        fu = vbDoc.querySelector('[action="check-for-updates"]');
+    }
+
+    var notFound = $("updates-noneFound"); //~fixme
+    var updated = $("updates-installed"); //~fixme
     // Avoid getting false results from the past update check (may not be required for "noneFound")
-    notFound.hidden = updated.hidden = true;
+    //~fixme notFound.hidden = updated.hidden = true;
 
-    $("cmd_findAllUpdates").doCommand();
+    //fu.doCommand();
+    fu.click();
+
+    var inProgress = $("updates-progress");
+    if(!inProgress) { // Firefox 72+
+        var um = vbDoc.getElementById("updates-message");
+        inProgress = um.shadowRoot.querySelector('[data-l10n-id="addon-updates-updating"]');
+        if(!inProgress) {
+            win.setTimeout(processAddonsTab, 5, win);
+            return;
+        }
+    }
+    btn.tooltipText = inProgress.getAttribute("value") || inProgress.textContent;
 
     var waitTimer = setInterval(function() {
         if(!doc.defaultView || doc.defaultView.closed) {

Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№9809-01-2020 13:44:59

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

Re: [CB]Attributes Inspector (для разработчиков)

Dumby пишет

Или вот, ещё вариант. Вроде работает (как идея).

работает без ошибок

Infocatcher пишет

Вроде, распорка эта больше и не требуется

работает без ошибок

Infocatcher пишет

Какой-то неработающий черновик

если сначала нажимаю на кнопку выдает ошибки
1. TypeError: el.closest(...) is null дляview-source:chrome://mozapps/content/extensions/aboutaddons.js в строке
function getTelemetryViewName(el) {
  return el.closest("[current-view]").getAttribute("current-view");
}
2. TypeError: autoUpdate is nul для var autoUpdateChecked = autoUpdate.getAttribute("checked") == "true"; и зацикливается
При перезагрузке открывается вкладка Управление дополнениями - доступные обновления

Если сначала открываю вкладку Управление дополнениями и затем нажимаю на кнопку, то находит обновления, но все равно кнопка и вкладка зацикливаются и выдают только вторую ошибку, если после этого закрываю вкладку, то выскакивает сообщение "Tab with addon-manager was closed" и тогда кнопка перестает работать

Не знаю поможет Вам или нет - вот на www.camp-firefox.de нашел работающий кусок кода

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


Выделить код

Код:

let frameScript = function() {
      addEventListener('pageshow', function onPageshow(event) {
        let document = event.target;
        if (document.URL != 'about:addons')
          return;
        removeEventListener('pageshow', onPageshow);
        content.setTimeout(function() {
          content.getHtmlBrowser().contentDocument.querySelector('[action="check-for-updates"]').click();
          let item = document.getElementById('category-availableUpdates');
          item.click();
          let categories = item.parentNode;
          categories.addEventListener('mousedown', function onMousedown(event) {
            if (event.target != item && event.target.parentNode != item) {
              item.hidden = true;
              categories.removeEventListener('mousedown', onMousedown);
            };
          });
        }, 0);
      });
    };

    let frameScriptURI = 'data:,(' + frameScript.toString() + ')()';
    let window = event.target.ownerGlobal;
    window.openTrustedLinkIn('about:addons', 'tab');
    window.gBrowser.selectedBrowser.messageManager.loadFrameScript(frameScriptURI, true);

Отредактировано Andrey_Krropotkin (09-01-2020 14:40:20)

Отсутствует

 

№9909-01-2020 14:35:52

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

Re: [CB]Attributes Inspector (для разработчиков)

Хочу добавить про Toggle on Top, раз обсуждалось.
Это для btnPos: 1 (at end of tabs).

В Firefox 72 переписали использование [align="right"],
и кнопка съехала в противоположную сторону, влево.

Причём, переписали неправильно, затем исправили,
и даже в бету пришлось вмешиваться.

Таким образом, наверно так

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


Выделить код

Код:

                case 1:
                    //box.setAttribute("align", "right");
                    if(this.platformVersion >= 72)
                        box.setAttribute("pack", "end");
                    else
                        box.setAttribute("align", "right");

Отсутствует

 

№10012-01-2020 23:24:54

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4316
UA: Firefox 56.0

Re: [CB]Attributes Inspector (для разработчиков)

Dumby пишет

Хочу добавить про Toggle on Top, раз обсуждалось.
Это для btnPos: 1 (at end of tabs).

В Firefox 72 переписали использование [align="right"],
и кнопка съехала в противоположную сторону, влево.

Спасибо! Обновил.
У меня причем ощущение, что я проверял (на какой-то бэта-версии) – и было нормально. :sick:

Dumby пишет

Причём, переписали неправильно, затем исправили,
и даже в бету пришлось вмешиваться.

Чик-чик – и в продакшн! ©

Добавлено 12-01-2020 23:35:00
А в 73.0b3 новая напасть: упорно лезет нулевая высота у свежедобавленной кнопки даже после волшебного пинка таймаута:


Выделить код

Код:

                    tabs.parentNode.insertBefore(box, tabs);
                    LOG("xxx " + window.getComputedStyle(btn, null).height);
                    LOG("xxx " + btn.getBoundingClientRect().height);
                    setTimeout(function() {
                        LOG("xxx " + window.getComputedStyle(btn, null).height);
                        LOG("xxx " + btn.getBoundingClientRect().height);
                    }, 5);
                    box.style.marginBottom = -(btn.boxObject || btn.getBoundingClientRect()).height + "px";

Отредактировано Infocatcher (12-01-2020 23:35:00)


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

Board footer

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