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

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

№110118-08-2009 15:38:38

MySh
Кактусогрыз
 
Группа: Extensions
Зарегистрирован: 17-12-2006
Сообщений: 4623
UA: Firefox 3.5

Re: Custom Buttons

Такой вопрос: можно ли с помощью кнопки реализовать подобную функцию?

Отсутствует

 

№110219-08-2009 09:37:43

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

А можете сделать кнопку для отчистки кэша в дополнении Textarea cache. а то задолбало каждый раз окно открывать =(


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№110320-08-2009 17:38:55

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

MySh

Такой вопрос: можно ли с помощью кнопки реализовать подобную функцию?

Можно, другой вопрос - кто бы справился с Selection и Range : )

Вот для одинарного выделения, вроде работает:

Выделить код

Код:

var doc = gBrowser. contentDocument;
var win = document. commandDispatcher. focusedWindow;
var sel = win. getSelection (). QueryInterface (Components. interfaces. nsISelectionPrivate);
var range = sel. getRangeAt (0). cloneRange ();
sel. startBatchChanges ();
sel. removeAllRanges ();
var r = doc. createRange ();
sel. addRange (r);
r. selectNodeContents (doc. body);
r. setEnd (range. startContainer, range. startOffset);
r = doc. createRange ();
sel. addRange (r);
r. selectNodeContents (doc. body);
r. setStart (range. endContainer, range. endOffset);
sel. endBatchChanges ();
//win. blur ();
//win. focus ();

Инвертирует одинарное выделение, правда, по самому выделению после выполнения операции этого не видно (синим окрашено как попало), но если скопировать и посмотреть во внешнем редакторе, то, вроде бы выделенное не копируется.

Добавлено 20-08-2009 17:51:37
Najlus
Вот команда для открытия диалога Textarea Cache:

Выделить код

Код:

window.openDialog ("chrome://tacache/content/cacheWindow.xul");

Добавлено 20-08-2009 17:54:05
ps:

Выделить код

Код:

gPref.clearUserPref("extensions.tacache.cache");

а это, вроде, очищает кэш


Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№110420-08-2009 19:57:06

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Anton пишет:

Вот команда для открытия диалога Textarea Cache:

Это и стандартная кнопка дополнения умеет =(

Anton пишет:

ps:
а это, вроде, очищает кэш

Не работает =(


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№110520-08-2009 20:29:27

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

Najlus
Попробуй добавить первой строкой перед "gPref.clearUserPref"

Выделить код

Код:

var gPref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);

Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№110620-08-2009 20:54:15

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Спасибо =) это работает =)
Единственный минус: в статусбаре всёравно продолжает гореть иконка данного дополнения.

Отредактировано Najlus (20-08-2009 20:55:01)


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№110720-08-2009 21:10:56

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

Najlus
Добавь в конце

Выделить код

Код:

window. focus ();

Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№110820-08-2009 23:16:27

MySh
Кактусогрыз
 
Группа: Extensions
Зарегистрирован: 17-12-2006
Сообщений: 4623
UA: Firefox 3.5

Re: Custom Buttons

Anton
Спасибо, буду пробовать :)

Интересно оно работает — текст инвертируется, но только в пределах одной строчки. Причём к ссылкам это не относится (они работают отдельно). Не совсем то, что мне хотелось, но для начала тоже неплохо! :)
Занятно, каким макаром захват выделения работает в Scrapbook — тот захватывает не только текст, но и все сопутствующие части страницы. Вот если бы ему как-то объяснить, что как раз их-то захватывать не надо… А возможно ли, условно говоря, перебрать все элементы страницы и узнать, выделены они или нет? Или так оно не сработает?

Отредактировано MySh (20-08-2009 23:27:20)

Отсутствует

 

№110921-08-2009 00:27:02

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

MySh

текст инвертируется, но только в пределах одной строчки

Выделение инвертируется полностью, только этого не видно. Предлагаю для проверки выделить кусок текста на этой странице, выполнить код кнопки, "Правка" -> "Копировать", и вставить куда-нибудь в OO Writer - там будет видно.

Занятно, каким макаром захват выделения работает в Scrapbook

Захватывает он, кстати, только одну из частей множественного выделения (при ручном выделении - первую). У меня, по крайней мере (версия 1.3.3.10).

Если надо удалить выделение из страницы перед сохранением в Scrapbook, есть код попроще:

Выделить код

Код:

var sel = document. commandDispatcher. focusedWindow. getSelection ();
sel. deleteFromDocument ();

Он работает и с множественным выделением.


Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№111021-08-2009 00:50:04

MySh
Кактусогрыз
 
Группа: Extensions
Зарегистрирован: 17-12-2006
Сообщений: 4623
UA: Firefox 3.5

Re: Custom Buttons

Anton

Выделение инвертируется полностью, только этого не видно

Гм… А ведь верно! Работает, и работает весьма неплохо! Правда, местами всё равно подчищать приходится. Чёткой закономерности пока не вывел. Поработаю ещё, попробую, как пойдёт.

Добавлено 21-08-2009 00:51:39

Если надо удалить выделение из страницы перед сохранением в Scrapbook

Наоборот — то, что не выделено изначально.

Отредактировано MySh (21-08-2009 00:50:36)

Отсутствует

 

№111121-08-2009 16:05:32

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Anton пишет:

Добавь в конце

Спасибо =)


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№111221-08-2009 20:43:30

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

MySh

Наоборот — то, что не выделено изначально.

Ну, пока только вот так:

Выделить код

Код:

var doc = gBrowser. contentDocument;
var win = document. commandDispatcher. focusedWindow;
var sel = win. getSelection (). QueryInterface (Components. interfaces. nsISelectionPrivate);
var range = sel. getRangeAt (0);
sel. startBatchChanges ();
var docfrag = range. extractContents ();
sel. removeAllRanges ();
range = doc. createRange ();
sel. addRange (range);
range. selectNodeContents (doc. body);
range. deleteContents ();
sel. endBatchChanges ();
doc. body. appendChild (docfrag);

только для одинарного выделения.


Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№111322-08-2009 21:24:46

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

Инверсия множественного выделения:

Выделить код

Код:

function notNull (x) x != null;
function compareRanges (r1, r2)
{
    return r1. compareBoundaryPoints (Range. START_TO_START, r2);
}
var doc = gBrowser. contentDocument;
var win = document. commandDispatcher. focusedWindow;
var sel = win. getSelection (). QueryInterface (Components. interfaces. nsISelectionPrivate);
var ranges = [];
var i, j;
for (i = 0; i < sel. rangeCount; i++)
    ranges. push (sel. getRangeAt (i). cloneRange ());
ranges. sort (compareRanges);
var range1, range2;
var css, cse, ces, cee;
for (i = 0; i < ranges. length; i++)
{
    range1 = ranges [i];
    if (!range1)
        continue;
    if (range1. collapsed)
    {
        ranges [i] = null;
        continue;
    }
    for (j = i + 1; j < ranges. length; j++)
    {
        range2 = ranges [j];
        if (!range2)
            continue;
        css = range1. compareBoundaryPoints (Range. START_TO_START, range2);
        cse = range1. compareBoundaryPoints (Range. START_TO_END, range2);
        ces = range1. compareBoundaryPoints (Range. END_TO_START, range2);
        cee = range1. compareBoundaryPoints (Range. END_TO_END, range2);
        if ((css <= 0) && (cee >= 0))
        {
            ranges [j] = null;
            continue;
        }
        if ((css <= 0) && (cse >= 0) && (cee <= 0))
        {
            range1. setEnd (range2. endContainer, range2. endOffset);
            ranges [j] = null;
            continue;
        }
    }
    if (range1. collapsed)
    {
        ranges [i] = null;
        continue;
    }
}
ranges = ranges. filter (notNull);
sel. startBatchChanges ();
sel. removeAllRanges ();
var range = doc. createRange ();
sel. addRange (range);
range. setStartBefore (doc. body. firstChild);
for (i = 0; i < ranges. length; i++)
{
    range. setEnd (ranges [i]. startContainer, ranges [i]. startOffset);
    if (range. collapsed)
        sel. removeRange (range);
    range = doc. createRange ();
    sel. addRange (range);
    range. setStart (ranges [i]. endContainer, ranges [i]. endOffset);
}
range. setEndAfter (doc. body. lastChild);
if (range. collapsed)
    sel. removeRange (range);
if (sel. rangeCount == 0)
    sel. addRange (doc. createRange ());
sel. endBatchChanges ();
win. blur ();
win. focus ();
//sel. deleteFromDocument ();

Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№111424-08-2009 14:35:32

MySh
Кактусогрыз
 
Группа: Extensions
Зарегистрирован: 17-12-2006
Сообщений: 4623
UA: Firefox 3.5

Re: Custom Buttons

Anton
Спасибо, кнопка работает прекрасно. Скорость выскрапбучивания данных из интернетов выросла в разы. :)
Заодно у меня тут пока и пиктограммка нарисовалась, а то с этих звёздочек уже в глазах рябит:
http://forum.mozilla-russia.org/uploaded/Is_script.png

Выделить код

Код:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAASCAIAAAA2bnI+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAD3GlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHja7ZZdTFNnGMf/5xxKW6CWjxap0vFaQQGxw+InCAJHEDK+0nasrQMpLZYC/fBwQAQCbhkytgluMToz5r4kWJ0yXYy6LOp0WRbGMp02tTFujCFxxDDmNjfDFnbBNsgull3MO/43z5P/8+b9v2/yu3gAsRUAaBpwOHlOuyWbGIwmIvQhCEpIEY1Qs6XeXajL1QOALocluSWbCWZFAQ+8oADgepIuh507+y+SWNwcD1AEwHprVb0FoAwAdlsdTitA3QTQbHVYrQCtB1DJGYwmgD4HQGab6YcAyCpn+mEAsp28mwfonwDIOL2WBRgRQIfY9FoWEMgAOqRSr2UBIQHoEIu5jgfESQBkjfaqnYA4E0AsX9XEAwDrcu/i7LZqnsRbEogmOTmF6MyO+ganjeTUVVl4zuW0W+oJ61InkQLeipl/AABi/zq4khSZ+QbOXEdYV52LIyWci6xSJ5N8thD/t+bkK//1oY9Ac7IFhBDyKDIMRtOf9za4gLQ3AOb1WU97Ajj9PLDMMOutUAFhfuBe66z3YwYoAFSk29LANf6N80xhIEQwwhAFggSsRhaKUAYndmM/PLiEm7hPSahEKp+yUy9SA9QNaoqOpYvpFtpD+5kgJp3hGA8zEhAdYAw4GOATKARlgrcF44EpgW2BnwkXCWuFF0QRohrRFbFS3Cz2B20I6g2mgm3BV0NSQ/olkZI9kocLnAvuSMul/tDSUG9YaZg/vDx8LMIVMSXrkivkxyI3RXoXOqJEUUcUrGJ0UefipMU3otuUCUrfY50xqTETpG9JuUqh8i09EGuIi477dtnx5Y3xbEJ4wmji2RXdSdtXZqqV6t8e/yr5o1X9mn0pzatta0rX5q3buF6zITE1Lk21cUn60ozlm9SZa7OysovZbZt35HTk9m45k3ct//snpAWawqeK2os9JV5tgG6NvvrJw6U+Q5ixyNS99WqZrHzrtiMVk5UZlh7ryPZ1tp7q72pya/scQmet68sdaVw/L2/oaPy1yblrrKWi9XZbWfvXz1ieHX+uvmO6s7sr5oXTL+Xt/aan9WXFK+f3P32AOug5pHsNvQOHzW/K3xp6Z09fdj919PKxjncLTsoHhk+dfL/9jPZs/Hl8cOvDcxdevdRyueLjvE80n5JB6RD1+YMvJq7dvX7HO+ob84/f+uH21LBoZOFo/Fj6Xf24417XxNHJwfsTP8t/yXhYM3Xo98Hp6XkW5lmYZ2GehX+yYOXtDgCYsxupZnYFgMk1H2c4k4m5eOoK+k+o8F5TEy5OmgDQfwBMZtCjN+4TcwAAACBjSFJNAABtqQAAc7QAAPq1AACAlQAAYy4AAOVvAAA3hQAAFbAnc1zwAAABjElEQVR42mRTO3IVMRDsbkl+yxV8AhJIXGQEriL0Aci4AoHLnIDsQcAVnBKTv4SQxCEH4Arss3Y1BKPPLk81wainRz0zkmhmZiiGYrYWLMVKQTErRgMIiCZSQhSDIFIEiYi2zGAGGF6+fXDk6XR8dVv93z+PlcDKZ9dcS9VcVitGM7y+fXg6HUmIFgNdM6hqqmuSIECAJPaLZAsNULs0AgS5Y9QtN5yRySbFoTwysT2URA2rOl46IdQ2/Gxe4C6zqXajgIvMzt4y9V9VY+h7Hi66iNc39+4FKaUwHdI0pemQXhzSn19f373/8vec53Oe5zyfc87rWsqFpg+A7BViU3kPDU20CyQpUWKQ3LwQNw/1bDOrmiIpioxB1aIAxKiOdM5IaaOnAim6CtuY61ZUoBqZpNBuWKJX5DZeWUNEqQltJsTRp4e3j3aHczOh/qb9r52+f3Lw7sO3H48f3X9z9xnjPxgAXt/ce4dXKaYYpilNVzGlGKMklVKWpeS8zM/LPOe8rM95KasVs38DALR8gMtwnJ/jAAAAAElFTkSuQmCC

Отсутствует

 

№111525-08-2009 16:54:21

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

Re: Custom Buttons

Кнопка для отмены закрытия вкладок (аналог расширения Undo Closed Tabs Button)

ЛКМ – отменить закрытие вкладки
СКМ, Ctrl+ЛКМ – очистить список закрытых вкладок
ПКМ – список закрытого

ПКМ по любому из пунктов меню – восстановить окно/вкладку без скрытия меню

Shift+ПКМ (а также ПКМ с любой другой клавишей-модификатором) – показать оригинальное меню кнопки

Скриншот:
http://forum.mozilla-russia.org/uploaded/undoCloseTabsList.png

Кнопка использует встроенную компоненту сохранения сессий, отмена закрытия окон работает в Firefox 3.5 и выше.
Используемые строки задаются в самом начале и их можно корректировать:

Выделить код

Код:

this._strings = {
    ...
};

Иконки взяты из расширения Undo Closed Tabs Button. Часть кода, определяющая внешний вид, начинается с

Выделить код

Код:

//===================
// Styles

Код (секция «инициализация»):

Выделить код

Код:

// http://infocatcher.ucoz.net/js/cb/undoCloseTabsList.js

// Undo Close Tabs List button for Custom Buttons
// version 0.2.0 - 2011-07-08
// (code for "initialization" section)
// (c) Infocatcher 2009-2011

//= Settings begin
this.settings = {
    menuTemplate: [
        "closedWindows",
        "separator",
        "restoreClosedWindows",
        "clearClosedWindows",
        "separator",
        "closedTabs",
        "separator",
        "restoreClosedTabs",
        "clearClosedTabs",
        "separator",
        "clearAll"
    ],
    openMenuOnMouseover: false
};
this._strings = {
    en: { // First entry used as default
        restoreAllTabs: "Restore all tabs",
        restoreAllTabsAccesskey: "t",
        clearTabsHistory: "Clear history of closed tabs",
        clearTabsHistoryAccesskey: "b",

        restoreAllWindows: "Restore all windows",
        restoreAllWindowsAccesskey: "w",
        clearWindowsHistory: "Clear history of closed windows",
        clearWindowsHistoryAccesskey: "d",

        clearAllHistory: "Clear all history",
        clearAllHistoryAccesskey: "C"
    },
    ru: {
        restoreAllTabs: "Восстановить все вкладки",
        restoreAllTabsAccesskey: "л",
        clearTabsHistory: "Очистить историю закрытых вкладок",
        clearTabsHistoryAccesskey: "д",

        restoreAllWindows: "Восстановить все окна",
        restoreAllWindowsAccesskey: "о",
        clearWindowsHistory: "Очистить историю закрытых окон",
        clearWindowsHistoryAccesskey: "н",

        clearAllHistory: "Очистить всю историю",
        clearAllHistoryAccesskey: "ч"
    }
};
//= Settings end

this.onclick = function(e) {
    if(e.target != this)
        return;
    if(e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey))
        this.clearAllLists();
    else if(e.button == 0) {
        if(this.closedTabCount)
            undoCloseTab();
        else
            this.showMenu(e, false);
        // Allow use "command" section only from hotkey:
        e.preventDefault();
        e.stopPropagation();
    }
};
this.defaultContextId = this.getAttribute("context") || "custombuttons-contextpopup";
this.oncontextmenu = function(e) {
    if(e.target != this)
        return;
    this.setAttribute(
        "context",
        e.ctrlKey || e.shiftKey || e.altKey || e.metaKey
            ? this.defaultContextId
            : this._mpId
    );
};
this.onmouseover = function() {
    this.updUI();
    if(!this.settings.openMenuOnMouseover)
        return;
    var mp = this._mp;
    if("openPopup" in mp)
        mp.openPopup(this, "after_start");
    else
        mp.showPopup(this, -1, -1, "popup", "bottomleft", "topleft");
};

var s = this._strings;
for(var p in s) if(s.hasOwnProperty(p)) {
    this._defaultLocale = this._locale = p;
    break;
}
var currentLocale = Application.prefs.getValue("general.useragent.locale", "en");
if(s.hasOwnProperty(currentLocale))
    this._locale = currentLocale; // e.g. "ru-RU"
else if(/^([a-z]+)-/.test(currentLocale) && s.hasOwnProperty(RegExp.$1))
    this._locale = RegExp.$1; // e.g. "ru"
this._localeStrings  = s[this._locale];
this._defaultStrings = s[this._defaultLocale];
delete this._strings;
this._string = function(sid) {
    return this._localeStrings[sid] || this._defaultStrings[sid] || "(" + sid + ")";
};

this.XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
this.parseFromXML = function(xml) {
    var pp = XML.prettyPrinting;
    XML.prettyPrinting = false;
    var elt = new DOMParser().parseFromString(xml.toXMLString(), "application/xml").documentElement;
    XML.prettyPrinting = pp;
    return elt;
};

this._mpId = this.id + "-context";
this._mp = this.appendChild(this.parseFromXML(
    <menupopup xmlns={this.XULNS}
        id={this._mpId}
        onpopupshowing="return this.parentNode.drawUndoList();"
    />
));
this._ss = (Components.classes["@mozilla.org/browser/sessionstore;1"] || Components.classes["@mozilla.org/suite/sessionstore;1"])
    .getService(Components.interfaces.nsISessionStore);
this.__defineGetter__("appInfo", function() {
    delete this.appInfo;
    return this.appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
        .getService(Components.interfaces.nsIXULAppInfo);
});
this.__defineGetter__("appVersion", function() {
    delete this.appVersion;
    return this.appVersion = parseFloat(this.appInfo.version);
});
this.__defineGetter__("appName", function() {
    delete this.appName;
    return this.appName = this.appInfo.name;
});

this.__defineGetter__("closedWindowCount", function() {
    if(!("getClosedWindowCount" in this._ss)) {
        delete this.closedWindowCount;
        return this.closedWindowCount = 0;
    }
    return this._ss.getClosedWindowCount();
});
this.__defineGetter__("closedTabCount", function() {
    return this._ss.getClosedTabCount(window);
});

this.clearUndoTabsList = function(redrawList) {
    // Not works in SeaMonkey
    const pId = "browser.sessionstore.max_tabs_undo";
    var val = Application.prefs.getValue(pId, 10);
    Application.prefs.setValue(pId, 0);
    Application.prefs.setValue(pId, val);
    this.updUIGlobal();
    redrawList && this.drawUndoList();
};
this.clearUndoWindowsList = function(redrawList) {
    if(!this.closedWindowCount)
        return;
    this._ss.setWindowState(window, '{"windows":[{}],"_closedWindows":[]}', false);
    this.updUIGlobal();
    redrawList && this.drawUndoList();
};
this.clearAllLists = function() {
    this.clearUndoTabsList();
    this.clearUndoWindowsList();
};
this.showMenu = function(e, isContext, mp) {
    document.popupNode = this.ownerDocument.popupNode = this;
    if(!mp)
        mp = this._mp;
    if("openPopupAtScreen" in mp)
        mp.openPopupAtScreen(e.screenX, e.screenY, isContext);
    else
        mp.showPopup(this, e.screenX, e.screenY, isContext ? "context" : "popup", null, null);
};
this.drawUndoList = function() {
    var mp = this._mp;
    while(mp.hasChildNodes())
        mp.removeChild(mp.lastChild);

    var wc = this.closedWindowCount;
    var tc = this.closedTabCount;
    if(!wc && !tc) {
        mp.hidePopup();
        return false;
    }

    this._undoWindowItems = wc && JSON.parse(this._ss.getClosedWindowData());
    this._undoTabItems    = tc && JSON.parse(this._ss.getClosedTabData(window));

    this.settings.menuTemplate.forEach(function(sid, indx, arr) {
        switch(sid) {
            case "closedWindows":
                wc && this.addUndoWindowsList(mp);
            break;
            case "restoreClosedWindows":
                wc && mp.appendChild(this.parseFromXML(
                    <menuitem xmlns={this.XULNS}
                        label={this._string("restoreAllWindows")}
                        accesskey={this._string("restoreAllWindowsAccesskey")}
                        tooltiptext=""
                        oncommand={"for (var i = 0; i < " + this._undoWindowItems.length + "; i++) undoCloseWindow();"}
                    />
                ));
            break;
            case "clearClosedWindows":
                wc && mp.appendChild(this.parseFromXML(
                    <menuitem xmlns={this.XULNS}
                        label={this._string("clearWindowsHistory")}
                        accesskey={this._string("clearWindowsHistoryAccesskey")}
                        tooltiptext=""
                        oncommand="this.parentNode.parentNode.clearUndoWindowsList();"
                        onclick="if(event.button == 1) this.parentNode.parentNode.clearUndoWindowsList(true);"
                    />
                ));
            break;
            case "closedTabs":
                tc && this.addUndoTabsList(mp);
            break;
            case "restoreClosedTabs":
                tc && mp.appendChild(this.parseFromXML(
                    <menuitem xmlns={this.XULNS}
                        label={this._string("restoreAllTabs")}
                        accesskey={this._string("restoreAllTabsAccesskey")}
                        tooltiptext=""
                        oncommand={"for (var i = 0; i < " + this._undoTabItems.length + "; i++) undoCloseTab();"}
                    />
                ));
            break;
            case "clearClosedTabs":
                tc && mp.appendChild(this.parseFromXML(
                    <menuitem xmlns={this.XULNS}
                        label={this._string("clearTabsHistory")}
                        accesskey={this._string("clearTabsHistoryAccesskey")}
                        tooltiptext=""
                        oncommand="this.parentNode.parentNode.clearUndoTabsList();"
                        onclick="if(event.button == 1) this.parentNode.parentNode.clearUndoTabsList(true);"
                    />
                ));
            break;
            case "clearAll":
                (wc && tc || wc && arr.indexOf("clearClosedWindows") == -1 || tc && arr.indexOf("clearClosedTabs") == -1)
                && mp.appendChild(this.parseFromXML(
                    <menuitem xmlns={this.XULNS}
                        label={this._string("clearAllHistory")}
                        accesskey={this._string("clearAllHistoryAccesskey")}
                        tooltiptext=""
                        oncommand="this.parentNode.parentNode.clearAllLists();"
                    />
                ));
            break;
            case "separator":
                if(mp.hasChildNodes() && mp.lastChild.localName != "menuseparator")
                    mp.appendChild(document.createElement("menuseparator"));
            break;
            default: Components.utils.reportError("[Custom Button :: Undo Close Tabs List] Invalid template entry: \"" + sid + "\"");
        }
    }, this);
    while(mp.lastChild && mp.lastChild.localName == "menuseparator")
        mp.removeChild(mp.lastChild);
    this._undoWindowItems = this._undoTabItems = null;
    return mp.hasChildNodes();
};
this.addUndoWindowsList = function(undoPopup) {
    // Code from chrome://browser/content/browser.js
    // Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.3a1pre) Gecko/20090824 Minefield/3.7a1pre
    // with some improvements

    // populate menu
    let undoItems = this._undoWindowItems;
    for (let i = 0; i < undoItems.length; i++) {
        let undoItem = undoItems[i];
        let menuLabel = "(%count) %title"
            .replace("%title", undoItem.title)
            .replace("%count", undoItem.tabs.length);
        let m = document.createElement("menuitem");
        m.setAttribute("label", menuLabel);
        let selectedTab = undoItem.tabs[undoItem.selected - 1];
        if (selectedTab.attributes.image)
            m.setAttribute("image", this.cachedIcon(selectedTab.attributes.image));
        m.setAttribute("class", "menuitem-iconic bookmark-item");
        m.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
        m.setAttribute("onclick", "if(event.button == 1) { undoCloseWindow(" + i + "); this.parentNode.parentNode.drawUndoList(); }");
        if(selectedTab.entries && selectedTab.entries.length) // Can be [] for about:blank
            m.setAttribute("tooltiptext", selectedTab.entries[selectedTab.index - 1].url);
        if (i == 0)
            m.setAttribute("key", "key_undoCloseWindow");
        undoPopup.appendChild(m);
    }
};
this.addUndoTabsList = function(undoPopup) {
    // Code from chrome://browser/content/browser.js
    // Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.3a1pre) Gecko/20090824 Minefield/3.7a1pre
    // with some improvements

    // populate menu
    //var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
    let undoItems = this._undoTabItems;
    for (var i = 0; i < undoItems.length; i++) {
        let m = document.createElement("menuitem");
        let undoItem = undoItems[i];
        m.setAttribute("label", undoItem.title);
        if (undoItem.image)
            m.setAttribute("image", this.cachedIcon(undoItem.image));
        m.setAttribute("class", "menuitem-iconic bookmark-item");
        m.setAttribute("value", i);
        m.setAttribute("oncommand", "undoCloseTab(" + i + ");");
        m.setAttribute("onclick", "if(event.button == 1) { undoCloseTab(" + i + "); this.parentNode.parentNode.drawUndoList(); }");
        m.setAttribute("tooltiptext", undoItem.state.entries[undoItem.state.index - 1].url);
        if (i == 0)
            m.setAttribute("key", "key_undoCloseTab");
        undoPopup.appendChild(m);
    }
};
this.cachedIcon = function(src) {
    if(
        !/^https?:/.test(src)
        // IDN, see https://bugzilla.mozilla.org/show_bug.cgi?id=311045
        || /^https?:\/\/[^.:\/]+\.[^a-z0-9-]+(?:\/|$)/.test(src)
        || this.appName == "SeaMonkey" && this.appVersion <= 2
        || this.appName == "Firefox"   && this.appVersion <= 3.5
    )
        return src;
    return "moz-anno:favicon:" + src; // https://bugzilla.mozilla.org/show_bug.cgi?id=467828
};
this.updUI = function() {
    if(this.closedWindowCount || this.closedTabCount)
        this.removeAttribute("disabled");
    else
        this.setAttribute("disabled", "true");
};
this.updUIGlobal = function() {
    var ws = Components.classes["@mozilla.org/appshell/window-mediator;1"]
        .getService(Components.interfaces.nsIWindowMediator)
        .getEnumerator("navigator:browser");
    const id = this.id;
    while(ws.hasMoreElements()) {
        let btn = ws.getNext().document.getElementById(id);
        btn && btn.updUI();
    }
};
this.evtHandler = {
    button: this,
    destroy: function() {
        window.removeEventListener("TabClose",       this, false);
        window.removeEventListener("SSTabRestoring", this, false);
        window.removeEventListener("unload",         this, false);
        this.button._mp.removeEventListener("DOMMenuItemActive",   this, false);
        this.button._mp.removeEventListener("DOMMenuItemInactive", this, false);
    },
    handleEvent: function(e) {
        switch(e.type) {
            case "TabClose":
            case "SSTabRestoring":
                this.button.updUI();
            break;
            case "DOMMenuItemActive":
            case "DOMMenuItemInactive":
                if(!("XULBrowserWindow" in window))
                    break;
                XULBrowserWindow.setOverLink(
                    e.type == "DOMMenuItemActive" && e.target.getAttribute("tooltiptext") || "",
                    null
                );
            break;
            case "unload":
                this.button.updUIGlobal();
                this.destroy();
        }
    }
};
this.onDestroy = function() {
    this.evtHandler.destroy();
};
var eh = this.evtHandler;
window.addEventListener("TabClose",       eh, false);
window.addEventListener("SSTabRestoring", eh, false);
window.addEventListener("unload",         eh, false);
this._mp.addEventListener("DOMMenuItemActive",   eh, false);
this._mp.addEventListener("DOMMenuItemInactive", eh, false);
this.updUIGlobal();

//===================
// Styles
// Used icons from Undo Closed Tabs Button extension
this.image = ""; // Styles are not applies, if button has "image" attribute
var sId = "__custombuttonsStyle__" + this.id; // Unique style "id"
var cssStr = <><![CDATA[
    %button% {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAPbSURBVEiJzVVbTBxlFP7+mX9ndmcvXIRiuYSL0K2him2hatIisRqoJqJV40M1NftirLHWqDGV+CCJlRhIm6gvpjV9wEbpk4kETU2pRDFSUWlrQV1a2LZQwZ1lZ9mZ2cvM8UFoYKkUiU38ku/lzznn+79z/gsjItxMCKtNPA6IY4ATAPvPBYJByP4YKmNxbB0EXMsGE9G/Yv8lcg3rdO/Pmt214/0vzlS1HPt2ufgVO2AAGwQUXzbuiSetA62fnGyuLcnb4OTC+mAQ8lv/0I2VCrBfALekoSGeSh14s/Or+vuqiqXWRzYzj8R97/7Q/7qrb+Tu8xpyT50CX5Q4f4raO9qeA7AfQHZmdYcss1uKy3n+7XXyO5//KD68cR2e2uKHVwKmojrOXp7Gse+GcXUmZm0rEI8Emne+6s/DLABiRIT2jjaJMabu2rVbzsleXJ8AxGyRjcZSwr6PvmT11evQVFuNoAaIDMiRgTVOoCYXuDxj4I3jXyNJ7ETrC41P1gLafIsUAHbBmgLTMEx9IWeNpBmxGB3tPcO4pMDvr8bIDJCyAdMCJnVgSAU6R4HxhAsfBhqhcGH7e53fvPw7IGXOwCai8EIKsMOKnYw8U78hpcdjODHwE2YNA3HDgG6Y1zhrmDg3nUDPWAotzVuF4JWplq7e83U8U4AxFl40JACKneKlbil+KNC49sXDPbKZSGJ9RRlAwPDFi4jGNGT5fCjKz4fq9cFKSrizrFgMTqivZAoQEYUz1sBAcFFSLfVI8UOBpoq9R3pcRsKEV3HjQmjM2r2tOjw8GfH2Dgy4Sm5di0RFGfSkzVJWumqJgCAIaqYA8Pd59lB65rYsWT8Y2FG993C3wrmMXEXSAnWlfcTKpUii5qEH2z/jHpcbU5Eo8txC7g1nsJAirAk3EkOVufLpg4Em1TT1NAimQPZVTtaVIp9MAojC0Sj+jKhouKN8cokDAEtatBCibcNLiYg/T1E/ePZ+iZlmaC6H9/02yYjAptUIeZwOe/tdlV2Lbx1jtiAIywrMtUvNouQfmwp9osP2mABIT1rOfZ/28zQRvIpotT79wFlO6ObtHW0OAHtW6uCaEyKIRGwuBy6nw/la0yZrIqoJDTVV474cb6uu4QLnnO8vLCzaWVRUPAjAD+C6Q74RLMDz+BY/GxkP/Roa6k8NhkI5Lz2/x+AASh979AmdMXYynU53r9RBJhxEMw7BfntjRUlBDktlj4+cEwEQZ0w4zTm/pGnax6spPA8iQiIeP+p0Oku5IGwGMAoAXBSF7xljim3bq9r5dYTSTGAGgAlgwXN9s7DqT/9/I/AXr+4N9n05Pw8AAAAASUVORK5CYII=") !important;
    }
    %button%:hover {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAPWSURBVEiJzVVbaFxVFF3n3MfM3EkmSWObTJrnmGJrEklpYj6iBSEaEpDQooJiv9L6IalURAP2xyrSfCRq0A+xIKIWYj/8kFa0lDbFKmptadImhJhM3s/Oo/O4c+/MnXu2PwkkY5umKYILNud87H3WWWvvw2FEhP8S/GFq+yfhBMA2SmJbUTAMqEiilCyUmDH8sc+LxD2TieiB4hKRcyhBDQMR0df62U8Du949fWWj/E1bxAB2DdAK0ngyadkfnvju4oEab161Q+a7hwEV97BqswRsCHArOvbrMevk8W8uPLPHm692PLuPOxXJ83Hfr+/0XB5puAnk9fdDXle42oPunq4jADoBZGXeXVYdLL+kQt2xp8598ux1pc5XjOfrq+CQgPH5ZYwu3MbFWxMQwk43Fsin2tsOdD72COIAiBERunu6VMZY4JWXD7k8npx1xxOABJPZeCzNj335M6utKEVj9S5MRdKQGKDJHB4HR3G2jKnlAL6+fB3Zbu38Bx3NL9UB0VWLNAAoLPSalmUl1oZp2eYdIdFX/YOMSwq8hUW4tRBDRDcQihuYDesYXozh/FgYwbQDrzU/hXBMb/r02ytv/g2omT0QRBRcGxwiqIlU+NDTNZZpmvhtaBSxhAndMKGvriv7yUAcN+bjeG5vFb82Onv8zKXhejmTgDEWXN8BwE2WVO5W9d7DLd6jp350WOk0SnYUgIgws7wM0zTgdDqR78lBwuVCVOHIz8uVxhfCb2UqoEwFRBSEEMsupPxlbmmst73FCISD8M/NYTEYQiB0236hvnzJt81hDPnH4J+dRSiagJGyWcqyKzMVEOc8dLc55QCyKH3H51ETnxxuffyNL85pQXC2XXNE2+vLfhH1FWogUdPa/NEPssvhgm0L6MnUtvv2YG1IsOddSA48mqv+1XukJSzSKYuBTCbEokz2XFG2gyQQxQ0DUT2G/VXli/9SACCIDaAIgWxKhivznKHP25sUShjTKzXyheEZTmCIxGPk0VTRVFvZt/7VMSY45xsSrNgVyqHU0hMFWZIiNBMARQxL6/z+T8kmgkeT0++/2jTAFZyTu3u6FADHNqtgFRIRJCK2UgOP06G/3bJXBBMGGqt807l5WSciKiZkznlnWWn5waKdOwcB+DZLkAkbyHqxYTdGZ2bHpwd/N25MTWw/+nqHKQMoaWs7qAM4a1mWCeCuU3Q/KJwiioT3aitKinMopU2O3GQASGaMXZUkaSkajZ7ZysGrICIkdf20y+XyyZxXA/ADgMwYu8oYGxFCbMmaTAghbM55FMAisMUv80HwMJ/+/4PgH15AMczwErl/AAAAAElFTkSuQmCC") !important;
    }
    %button%[disabled="true"] {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAMJSURBVEiJvZVLbxtVFMf/59x7Z+zadVXHYMdikGmSsUOQKK8s2CBF8B34AGxAirJg4awCCySUXVcsIsQnYMUmiEWzQUg8khhQm6I8JBPjoSFOYns8djyPy4ZGaWP3kSj8VyPNOed3f2dGuqS1xmWGL3X6RQHlcvn6/Pz8+4+rofOuqFwuj0opvw+C4AYAc3FxsT+o7lwGCwsLNxKJxNrU1NSLiUSiZ5rmlWG1JwbrlVUG8C6A9OOG13Zr1sbGH5/Yth0fGxvjlZWV4yiK/o7FzLupVOrHyZdLt167+UbzDKDy69ptIWRBSvHPsOH7+/vJtdVKsVQqiXw+DwAIggDNZhOtVgt1px5JIcNOp/P23NzcLyeA9cpqEsDezVdfV0EQdAcNdxxHLC8vx23bpkwmM/AAWms4joPt7e1eGIZvzs7O3pH/vZMAfADadd3eoOajoyMzHo8jlUoNXR8RIZ/PQwhhVqvVb5aWlqbkIzUaQGNQs2VZ6Ha76a2trczExAQrpYaCstksua6ba7fbn50BENFAAAAUi8UGEXWr1eoLhUJBCCFQq9VC13VZKRUlk0keGRkhpRSy2ewV3/ffGWRwMPRoAGzbPgBwXK/Xx3K5nPB9HzMzM8ue58Xb7fZbOzs7CcuyyDAMGIaROwNg5qEGD1IqlX5g5n6j0ZiMxWKRYRh7hmHAsiz7/t590ev14lJKmKapHwIQ0RMNTpl8t7m56XueVzjVE0khWSkFz/M6SqnPzxhorZ9o8CDj4+Nfa61Zax0BwOHhoRJSGGEY+sx8aJrmV8/8DR4NEZ08O45zXUlFRPS7Uuq96enpY7leWc0C+JKIPAAGhvymT2lU37h3J9RatwG8BOBAMvOno6P5V5KJq00AV6WUz2RwOoZhdIr2ZMzretnd3eqHAD6QzNx9LvP8Xd/3v+j3++FFDPr9/sdCiNi11LWP/mL+EwAkEf9ERLUwDH8DAObz30FRFDWISDDzbSK+BwCSmX4GEG+1WudezekwM6XT6W+ZqQlc4EZ7auClTv8/AP8CT2Mu5lYEkjwAAAAASUVORK5CYII=") !important;
    }
    toolbar[iconsize="small"] %button% {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABZVBMVEX////w8PD09PTx8fHw8PCPkIvv7++LjIfw8PDu7u6ZmZXv7+/29vbw8PD///+Txdt8lJ2RkY2Sk4+bzeJcnLsbcp6LjIcwf6bg4N/m//+XyuDf7/+LvNGmr68ufqbg4N9OhaLm8PJvrstCjrPg4N9Rk7Q8hqfk8PRoqMc5h60vgKk9ia/f4N7w8PDi7/ZgpMOLtMny9fYmeaIqfaff4N6hpKLv7+/h8PVwqcTB1N3L3ebv7+9trMqLjIeOj4rf39719vbM7PaMt81hpMPL7fmbnJeoqaXr6+tin774+/vF2t+lq6qKlI+hop38/Pz7+/v5+fn9/f29vruLjIeqq6f7+/v5+fnGxsSLjId5rcfg8vw4ibN8ud3n8vgacZ2extrA5//4+/wacp4yha8ZcZ18wuyIxuthrNc5irdvt+KRzvO62ep+w+7N6PeY1/+U1v+h2/9am7sbcp4keaXm8/ovgq07jLe+yJo8AAAAWXRSTlMAES5KZr+CMJ7X7Lr4ZwHdD4f0yftxJtP6Cj4Q/EIe9HPg/tXy/kvL/fr++fGfuf3Bzv787+6DptCRyLvRDs/u+P3O+TSw5Or8ovXiHqKWW0aBpyVHNSZMDw1FfDAAAACvSURBVHhehchTcwRBAIXRXmewtG3btm0jtn9/elPZmpqnnKd7P0DgADK5glyUQpH4b0pYkJo730t1PADxBSiKhlVvT4v11myBgSHD8Vz+cP388rr7rGlg0CIIojccrx5v7u4fjDCYMAxLWm1f33bHcuWEwXUBuT3eS58/cBuEIcQ8iURj8cT7RwqkM1n6LzabXtgUS6BcqdLO6o1mC7Q7XepZrz8YgtGYQphMZ+BfP976HHRDoNUhAAAAAElFTkSuQmCC") !important;
    }
    toolbar[iconsize="small"] %button%:hover {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJBSURBVDiNlZNdSJNhFMf/Z+/HfOfHXMvwYyZNIleWTCUpjC7Mishl1E0QgXQVXeqVV1Y3XrjIroIoLAILgu7CSLpQ+1DCzI8lSKJu6LA5B+51m3vf93Q1W6m1fvBcPJznf/ifc55DzIxMIAIxY8tjUyZiHyD3Ti1XEUD/neAHkDPydfHNq8EvIyWtPTe2OEuV0OXtLAOgpAdL9x2wRhxVj4cmZg+2nanGtYd9n0vk5ANXsdDrbbm6vpmg+/7d2wBaJUmKp8RmS7YpWlqb2zfuF1pO1SHfYsZyOIzx+SAm5pdYjcdOD7Rf6Sdmxr3urncez8UTRYXFBgAwgJl1kjydz+nyyWOQlVxoBiNbMsFuESHpKl4MjekRNV4mppWixePxuZSDPaKknD/q2ts/OknVFS4QgOlIBJasLNjzcrDfUST4/MHXIn7BRBRIXRTWqL2xMnRL090ffVMmsyxDhJaMJXVRECQq3F2A1WisYnMKBDKIyJ92FnJIm+g4535bU15oLIZW0HzYMTzU1jQWVaMcXAmDmYV0B2DmAP7AgkTgjqcmZJNNh447C0a/BVfr1jeSxOoaGt3lk2KXt9MqCMIuBhtE5N/uL+Qh6e84WzkAgB99+l4PEBqqnBvXG2tbRJvN9jQ/32a35ln19B7sxM2GI1P1TnvFzNhwaPDJ+1VRkuSV5guXXhqG8SGRSGzr4Dd0vcftdEyv+WdcSwuzoqgolmfMHFZVde6fYgCapgUURZk3m+VyAMuU6TbuREbb+Dd+Auhp6cpgWPGjAAAAAElFTkSuQmCC") !important;
    }
    toolbar[iconsize="small"] %button%[disabled="true"] {
        list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAHnSURBVDiNvZPPi9NQEMdnXl7yknTbpdCljaLSluCpIrQWRBC9Sukf4a0nj4Fe/Q88yR4E0WNvnmV19Wi3P9h61JW+2tDqNhpqaF7a58UusbqsKPiFOc18P/NlYFBKCf8i8qeDjuPcdBwn81eAZrPZQMQXiHh3s4dSSuh02zoA1ABga3Og/ebgjud9qedyOTYej93Udur1+XPWw1qt/vwE0Ot3nupMr2uaJuLmweCtORp9ZOVyGSmlMJ1OYTabgeu6oKrqvUaj8WAN2Cvki9cBMFybwzDEVqu1VSqVIJlM/pQqCALo9/tBFEU3Tm4gAaLlcnm0LkVR3lerVT4cDldhGIIQAiaTCXieB4wxsG1bT6VSuzQGXiEij28qFApcSvmVc36ZMYaKohwLIRKcc92yLDQMIx8HSAAYbR6xWCyOCCHfXNetWJY1sG3b3N9/WQ6CABOJREBj9l8SxJOYpvkunU4f+b5/S9MYkVIudF2/TzvddhYRdxBBAvweAABgWRYHAPB9/7ZhGBIRnlUq13YpY/pj0zS3NY2JxWJxKmCtbDZ7qCgkfzz7fKXbOyhQVVX5xQuXelEUvSKEnAkQQjzKZHa6q9Xq6vTTFKmqqk8IIbP5fP7hLPMPAAcATik9JIRM8L9942n6DjCB0nCnWKo+AAAAAElFTkSuQmCC") !important;
    }
    ]]></>
    .toString()
    .replace(/%button%/g, "#" + this.id);
function sheet(cssStr, removeFlag) {
    var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
        .getService(Components.interfaces.nsIStyleSheetService);
    var ios = Components.classes["@mozilla.org/network/io-service;1"]
        .getService(Components.interfaces.nsIIOService);
    var data = "data:text/css," + encodeURIComponent(cssStr);
    var uri = ios.newURI(data, null, null);
    if(sss.sheetRegistered(uri, sss.USER_SHEET))
        sss.unregisterSheet(uri, sss.USER_SHEET);
    if(removeFlag)
        return;
    sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
    window[sId] = cssStr;
}
if(!(sId in window))
    sheet(cssStr);
else if(window[sId] != cssStr) {
    sheet(window[sId], true);
    sheet(cssStr);
}

Добавлено 21-11-2009 19:53:33
Вместо showPopup используется метод openPopupAtScreen (если доступен).

Добавлено 04-06-2010 21:48:17
Добавлено восстановление закрытых окон и вкладок кликом средней кнопки мыши без скрытия списка.
Добавлена опция для разворачивания меню при наведении мыши («this.openOnMouseover = false;» в начале кода).

Добавлено 04-06-2010 23:53:51
Улучшено предотвращение появления оригинального контекстного меню кнопки.

Добавлено 08-07-2011 09:58:40
Изменен способ отображения контекстного меню (теперь меню в Linux должно показываться сразу после нажатия правой кнопки мыши).
Добавлено отображение ссылки в строке состояния при выделении пунктов меню с помощью клавиатуры.
Исправлено кэширование иконок (например, moz-anno:favicon:http://нигма.рф/themes/nigma/img/favicon.ico не работает).

Отредактировано Infocatcher (08-07-2011 09:59:21)


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

Отсутствует

 

№111625-08-2009 17:31:58

3Jlou
Участник
 
Группа: Members
Зарегистрирован: 14-08-2008
Сообщений: 211
UA: Firefox 3.5

Re: Custom Buttons

Infocatcher, а вот за это громадный +
Единственное - попробую ка я сменить порядок: сначала вкладки, затем окна

Отсутствует

 

№111725-08-2009 17:38:20

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

Re: Custom Buttons

3Jlou пишет:

Единственное - попробую ка я сменить порядок: сначала вкладки, затем окна

Заменить

Выделить код

Код:

    if(wc) {
        this.addUndoWindowsList(mp);
        tc && mp.appendChild(document.createElement("menuseparator"));
    }
    if(tc)
        this.addUndoTabsList(mp);

на

Выделить код

Код:

    if(tc) {
        this.addUndoTabsList(mp);
        wc && mp.appendChild(document.createElement("menuseparator"));
    }
    if(wc)
        this.addUndoWindowsList(mp);

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

Отсутствует

 

№111825-08-2009 18:51:22

Jarichek
Member I
 
Группа: Members
Откуда: Минск
Зарегистрирован: 09-04-2009
Сообщений: 306
UA: Firefox 3.5

Re: Custom Buttons

Infocatcher
Спасибо, очень полезная кнопка! А можно зделать кнопочку История (Журнал), чтобы по ЛКМ выпадал список журнала (ну скажем последние 30 посещенных ссылок), ПКМ - открытие в боковой панели, а СКМ - открытие Журнала в отдельном окне?
Кстати, извиняюсь что еще раз возвращаюсь к вопросу по поводу кнопки "Закладки", знаю что Anton много раз говорил, что к этому вопросу больше не подойдет, но все же. Есть расширение Personal Menu, оно при установке добавляет кнопку Закладок. Хочу спросить, возможно ли эту кнопку выдернуть в CB или там это сделано по другому совсем (может это не кнопка а кусок из меню переброшен :) )?

Отсутствует

 

№111925-08-2009 20:28:06

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Помогите, дайте пожалуйста CSS код для изменения фона полей ввода на белый и цвета букв на чёрный (Тема просто стоит такая =(   ).


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№112026-08-2009 00:34:53

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

Re: Custom Buttons

Najlus пишет:

Помогите, дайте пожалуйста CSS код для изменения фона полей ввода на белый и цвета букв на чёрный

Или userContent.css

Выделить код

Код:

input[type="text"], textarea {
  color: black !important;
  background-color: white !important;
}

, или нужны подробности.

Добавлено 26-08-2009 00:39:43
P.S. Подправил удаление обработчиков при закрытии окна.


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

Отсутствует

 

№112126-08-2009 07:07:29

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Или userContent.css
Не работает :(


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№112226-08-2009 08:27:25

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

Re: Custom Buttons

Najlus пишет:

Не работает :(

А так:

Выделить код

Код:

input[type="text"], input:not([type]), textarea {
  color: black !important;
  background-color: white !important;
  -moz-appearance: none !important;
}

?


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

Отсутствует

 

№112326-08-2009 09:33:15

Najlus
Рррррррррррь!
 
Группа: Extensions
Откуда: Город N
Зарегистрирован: 11-01-2009
Сообщений: 1986
UA: Firefox 3.5

Re: Custom Buttons

Не пашет =(
Может то что на Linux, и тема стили браузера перебивает?


Вы ленивы, следовательно вы изобретательны (Граф Де Гиш)
Список настроек About:config на русском языке с пояснениями и рекомендациями

Отсутствует

 

№112426-08-2009 18:17:51

Anton
Участник
 
Группа: Extensions
Откуда: от верблюда
Зарегистрирован: 14-12-2004
Сообщений: 3057
UA: Firefox 3.5
Веб-сайт

Re: Custom Buttons

(На всякий случай.)

Вниманию пользователей:

Версия 0.0.4.4, устраняющая несовместимость с Adblock Plus 1.1.1 выпущена 16.08.09
Загрузить можно со страницы http://custombuttons.mozdev.org/installation.html

На AMO выложена тоже 16.08.09, но пока ещё ожидает рецензии.


Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!

Отсутствует

 

№112526-08-2009 18:19:35

ishua
Участник
 
Группа: Members
Зарегистрирован: 26-08-2009
Сообщений: 2
UA: Firefox 3.5

Re: Custom Buttons

гм... у гугла есть прекрасная кнопка, работающая из закладок вида:

Выделить код

Код:

javascript:var%20b=document.body;var%20GR________bookmarklet_domain='http://www.google.com';if(b&&!document.xmlVersion){void(z=document.createElement('script'));void(z.src='http://www.google.com/reader/ui/link-bookmarklet.js');void(b.appendChild(z));}else{}

А можно как нибудть это в кнопку интегрировать? банальным

Выделить код

Код:

loadURI('')

непроходит...

Отсутствует

 

Board footer

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