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

Пользователи не любят читать документацию. Станьте оригинальным, будьте не как все. Ознакомьтесь с нашей базой знаний.

№1347609-07-2019 10:02:33

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

Re: Custom Buttons

momo2000 пишет

Подскажите, на 68 теперь не работает

замени везде "getBrowser ()" на "gBrowser"

Добавлено 09-07-2019 10:14:33

Dumby пишет

Чисто теоретически,

Окно не появляется.
В ошибках пусто,
В предупреждениях:

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

Выделить код

Код:

SyntaxError: test for equality (==) mistyped as assignment (=)? data:((dir, sx, sy) => { var window = content; var createWindow :89:48
SyntaxError: test for equality (==) mistyped as assignment (=)? data:((dir, sx, sy) => { var window = content; var createWindow :96:29
ReferenceError: assignment to undeclared variable TKK data:((dir, sx, sy) => { var window = content; var createWindow :102:9
ReferenceError: reference to undefined property 1 data:((dir, sx, sy) => { var window = content; var createWindow :134:9

Отредактировано Andrey_Krropotkin (09-07-2019 10:16:32)

Отсутствует

 

№1347709-07-2019 11:03:26

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

Re: Custom Buttons

Dumby пишет

Чисто теоретически, можно попробовать дописать в кнопку

Страницу переводит, окно на выделенный текст не появляется. Но это не особо и важно для меня, т.к. пользуюсь для перевода выделенного QTranslate (можно и поиском, чисто теоретически ;) ). Спасибо.

Отсутствует

 

№1347809-07-2019 14:53:07

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

Re: Custom Buttons

Andrey_Krropotkin пишет

Окно не появляется.

Я, когда пробовал, изменил xhr.onreadystatechange
и окошко появляется, а в автономном режиме вообще сразу.
Думал и без изменения подхватится, но, значит, не подхватилось. Жаль.

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

Выделить код

Код:

xhr.onreadystatechange = function() {
            try{
                /*
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = '', status = '', tmp = JSON.parse(xhr.responseText.replace(/\[(?=,)/g, '[0').replace(/,(?=,|\])/g, ',0'));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                */
                    var result = txt;
                    result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;">' + result + '</span>';

                    //status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                    var status = "STATUS";

                    createWindow(result, status, '<a href="'+url.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:17px Times New Roman;">Google Translate</a>', '_gt', btn.lastClick);
                //}
            } catch (x){LOG(x)};
        };

Отсутствует

 

№1347909-07-2019 17:51:04

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

Re: Custom Buttons

Dumby окно появляется, но не переводит а копирует текст, при нажатии на заголовок (должен отправить выделенный текст на перевод в новой вкладке) вместо текста посылает - 531391.531391.
Я думаю этот вариант для кнопки не подойдет. Давайте попробуем попроще вариант с этим же окном

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

Выделить код

Код:

/*CODE*/
//var createWindow = function(text, status, title, id, pos, size){
var createWindow = function(text, title, id, pos, size){
    //var win = document.commandDispatcher.focusedWindow.top == content ? document.commandDispatcher.focusedWindow : content;    
    var win = content;
    var doc = win.document, wId = 'ujs_window'+(id || ''), w = doc.getElementById(wId);
    var keyDown = function(e){if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode == 27)doc.getElementById(wId).closeWin()};
    if(w)w.closeWin();
    w = doc.createElement('div');
    w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:3px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#f3f5f7;padding-top:4px;border-radius:4px;box-shadow:0 0 12px rgba(0,0,0,.4);' : 'background:-o-skin("Window Skin");'));
    w.id = wId;
    w.closeWin = function(){
        doc.removeEventListener('keydown', keyDown, false);
        this.parentNode.removeChild(this);
    };
     w.clearClipboard = function(){
        copyToClipboard("");
        result = "";
        w.closeWin();
       // createWindow(result, status, '<a href="#" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman ;"><b>Буфер обмена</b></a>');
        createWindow(result, '<a href="#" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman ;"><b>Буфер обмена</b></a>');
    };
    w.addEle = function(str, style){
        var ele = doc.createElement('div');
        ele.setAttribute('style', style);
        if(str){
            ele.innerHTML = str;
            for(var el, all = ele.getElementsByTagName('*'), i = all.length; i--;){
                el = all[i];
                if(/^(script|frame|iframe|applet|embed|object)$/i.test(el.nodeName)){
                    el.parentNode.removeChild(el);
                }else{
                    for(var att = el.attributes, j = att.length; j--;){
                        if(/^on[a-z]+$/i.test(att[j].name))att[j].value = '';
                    }
                }
            }
        };
        return this.appendChild(ele);
    };
    var img = doc.createElement('div');
    img.setAttribute('style', 'display:block;float:right;width:18px;height:18px;padding:0;margin:0;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAAZElEQVR42mNgGNyAGQixsVGU/AdCXjCbHczmxKaMFywlAlWiw6DAwIZNmQhYGqJEDWoqFiAGVmKKTwk73CRJ/Ep0GIyhbsPpO4hbIG4TwKaMk0EZ7hYBBk1cvmNDEmbDrmSwAADE8h10+qICXwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAASUVORK5CYII=");background:-o-skin("Caption Close Button Skin");');
    //img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.title = 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    
    w.addEle(title, 'display:table;color:#000;font:16px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
    var cnt = w.addEle(text, 'display:block;border:1px solid #aaa;margin:2px 0 1px 0;padding:4px;background-color:#fafcfe;color:#000;font:14px Times New Roman;width:240px;height:120px;overflow:auto;cursor:text;');
  //  w.addEle(status, 'display:table;color:#555;font:10px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
    
    var img1 = doc.createElement('input');
    img1.setAttribute ('type', 'button');
    img1.setAttribute('style', 'float:left;width:75px;height:18px;font:10px Times New Roman;padding:0;border-width: 1px ! important; border-style: solid ! important; border-color: rgb(192, 225, 240) rgb(154, 201, 221) rgb(154, 201, 221) rgb(192, 225, 240) ! important; color: rgb(51, 51, 51);margin:0;cursor:pointer;');
    img1.setAttribute ('value', 'Очистить');
    img1.addEventListener('click', function(){this.parentNode.clearClipboard()}, false);
    w.appendChild(img1);

    w.addEventListener('mousedown', function(e){
        if(e.target == w){
            e.preventDefault();
            var grabX = e.clientX, grabY = e.clientY, origX = parseInt(w.style.left), origY = parseInt(w.style.top);
            var mouseMove = function(ev){
                w.style.left = origX+ev.clientX-grabX+'px';
                w.style.top = origY+ev.clientY-grabY+'px';
            };
            doc.addEventListener('mousemove', mouseMove, false);
            doc.addEventListener('mouseup', function(){doc.removeEventListener('mousemove', mouseMove, false)}, false);
        }
    }, false);
    doc.documentElement.appendChild(w);

    if(size){
        cnt.style.height = size.height;
        cnt.style.width = size.width;
    }else{
        for(var i = 3; i < 10; i++){
            if(cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth){
                cnt.style.height = 100*i+'px';
                cnt.style.width = 100*i+'px';
            }else break;
        }
    };
    var docEle = doc.compatMode == 'CSS1Compat' ? doc.documentElement : doc.body;
    var mX = docEle.clientWidth-w.offsetWidth, mY = docEle.clientHeight-w.offsetHeight;
    if(mX < 0){cnt.style.width = parseInt(cnt.style.width)+mX+'px'; mX = 0};
    if(mY < 0){cnt.style.height = parseInt(cnt.style.height)+mY+'px'; mY =0};
    var hW = parseInt(w.offsetWidth/2);
    w.style.left = (pos && pos.X < mX+hW ? (pos.X > hW ? pos.X-hW : 0) : mX)+'px';
    w.style.top = (pos && pos.Y+10 < mY ? pos.Y+10 : mY)+'px';
    w.style.visibility = 'visible';
    doc.addEventListener('keydown', keyDown, false);
};

function readFromClipboard() {
  var string;
  try {
      var clipboard = Cc["@mozilla.org/widget/clipboard;1"].
                      getService(Ci.nsIClipboard);
      var trans = Cc["@mozilla.org/widget/transferable;1"].
                  createInstance(Ci.nsITransferable);
      trans.addDataFlavor("text/unicode");
      if (clipboard.supportsSelectionClipboard()) {
        clipboard.getData(trans, clipboard.kSelectionClipboard);
      } else {
        clipboard.getData(trans, clipboard.kGlobalClipboard);
      }
      var data = {};
      var dataLen = {};
      trans.getTransferData("text/unicode", data, dataLen);
      if (data) {
        data = data.value.QueryInterface(Ci.nsISupportsString);
        string = trans.getTransferData.length == 2
          ? data.data : data.data.substring(0, dataLen.value / 2);
      }
  } catch (ex) {
  }
  return string;
};

function copyToClipboard(aString) {
  let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
                        getService(Ci.nsIClipboardHelper);
  clipboardHelper.copyString(aString);
};


                    var result =readFromClipboard();
                    result = '<span style="background-color:inherit;color:inherit;font-size:inherit;font-family:Times,serif;" >' + result.replace(/\&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/`/g,"&#x60;"); + '</span>';
                 //   var   status ='';


//createWindow(result, status, '<a href="#" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman ;"><b>Буфер обмена</b></a>');
createWindow(result, '<a href="#" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman ;"><b>Буфер обмена</b></a>');


В многопроцесорноном режиме ругается на var win = content; (это во всех кнопках) и на  w.addEle , в частноти на ele.innerHTML = str;

Отредактировано Andrey_Krropotkin (09-07-2019 22:59:11)

Отсутствует

 

№1348010-07-2019 14:32:41

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

Re: Custom Buttons

Dumby подскажи пожалуйста на 68 поймал такую ошибку doc.load is not a function в коде

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

Выделить код

Код:

function getPaleteButtonsURI(but) {
   var doc = document.implementation.createDocument("", "", null);
   doc.async = false;
   doc.load("chrome://custombuttons/content/nbftemplate.xml");

   ["help,Help", "name,label", "image,image", "mode,cb-mode", "initcode,cb-init", "accelkey,cb-accelkey", "code,cb-oncommand"]
   .forEach(str=> {
      var arr = str.split(',');
      var value = but.getAttribute(arr[1]), name = arr[0];
      custombutton.buttonSetText(doc, name, value, true);
   });

   var ser = new XMLSerializer();
   return "custombutton://" + escape(ser.serializeToString(doc));
};


я так понимаю из-за Removed the non-standard XMLDocument.load() и Removed the non-standard XMLDocument.async и использовать XMLHttpRequest или fetch() вместо, а как это сделать?

Отредактировано Andrey_Krropotkin (10-07-2019 18:08:20)

Отсутствует

 

№1348110-07-2019 19:32:46

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

Re: Custom Buttons

Andrey_Krropotkin пишет

как это заменить

Например так

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

Выделить код

Код:

var uri = "chrome://custombuttons/content/nbftemplate.xml";
   var stream = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true}).open();
   var doc = new DOMParser().parseFromStream(stream, null, stream.available(), "application/xml");
   stream.close();

Отсутствует

 

№1348210-07-2019 20:24:27

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

Re: Custom Buttons

Dumby спасибо все работает. На 68 работают все кнопки с заменой "createElement" на "createXULElement" и все изменения, которые вносил для 69b1

Отсутствует

 

№1348311-07-2019 06:56:08

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

Re: Custom Buttons

Garalf починил для Вас для 68 Экспорт всех CB кнопок в HTML файл (помог Dumby)

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

Выделить код

Код:

this.onclick =()=> menuPopup.openPopup(this, "after_start");


var array = [
   [ "Экспорт всех CB кнопок в HTML файл", "setPathToHtmlFile()", "data:image/x-icon;base64,AAABAAEAEhIAAAEAIACABQAAFgAAACgAAAASAAAAJAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/w4P6P8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/zUq6P8OD+j/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/0RC//0cE+X/Dg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQW5/8tMOT/Njfw/0BA+v9JSP//UU///1hT//9aVv3/RUL5/zQy+f8zNPH/JSHa/w4P6P8AAAAAAAAAAAAAAAAAAAAAAAAAABAR5v0UFeL/Hh7v/Soo+P80Mf39PDn+/0I+//05NPn/F5sr/zlO0/08PeL/NDbb/Rwdyv8OD+j/AAAAAAAAAAAAAAAAAAAAAA4P6P8XGOn/Hh7x/yQk9f8rKvX/MjD1/zk0+f85NPn/F5sr/xebK/8lQ6n/Hx/D/w4P6P8AAAAAAAAAAAAAAAAAAAAAAAAAAA4P6P8OD+j/Dg/o/w4P6P8OD+j/Dg/o/w4P6P8OD+j/F5sr/zfyX/0Xmyv/Dg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH3EgP+W8J//m/Sk/6D5qv+k/K7/qPyz/6z8uP9t2H7/QuJf/zz/Xv8f7UX/F5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQFP8f5D3/KexI/zL3U/87/V3/Qf9k/0T/aP9K/2v/Qf9j/zn5Wf8571X/Kt1J/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAeUGf0Y6Tj/IvNE/Sn6Tv81/lj9Pv9h/0X9Z/1H/mf/Rvpk/0HvXP064VP/MtZL/RrHN/8Xmyv/AAAAAAAAAAAAAAAAAAAAAAmYHP8JmBz/CZgc/wmYHP8JmBz/CZgc/wmYHP8JmBz/CZgc/zjgUf8x1kj/FMIy/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKL08/zDXSP0NvCz/F5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHKsv/xS9Lv8Xmyv/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//8BB/9/AQf/PwEH/x8BB/8PAQcABwEHAAMBBwAHAQcADwEHAA8BBwAHAQcAAwEHAAcBB/8PAQf/HwEH/z8BB/9/AQf//wEE="],
   [ "Открыть в вкладке HTML файл", "openHtmlFileInTab()", "data:image/x-icon;base64,AAABAAEAEhIAAAEAIACABQAAFgAAACgAAAASAAAAJAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXmyv/F5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABebK/8UvS7/HKsv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/w28LP8w10j9KL08/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXmyv/FMIy/zHWSP844FH/CZgc/wmYHP8JmBz/CZgc/wmYHP8JmBz/CZgc/wmYHP8JmBz/AAAAAAAAAAAAAAAAAAAAABebK/8axzf/MtZL/TrhU/9B71z9Rvpk/0f+Z/9F/Wf9Pv9h/zX+WP0p+k7/IvNE/RjpOP8HlBn9AAAAAAAAAAAAAAAAAAAAAAAAAAAXmyv/Kt1J/znvVf85+Vn/Qf9j/0r/a/9E/2j/Qf9k/zv9Xf8y91P/KexI/x/kPf8DkBT/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/x/tRf88/17/QuJf/23Yfv+s/Lj/qPyz/6T8rv+g+ar/m/Sk/5bwn/99xID/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/xebK/838l/9F5sr/w4P6P8OD+j/Dg/o/w4P6P8OD+j/Dg/o/w4P6P8OD+j/AAAAAAAAAAAAAAAAAAAAAAAAAAAOD+j/Hx/D/yVDqf8Xmyv/F5sr/zk0+f85NPn/MjD1/ysq9f8kJPX/Hh7x/xcY6f8OD+j/AAAAAAAAAAAAAAAAAAAAAA4P6P8cHcr/NDbb/Tw94v85TtP9F5sr/zk0+f9CPv/9PDn+/zQx/f0qKPj/Hh7v/RQV4v8QEeb9AAAAAAAAAAAAAAAAAAAAAAAAAAAOD+j/JSHa/zM08f80Mvn/RUL5/1pW/f9YU///UU///0lI//9AQPr/Njfw/y0w5P8UFuf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/xwT5f9EQv/9Dg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P6P81Kuj/Dg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD+j/Dg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/o/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//8BB/v/AQfz/wEH4/8BB8P/AQeAAwEHAAMBB4ADAQfAAwEHwAMBB4ADAQcAAwEHgAMBB8P/AQfj/wEH8/8BB/v/AQf//wEE="], 
   [ "separator" ],
   [ "Открыть папку для экспорта CB кнопок", "openHtmlFileFolder()", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xMS8wNdiEE10AAAAldEVYdFNvZnR3YXJlAE1hY3JvbWVkaWEgRmlyZXdvcmtzIE1YIDIwMDSHdqzPAAACiUlEQVR4nKWTy0uUYRTGf+/np6PTODOmMpaGhJRaZmQgRAQtglaBf4BRtGgTFLUqKjBoF1QQlBLdKCgrscuiFEq6gGmQBWWSYLfpMqXMTM71+773PS0kQXBR9MBvdZ7z8HDgKBHhf2T9jUkdUbVKKTXfzH7eqVpdXbDDzWvRmrDngePyMZniXfsxLtLBFuAWhziqlOoQET0n4dlprk5/uysisTncO7Gqt3s/N5eeWCjD8T5ZcWa5nNvFmc6d7AEKRAQRgaHT9Gcyb0XyB+ain8jGC+ul5/15GXTuSN+3bmntapHj2+kFyv6E2K7DSrw0Yw9v8ys6gS9chfbgWvA5K2qXUb2knAfZflaXrWXTqg2MByNt12sG25JTiaRSqsI2wuLU5HdyU19p2TZOga+IfX27CUdqqG8KMeK9IKdchtLP8GpdaivXcN8S1g3cDwERWxvIJmP4K1qwfRmQl5wc6p450B14dLiHCecTzf5mtp7aC0BlqJx1M44iywjk4q/xVzSDxMEkkYNXkIOXKSsOoESwUChgoS+At/8GI5u7JOswDIhlDKR/DBKoXA4mCiYxS124nBLxqKCQoGjqwuV46QSTH0fIOYwCjm0MuOnPFAXrwB2eKWY8yKdoDJbgd35S5eYJmWkaQqWYfCGf3wyQc4gCrm0EvMwXiksXQW4SslnIZ0GEhkAJC3IJIq4mpNM0lgaxiqpJTX1SP38xCni2ESgtsxBjgd0OAYHATJHGmgH8Ja1ECusIWSHqa6rI5MKk4lGejjEKuLbWvJqMmdVDZ5vwPGbRGr5rxeDjahJuCtsUE43FSOaFRJpLIx9IAK4CbKAS8AHzPsw8MkAaiCsRQSll/8PybIiI6N8D8VYf0gJ8eQAAAABJRU5ErkJggg=="],
   [ "Экспорт всех CB кнопок в HTML файл без запроса", "exportsButtonsToHtmlFile()", "data:image/x-icon;base64,AAABAAEAEhIAAAEAIACABQAAFgAAACgAAAASAAAAJAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8A/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8A/wBPAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8A/wBkAP8ATwD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8A/wB6AP0AUgD/AE8A/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAP8AZQD/AG4A/wB3AP8AfwD/AIQA/wCHAP8AiAD/AHkA/wBtAP8AbAD/AFgA/wBPAP8AAAAAAAAAAAAAAAAAAAAAAAAAAABQAP0AUgD/AFwA/QBmAP8AbgD9AHQA/wB4AP0AbwD/F5sr/wBzAP0AbgD/AGcA/QBQAP8ATwD/AAAAAAAAAAAAAAAAAAAAAABPAP8AVgD/AF0A/wBiAP8AZwD/AGsA/wBvAP8AbwD/F5sr/xebK/8AXgD/AFAA/wBPAP8AAAAAAAAAAAAAAAAAAAAAAAAAAABPAP8ATwD/AE8A/wBPAP8ATwD/AE8A/wBPAP8ATwD/F5sr/zfyX/0Xmyv/AE8A/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH3EgP+W8J//m/Sk/6D5qv+k/K7/qPyz/6z8uP9t2H7/QuJf/zz/Xv8f7UX/F5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQFP8f5D3/KexI/zL3U/87/V3/Qf9k/0T/aP9K/2v/Qf9j/zn5Wf8571X/Kt1J/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAeUGf0Y6Tj/IvNE/Sn6Tv81/lj9Pv9h/0X9Z/1H/mf/Rvpk/0HvXP064VP/MtZL/RrHN/8Xmyv/AAAAAAAAAAAAAAAAAAAAAAmYHP8JmBz/CZgc/wmYHP8JmBz/CZgc/wmYHP8JmBz/CZgc/zjgUf8x1kj/FMIy/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKL08/zDXSP0NvCz/F5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHKsv/xS9Lv8Xmyv/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/xebK/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5sr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//8BB/9/AQf/PwEH/x8BB/8PAQcABwEHAAMBBwAHAQcADwEHAA8BBwAHAQcAAwEHAAcBB/8PAQf/HwEH/z8BB/9/AQf//wEE="]
];
var menuPopup = self.appendChild(document.createXULElement("menupopup"));
array.forEach((m,i)=> {
   if ( m[0] == "separator" ) { menuPopup.appendChild(document.createXULElement("menuseparator")); return };
   var mItem = menuPopup.appendChild(document.createXULElement("menuitem"));
   mItem.setAttribute("label", m[0]);
   mItem.setAttribute("class", "menuitem-iconic");
   mItem.setAttribute("image", m[2]); 
   mItem.addEventListener("command", ()=> eval(m[1]));
});
menuPopup.setAttribute("onclick", "event.stopPropagation()");


function openHtmlFileInTab() {
   var fp = window.makeFilePicker();
   fp.init(window, "Выберите HTML-файл для импорта закладок", fp.modeOpen);
   fp.appendFilters(fp.filterHTML);
   Cu.import("resource://gre/modules/FileUtils.jsm");
   fp.displayDirectory = FileUtils.File(getPathToHtmlFileFolder());
   fp.open(re=> { 
      if ( re == fp.returnOK )
           gBrowser.selectedTab = gBrowser.addTab(fp.file.path, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),})
   })
};

function exportsButtonsToHtmlFile() {
   var visibleCBbuttons = [...document.querySelectorAll('[cb-mode]')];
   var paletteCBbuttons = [...custombuttons.palette.querySelectorAll('[cb-mode]')];
   var allCBbuttons = visibleCBbuttons.concat(paletteCBbuttons);
   
   var array = [];
   allCBbuttons.forEach(but=> {
      var uri = but.URI ? but.URI : getPaleteButtonsURI(but);
      var name = but.getAttribute("label") || "Без названия";
      var image = but.getAttribute("image") || "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACNFBMVEXDRgDweQDnbwC0NgDCRQC7PQDtpTu+QQD78q3PUwDCRAD//8vbYQDLTgDocAD0iQX1jQbGSgD7iAD4gwDVaw7vdwDyegD+igDweQDlawDyhAXveADmZwDzmBbtcwDwkhHveADmhBTkgxbweADkfRH+igD7hADXZQX0gADyjA/tfgvveQDiawDQVADRXgfnbwD1jAb9iQD9z0PVZAbxpinykRHtdgD5mRbERQDDRgDOYArCRAD9iQD3ewDxegD3dwDFRgDAQAD+hgD4fQDucgDtgQftfwTISQDCRQDvdgD5lxb1kRb2qh7wnynkagD766LDRQDDRwDDRQDspjbtpzbuqDbvqzv//8DUZAbCRQD//83pjhvveQbvggW+QQDfcxLlmUb//8veYADMTwDHSADVVwC8PgDwixb78q3oZgDUWADRVADCRQD9iQDERwDBQQDYVQC+PgC0NgDbYQDWWgDUWADSVQDFSAC+QAC7PAC0NgD+wRL+/kD+/zb+7i3+8Cv+/DX+wBL/+DD/rwz+qgz+rwz/tAz+sQzfbAT+3iP/+jD//Dz1jwP+nwf5iwf7pBz2tRr4lwb/ogfsdQT+2R7/9ET+2iT8yyLmgBL5iQL2egLokhP7zzT60zv1zUr0gAL1ewP50yn9+UL++EXooyngaAH41EPzowzyySj+xxzlhhHvvyruwjXxvTnUag3+zxrwigP+swz86U/ZXwD75lHqegD6xzb//kn+uhPTXAG3OAD/+UC2vFeJAAAAe3RSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAACfnwAIaelpAAA2+wD7UQAAa3oArKzRzMysnwgAvPQA/gAAw3prw0oALr16vS4AACnF6bspAAAA/mIAADQAAAAAAI8AAEwA0vv7kd2yAuuvr+vKABL23U+8Sk/d9vUDIIAQAAAQgCAfvupHAAABB0lEQVR4Xi3IU3fDABgA0C+u26FdZ9u2bdu2vZSzbds2/tyac3IfLxjpGyA6MimqY6gHTNgiiNwkwRM1E7EhTrYyTfMzzsh0ZEPiH+D6+u5mV1jEhpe5haVCYW1T4suEvUOkk7PLpVJ5WFnl7hEUDN5LPvsHJ6cazdn13f3DYxu0B35+/Y2qVSr17NzGeUgohIVHLK/PMDa39qKieRATGxd/9cS4uU1MwnmQktqY/qGlaVr7/ZOVDTmQm5df8PwyNj4xOTVdjOM4kCRZOr+wWFa+srpWQVEU8PnV2zu7NbV19UfHDQRBAIfTdNHc0soVdnR2dfdgGAgEvW99/QNc4eDQ8O8Ihv0D77NPgbVLZ6kAAAAASUVORK5CYII=";
      
      array.push("<img src=" + image + ">&nbsp<a href=" + uri + ">" + name +"</a><br>\n");
   });
   
   var before = "<html>\n<head>\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n</head>\n<body>\n";
   var after = "\n</body>\n</html>";
   var text = before + array.join("") + after;
   var text = convertFromUnicode("UTF-8", text); 
   
   var date = new Date();
   var time = date.toLocaleString('ru', {year: 'numeric', month: 'numeric', day: 'numeric'})
   var time = time + '. ' + date.toLocaleTimeString().replace(/:/g, "˸");

   var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
   file.initWithPath(getPathToHtmlFileFolder());
   file.append("CB buttons " + time + ".html");
   custombuttonsUtils.writeFile(file.path, text);

   var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
   alertsService.showAlertNotification(self.image, self.label, "Экспортировал все CB кнопки как HTML в " + file.path);
   setTimeout(()=> alertsService.closeAlert(), 4000);
};


function getPaleteButtonsURI(but) {
   var uri = "chrome://custombuttons/content/nbftemplate.xml";
   var stream = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true}).open();
   var doc = new DOMParser().parseFromStream(stream, null, stream.available(), "application/xml");
   stream.close();

   ["help,Help", "name,label", "image,image", "mode,cb-mode", "initcode,cb-init", "accelkey,cb-accelkey", "code,cb-oncommand"]
   .forEach(str=> {
      var arr = str.split(',');
      var value = but.getAttribute(arr[1]), name = arr[0];
      custombutton.buttonSetText(doc, name, value, true);
   });

   var ser = new XMLSerializer();
   return "custombutton://" + escape(ser.serializeToString(doc));
};


function openHtmlFileFolder() {
   var folder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
   folder.initWithPath( getPathToHtmlFileFolder() );
   folder.launch();
};


function setPathToHtmlFile() {     
   var fp = window.makeFilePicker();
   fp.init(window, "Укажите папку для экспорта CB кнопок!", fp.modeGetFolder);
   fp.open(re=> { 
      if ( re != fp.returnOK ) return;
      cbu.setPrefs("CB.exportsButtonsToHtmlFile.path", convertFromUnicode("UTF-8", fp.file.path));
      
      exportsButtonsToHtmlFile();
   })
};


function getPathToHtmlFileFolder() {
   var s = "CB.exportsButtonsToHtmlFile.path", pref = Services.prefs;
   var str = pref.getStringPref ? pref.getStringPref(s) : pref.getComplexValue(s, Ci.nsISupportsString).data;
   try { return str } 
   catch(e) { return "C:" };
};


function convertFromUnicode(charset, str) {
   var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
   converter.charset = charset;
   str = converter.ConvertFromUnicode(str);
   return str + converter.Finish();
};


this.onmouseover =()=> { 
   this.tooltipText = self.label + "\nЛ: Меню кнопки\nП: CB меню\n\nПапка для экспорта:\n" + getPathToHtmlFileFolder();
};

Отсутствует

 

№1348411-07-2019 08:30:34

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

Re: Custom Buttons

Andrey_Krropotkin
Большое спасибо! Как раз сейчас пытался ее реанимировать)

ps А в вашей кнопке Дополнительные пункты в контекстном меню кнопки, что надо поправить, чтобы и в ней работало?

Отредактировано Garalf (11-07-2019 08:44:49)

Отсутствует

 

№1348511-07-2019 10:14:36

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

Re: Custom Buttons

Garalf полный код

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

Выделить код

Код:

/*Initialization Code*/ 

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Создание меню ///////////////////////////////
/////////////////////////////////////////////////////////////////////////////

function $(aId) {
  return document.getElementById(aId);
};

function addMenuItem(aNewIDs, aNodeIDs, aLabel, aIcon, aCommand) {
  for (var i = 0; i < aNewIDs.length; i++) {
    
    if ($(aNewIDs[i])) $(aNewIDs[i]).parentNode.removeChild($(aNewIDs[i]));

  var mi = document.createXULElement("menuitem");
           mi.setAttribute("id", aNewIDs[i]);
           mi.setAttribute("class", "menuitem-iconic");
           mi.setAttribute("image", aIcon);
           mi.setAttribute("label", aLabel);
           mi.setAttribute("oncommand", aCommand);
        
    if (i == 0)
      mi.setAttribute("observes", "custombuttons-contextbroadcaster-primary");

    if ($(aNodeIDs[i])) {
      if ($(aNodeIDs[i]).nextSibling) {
        $(aNodeIDs[i]).parentNode.insertBefore(mi, $(aNodeIDs[i]).nextSibling);
      } else {
        $(aNodeIDs[i]).parentNode.appendChild(mi);
      }
    }
  }
};

var saveImg1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnUlEQVQ4jc3RPQ4BURTF8Z+PgrAPtUJnIxZgBZagkolVqDWWIliARCFR6GSq0Twyw2SemcpJTnPzzv/edy//ohOymj7mARl6NRoOQ6YAiGmNFAm6TQBpePdAJwYYYIF+rpaE8CoGaGEbarsw7qfaVYCl4rY3mOOGaQwwU326O8Zhyi/AJPwxdv8rRmWAyw/hl89lgCZ+69AgvPcXegKfOWlGgoA/rgAAAABJRU5ErkJggg==";
var saveImg2 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAADbAAADpcAAA//AAANVwAAD/8AAAKsAAAD/AAAP//AAAP8AAAD/AAAD/8AAAwDAAAP/wAAA/wAAAP8AAA";
var saveImg3 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQf//rEH4j6xB8IesQeHDrEHD4axBh/CsQYf4rEGH8KxBw+GsQeHDrEHwh6xB+I+sQf//rEH//6xB//+sQQ==";
var saveImg4 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAA/wAAAP8AAA";
var saveImg5 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU1FQr1FRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wU1FQrwAAAAAAAAAAAAAAAHd0cpz//////////////////////////////////////////////////////////3d0cpwAAAAAAAAAAAAAAAB4d3Sc/////+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg//////94d3ScAAAAAAAAAAAAAAAAenh3nP/////i4uL/4uLi/5yiz/9HYcT/PWrR/1qQ3P+nuNr/4uLi/+Li4v//////enh3nAAAAAAAAAAAAAAAAH18eJz/////5OTk/2FluP8IJ6r/D1TU/wli4v8FZeb/D3He/4y+5f/k5OT/+/v7/318eJwAAAAAAAAAAAAAAACBfXyc/////5Wc0v8JKq//E2Pd/yFTrv9EKTn/LjVZ/xaF2/8OdNP/zNnm//z8/P+BfXycAAAAAAAAAAAAAAAAhIGBnP////89Xc7/Dk7N/wpQ0/8zVp//TGCK/4U2Cf9DW2b/Eqj7/5C+5//8/Pz/hIGBnAAAAAAAAAAAAAAAAIaEgZz/////Kmnf/wlFzf8gPZ7/uXcl/8OAK/+UTBL/b1Az/zfG9f9srdX/+fn5/4aEgZwAAAAAAAAAAAAAAACJhoac/////0iN6P8HQtH/EVzd/2mCqf/dqkz/0pY6/6FnKv9Nvt7/kMfs//X19f+JhoacAAAAAAAAAAAAAAAAiomJnP////+Mr+r/FFnU/xVRyv+LorL/8Oqh//nXbP+5omH/Urvf/8bj7v/s7Oz/iomJnAAAAAAAAAAAAAAAAI6Kipz/////2+n3/5aSm/+hcEn/4uXC////2P/25KD/rqSD/7HR5//o6Oj/4eHh/46KipwAAAAAAAAAAAAAAACPjo6c//////j4+P/4+Pj/3s/F/9i/n//p27n/5NG0/+7r6f/r6+v/3t7e/9LS0v+Pjo6cAAAAAAAAAAAAAAAAk4+PnP/////6+vr/+vr6//r6+v/6+vr/+vr6//j4+P/19fX/r66t/62sq/ObmprrkI2NpgAAAAAAAAAAAAAAAJOTk5z//////Pz8//z8/P/8/Pz/+/v7//r6+v/4+Pj/9fX1/66trfHs7Ozrp6emp4aGhhMAAAAAAAAAAAAAAACWlpOc/////////////////v7+//39/f/6+vr/9/f3//Pz8/+bmprrp6enp3NzcxYAAAAAAAAAAAAAAAAAAAAAmJiWnJiYlpyYmJacmJiWnJeTk52SkZGemJiWnJeTk52SkZGej4+LpIaGhhMAAAAAAAAAAAAAAAAAAAAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACABwAAgA8AAA==";
var saveImg6 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKklEQVR42mNkQAMNDAxCQMoTiB2BWAEq/ACI9wPxdqD8O2T1jGiao4HUEgb8IAaobimGAUDBGiDVzEAcqAWqb4EbQKTNWF3CCPXzW5ho/f//YDqHkZFhCpQNA7lAMV4gzY4QEmZEtx1mgCtQ8W4o2xLIPg5lJwDZUghDYkAGzAEyktENMAQqPA9l6wDZEkB6D6Yhc0EG7AGynfEZYAxkawHpxVC+A5CvC6RFGBj2Em2AIZCeg8Q3BtLSUAMIegGkwQBIz8U0YC7OQEQ2wAjIPoekGRQTUC/E4IxGkMKzaNEI8jso4chDbGdgA0UjekJ6A8S3gRikFWQyKOF/higGR50UFLPBEhLM9AZoUv4F1cAA1QTi/2SAJFkQnxdCoyZlJEPIz0xIhpCUnQFx83abgfUZOQAAAABJRU5ErkJggg==";
var saveImg7 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASUlEQVR42mNkoBAw0s6ABob/aHxGkg1I8zEGM2dtOTskDED3MxCgGIBpASOGATANhACyi6hrAGVeoDgQB6UB2PxMvAFEAooNAAC7izYR2pQ0nAAAAABJRU5ErkJggg==";
var saveImg8 = "data:application/file;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///8A////AESqAABHpgAASKAAAEukAQxMpQMYR6MAAEepAQ9MpgOLRKgACUenAABHpgAARKoAAP///wD///8A////AP///wBEqgAARaIAAFS2FVBj0jS3Y9AzyVG0EUROrwt8TKcDs0ikAANInwAAR6YAAESqAAD///8A////AP///wD///8ARKQAAVvJKJtj0jX/SaAJ/0abCv9UtSH/U7QX8lW5IMddwyfQW8Iii0mqBQ1DqQAA////AP///wD///8A////AEWlAAFYwB6YXsYc5F7GFt9bwA+vVbgWvU6rAKBRrgf0RZgA/02oDP9ezCzJR6UBA////wD///8A////AP///wBFrAAASKIAADiGNQAeYIIpF1iJHVa4GKEve0tFLHl1Pla7J51exRnUWL8VjEetAAP///8A////AP///wD///8AC0WuAAk/tAAANdpIAFD6/wA+7f8gd6jqBlPX+QBE9PIGS8uDLnZLADqNJwAzjDMA////AP///wD///8A////AAAw0QAALc0AAEPdegBI4f8AK8P/ADHX/wAwzf8AL8b/AEno/gAz2zYALtEQAC3VAP///wD///8A////AP///wAAMssAADjSMwBA2pIATen/ADG9/wBe1v8ATcz/ADHK/wBN5/4ASeH/AEvl6wA10DP///8A////AP///wD///8AADnTSQBO5/8ANc7/ADnR/xC+9/8C0f//AMj//wCP8P8ALcX/ACrC/wBE3f8ASeOf////AP///wD///8A////AABI4Z4ARN3/ACvG/wJAxP8Z5v//AMT//wDE//8Axv7/AETM/wA51P8AUervADjSPP///wD///8A////AP///wAAOdRiAFry+QBS6/QATOP/H+P8/xDe//8J1///E9H4/wFE2f8AReC6ADTOEwAyywD///8A////AP///wD///8AADDNAAAyzCcARN7WACvG/wVfzf8d0vf/HM30/whf0/8AI7n/ADzV+AA40kUAMswA////AP///wD///8A////AAAwywAAPNdTAEfg/wAsw/8AOdb/ADLP/wAswv8AReP/AC7H/wA40f8AR+GfADDKAP///wD///8A////AP///wAAMswAADfRQgBY8f8AT+j/AE7o7AA+1/8AK8T/AE7o/wBN5f8AVe7/AD/ZbAAwywD///8A////AP///wD///8AADPMAAAyywAANM4vADjSUQA0zikAU+z3AEff/wBJ4sMAN9EtADjROQAyywAAM8wA////AP///wD///8A////AAAzzAAAM8wAADHLAAAwywAAMcsAAD/YXQBK4pYAN9AxAC/KAAAwygAAM8wAADPMAP///wD///8A+R8AAPAfAADABwAAwAMAAPgDAADwHwAA8AcAAOADAADAAwAAwAMAAMAHAADgBwAA4AcAAOAHAADwDwAA/j8AAA==";
var saveImg9 = "data:application/file;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAFwAAAGkAAABzAAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAADkAAAAP////AQAAAIdgZmj/YWlt/2FobP9haGz/YGhr/2Boa/9fZ2v/X2dr/15mav9dZWn/XGRo/0ZNUP8AAACdAAAAFf///wEAAACr2tzc/9ve4P/a3t//1dnZ/7S2tf+foJz/m5ya/6apqP/O0tP/09fZ/9DV1v+hqq//AAAAuQAAABX///8BAAAAq+3u7//e4eL/ub29/2hnXv9oVUX/U0As/zgxGf83Lx3/YWBX/7a5uv/S1tj/o6yx/wAAALkAAAAV////AQAAAKv29/f/19na/1dUQf9jXDv/dmtJ/4FoSP9VQiL/V0Ek/008Iv9HQTP/yc3P/6Wus/8AAAC5AAAAFf///wEAAACr+Pj4/5uamP9tY0L/g31b/6GLa/+McVH/eFY5/4xwUv9yXkD/RTki/4uMiv+nsLT/AAAAuQAAABX///8BAAAAq/n6+v+FfXL/waSM/8qznf/DrZP/ooFi/7WfhP+qh2//blk9/1A+Iv9aWlH/pK2x/wAAALkAAAAV////AQAAAKv6+/v/d3Rr/9zCsP/RxbH/z8Wu/9fJt//Qvab/qItv/5iOb/9tYUH/VVJK/6Wtsf8AAAC5AAAAFf///wEAAACr+/z8/4mHff+3pI//3NK//+HXxf/m3Mz/5trJ/9rMuf+bgWT/d14//2hnYP+osbX/AAAAuQAAABX///8BAAAAq/z9/f/FxL7/j4l+//Xw5f/29ez/8/Dl/+DMuv/VuaP/poZn/2dFKv+srav/oamt/wAAALkAAAAV////AQAAAKv+/v7/+/z8/5iZjf+5uqr/6+PW/+3i1P/kzL3/vZR+/4NhSf+Qh3z/z9HS/4qQkv8AAAC1AAAAFf///wEAAACr/v7+//7+/v/u7u3/tbiv/5WSgP+DfGj/e25Z/29gTv+sppz/vr6+/5aYmP90eHr/AAAApwAAABP///8BAAAAq/////////////////7+/v/9/f3//f39//v8/P/5+fn/1dXV/2pqav9TU1P/QUFB/wEBAYkAAAAJ////AQAAAKv7+/v//////////////////v7+//7+/v/+/v7/+vr6/9fY2P/V1tb/7Ozs/4KCgv8EBAQrAAAAA////wEAAACFlJSU/6ioqP+qqqr/qqqq/6qqqv+qqqr/qKio/6anp/2kpaX9o6Oj/4qKitUZGRk9////Af///wH///8BAAAAFQAAAFUAAABVAAAAVQAAAFUAAABVAAAAVQAAAFUAAABTBAQEUx8fH1dfX18z////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w==";
var loadImg = "data:image/x-icon;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////AQAAAB+yg2l71ZRt+daTa//Wk2v/1pNr/9aTa//Wk2v/v4NlywYEAycAAAAX////Af///wH///8B////Af///wHdo4M53Zx3/+Sgef/innb/4p52/+Kedv/lo3r/5aR6/+mqgfvPj27N////Af///wH///8B////Af///wH///8B4KSD8+mmff/opH3/56N6/+Whef/no3r/66qB/8KBXf/Fg1//0Y5s78+Pbqn///8B////Af///wH///8B////AeGlg//trIX/7ayE/+6thP/urIX/9bWL/8eFYf/GhF//yYZh/9SPa/nkn3j/////Af///wH///8B////Af///wHkn3j/76+G/+6uh//vrob/76+G//W3jP/GhF//y4di/9ONZ//XkWr/5J94/////wH///8B////Af///wH///8B5J94/++wif/wsIj/8LGJ//CxiP/0toz/y4di/8+KZf/vroP/766D/+SfeP////8B////Af///wH///8B////AeSfeP/xs4v/8bOL//Cziv/ws4v/87WL/9CNa+3QjWvt3p96/96fev/en3r/////Af///wH///8B////Af///wHkn3j/8rWN//K2jf/ytY3/8rWN//O2jvfdo4Lj0I5sJdCObCXQjmwl0I5sJf///wH///8B////Af///wH///8B5J94//O3j//zuI//87iP//O4j//zuZDx3aOD7////wH///8B////Af///wHdo4M/5J94/+SfeP/kn3j/5J94/++2j//zupH/9LqR//O6kv/0upL/87qR/+SfeP/kn3j/5J94/+SfeP////8B////Af///wHkoXr/9cCY//W8k//0vJT/9L2T//S8lP/0vZT/9LyU//S8lP/1vJT/9cCY/+Shev////8B////Af///wH///8B9b+WC+SjfP/2yqP/9b+W//a/lf/2v5X/9b6V//W+lv/1vpX/9sqj/+SjfP////8B////Af///wH///8B////Af///wH2wZgX5aZ+//fTrP/2wJj/9sCY//bAmP/2wZj/99Os/+Smf/////8B////Af///wH///8B////Af///wH///8B////Af///wHkqYH/99ax//fCmv/3wpn/99aw/+Sogf////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AeWrhP/317L/99ey/+WrhP////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B5a2F/+Wthf////8B////Af///wH///8B////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w==";
var moveToMenu = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKElEQVR42o3TMUvDQBQH8P+7tLlEwaW4ugl+iU6CCA4i0tbdqavgZ/ErCE79DsVBkYpKLR2kuApOatG297zLJWkqXnIPwrsk937cveQIJXHZBZt8cgFyzaEqYGuTvl7feM2FVAIHR8Bj341UAu1T4PPdjXgBJgzyPKDFy4SDIkJZo1yRASZ+FDB5Itzfct7YBGjuBBBh6oT6ed2OazGjsV3wQ2Cu64bXUKM7FgZJgPaufinTSVFhrDPFheVIe01nwLgfq9HNVCRAaw8Q6USWS4B05mgVIH2/qG+ABh+46im7heP9EELOLRDZpVqAQev8ZwUS/DBLivMtlDWxc7Ycs6yBhyov9vqMGcBBDB5/rxT7/Qfntjn/FXsDrmIvoHUonMVegMllx/kXlvSRMQ0GPE4AAAAASUVORK5CYII=";
var removeFromToolbar = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACMElEQVR42p3Sz2/SUBwA8G9pgQJd6QYZQQkOjUFdXMCLMn9B4l3myRgXhydPZgcTY2KyLfGiF/wT9GTmhfIXjMQ4NP5YD5qZTGdVdEx+9FVKSwttrTV4QD3AN3mH9837fr7v+/Kww1e4ic2HiSYMRGxufcHjxs87nQ5GN0zodnXQNLVomvCAL6ZR/xxmAS9VsX1umz1pJ/dfKGeD4+58OERNYQQO7Y4BWs8E3XCAqvRAEkWkdpTcNptm+4DpMVUOtboZl4tY2reXWmTGvbDTVKFnALicTrvYsFqbpgEOBw6tpgiigOb4Yoa1gTMzY1B+XUexKM1gLid8a3QgQHtBklQQBJm3RuAxDBiPl0z4aMq+eu1rFYmiFLOBowd8QJEEiLIBlbpV7PdArdZCApJX3j9O3e/Pe/Di0zTpJgvB8CSjSG1o7O7mbCA04QIHjoGsGuAfI6FRk0D8ISe3VlPc4OPGL61nab+/QDE0VD9/+T1CKOCCtqoDQRBAe0n4yH/nZUVLVtjTCP4R8cvPN8LRSKL6qVKygUjIC0rXAAMw6+EI6GkmoGaDM0DP8KuzfyHx+WfLe6KRpdpOlbMB+E9oWof78OhEcjB/5OqLbHAyUEB1oYTBCDFz7VWaYZg11BTYkYBj17lFyu3Lo5aYGwk4fuNNHgd8QVHk2EjA7K3NDVM3iuV708tDA2dXtqb0rr5mrWT57jQaGjh1+13eKio+uXOo9Gs/NJC6+TZhdf7zQ38Ceg0HgF1MCP0AAAAASUVORK5CYII=";
var iconADD = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACDUlEQVR42nWT30sUURTHz91Zd9FkVBRrX0oScTMI8weSIYSU/QMFbb5oGAn+AQo9B/UH9BAF+lIr+OLrSETQQ4GhEVRrUFkP/SLRNcvUnXv8nrmz7XVcB86cy7nn+5kz556ryHrueKxIYcFkPMmbxXHgzA6NDyguatQewBzHkKMMQDnWPgDsIwYh8/hATP8HQCRJEFIc5iA1DpljZIGogJU/9WXp39DR1pj99QBwe45dZb6UhCXE2Hx6m4xtQZQ/8SDni+DdSNopVYtysUiFpVbDqp4vPL4uCWc6zt+H+wvbAOBrCBCRFgh0AtIA6BboBVADc6eeZLMCGOq/kkF8Hcs8AO8tgDwav5M0AI/bw87Xw9dml+bvSUamtfsGYmuIrQDwKgIoQirkF3pR9uCbz28vx+tTMWo6VRdsL79eLax80yePtc3MTlwYKwMIT8HTvYufFkc+bq4NOjWN9Kf6cIVsHNr4sePnf9LxytqH06Od1w6oICGA9uZGOnvEpb7tgkrefLl8UXZvdTV5CYe3vv9Wzy6dVnfL9KAKfkcALeihaSKT+yj3Imji1XRPBvFyTTSn4LHMi5Y5SCnrGFc3c5MCqKtMD5c5RnsOisfILlmD1NxA5yThwy96GhkkRtlxrP3oIO0d5ZKXfSSbUYaJ1/tGef9lovAyUeQyAaKCO4nLpPRBABWJlwCWt6vYBccZ9A793wmLAAAAAElFTkSuQmCC";
var customBtn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjVJREFUeNqcUkuIUmEUPl4fML6bBsFRacRF2EaCcRO48bFLEIJcBIJLxb2b2UWLkIEgQQjauVFaKmgYuclUTMUHKoaKE4GPxnxh5r3ezh0QHJFmmA/OPZfDfx7fdw7AfojQ7qGx4QawdgMymeyRyWR6IZVKucFg8N10Ov0Ot4VGozmNRCLx5XL5F/HHbrefYZh7m1yWWq0+TafTn2kEdqXr9TrtcDje3JR4xRHH1QYCgXOz2Wzs9/sQj8dBIpEATtGrVqu9yWSywmdLNGq3AAeNsFgsz202mxk7QzKZBK1WCzqdjtHjKUmSx41Go4L+slQqpYvF4keKoibXpnA6nWfY+VehUKBSqRTJ0Oh2u3Qul6MHgwE9Ho9pLMD4H16v95zD4RxuU6BbrdYlPh5g8tfFYvET9XiIiRylUsnQgPl8DtgVhsOheL1eS6LRaGy1Wg02FAA5VmKxWB1/yUQioWOxWHKXy2XEYsDQEggEgKJCJpOBcrnMbOliW4MNSOaDCbVKpVISCoVGHBnQQygUgnK1AkeH9z+Ew+HX2xoQezZDjUaj3ygDiMViaLfbV8kK+TGw2WysJzzafry3QK1W+9Lr9RpIDbLZLEhE4vedTsdvMBieuN3ulwRBPLh2B7uYzWYXzWZzjBoc5PP5MJ70K1xfEsVc4cpNeDcnuLFvzM3978gILpcrRy/w+XybGE+v1z/z+/2frFarG9d5AHeBSqUyeDyetwqF4jHcFXw+/4TH44n+CTAA3Ccog288LRAAAAAASUVORK5CYII=";
var saveAll = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACOElEQVR42mNkwAJ+7xf7//3tKwZeIUELRqf3JxnwAEZkzrtlwnv/MzE6/WfkWCwS/iTu7RLO/wzMPAwc/z4Lc0f/eIfTgP/7BM0PXDY5ofB9N8M/EB8k+BcoyQw1mEWd4SurLIO97lkUFzX9b/oPNmBznc7/////MbAzfIdoBoI/P77Abfnzn4XhH9A0kOLA7icQV88HKn0EdcH6Ss3/yM76/f0jg2vTXYZ/f39j9fdUgQkMdTp1DNFXoiEGrCzFNMCj6SrD/79/MDQzsbAzCEfyMTBwADkbGBjBBiwrRDXgF9AAz6ZLWF1QIlHCsFRnKdj2pYxLIQYsytPAMMC75SLYBVMkpzDkPM+By0lFSTEwCDAwvJ79eouoqKgv2IB5WWgGfPvI4N95kUEyQQwcJVXbq8CGeEp6MlzUuQi2fcKbCQgDZqWhG/CJIaDrLIPMf0kGBjeggAoDw5YNWxh8rHwYGMQZGB5PfszAysq6RUJCAmLAtCR1DAMCu08zzJSZxtDm0cbA8AQoyAxJGyDbWx+2MrCwsGyRkZGBGDApDpsBx8FhME95HkObfhtYM4MqA8OdnjtgNSAXyMvLQwzoi8JmwGF4NGoc12Bg6IHYXnuzFm6AsrIyxIAJ+UHXfj27oomIhc9AA/ajpAOdPToMV1yuwPnMzMxbNDU14QaEAqnGH28fqYGywt/fP5i8q5czYUtIMABygY6ODsSAJUuWOKMrUFHT2PPvzy90YZhX/79//36dt7d3KACPfPJHOU7GxAAAAABJRU5ErkJggg==";

let cIDs = ["custombuttons-contextpopup-exportXML",
            "custombuttons-contextpopup-exportXML-sub"];
let bIDs = ["custombuttons-contextpopup-bookmarkButton",
            "custombuttons-contextpopup-bookmarkButton-sub"];
addMenuItem(cIDs, bIDs, "Сохранить код кнопки в XML файл", saveImg9,
            "document.getElementById('" + this.id
          + "').saveXML(('triggerNode' in this.parentNode) "
          + "? this.parentNode.triggerNode.URI "
          + ": document.popupNode.URI);", "X");
let xIDs = ["custombuttons-contextpopup-importnewbutton",
            "custombuttons-contextpopup-importnewbutton-sub"];
let aIDs = ["custombuttons-contextpopup-addnewbutton",
            "custombuttons-contextpopup-addnewbutton-sub"];
addMenuItem(xIDs, aIDs, "Добавить кнопку из XML файла\u2026", loadImg,
            "document.getElementById('" + this.id +
            "').loadXML();");          
let fIDs = ["custombuttons-contextpopup-copyImageURI",
            "custombuttons-contextpopup-copyImageURI-sub"];
let b2IDs = ["custombuttons-contextpopup-copyURI",
            "custombuttons-contextpopup-copyURI-sub"];            
addMenuItem(fIDs, b2IDs, "Копировать изображение кнопки в формате base64", saveImg1,
            "document.getElementById('" + this.id
          + "').copyImageURI();");
let f1IDs = ["custombuttons-contextpopup-saveButtonImage",
            "custombuttons-contextpopup-saveButtonImage-sub"];
addMenuItem(f1IDs, cIDs, "Сохранить изображение кнопки", saveImg8,
            "document.getElementById('" + this.id
          + "').saveImageURI();");  
let f2IDs = ["custombuttons-contextpopup-copyButtonsCodeText",
            "custombuttons-contextpopup-copyButtonsCodeText-sub"];
addMenuItem(f2IDs, b2IDs, "Копировать код кнопки как текст", saveImg2,
            "document.getElementById('" + this.id
          + "').copyButtonsCodeText();");                    
let f3IDs = ["custombuttons-contextpopup-copyAsHTML",
            "custombuttons-contextpopup-copyAsHTML-sub"];
addMenuItem(f3IDs, b2IDs, "Копировать код кнопки как HTML ссылку", saveImg3,
            "document.getElementById('" + this.id
          + "').copyToHTMLCode();");
let f4Ds = ["custombuttons-contextpopup-copyToBBCode",
            "custombuttons-contextpopup-copyToBBCode-sub"];
addMenuItem(f4Ds, b2IDs, "Копировать код кнопки как BBcode сылку", saveImg4,
            "document.getElementById('" + this.id
          + "').copyToBBCode();");          
let f5Ds = ["custombuttons-contextpopup-saveAsHTML",
            "custombuttons-contextpopup-saveAsHTML-sub"];
addMenuItem(f5Ds, bIDs, "Сохранить код кнопки в HTML файл", saveImg5,
            "document.getElementById('" + this.id
          + "').saveToHTMLCode();");
let f8Ds = ["custombuttons-contextpopup-saveAsHTMLAll",
            "custombuttons-contextpopup-AsHTMLAll-sub"];
addMenuItem(f8Ds, f5Ds, "Сохранить все кнопки в HTML файл", saveAll,
            "document.getElementById('" + this.id
          + "').saveToHTMLALLCode()");          
let f6Ds = ["custombuttons-contextpopup-getButtonId",
            "custombuttons-contextpopup-getButtonId-sub"];
let b1IDs = ["custombuttons-contextpopup-remove",
            "custombuttons-contextpopup-remove-sub"];            
addMenuItem(f6Ds, b1IDs, "Показать Id кнопки", saveImg6,
            "document.getElementById('" + this.id
          + "').idMIonclick(content.document);");
let f7Ds = ["custombuttons-contextpopup-addNextButton",
             "custombuttons-contextpopup-addNextButton-sub"];
   
                                        
var addMI = document.getElementById('custombuttons-contextpopup-addnewbutton');
addMI.setAttribute('image', iconADD);
var addMI1 = document.getElementById('custombuttons-contextpopup-addnewbutton-sub');
addMI1.setAttribute('image', iconADD);
var addMI2 = document.getElementById('custombuttons-contextpopup-move-moveToPanel');
addMI2.setAttribute('image', moveToMenu);
var addMI3 = document.getElementById('custombuttons-contextpopup-move-removeFromToolbar');
addMI3.setAttribute('image', removeFromToolbar);
var addMI4 = document.getElementById('custombuttons-contextpopup-customize');
addMI4.setAttribute('image', customBtn);

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Общие функци ////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

var options1 = {year: "numeric"};
var options2 = {day: "numeric", month: "long"};
var cDate = new Date().toLocaleDateString("ru-RU", options1);
var dDate = new Date().toLocaleDateString("ru-RU", options2);
var aDate = cDate + "г" + " " + dDate;

var options3 = {weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false};
var bDate = new Date().toLocaleDateString("ru-RU", options3);

var saveToFile = function (fileContent, fileName) {
    var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    uc.charset = 'utf-8';
    fileContent = uc.ConvertFromUnicode(fileContent);

    var nsIFilePicker = Components.interfaces.nsIFilePicker;
    var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
    fp.init(window, '', fp.modeSave);
    fp.defaultString = fileName;
    fp.appendFilters(fp.filterHTML);
    fp.appendFilters(fp.filterAll);
        fp.open(function (rv) {
        if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
              var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
              stream.init(fp.file, 0x02|0x20|0x08, 0666, 0);
              stream.write(fileContent, fileContent.length);
             stream.close();
             }
         });
};

/////////////////////////////////////////////////////////////////////////////
////////////////////////////Остальные функци ////////////////////////////////
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////// Показать Id кнопки ///////////////////////////////

this.idMIonclick = function idMIonclick() {
  var btn = document.popupNode.id;
  var box = custombuttons.confirmBox("Копировать в буфер", btn, "Да", "Нет");
  if (box) {
    custombuttons.cbService.writeToClipboard(btn);
    custombuttons.alertSlide(btn, "Скопирована в буфер");
} }
function  mostRecentWindow(windowType) {
  return Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow(windowType);
}

/////////////////////////////// Копировать изображение кнопки в формате base64 ///////////////////////////////

this.copyImageURI = function copyImageURI() {
    var btn = document.popupNode;
    if (!btn) return;
    cbu.gClipboard.write(btn.image);
  var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
  as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Изображение кнопки скопировано в буфер", false, "", null);
}

/////////////////////////////// Копировать код кнопки как текст ///////////////////////////////

this.copyButtonsCodeText = function copyButtonsCodeText() {
  var btn = document.popupNode;
  if (!btn) return;
  var code = ((btn.cbCommand == "") || (btn.Command == "/*CODE*/"))
              ? ""
              : ("\n/*CODE*/\n" + btn.cbCommand + "\n");
    var init = ((btn.cbInitCode == "") || (btn.cbInitCode == "/*Initialization Code*/"))
              ? ""
              : ("\n/*Initialization Code*/\n" + btn.cbInitCode);
    cbu.gClipboard.write(code + init);
    //custombuttons.alertSlide(btn.name, "Код скопирван в буфер");
    var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
        as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Код скопирван в буфер", false, "", null);

}

/////////////////////////////// Копировать код кнопки как HTML ссылку ///////////////////////////////

this.copyToHTMLCode = function copyToHTMLCode() {
  var btn = document.popupNode;
  if (!btn) return;
  var code = "<p><div id=\"install\" style=\"background: transparent -moz-linear-gradient(center top , rgb(224, 102, 255) 30%, rgb(125, 38, 205) 55%); text-shadow: 0pt -1px 0pt rgb(122, 55, 139); border: 1px outset rgb(85, 26, 139); border-radius: 1em; padding: 0; width: 240px; text-align: center;\"><a href=\"" + btn.URI + "\" style=\"display: block; padding: 1em; color: #ffffff; text-decoration: none;\" title=\"Click here to install " + btn.name + "\" rel=\"nofollow\"><img src=\"" + btn.image + "\" alt=\"" + btn.name + "\" style=\"vertical-align: middle; float: left;\"/>" + btn.name + "</a></div></p>";
  cbu.gClipboard.write(code);
  var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
  as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "HTML кнопки скопирован в буфер", false, "", null);

}

/////////////////////////////// Копировать код кнопки как BBcode сылку ///////////////////////////////

this.copyToBBCode = function copyToBBCode() {
  var btn = document.popupNode;
  if (!btn) return;
  var code = "[url=" + btn.URI + "][B]" + btn.name + "[/B][/url]";
  cbu.gClipboard.write(code); //.toXMLString());
  var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
  as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "BBCode кнопки скопирован в буфер", false, "", null);
}

/////////////////////////////// Сохранить изображение кнопки ///////////////////////////////

this.saveImageURI = function saveImageURI(btn) {
 
  var remove = gBrowser.removeCurrentTab.bind(gBrowser);
    var promiseTargetFile = async (...args) => {
        var res = await window.promiseTargetFile(...args);
        setTimeout(remove, 0);
        return res;
    }
    var internalSave = eval(`(${window.internalSave})`);
    var save = eval(`(${window.saveDocument})`);
     
     var btn = document.popupNode;
  if (!btn) return;
  
  (saveButtonImage = btn => {
        if (btn.image != "") {
            var tab = gBrowser.selectedTab;
            gBrowser.selectedTab = gBrowser.addTab(btn.image, {
                triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
            });
            setTimeout(function() {
                window.content.document.title = btn.name;
                save(window.content.document);
            }, 2000);
        } else
            custombuttons.alertBox("Эта кнопка не имееет изображения!");
    })(btn);
 
}



/////////////////////////////// Сохранить кнопку в XML файл ///////////////////////////////

this.saveXML = function saveXML(aStrURI) {
  var cbURI = (aStrURI != undefined) ? aStrURI : readFromClipboard();
  if (!cbURI || !/^custombutton\:\/\//.test(cbURI)) {
    custombuttons.uChelpButton(this);
    return;
  }
var topicURL = "http://forum.mozilla-russia.org/viewforum.php?id=34"
  var cbXML = cbURI.replace(/^custombutton\:\/\//, "");
  var decodeXML = unescape(cbXML);
  var btnName = decodeXML.match(/\<name\/?.+/).toString();
  var name = "untitled";
  if (!/\<name\/\>/.test(btnName)) {
    name = btnName.replace(/\<\/?\w+\>/g, "").toString();
  }
  var image = decodeXML.match(/\<image\/?.+/).toString();
  var icon = "";
  if (!/\<\image.*\[\].*\>$/.test(image)) {
    icon = image.match(/[^\[\]]+/g)[2].toString()
                .replace(/custombuttons\-stdicon\-\d/, "").toString();
  }

  function htmlEntities(str) {
      return str.replace(/&/g, "&amp;").replace(/</g, "&lt;")
                .replace(/>/g, "&gt;").replace(/"/g, "&quot;");
  }

  var xmlTemplate = "custombuttons/\"\n\
              xmlns:html=\"http://www.w3.org/1999/xhtml\">\n\
  <html:head>\n\
    <html:title><![CDATA[" + name + "]]></html:title>\n\
    <html:link rel=\"shortcut icon\" href=\"" + icon + "\"/>\n\
    <html:style type=\"text/css\"><![CDATA[\n\
body { font-size: medium; margin: 0; }\n\
body, code:before, help:before, initcode:before {\n\
  font-family: \"Verdana\", sans-serif;\n\
}\n\
#wrapper { position: fixed; top: 1em; right: 1em; text-align: center; }\n\
p { font-size: small; text-align: center; }\n\
#button {\n\
  background-color: rgb(85, 168, 2);\n\
  background-image: linear-gradient(to bottom, rgb(147, 200, 94),\
 rgb(85, 168, 2));\n\
  background-image: -moz-linear-gradient(top, rgb(147, 200, 94),\
 rgb(85, 168, 2));\n\
  background-image: -o-linear-gradient(top, rgb(147, 200, 94),\
 rgb(85, 168, 2));\n\
  background-image: -webkit-linear-gradient(top, rgb(147, 200, 94),\
 rgb(85, 168, 2));\n\
  border: 1px solid rgb(58, 116, 4);\n\
  border-radius: .5em;\n\
  -moz-border-radius: .5em;\n\
  -webkit-border-radius: .5em;\n\
  padding: 0;\n\
  margin-bottom: 1em;\n\
  box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\
  -moz-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\
  -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\
  -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\
}\n\
#button a {\n\
  color: #000;\n\
  text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5);\n\
  padding: 1em;\n\
  text-decoration: none;\n\
}\n\
:-moz-any-link:focus {\n\
  color: white;\n\
  outline-color: transparent;\n\
  text-decoration: none;\n\
}\n\
#button a, code, code:before, initcode, initcode:before, help, help:before {\
\n  display: block;\n\
}\n\
#credits { position: fixed; bottom: 1em; right: 1em; font-size: small; }\n\
custombutton { background-color: rgb(171, 171, 171); margin: 1em; }\n\
date, image, mode, accelkey { display: none; }\n\
name { font-weight: bold; font-size: x-large; }\n\
code:before, help:before, initcode:before {\n\
  font-weight: bold;\n\
  font-size: large;\n\
  margin: 0 0 1em;\n\
  padding: .5em;\n\
}\n\
code:before { content: \"Код\"; }\n\
help:before { content: \"Справка\"; }\n\
initcode:before { content: \"Инициализация\"; }\n\
code, initcode, help {\n\
  background-color: rgb(255, 255, 255);\n\
  border: 1px inset rgb(170, 170, 170);\n\
  font: medium monospace;\n\
  margin: 1em 1em 2em 0;\n\
  padding: 1em;\n\
  text-align: left;\n\
  width: 840px;\n\
  white-space: pre-wrap;\n\
  word-wrap: break-word;\n\
}\n\
.clear { clear: both; }\n\
]]></html:style>\n\
  </html:head>\n\
  <html:body>\n\
    <html:div id=\"wrapper\">\n\
      <html:div id=\"button\">\n\
        <html:a href=\"" + cbURI + "\" rel=\"nofollow\" title=\"Установить " +
        htmlEntities(name, "ENT_COMPAT") +"\">\n\
        <![CDATA[Установить кнопку]]>\n\
        </html:a>\n\
      </html:div>\n\
      <html:div id=\"credits\">\n\
        <html:a href=\"" + topicURL +"\">\n\
          <![CDATA[Другие кнопки]]><html:br/>\
<![CDATA[на форуме Mozilla Россия]]>\n\
        </html:a>\n\
      </html:div>\n\
    </html:div>\n\
  </html:body>";

  decodeXML = decodeXML.replace(/custombuttons\/\"\>/, xmlTemplate);

  name += ".xml";
  saveToFile(decodeXML, name);
 var btn = document.popupNode;
 var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
 as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в XML файл", false, "", null);
}
var mrw = mostRecentWindow('navigator:browser');
var css = '@-moz-document url("chrome://browser/content/browser.xul"){' + this.Help + '}';
var uri = makeURI('data:text/css,' + encodeURIComponent(css));
var sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
if (!sss.sheetRegistered(uri, sss.USER_SHEET)) sss.loadAndRegisterSheet(uri, sss.USER_SHEET);

/////////////////////////////// Добавить кнопку из XML файл ///////////////////////////////

this.loadXML = function loadXML() {
  var nsIFilePicker = Ci.nsIFilePicker;
  var fp = window.makeFilePicker();
  fp.init(window, "Установить кнопку из XML файла",
          nsIFilePicker.modeOpen);
  fp.appendFilters(fp.filterXML);
  fp.appendFilter("Все файлы", "*.*");
  fp.open(re=> { 
      if ( re == fp.returnOK ) gBrowser.selectedTab = gBrowser.addTrustedTab(fp.file.path);
   })

}


/////////////////////////////// Сохранить все кнопки в HTML файл ///////////////////////////////

this.saveToHTMLALLCode = function saveToHTMLALLCode() {
 var visibleCBbuttons = [...document.querySelectorAll('[cb-mode]')];
   var paletteCBbuttons = [...custombuttons.palette.querySelectorAll('[cb-mode]')];
   var allCBbuttons = visibleCBbuttons.concat(paletteCBbuttons);

var gn = btn => btn.getAttribute("label") || "Без названия";
allCBbuttons.sort((a, b) => gn(a).localeCompare(gn(b)));

var array = [];
   allCBbuttons.forEach(but=> {
      var uri = but.URI ? but.URI : getPaleteButtonsURI(but);
      var name1 = but.getAttribute("label") || "Без названия";
      var image = but.getAttribute("image") || "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACNFBMVEXDRgDweQDnbwC0NgDCRQC7PQDtpTu+QQD78q3PUwDCRAD//8vbYQDLTgDocAD0iQX1jQbGSgD7iAD4gwDVaw7vdwDyegD+igDweQDlawDyhAXveADmZwDzmBbtcwDwkhHveADmhBTkgxbweADkfRH+igD7hADXZQX0gADyjA/tfgvveQDiawDQVADRXgfnbwD1jAb9iQD9z0PVZAbxpinykRHtdgD5mRbERQDDRgDOYArCRAD9iQD3ewDxegD3dwDFRgDAQAD+hgD4fQDucgDtgQftfwTISQDCRQDvdgD5lxb1kRb2qh7wnynkagD766LDRQDDRwDDRQDspjbtpzbuqDbvqzv//8DUZAbCRQD//83pjhvveQbvggW+QQDfcxLlmUb//8veYADMTwDHSADVVwC8PgDwixb78q3oZgDUWADRVADCRQD9iQDERwDBQQDYVQC+PgC0NgDbYQDWWgDUWADSVQDFSAC+QAC7PAC0NgD+wRL+/kD+/zb+7i3+8Cv+/DX+wBL/+DD/rwz+qgz+rwz/tAz+sQzfbAT+3iP/+jD//Dz1jwP+nwf5iwf7pBz2tRr4lwb/ogfsdQT+2R7/9ET+2iT8yyLmgBL5iQL2egLokhP7zzT60zv1zUr0gAL1ewP50yn9+UL++EXooyngaAH41EPzowzyySj+xxzlhhHvvyruwjXxvTnUag3+zxrwigP+swz86U/ZXwD75lHqegD6xzb//kn+uhPTXAG3OAD/+UC2vFeJAAAAe3RSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAACfnwAIaelpAAA2+wD7UQAAa3oArKzRzMysnwgAvPQA/gAAw3prw0oALr16vS4AACnF6bspAAAA/mIAADQAAAAAAI8AAEwA0vv7kd2yAuuvr+vKABL23U+8Sk/d9vUDIIAQAAAQgCAfvupHAAABB0lEQVR4Xi3IU3fDABgA0C+u26FdZ9u2bdu2vZSzbds2/tyac3IfLxjpGyA6MimqY6gHTNgiiNwkwRM1E7EhTrYyTfMzzsh0ZEPiH+D6+u5mV1jEhpe5haVCYW1T4suEvUOkk7PLpVJ5WFnl7hEUDN5LPvsHJ6cazdn13f3DYxu0B35+/Y2qVSr17NzGeUgohIVHLK/PMDa39qKieRATGxd/9cS4uU1MwnmQktqY/qGlaVr7/ZOVDTmQm5df8PwyNj4xOTVdjOM4kCRZOr+wWFa+srpWQVEU8PnV2zu7NbV19UfHDQRBAIfTdNHc0soVdnR2dfdgGAgEvW99/QNc4eDQ8O8Ihv0D77NPgbVLZ6kAAAAASUVORK5CYII=";
      
      array.push("<li>\n<img src=" + image + ">&nbsp\<a href=" + uri + ">" + name1 +"</a><br>\n");
   });
   
   var before = "<html>\n<head>\n<title>Custom Buttons</title>\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n";
   var before1 = "<style type='text/css'>\nbody {background: beige;} a:link {color: black; text-decoration: none;} img {border: 0; margin: 0px 10px;}\n</style>\n";
   var before2 = "</head>\n<body>\nCustom Buttons\n<p>\n";
   var info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
   var before3 = info.vendor + " " + info.name + " " + info.version + " (build " + info.appBuildID + ")\n";
   var after = "\n</ol>\n</body>\n</html>";
    
   var text = before + before1 + before2 + before3 + "<p>\n" + bDate + "<p>\n" + "<ol>" + array.join("") + after;
   var name = "CB buttons " + aDate + ".html"
   saveToFile(text, name);

   var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
   alertsService.showAlertNotification(saveImg5, "Экспорт в HTML", "Экспортировал все CB кнопки как HTML");
   setTimeout(()=> alertsService.closeAlert(), 4000);
};


function getPaleteButtonsURI(but) {

   var uri = "chrome://custombuttons/content/nbftemplate.xml";
   var stream = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true}).open();
   var doc = new DOMParser().parseFromStream(stream, null, stream.available(), "application/xml");
   stream.close();
 
["help,Help", "name,label", "image,image", "mode,cb-mode", "initcode,cb-init", "accelkey,cb-accelkey", "code,cb-oncommand"]
   .forEach(str=> {
      var arr = str.split(',');
      var value = but.getAttribute(arr[1]), name = arr[0];
      custombutton.buttonSetText(doc, name, value, true);
   });

   var ser = new XMLSerializer();
   return "custombutton://" + escape(ser.serializeToString(doc));
};


/////////////////////////////// Сохранить кнопку в HTML файл ///////////////////////////////

this.saveToHTMLCode = function saveToHTMLCode() {
  var btn = document.popupNode;
  var xml = '<html xmlns="' + xhtmlns + '">\n';
      xml += '<head>\n';
      xml += '<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8"/>\n';
      xml += '<title>  ' + btn.name + ' для Custom Buttons </title>\n';
      xml += '<link rel="icon" type="image/vnd.microsoft.icon" href = "'+ btn.image +'" />\n';
      xml += '<style type="text/css">\n';
      xml += '.button a{ \n';
      xml += 'background-color: rgb(85, 168, 2); \n';
      xml += 'background-image: linear-gradient(to bottom, rgb(147, 200, 94), rgb(85, 168, 2)); \n';
      xml += 'background-image: -moz-linear-gradient(top, rgb(147, 200, 94), rgb(85, 168, 2)); \n';
      xml += 'border: 1px solid rgb(58, 116, 4); \n';
      xml += 'border-radius: .5em; \n';
      xml += ' -webkit-border-radius: .5em; \n';
      xml += 'padding: 0; \n';
      xml += 'margin-bottom: 1em; \n';
      xml += 'box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n';
      xml += ' -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n';
      xml += ' -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n';
      xml += ' color: #000; \n';
      xml += ' text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5); \n';
      xml += ' padding: 0.5em; \n';
      xml += ' text-decoration: none; \n';
      xml += '} ';
      xml += 'pre { border: 1px inset rgb(170, 170, 170); \n';
      xml += 'background-color: rgb(255, 255, 255);} \n';
      xml += 'body { background-color: rgb(245, 245, 220);} \n';
      xml += '</style> \n';
      xml += '</head>\n';
      xml += '<body>\n';
      xml += '<section id="install"><h1> ' + btn.name + ' </h1> \n';
      xml += '</section>\n';
      xml += '<div class="button"><a href = "' + btn.URI + '">Установить кнопку</a></div> \n';
      xml += '<section id="init"><h2>Инициализация</h2><pre>' + e4xConv_encodeHTML(btn.cbInitCode) + '</pre></section>\n';
      xml += '<section id="code"><h2>Код</h2><pre>' + e4xConv_encodeHTML(btn.cbCommand) + '</pre></section> \n';
      xml += '<section id="help"><h2>Справка</h2><pre>' + e4xConv_encodeHTML(btn.Help) + '</pre></section> \n';
      xml += '</body> \n';
      xml += '</html> ';
  var html = '<!DOCTYPE html>\n' + xml;
  var name = btn.name + ".HTML";
  saveToFile(html, name);
  var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
  as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в HTML файл", false, "", null);
}

function e4xConv_encodeHTML(s, isAttr) {
    s = String(s)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;");
    if(isAttr) {
        s = s
            .replace(/\t/g, "&#x9;")
            .replace(/\n/g, "&#xA;")
            .replace(/\r/g, "&#xD;");
    }
    return s;
};


/////////////////////////////// Переместить кнопку ///////////////////////////////

this.MoveToolbarButtons = MTB = {
    // Start editable preferences
    MoveButtonMICBContext: true, // Add "Move button" menu item to Custom Buttons context menu?
    MoveButtonMITBarContext: false, // Add "Move button" menu item to toolbars context menu?
    ShowMoveAlert: false, // Show the alert with instructions when moving buttons?
    MoveBtnImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAYklEQVQ4jWNgGJTgaAXHf2LEcGrGZQBBQ45WcPz/fZ0XpwG45FAUEDIAqzyyJLIiZIxNHqdmYvHRCo7/DLhsIEYziivQDcHnBawxgqyQUCzgjQlC6YCotEB2QkJWTIzY4AAAezv/caeCLKcAAAAASUVORK5CYII=",
    // End editable preferences

    _UID: "__cb_move_toolbar_buttons_" + custombuttons.getNumber(self.id),
    WindowIDs: ["main-window", "messengerWindow", "msgcomposeWindow"],
    ToolbarContexIDs: ["toolbar-context-menu", "aios-toolbar-contextmenu", "aios-sbhtoolbar-contextmenu"],
    Pref: "extensions.custombuttons.MoveToolbarButtons.Id" + custombuttons.getNumber(self.id) + ".MoveButtonID",
    SP: Services.prefs,

    Init: function() {
        if (!(MTB._UID in window)) {
            window[MTB._UID] = {
                Initialized: false
            };
        }

        if (!window[MTB._UID]["Initialized"]) {
            window[MTB._UID]["Initialized"] = true;
            custombuttons.isPref(MTB.Pref, "");

            if ("CustomizableUI" in window) {
                var originalFunction = custombuttons.persistCurrentSets.toString();
                eval("custombuttons.persistCurrentSets=" + originalFunction
                    .replace(", newButtonId)", ", newButtonId, aToRight)")
                    .replace("pos + 1", "aToRight ? pos : pos + 1"));
            }

            if (MTB.MoveButtonMICBContext) {
                var contextPops = document.getElementsByTagName("menupopup");
                let p = 0,
                    pLen = contextPops.length;
                for (; p < pLen; p++) {
                    var cPopID = contextPops[p].id;
                    if (cPopID.substr(0, 26) === "custombuttons-contextpopup") {
                        var cPopEl = document.getElementById(cPopID);
                        var moveMIID = "custombuttons-contextpopup-moveButton" + cPopID.slice(26);
                        var moveMIEl = document.getElementById(moveMIID);
                        if (!moveMIEl)
                            MTB.CreateMoveMI(moveMIID, cPopEl);
                    }
                }
            }

            if (MTB.MoveButtonMITBarContext) {
                Array.prototype.slice.call(MTB.ToolbarContexIDs).forEach(function(aTBCtxID, aIndex) {
                    let Ctx = document.getElementById(aTBCtxID);
                    let tBarCtxMIID = MTB._UID + "moveButton" + aIndex;
                    if (!document.getElementById(tBarCtxMIID)) {
                        if (Ctx) {
                            MTB.CreateMoveMI(tBarCtxMIID, Ctx);
                            Ctx.addEventListener("popupshowing", function(aE) {
                                document.getElementById(tBarCtxMIID).hidden = (document.popupNode.tagName !== "toolbarbutton");
                            }, false);
                        }
                    }
                });
            }

            addDestructor(function(aReason) {
                if (aReason === "delete") {
                    SP.resetUserPrefs(MTB.Pref);
                    delete window[_UID];
                }
                if (aReason === "delete" || aReason === "update") {
                    window[MTB._UID]["Initialized"] = false;
                }
            });
        }
    },

    getPopupNode: function(aEl) {
        if (custombuttons.popupNode)
            return custombuttons.popupNode;
        var popupNode = aEl;
        while (popupNode.tagName.toLowerCase() !== "toolbarbutton") {
            popupNode = popupNode.parentNode;
        }
        return popupNode;
    },

    CreateMoveMI: function(aMItemID, aPopupEl) {
        let moveMIEl = aPopupEl.appendChild(document.createElementNS(xulns, "menuitem"));
        moveMIEl.setAttribute("id", aMItemID);
        moveMIEl.setAttribute("label", "Переместить кнопку...");
        moveMIEl.setAttribute("class", "menuitem-iconic");
        moveMIEl.setAttribute("image", MTB.MoveBtnImage);
        moveMIEl.setAttribute("tooltip", MTB._UID + "moveButtonMI_tooltip");
        moveMIEl.setAttribute("onclick", "document.getElementById(\"" +
            self.id + "\").MoveToolbarButtons.MoveOnClick(event);");
    },

    MoveOnClick: function(aE) {
        var popupNode = MTB.getPopupNode(aE.target);
        if (!popupNode)
            return;
        aE.stopPropagation();
        aE.preventDefault();
        if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) {
            MTB.SP.setCharPref(MTB.Pref, popupNode.id);
            window.addEventListener('click', MTB.MoveListener, true);
            window.addEventListener('mouseup', MTB.DefaultPrevention, true);
            window.addEventListener('mousedown', MTB.DefaultPrevention, true);
            window.addEventListener('contextmenu', MTB.DefaultPrevention, true);
            MTB.HidePopup(aE.target);
            MTB.ShowMoveAlert && Services.prompt.alert(null, self.name,
                "Now click ANY toolbarbutton element inside ANY toolbar.\n" +
                "Left click will position the button to the left of the target.\n" +
                "Right click will position the button to the right of the target.\n\n" +
                "To cancel the movement, just click ANY element inside the browser that IS NOT a toolbarbutton.\n");
        }
    },

    MoveListener: function(aE) {
        MTB.DefaultPrevention(aE);
        window.removeEventListener('click', MTB.MoveListener, true);
        window.removeEventListener('mouseup', MTB.DefaultPrevention, true);
        window.removeEventListener('mousedown', MTB.DefaultPrevention, true);
        window.removeEventListener('contextmenu', MTB.DefaultPrevention, true);
        var anchor = aE.target;
        if (anchor.tagName !== "toolbarbutton")
            return;
        var toolbar = anchor.parentNode;
        var BtnToMove = document.getElementById(MTB.SP.getCharPref(MTB.Pref));
        if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey)
            toolbar.insertBefore(BtnToMove, anchor);
        else if (aE.button === 2 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey)
            toolbar.insertBefore(BtnToMove, anchor.nextSibling);
        if ("CustomizableUI" in window)
            custombuttons.persistCurrentSets(toolbar.id, anchor.id,
                BtnToMove.id || BtnToMove.getAttribute("id"), !(aE.button === 2));
        else {
            toolbar.setAttribute("currentset", toolbar.currentSet);
            document.persist(toolbar.id, "currentset");
        }
        MTB.SP.setCharPref(MTB.Pref, "");
    },

    DefaultPrevention: function(aE) {
        aE.preventDefault();
        aE.stopImmediatePropagation && aE.stopImmediatePropagation();
        aE.stopPropagation();
    },

    Tooltips: function(aRem) {
        var popSetID = MTB._UID + "popupset";
        var popSetEl = document.getElementById(popSetID);
        if (popSetEl)
            popSetEl.parentNode.removeChild(popSetEl);

        if (aRem)
            return;

        if (!popSetEl) {
            popSetEl = document.createElementNS(xulns, "popupset");
            popSetEl.setAttribute("id", popSetID);
        }

        popSetEl.appendChild(MTB.parseXML("<tooltip xmlns=\"" + xulns + "\" xmlns:html=\"" + xhtmlns +
            "\" id=\"" + MTB._UID + "moveButtonMI_tooltip" + "\">" +
            "<description><html:b>Instructions</html:b> : After clicking this menu item, you can " +
            "click ANY toolbarbutton element inside the application to place the currently " +
            "selected button to the left (with Left click) or to the right (with Right click) " +
            "of the targeted toolbarbutton.</description>" +
            "<separator/>" +
            "<description><html:b>Note</html:b> : It can be ANY toolbarbutton, not just " +
            "other Custom Buttons.</description>" +
            "</tooltip>"));

        setTimeout(function() {
            Array.prototype.slice.call(MTB.WindowIDs).forEach(function(aWinID) {
                let win = document.getElementById(aWinID);
                if (win)
                    !document.getElementById(popSetID) && win.appendChild(popSetEl);
            });
        }, 100);
    },

    parseXML: function(aXML) { // Return parsed XML
        aXML = aXML.replace(/>\s+</g, "><"); // Linearize XML
        return (new DOMParser).parseFromString(aXML, "application/xml").documentElement;
    },

    HidePopup: function(aEl) {
        try {
            aEl.hidePopup();
        } catch (aError) {
            try {
                aEl.parentNode.hidePopup();
            } catch (aError) {
                try {
                    aEl.parentNode.parentNode.hidePopup();
                } catch (aError) {
                    try {
                        aEl.parentNode.parentNode.parentNode.hidePopup();
                    } catch (aError) {}
                }
            }
        }
    }
};

this.MoveToolbarButtons.Init();

Отсутствует

 

№1348611-07-2019 10:28:41

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

Re: Custom Buttons

Andrey_Krropotkin
Благодарю.

Андрей, еще на досуге посмотрите, пожалуйста, пару кнопок.
1. Открыть в нижней панели. Неработающая

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

Выделить код

Код:

// Блокировать повторный запуск функций и обработчиков при открытии настройки панелей ........................


var icon = document.getAnonymousElementByAttribute( this, 'class', 'toolbarbutton-icon');
icon.style.width = '16px', icon.style.height = '16px';

this.bottomPanel = function(aURL) {
  var prefBranch = "custombuttons.bottomPanel."

  if(!aURL && aURL != "") {
    try {
      aURL = gPrefService.getCharPref(prefBranch + "url");
    } catch(ex) {
      aURL = "";
    }
  }
  if(aURL == "") return;

  if(aURL == gURLBar.value && !aURL.match(/^\w+?\:/)) aURL = "http://" + aURL;

  var panelID = "bottom-panel";
  var gPanel = document.getElementById(panelID);
  var height;
  try {
    height = gPrefService.getIntPref(prefBranch + "height");
  } catch(ex) {
    height = 400;
  }

  if(gPanel) {

    var src = gPanel.firstChild.nextSibling.getAttribute("src");
    if(aURL != src) {
      gPanel.firstChild.nextSibling.setAttribute("src", aURL);
      //gPanel.firstChild.nextSibling.loadURI(aURL);
    } else {
      gPrefService.setIntPref(prefBranch + "height", gPanel.height);
      gPanel.parentNode.removeChild(gPanel.previousSibling);
      gPanel.parentNode.removeChild(gPanel);
    }

  } else {

    var appContent = document.getElementById("appcontent");

    var spl = appContent.appendChild(document.createElementNS(xulns,"splitter"));
        spl.setAttribute("collapse", "after");
        spl.style.border = "none";
        spl.style.borderTop = "1px solid threedhighlight";
        spl.setAttribute("onclick", "this.setAttribute('state', '');");

    var box = appContent.appendChild(document.createElementNS(xulns,"hbox"));
        box.id = panelID;
        box.height = height;
        box.orient = "vertical";

    var tbr = box.appendChild(document.createElementNS(xulns,"toolbar"));
        tbr.setAttribute("fullscreentoolbar", true);

    var spr = tbr.appendChild(document.createElementNS(xulns,"spacer"));
        spr.setAttribute("flex", 1);

    var btn = tbr.appendChild(document.createElementNS(xulns,"toolbarbutton"));
        btn.style.listStyleImage = "url(chrome://global/skin/icons/Minimize.gif)";
        btn.minimize = function() {
          var gPanel = document.getElementById("bottom-panel");
          gPanel.previousSibling.setAttribute("state", "collapsed");
        }
        btn.setAttribute("oncommand", "this.minimize()");

    var btc = tbr.appendChild(document.createElementNS(xulns,"toolbarbutton"));
        btc.className = "tabs-closebutton";        
        btc.closePanel = function() {
          var gPanel = document.getElementById("bottom-panel");
         // gPrefService.setIntPref(prefBranch + "height", gPanel.height);
          gPanel.parentNode.removeChild(gPanel.previousSibling);
          gPanel.parentNode.removeChild(gPanel);
        }
        btc.setAttribute("id", "closeBottomPanel");
        btc.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACt0lEQVQ4jaWSzUtUYRTGn/fcGZ25H+m9Iyne8fpFq4lGCsFFIW21NiKKuHIn4qpazDraabnMTVEh+Af0B0QIIohBowhlkM1MMTre+VLngzv3PW1SKWvVWR0eOL/zcM4jmBn/U4G/iTuzsyK7unoLUl4HABDtdExNbV1fXr60Tfzp4J1h3Dd1/ak1OHhN7+kBiHCaTsPd2NgrlMsP7x4fv/0nYE3XH9ix2GLbzIwQmvYbmCsVHL16xd+3tx/dOTl5dqbTWfPeMIavOs6COT0tmBmyWAS1toJaWyGLRbCUMKemxFXHWXhvGMOXACrw2BwdJYUITX190MbG4O/twf/yBdrYGJr6+6EQwbx3j1QhHv8GWDfNNjUavR3u6ACyWQRjMQRsG+rkJNSJCQRsG8FYDDKbRbi9Harj3F43zbYLB41Gr2bbRIUCFACnS0vwMhkEbBsB24aXyaCcSEDJZiFyOWidnYRGo/f8jQpQp9NTiFwOACCJACEuDsgMeXAAuC7YMECeBwWonwOaLOtT/evXMhTlSs00oS8vI2jbqGcyADOau7pgvHiB8vg4tMND1F233GRZn87pzIwtXX9eiEb5uLubC2/ecC2V4qOhIT4aGuJqKsX516/52HG4EI3ylq4/P5s7z8FHy2qXnvehOxTqDBGhFongiusCAMqWhVA+j5qU+Far/RDB4M2BfP7gUpCSLS03qr7/NiyEExEC6i+9AsBlRpU5FVaU+zdKpeSlHCSTSazOzW0XNW2gCjzZ9/3Pu77Pu77P+77/uQo8cTVt4OXMzM7a2tpFlBOJhFhZWWkulUphz/NUKWWYmUPM3GwCKgBRAKoA6kRUI6JKIBCo6rpeGRkZqQlmRjqdxuLiIm1ublIul6NKpaI0Gg3yfV8AABFxMBiUoVBIRiIRPx6Py/n5eRmPx/ETBvM/dPD/rBwAAAAASUVORK5CYII=)";
        btc.setAttribute("oncommand", "this.closePanel()");

    var ifr = box.appendChild(document.createElementNS(xulns,"browser"));
        ifr.setAttribute("type", "content");
        ifr.setAttribute("flex", 1);
        ifr.setAttribute("src", aURL);
        ifr.setAttribute("tooltip", "aHTMLTooltip");
        ifr.setAttribute("onclick", "return contentAreaClick(event, true)");
        ifr.setAttribute("autocompletepopup", "PopupAutoComplete");
        ifr.setAttribute("contextmenu", "contentAreaContextMenu");
        ifr.setAttribute("contentcontextmenu", "contentAreaContextMenu");
  }

  gPrefService.setCharPref(prefBranch + "url", aURL);

}  
//------------------------------------

function addMenuitem(aLabel, aURL, aNode, aObjString) {
  var mItem = aNode.appendChild(document.createElementNS(xulns,"menuitem"));
  mItem.setAttribute("label", aLabel);
  mItem.setAttribute("oncommand",
                     aObjString + ".bottomPanel('" + aURL + "');");
}


function addSeparator(aNode, aNum) {
  var separator = aNode.appendChild(document.createElementNS(xulns,"menuseparator"));
  separator.id = "bottom-panel-button-separator" + aNum;
}

var mPopup = document.createElementNS(xulns,"menupopup");
mPopup.setAttribute("oncommand", "event.stopPropagation()");
mPopup.setAttribute("onpopupshowing", "this.parentNode.popupShowing(this)");



objString = "this.parentNode.parentNode";
addMenuitem("about:about", "about:about", mPopup, objString);
addMenuitem("about:config", "about:config", mPopup, objString);
addMenuitem("about:support", "about:support", mPopup, objString);
addMenuitem("about:memory", "about:memory", mPopup, objString);
addMenuitem("about:debugging", "about:debugging", mPopup, objString);
addMenuitem("about:cache", "about:cache", mPopup, objString);
addMenuitem("about:networking", "about:networking", mPopup, objString);
addMenuitem("about:performance", "about:performance", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Настройки", "about:preferences", mPopup, objString);
addMenuitem("Дополнения", "chrome://mozapps/content/extensions/extensions.xul?type=extensions", mPopup, objString);
addMenuitem("Менеджер Паролей", "chrome://passwordmgr/content/passwordManager.xul", mPopup, objString);
addMenuitem("DOM Inspector", "chrome://inspector/content/inspector.xul", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Загрузки", "about:downloads", mPopup, objString);
addMenuitem("Управление закладками", "chrome://browser/content/places/places.xul", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Домашняя страница", "about:home", mPopup, objString);
addMenuitem("Текущая страница", "' + gBrowser.currentURI.spec + '", mPopup, objString);



this.appendChild(mPopup);
this.type = "menu";
this.orient = "horizontal";


function handleKeydown(e) { 
  if ( !e.shiftKey && !e.altKey && !e.ctrlKey && e.keyCode == 27 ) {
       if ( !document.getElementById('closeBottomPanel') ) return;
            e.preventDefault();
            e.stopPropagation();
            document.getElementById('closeBottomPanel').click();
       };  
}
window.addEventListener('keydown', handleKeydown, false);



// ===== HIDE DROPMARKER IN BUTTON =====

var that = this;
this.hideDropMarker = function() {
  var dropMarker = document.getAnonymousElementByAttribute(that, "class", "toolbarbutton-menu-dropmarker");
  if (dropMarker) {
    dropMarker.setAttribute("hidden", "true");
  } else {
    setTimeout(that.hideDropMarker, 10);
  }
}
this.hideDropMarker();


2. Открыть 'about:config'
скрытый текст

Выделить код

Код:

// Настройка функций кликов мыши(Mouse Click settings) .......................................................
this.onclick = function(e) {
     if ( e.button == 0 ) getBrowser (). selectedTab = getBrowser (). addTrustedTab("about:config");  
     
     if ( e.button == 1 ) { 
          // запомнить текст из буфера обмена и скопировать текст на странице ....
          var clip = gClipboard.read();
          window.content.focus();
          goDoCommand("cmd_copy");            

          gBrowser.selectedTab = gBrowser.addTrustedTab( 'about:config' ); 
          
          // oбработчик ждет пока откроется "about:config", вставит текст из буфера обмена и удаляет себя ....
          gBrowser.addEventListener("pageshow", function(e) {               
               this.removeEventListener("pageshow", arguments.callee, true);
                
               content.document.getElementById("textbox").value = gClipboard.read(); 
               content.document.getElementById("textbox").doCommand();               
                                  
               if ( clip ) gClipboard.write( clip ); // вернуть текст в буфер обмена
          }, true);
          }   
};

 
// Создать меню ..............................................................................................
this.ss = [
     { label:"Все about:", value: 'about:about'},
     { label:"О плагинах", value: 'about:plugins'},
     { label:"Новая вкладка", value: 'about:newtab'},
     { label:"Настройки как таб", value: 'about:preferences'},
     { label:"Информация о кэше", value: 'about:cache'},   
     { label:"Восстановление сессии", value: 'about:sessionrestore'},
     { label:"Управление разрешениями", value: 'about:permissions'},
     { label:"Информация для решения проблем", value: 'about:support'},
     { label:"Показать исплъзование памяти подробно", value: 'about:memory'}
          ];
             
this.mObj = custombuttons.getCbContextObj(this);
this.init = function(x) {
   x.mObj.setSub();
   var nItem = {}, mItem = {};
   document.getElementById(CB2const.sCBCtxtMenu).setAttribute("oncommand", "event.stopPropagation()");
   for ( var i in x.ss ) {
         nItem = new x.mObj.getItem();
         nItem.label = x.ss[i].label;
         if ( nItem.label == "separator" ) var nItem = document.createElementNS(xulns,"menuseparator");
         var mItem = x.mObj.insertBefore(nItem, x.mObj.oMenu.lastChild);
         mItem.setAttribute('onclick', 'getBrowser().selectedTab = getBrowser().addTrustedTab("' + x.ss[i].value + '")');           
         };   
   x.mObj.getItem();
   nItem = x.mObj.getItem();
   this.separator = x.mObj.insertBefore( nItem , x.mObj.oMenu.lastChild);
};
this.init(this);



// Подсказка кнопки ............................................................................................
this.tooltipText = "Л: Открыть 'about:config'\nС: Открыть 'about:config' с настройкой ( выделенной или из буфера )\nП: Показать все about:";


Здесь работает пункт nС: Открыть 'about:config' с настройкой ( выделенной или из буфера )

Отредактировано Garalf (11-07-2019 10:32:35)

Отсутствует

 

№1348711-07-2019 10:33:03

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

Re: Custom Buttons

Garalf пишет

Открыть в нижней панели

проверьте

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

Выделить код

Код:

// Блокировать повторный запуск функций и обработчиков при открытии настройки панелей ........................


var icon = this.icon ||document.getAnonymousElementByAttribute( this, 'class', 'toolbarbutton-icon');
icon.style.width = '16px', icon.style.height = '16px';

this.bottomPanel = function(aURL) {
  var prefBranch = "custombuttons.bottomPanel."

  if(!aURL && aURL != "") {
    try {
      aURL = gPrefService.getCharPref(prefBranch + "url");
    } catch(ex) {
      aURL = "";
    }
  }
  if(aURL == "") return;

  if(aURL == gURLBar.value && !aURL.match(/^\w+?\:/)) aURL = "http://" + aURL;

  var panelID = "bottom-panel";
  var gPanel = document.getElementById(panelID);
  var height;
  try {
    height = gPrefService.getIntPref(prefBranch + "height");
  } catch(ex) {
    height = 400;
  }

  if(gPanel) {

    var src = gPanel.firstChild.nextSibling.getAttribute("src");
    if(aURL != src) {
      gPanel.firstChild.nextSibling.setAttribute("src", aURL);
      //gPanel.firstChild.nextSibling.loadURI(aURL);
    } else {
      gPrefService.setIntPref(prefBranch + "height", gPanel.height);
      gPanel.parentNode.removeChild(gPanel.previousSibling);
      gPanel.parentNode.removeChild(gPanel);
    }

  } else {

    var appContent = document.getElementById("appcontent");

    var spl = appContent.appendChild(document.createXULElement("splitter"));
        spl.setAttribute("collapse", "after");
        spl.style.border = "none";
        spl.style.borderTop = "1px solid threedhighlight";
        spl.setAttribute("onclick", "this.setAttribute('state', '');");

    var box = appContent.appendChild(document.createXULElement("hbox"));
        box.id = panelID;
        box.height = height;
        box.orient = "vertical";

    var tbr = box.appendChild(document.createXULElement("toolbar"));
        tbr.setAttribute("fullscreentoolbar", true);

    var spr = tbr.appendChild(document.createXULElement("spacer"));
        spr.setAttribute("flex", 1);

    var btn = tbr.appendChild(document.createXULElement("toolbarbutton"));
        btn.style.listStyleImage = "url(chrome://global/skin/icons/Minimize.gif)";
        btn.minimize = function() {
          var gPanel = document.getElementById("bottom-panel");
          gPanel.previousSibling.setAttribute("state", "collapsed");
        }
        btn.setAttribute("oncommand", "this.minimize()");

    var btc = tbr.appendChild(document.createXULElement("toolbarbutton"));
        btc.className = "tabs-closebutton";        
        btc.closePanel = function() {
          var gPanel = document.getElementById("bottom-panel");
         // gPrefService.setIntPref(prefBranch + "height", gPanel.height);
          gPanel.parentNode.removeChild(gPanel.previousSibling);
          gPanel.parentNode.removeChild(gPanel);
        }
        btc.setAttribute("id", "closeBottomPanel");
        btc.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACt0lEQVQ4jaWSzUtUYRTGn/fcGZ25H+m9Iyne8fpFq4lGCsFFIW21NiKKuHIn4qpazDraabnMTVEh+Af0B0QIIohBowhlkM1MMTre+VLngzv3PW1SKWvVWR0eOL/zcM4jmBn/U4G/iTuzsyK7unoLUl4HABDtdExNbV1fXr60Tfzp4J1h3Dd1/ak1OHhN7+kBiHCaTsPd2NgrlMsP7x4fv/0nYE3XH9ix2GLbzIwQmvYbmCsVHL16xd+3tx/dOTl5dqbTWfPeMIavOs6COT0tmBmyWAS1toJaWyGLRbCUMKemxFXHWXhvGMOXACrw2BwdJYUITX190MbG4O/twf/yBdrYGJr6+6EQwbx3j1QhHv8GWDfNNjUavR3u6ACyWQRjMQRsG+rkJNSJCQRsG8FYDDKbRbi9Harj3F43zbYLB41Gr2bbRIUCFACnS0vwMhkEbBsB24aXyaCcSEDJZiFyOWidnYRGo/f8jQpQp9NTiFwOACCJACEuDsgMeXAAuC7YMECeBwWonwOaLOtT/evXMhTlSs00oS8vI2jbqGcyADOau7pgvHiB8vg4tMND1F233GRZn87pzIwtXX9eiEb5uLubC2/ecC2V4qOhIT4aGuJqKsX516/52HG4EI3ylq4/P5s7z8FHy2qXnvehOxTqDBGhFongiusCAMqWhVA+j5qU+Far/RDB4M2BfP7gUpCSLS03qr7/NiyEExEC6i+9AsBlRpU5FVaU+zdKpeSlHCSTSazOzW0XNW2gCjzZ9/3Pu77Pu77P+77/uQo8cTVt4OXMzM7a2tpFlBOJhFhZWWkulUphz/NUKWWYmUPM3GwCKgBRAKoA6kRUI6JKIBCo6rpeGRkZqQlmRjqdxuLiIm1ublIul6NKpaI0Gg3yfV8AABFxMBiUoVBIRiIRPx6Py/n5eRmPx/ETBvM/dPD/rBwAAAAASUVORK5CYII=)";
        btc.setAttribute("oncommand", "this.closePanel()");

    var ifr = box.appendChild(document.createXULElement("browser"));
        ifr.setAttribute("type", "content");
        ifr.setAttribute("flex", 1);
        ifr.setAttribute("src", aURL);
        ifr.setAttribute("tooltip", "aHTMLTooltip");
        ifr.setAttribute("onclick", "return contentAreaClick(event, true)");
        ifr.setAttribute("autocompletepopup", "PopupAutoComplete");
        ifr.setAttribute("contextmenu", "contentAreaContextMenu");
        ifr.setAttribute("contentcontextmenu", "contentAreaContextMenu");
  }

  gPrefService.setCharPref(prefBranch + "url", aURL);

}  
//------------------------------------

function addMenuitem(aLabel, aURL, aNode, aObjString) {
  var mItem = aNode.appendChild(document.createXULElement("menuitem"));
  mItem.setAttribute("label", aLabel);
  mItem.setAttribute("oncommand",
                     aObjString + ".bottomPanel('" + aURL + "');");
}


function addSeparator(aNode, aNum) {
  var separator = aNode.appendChild(document.createXULElement("menuseparator"));
  separator.id = "bottom-panel-button-separator" + aNum;
}

var mPopup = document.createXULElement("menupopup");
mPopup.setAttribute("oncommand", "event.stopPropagation()");
mPopup.setAttribute("onpopupshowing", "this.parentNode.popupShowing(this)");



objString = "this.parentNode.parentNode";
addMenuitem("about:about", "about:about", mPopup, objString);
addMenuitem("about:config", "about:config", mPopup, objString);
addMenuitem("about:support", "about:support", mPopup, objString);
addMenuitem("about:memory", "about:memory", mPopup, objString);
addMenuitem("about:debugging", "about:debugging", mPopup, objString);
addMenuitem("about:cache", "about:cache", mPopup, objString);
addMenuitem("about:networking", "about:networking", mPopup, objString);
addMenuitem("about:performance", "about:performance", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Настройки", "about:preferences", mPopup, objString);
addMenuitem("Дополнения", "chrome://mozapps/content/extensions/extensions.xul?type=extensions", mPopup, objString);
addMenuitem("Менеджер Паролей", "chrome://passwordmgr/content/passwordManager.xul", mPopup, objString);
addMenuitem("DOM Inspector", "chrome://inspector/content/inspector.xul", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Загрузки", "about:downloads", mPopup, objString);
addMenuitem("Управление закладками", "chrome://browser/content/places/places.xul", mPopup, objString);
addMenuitem("Куки", "chrome://browser/content/preferences/siteDataSettings.xul", mPopup, objString);
addMenuitem("История", "chrome://browser/content/places/historySidebar.xul", mPopup, objString);
addMenuitem("О Firefox", "chrome://browser/content/aboutDialog.xul", mPopup, objString);
addSeparator(mPopup, 0);
addMenuitem("Домашняя страница", "about:newtab", mPopup, objString);
addMenuitem("Текущая страница", "' + gBrowser.currentURI.spec + '", mPopup, objString);



this.appendChild(mPopup);
this.type = "menu";
this.orient = "horizontal";


function handleKeydown(e) { 
  if ( !e.shiftKey && !e.altKey && !e.ctrlKey && e.keyCode == 27 ) {
       if ( !document.getElementById('closeBottomPanel') ) return;
            e.preventDefault();
            e.stopPropagation();
            document.getElementById('closeBottomPanel').click();
       };  
}
window.addEventListener('keydown', handleKeydown, false);


на второй вопрос писал выше "getBrowser ()" заменить везде на "gBrowser"

Отредактировано Andrey_Krropotkin (11-07-2019 10:39:24)

Отсутствует

 

№1348811-07-2019 11:08:23

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

Re: Custom Buttons

Andrey_Krropotkin пишет

Открыть в нижней панели

Отлично. Работает
2. Открыть 'about:config' - работает.

Отредактировано Garalf (11-07-2019 11:14:45)

Отсутствует

 

№1348911-07-2019 11:12:35

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

Re: Custom Buttons

Garalf пишет

Вроде все заменил и перепроверил

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

Выделить код

Код:

/*Initialization Code*/
// Настройка функций кликов мыши(Mouse Click settings) .......................................................
this.onclick = function(e) {
     if ( e.button == 0 ) gBrowser. selectedTab = gBrowser. addTrustedTab("about:config");  
     
     if ( e.button == 1 ) { 
          // запомнить текст из буфера обмена и скопировать текст на странице ....
          var clip = gClipboard.read();
        //  window.content.focus();
          goDoCommand("cmd_copy");            

          gBrowser.selectedTab = gBrowser.addTrustedTab( 'about:config' ); 
          
          // oбработчик ждет пока откроется "about:config", вставит текст из буфера обмена и удаляет себя ....
          gBrowser.addEventListener("pageshow", function(e) {               
               this.removeEventListener("pageshow", arguments.callee, true);
                
               content.document.getElementById("textbox").value = gClipboard.read(); 
               content.document.getElementById("textbox").doCommand();               
                                  
               if ( clip ) gClipboard.write( clip ); // вернуть текст в буфер обмена
          }, true);
          }   
};

 
// Создать меню ..............................................................................................
this.ss = [
     { label:"Все about:", value: 'about:about'},
     { label:"О плагинах", value: 'about:plugins'},
     { label:"Новая вкладка", value: 'about:newtab'},
     { label:"Настройки как таб", value: 'about:preferences'},
     { label:"Информация о кэше", value: 'about:cache'},   
     { label:"Восстановление сессии", value: 'about:sessionrestore'},
     { label:"Управление разрешениями", value: 'about:permissions'},
     { label:"Информация для решения проблем", value: 'about:support'},
     { label:"Показать исплъзование памяти подробно", value: 'about:memory'}
          ];
             
this.mObj = custombuttons.getCbContextObj(this);
this.init = function(x) {
   x.mObj.setSub();
   var nItem = {}, mItem = {};
   document.getElementById(CB2const.sCBCtxtMenu).setAttribute("oncommand", "event.stopPropagation()");
   for ( var i in x.ss ) {
         nItem = new x.mObj.getItem();
         nItem.label = x.ss[i].label;
         if ( nItem.label == "separator" ) var nItem = document.createElementNS(xulns,"menuseparator");
         var mItem = x.mObj.insertBefore(nItem, x.mObj.oMenu.lastChild);
         mItem.setAttribute('onclick', 'gBrowser.selectedTab = gBrowser.addTrustedTab("' + x.ss[i].value + '")');           
         };   
   x.mObj.getItem();
   nItem = x.mObj.getItem();
   this.separator = x.mObj.insertBefore( nItem , x.mObj.oMenu.lastChild);
};
this.init(this);



// Подсказка кнопки ............................................................................................
this.tooltipText = "Л: Открыть 'about:config'\nС: Открыть 'about:config' с настройкой ( выделенной или из буфера )\nП: Показать все about:";

Отредактировано Andrey_Krropotkin (11-07-2019 11:20:37)

Отсутствует

 

№1349011-07-2019 13:28:25

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

Re: Custom Buttons

Сегодня автоматически обновился браузер до v68 и СВ перестал работать.
Думаю сразу установить 69, а после буду манипулировать с CВ чтоб заставить его работать.
Только вот я не пойму откуда его выкачать. На офсайте для скачивания только 68
https://www.mozilla.org/ru/firefox/

Погуглил 69 и нашел на других сайтах эту версию, но опасаюсь устанавливать с непроверенных источников.
Подскажите пожалуйста где скачать 69

Отсутствует

 

№1349111-07-2019 13:38:57

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

Re: Custom Buttons

leex что 68, что 69 разницы нет, скачивать надо с сайта https://www.mozilla.org/ru/ (вкладка разработчикам), 69 сейчас в стадии beta.
СВ последняя работает на 68

Отсутствует

 

№1349211-07-2019 14:42:19

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

Re: Custom Buttons

custom_buttons-0.0.7.0.0.5-fx-paxmod.xpi
установился в списке с расширениями появился но не работает.
config.js и config-prefs.js. есть

А custom_buttons-0.0.7.0.0.5-fx-bootstrap.xpi не устанавливается хотя все разрешения для неподписанных имеются.
Закидывал его в ручную папку \extensions Но он так и не появился в списке с расширениями
bootstrap-loader.js долженн быть в корневой Мозилы? C:\Program Files (x86)\Mozilla Firefox\bootstrap-loader.js

Может быть 68 версия что загрузилась автоматом имеет свежие фиксы отличные от вашей 68 ?

Отсутствует

 

№1349311-07-2019 15:16:08

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

Re: Custom Buttons

leex в config.js для CB-paxmod.xpi допиши, то что в bootstrap-loader.js и установи custom_buttons-0.0.7.0.0.5-fx-bootstrap.xpi и все появиться, потом можешь сверху установить custom_buttons-0.0.7.0.0.5-fx-paxmod.xpi и все будет работать.
Дальше надо установить однопроцессорный режим по методу Dumby мой пост

Отредактировано Andrey_Krropotkin (11-07-2019 15:22:12)

Отсутствует

 

№1349411-07-2019 16:51:59

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

Re: Custom Buttons

Andrey_Krropotkin

Скопировал содержимое bootstrap-loader.js в config.js
установил однопроцессорный режим  и все заработало!

Спасибо :)

Отсутствует

 

№1349511-07-2019 18:38:33

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

Re: Custom Buttons

"Непереводмиый" сайт https://discourse.mcneel.com оказалось поддается переводу на русский в ФФ Квантум только при помощи Translate API
Я активировал Яндекс

Этот сайт сделан на движке Discourse https://www.discourse.org/about  и данные этого сайта не могут подхватить сторонние переводчики в ФФ Квантум. То-ли технологии несовместимы то-ли что-то еще. А раньше до 56 версии ФФ, эти сайты переводились в текущей вкладке гугловским виджетом.


Но вот непонятные странности. Кнопка встроенного переводчика, то появляется на этом сайте, а то ее совсем нет.
На других иностранно-язычных ресурсах она появляется всегда.
А в контекстном меню страницы  нет пункта от Translate API "перевести страницу" Например в Хроме этот пункт в контекстном меню страницы есть

Возможно ли сделать кнопку встроенного переводчика всегда активной при помощи CB или продублировать ее функционал в стандартной СВ кнопке?
вот так она выглядит если активировать Translate API
d6bcad7389aed7440d46d480d0772ba0.jpeg

Отредактировано leex (11-07-2019 22:44:08)

Отсутствует

 

№1349611-07-2019 23:10:36

anywho
Забанен
 
Группа: Members
Зарегистрирован: 21-05-2019
Сообщений: 54
UA: Firefox 68.0

Re: Custom Buttons

"Отменить" в 68 не так работает, крестик приходиться жать 2 раза...СВ - все перепробовал.
Да, и на этом форуме пароль вылезает при переходе....

Отсутствует

 

№1349712-07-2019 17:48:18

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

Re: Custom Buttons

Dumby

В 69b4 в about:addons у CB появилось предупреждение Работа расширения не может быть проверена,
поэтому оно было отключено. Но расширение работает, хотя и перенесено в отключенные.
ps все - отключилось CB, не работает

Отредактировано Garalf (12-07-2019 19:20:18)

Отсутствует

 

№1349812-07-2019 21:32:49

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

Re: Custom Buttons

Garalf пишет

В 69b4 в about:addons у CB появилось предупреждение Работа расширения не может быть проверена,
поэтому оно было отключено. Но расширение работает, хотя и перенесено в отключенные.
ps все - отключилось CB, не работает

Не получается воспроизвести на 69.0b4. Ни на бете, ни на Developer Edition.
Add Toolbar Buttons 2019.5.24 тоже работает.
Может проверь папку установки, всё ли в порядке с конфигурацией.

Отсутствует

 

№1349912-07-2019 22:45:26

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

Re: Custom Buttons

Dumby Вот нашел код , который работает для многопроцессорного режима

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

Выделить код

Код:

(function () {
    if (location != 'chrome://browser/content/browser.xul')
        return;
    let translate = function () {
        let browserMM = gBrowser.selectedBrowser.messageManager;
        browserMM.addMessageListener('getSelection', function listener(message) {
            let t = (message.data !== '');
            let e = (document.charset || document.characterSet);
            if (t) {
                openWebLinkIn('https://translate.google.com/#view=home&op=translate&sl=auto&tl=ru&text=' + encodeURIComponent(message.data), 'tab');
            } else {
                openWebLinkIn('https://translate.google.com/translate?u=' + encodeURIComponent(gBrowser.currentURI.spec) + '&hl=de-DE&ie=' + e + '&sl=auto&tl=ru-RU', 'tab');
            };
            browserMM.removeMessageListener('getSelection', listener, true);
        });
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelection", content.document.getSelection().toString())', true);
    }
    let menuitem = document.createElement('menuitem');
    menuitem.id = 'context-googletranslate';
    menuitem.setAttribute('label', 'Перевести на русский');
    menuitem.setAttribute('tooltiptext', 'Перевод текста и страниц в новой вкладке');
    menuitem.setAttribute('oncommand', '(' + translate.toString() + ')()');
    menuitem.classList.add('menuitem-iconic');
    menuitem.style.listStyleImage = ' url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAwCAYAAABT9ym6AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAHYklEQVRoQ+2Y6U+UVxSH9Xs/NGnSv6et1h1REWOrUEaomiZt2tQqRQFFcNiRImg1rnVBbZUoorhRYNhGZweGfYcBoQ6bn0/Pue+9w7vcGRhpRz94kidDDHn5PZ5z7tyZFR/qfS4AWGkq9ZtiimZGY4vfQOzJBbZzYjjbioxsLVTYwvnu1MRH/NGRrfiSKRMT4IjwGgGBWoAjBKI5URn92/ijI1sxhbwTOhEhIRMREjKRjVnjtfzRkS2ZhLQbxBJEogvewDfpjo/54yNX6vB6icVEhIReZMOR7h388ZGrcCVkIgEJLvJOxksmEEpESIQSeSfjtagAwSVk3dCIcAnWlcN9sfxPRKZCChASicW6sRkxlb4Gm70LenuHYWTUBz6fD8bHx9mrYGxsjDE6OmpgZGQkwPDw8Fh//9BXPLK8pOEFXCCYRLBukAhx+6Eb2r19GIaCj8PExASTEeiF1Mjkurp6vuaxjbWYwJIkCJ0EcfyPPmhsckJ3zwCG04rIOrOYyMDAwDCPbSx9aD0U3vT7PFyvm4XW/mmYnPLD1D9+aMefr9fPQsKZeWk3iPiSSairt4Pd3gpDw6PSboQjQvDYxpKFJ0QHcu7NwcTUNPj9finjk344envOIBGVr0Dj1WJ1Q2urF2d9ZFkitC88trFEYBkk8VoVumNwGu5ZZxn0M/1b56Af9mDH1CJCgqDxsjQ4wOlqBa+3kwWKqAiNk+gEjVJh5axmL+jn/HuzEF+mlVCLbELifhPj5YG29g5c2C4WKJQEsSwR9SJfw50QnSh9hKOD/6YBAwtkEkKEuF1F4+UCj6cdOjo6mQweqWF1gwgpog6vhhabJAZ800zybSWIwHg5lfHq7OyE7u5uJvO/ilBYOp1I5LlrxiAgOqXnsWPGILEpTxmv2jo72GzKeHV0KCOWmJoDSUcLlyRCEiFFAiF1aES4wGIiNe4Zg4TgVpUrMF5e74LIntRcTWdkEsRbi3j6lNEaFKPFJWiECu7PBjhdvbBLd5pmg4psPfwMdh/IgfhkM5gOZ8OeIwSKIIko8+2xAtibUYSvCyQdKwxDhAfUc7V2IWBZ9ZxmFwQ0RmefLPyeuWJOKrERicoahDgUSUhGAexEYmo2JKblQhKRjiJH85iMWkKICIm3EqFjdfyVEpCO3+Iq5eQSAgQFFyM4OObHN9J5qYTg1gMXNLe4wO1uC4wXQYtP5J67ijtTAPee1gU68VYi+v/xrDvaN8SuoWmofDED960z0D6gfbc/jr8bSmJD7jxkXOmDeosNXtpc0Nbm1YjYXW7sTD52Jh+8Xd1SiZAi+vB6SMbHOyPjFXakEHdFLSCTIHYVT8KveRcg/qAZii/fCpxeJFJy5SZb/KKL5Xj172UHwLJFxOgIdpfOw5W/Z8HdO43BlYtjG3akvH4GEs9qBYJJEOuRszcbIe5gDphSsqGmoZmJ1DZZ2cJTR6w2B/T09EBfXx8MDQ0tXUQfOhiBJVbDgy9Vgjh2pRdyym5A3KETcCCnDOxONxzIPcVOr3PlFUyCoK4Qehke21iy0AJpeAEPLhMIJkHsKp6Cp8+t8GNmCSTgMbz/WD6YUOJQwWnowHd8ISJk1J2hceOxjSUNGQwMKGOpEoycebiJp9eDJxZISMHjGEcsMS0PrC/tbFdIQLwKkf7+fiazPBEMFoxQAsEkiPSLPZBedBHHy8xEEvDNsfhyOduXYCLE4OBgCBEMEC56gXAkiGjzCOz8yQyJKXlwreIh7GPjlQ0nL5XjhVI5xWQiBI9tLFlQGbLwRDgCxDrOVwfPQcWDWnb3el7fjDIFbFcKL9xgMv+JiCywHr1AOBLEgTPteLW3g4Nf7Z9bmnDxC5lM3vnrbMyEiCCkiCxkMGThCYMAwcPLJNZmY0eKpvBqbwtc7ekzSg3K7MsoYDuTe/6apiuLiqw74ffJQhOy0GrCFRASgvJKJzQ1OzWfHGsszbAXrymX/rwfEFGPGI9trA0nxuJkIYMhDU9gyHAk1iDpl3rx7mUHp4sukYoILTrdu8TC63eFx5bX6pTepDWZU7712dMgY10ozEbWmv0a1pzQ8iVnZ8E41NU7wGb3aETEq+z04pEjU7+kPsv8fEsFEJ9F39WymRN1Fw5lVIOl0QEOBy38wrVe8M5F9v/816dfxFSChm0qtlZCatYzdmpZX9DHXy/bEVp4EhCvehGC/4nIVcL31ZOrdlQBI1bF9ipIy6mBxiYHXktc4HK1ss8mdKUnAYFeRMjwx0eu0rJrU1djcA0ocTS7BhoabWC10kjRV6nKlxEUXi2jFlF3hT8+cpWc/OST1bEPUUBhVUwVpKNEY5MdXrxwMglPaxu0tyvdEOhF9OPFHx/ZSvjh8SSNEkmkqTpht+Pndg+NFHXDy9CL6LtCIti5Mf7oyFZK5rNU0QlLw0toaaHvgHEv3B4cqTYUoY4oMmoR8aoXefS4ycQfHdmi8UozP4Ha2mawWFpQ5CW+Z9BuOHHJ6dsUHC8PSbUaUEvi7/uqHjXswUeuVJ78od7HWrHiXwQB769LvTEjAAAAAElFTkSuQmCC")';
    let refItem = document.getElementById('context-inspect');
    refItem.parentNode.insertBefore(menuitem, refItem);
})();


Подскажи пожайлуста, что это такое и как влияет на браузер ( в инете пишут - вроде как подключаемая библиотека):
let browserMM = gBrowser.selectedBrowser.messageManager;
browserMM.addMessageListener('getSelection', function listener(message)

Отредактировано Andrey_Krropotkin (12-07-2019 23:01:03)

Отсутствует

 

№1350013-07-2019 09:12:43

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

Re: Custom Buttons

Andrey_Krropotkin пишет

Подскажи пожайлуста, что это такое и как влияет на браузер ( в инете пишут - вроде как подключаемая библиотека):
let browserMM = gBrowser.selectedBrowser.messageManager;

Как что, это ChromeMessageSender (webidl).
Как его существование влияет на браузер, я без понятия.
Есть опасение, как бы Fission его не пожрал.

В этом коде true вторым аргументом в loadFrameScript() как-то не смотрится.
И вообще, зачем нужно межпроцессное взаимодейстие, если, при открытом
контекстном меню, выделенный текст проброшен в родительский процесс,
и доступен через gContextMenuContentData.selectionInfo.fullText
Но в качестве примера сойдёт.

Отсутствует

 

Board footer

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