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

Будьте в курсе последних изменений в мире Mozilla, следя за нашим микроблогом в Twitter.

№1412625-01-2020 19:16:39

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 68.0

Re: Custom Buttons

Andrey_Krropotkin пишет

shadow_user  на предыдущей странице, если Вы говорите про пост solombala то сточка
var cnt = w.addEle(text,

Спасибо! Разобрался с размером шрифта и окна, по умолчанию работает и копирование перевода. Хочу убрать доп. выпадающее меню с 6 пунктами (чтобы остались только пункты "перевести на eng", "перевести на ru" в основном меню), я так понял, этот раздел начинается со строки 18 (//Варианты выбора языка переводчика для перевода текста в окне...), но при закомментировании хотя бы одной строки var lang... перестает работать копирование перевода.

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

Да, возможно, вы не заметили, разница между вашим кодом с предыдущей страницы, и исправленным кодом для solombala - первый код удаляет пустые строки в переводе, поэтому в окне перевода тройным кликом выделяется весь текст. Второй код не удаляет пустые строки в переводе, оставляет, как в оригинальном тексте, поэтому тройной клик выделяет только один абзац.

Качество перевода кнопки уступает переводу расширения Simple Translate (здесь https://forum.mozilla-russia.org/viewto … 81#p776281 раскрыта причина).
Кнопка:

я сделал обновление от win8, снял его, сделал чистую установку и восстановил мою Win8. поэтому я не могу сказать пированные с у моих об обновлениях, но в последних неделях я прочитал о многих проблемах, о отказавшихся модернизациях,

Simple Translate:

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

Отредактировано shadow_user (25-01-2020 20:33:23)

Отсутствует

 

№1412725-01-2020 22:05:27

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

Re: Custom Buttons

solombala я забыл включить код для перевода страниц, исправил , должно быть

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

Выделить код

Код:

var ujs_google_translate = function (dir){
    var lng = window.navigator.language.slice(0, 2), txt = gContextMenu.selectionInfo.fullText, l = dir.split('|');
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=t&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        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').replace(/\\n/g, "<br />"));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
         xhr.send('q=' + encodeURIComponent(txt));
    } else {
        var urlt = gBrowser.currentURI.spec;  
        var url = "http://translate.google.com/translate?u="+encodeURIComponent(urlt)+"&hl="+lng+"&langpair="+dir+"&tbb=1";
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
    };

shadow_user пишет

Качество перевода кнопки уступает переводу расширения Simple Translate

посмотрю на досуге, хотя и сами можете заменить client=t на client=gtx в строчке "var url = и т.д."

если нужен сплошной текст - попробуйте, но нужна кнопка "Autocopy", если без нее то позже посмотрю

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

Выделить код

Код:

var ujs_google_translate = function (dir){
    var lng = window.navigator.language.slice(0, 2), txt = gClipboard.read() , l = dir.split('|');
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        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').replace(/\\n/g, "<br />"));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
         xhr.send('q=' + encodeURIComponent(txt));
    } else {
        var urlt = gBrowser.currentURI.spec;  
        var url = "http://translate.google.com/translate?u="+encodeURIComponent(urlt)+"&hl="+lng+"&langpair="+dir+"&tbb=1";
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
    };
};

Отредактировано Andrey_Krropotkin (25-01-2020 23:04:27)

Отсутствует

 

№1412825-01-2020 23:02:40

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
UA: Firefox 72.0

Re: Custom Buttons

Andrey_Krropotkin

Andrey_Krropotkin пишет

я забыл включить код для перевода страниц, исправил , должно быть

Хвала брате !

Отсутствует

 

№1412926-01-2020 04:55:49

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 220
UA: Firefox 74.0

Re: Custom Buttons

Dumby, ура заработал! просто до этого пробовал не получалось.. с перезапуском сработал.
Насчет стилей я думал `..` значит там стиль, ну и <> скорее html ну или код верстки какой-то), ну я не прогер поэтому синтаксис не очень знаю. Видел код на js, скроллбар вроде там и стиль был и скрипт, интересно зачем к примеру в findbar-е один код используют как .css а другой как скрипт, когда удобнее в одно все сложить, хотя бы чтоб не путать.
upd: проверял кнопку, интересно он работает только после правки, а так после запуска [firefox] не работает.
Если внести любое изменение и сохранить, кнопка оживает и все работает как надо.

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

Выделить код

Код:

//Quick toggle for about:config preferences 24.07.2016[Fx] - forum.mozilla-russia.org/viewtopic.php?pid=777019#p777019||777123#p777123||777188#p777188
this.type="menu";custombuttons.initAutoPopup(self);
var menuPopup=self.appendChild(document.createXULElement("menupopup"));this.matches("toolbar[orient=vertical]>:scope")&&menuPopup.setAttribute("position","end_before");

//[?]menuPopup.id='quick-aboutconfig-menupopup';
 
// Изменить иконку при несоответствие любого параметра пользовательскому предпочтению (см.ниже)||Иконка меняется только при изменеии параметров через меню кнопки, либо после его открытия.
  var s='CB.hasNotUserChoice';function toggleImage(){var val=custombuttons.getPrefs(s);self.image=val
//var s='CB.hasNotUserChoice';function toggleImage(){        custombuttons.getPrefs(s)?self.style.cssText='':self.style.cssText='filter:grayscale(100%)';};
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB6klEQVQ4jZWTv2tUQRDHv8ntd28GLLQQfwS5VkuDSgRF/wlRiIiCQQQhhZ1VII1/wDUWkkLTBAsbC0FJYZGQ3NuZRcHYW6UQEQzoeXkW791xXh5CptodZr8z85kd4BBWRJwDgB5wyoCjh3mLbfK8C/ddW11XJlduNgYaeTFpvJWA0+P+BBx3Cf2sLEy5m4WrS8A0AGANaBUSrgKAKzdcY5k0PF4HJGm47NK6nSUMXOIXAEgSrrnG0oU/AGDKNb6qHe9c+Ms1lqbxqws/uoTfWVp3ksRll/DTJM6bcMWEn1KbDysBCW+zsnSNpWssTbg3PNf3uw7MuHDgym8uoW8aX496SxKXs7J0iTsFObcGRBfey8rShP1EXthSnDHhShJ0vM0H1uYiAKBSHWZqLYyDc+H7sSpeNlMX9l1jWWebEAgjgSxcbRRYB46YhCcVxH9bqDP3nbyUBB0XPk+Cjgnvj1qoqohvJqDtTUBdcGAmSzgIEQBM2R0fY/U41GPkwNpcTBKfmnDPNN4w4TOX+NnbfAQAWAKmXcMVAMgaNqrM1UfqkbMmrXkT/nGJO1XF4Xod8/0Ak4KcKzTe3AROjPs/AMdM2M8atk25a8IXAKYawTZZj5jNEvZN2TVldg3Ny/RfkYizALAFnByu819tzvCRWXKqTwAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAACXBIWXMAAABnAAAAZwHVKNQmAAADGGlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaY2BgnuDo4uTKJMDAUFBUUuQe5BgZERmlwH6egY2BmYGBgYGBITG5uMAxIMCHgYGBIS8/L5UBA3y7xsDIwMDAcFnX0cXJlYE0wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ3p5SUEJAwNjDAMDg0hSdkEJAwNjAQMDg0h2SJAzAwNjCwMDE09JakUJAwMDg3N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ15yflFBflFiSWoKAwMD1A4GBgYGXpf8EgX3xMw8BUMDVQYqg4jIKAX08EGIIUByaVEZhMXIwMDAoM2Qw7CDkY8xi/EskynTYmYR5i4WFpZGVibWNjYetmnsyuybOVw5bnIWcHFyLeV24n7E08KrwXuOr4xfnv+0QIWguuANoS5hO+EvIqtFU8TkxW6Jz5AIlxSXvCE1RzpBRk3mrexWuXp5LwUxhSeKm5SalENU1FR+qp5TW6JerRGsqaPFpvVIe5/ObN0qvSh9KwMZg3+Gj4yOG68xmWxaZZZs7mNhbqlkxWf12/qlzQ3bE3Y77Vc7zHWc6NTqXOVS4JruFuce7hHg6eXl6u3oY+dr7WfpbxFgEWgRZBlsHWIX6hTmFu4dERgZHhUfnR5TEFsZ1xzflzArcVnS5uSDKedT76W9S/+XKZClmG2S454bnZef31owq3Bj0YniByU/ygTLtStcKxOqaqpn1GytvVT3oYG/Ua/Jrzm/ZULrprYr7d87pbvsu5N7OnvX9V3t/zNRZZLP5JIp86aemPZphuxMz1mlsxfOOT/3z3ztBVELOxftXPxqqfQyn+V1KzaufLJaYo3P2sZ129a/2ai0KXLzxC0ntjFut9pRvHPtrhd7lPbG7Zu1/9pB4UOBh/uPnD3Gc9z7RPfJM6d5zvidnXDu0gXRixGX5lx+cFXlWtb19Te+3rK53Xzn1D2h+9EPljx8+9j8SePTM8/FXyS9XPfq9xuPt1PfPf5g+LHh0/kv8l/zv+3/IfAz6deWP2x/I/6t/v8fAATCIM0IpJTRAAAAIGNIUk0AAHolAACAgwAA+f8AAIDoAABSCAABFVgAADqXAAAXb9daH5AAAAEOSURBVHjabJGtS0MBFMXPJojBMMPwC1nV6FCZoGj/ZVGYiIJDBOEFm3XFP2DFIAu6ZrAYBM0OREEUnN20ICI40OfbsTzYB48b7oF74J4PWUnDjMU4GSv5PEubCo/UuwjMs8FEjLOEPNCkRloWAyxb3GEOGWKRTSLeLFYwXyLFBeaGH8w7z/yyRZlvilR5YV+kuMYY04r3NpNEfBByaYksZUyDAoPsYELmmKJKjj0CS0QYU4rl3WLMeceRCBMItW7CMEd9LxbIcUqOXQJLFld9Iks9Ii0qPTYjAo5pscYJrxzIIs1SV1B5ivzRsFjFfHaiLrDOaIxHCLmnyRmp5LLytKnw1FNWH2XaYoyM9T8AOvnw3YUOg90AAAAASUVORK5CYII=';};
    toggleImage();Services.prefs.addObserver(s,toggleImage,false);
addDestructor(()=>Services.prefs.removeObserver(s,toggleImage));

// nodeName: menuitem - для логических(boolean) параметров, menu - для целых(integer) и строковых(string). menuseparator - для разделителя.
// pref - параметр about:config.
// Параметры имеющие значения отличные от дефолтных - выделены жирным стилем текста.
// restart (задавать с пустым значением. т.е., restart: "") - добавляет возможность перезапуска браузера
// (с подтверждением в диалоговом окне) после изменения параметра.
// key - задает accesskey - клавиши для быстрой навигации по меню.
// userChoice - задает предпочитаемое значение и если текущее значение с ним не совпадает, пункт меню/название меню помечаются красным цветом.
// Также можно установить предупреждающую иконку для таких пунктов. См. стиль в посте ккнопки.
// А также меняется иконка самой кнопки (см. выше).
// strValues - значения и отображаемое в меню название значения. Задавать для целых(integer) и строковых(string) параметров.
// Задается в виде: значение,,,название,,,accesskey|||значение2,,,название2,,,accesskey2|||значение3,,,название3 и т.д. (accesskey - задается опционально)
// Полное значение отображается в подсказках, при наведении на название подменю/пункт подменю.
// Для логических(boolean) - отображается сразу после самого параметра (значение true - также ставит галочку для него).
// ЛКМ по пунктам меню - перключает значения для логических(boolean) параметров,
// любая кнопка по пунктам в субменю - задает это значение для целых(integer) и строковых(string) параметров.
// ПКМ по пунктам меню и названию субменю - сбрасывает значение параметра в дефолтное.
// Клавиатура: Enter - переключение параметра.
// Спецклавиша вызова контекстного меню / Shift+Enter - сброс в дефолтное значение.
// Alt + M - открыть меню кнопки. (Сочетание можно сменить на свое. См. в конце кода)
[ //{nodeName:"menuitem", name:"Откл. дискового кэша", pref:"browser.cache.disk.enable", userChoice:"false"},
  //{nodeName:"menuitem", name:"Откл. кэша в оперативной памяти", pref:"browser.cache.memory.enable", userChoice:"false"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menuitem", name:"Откл. локального хранилища DB (Storage)", pref:"dom.indexedDB.enabled", key:'d'},
  //{nodeName:"menuitem", name:"Откл. локального хранилища", pref:"dom.storage.enabled", key:'s'},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", name:"Back-story-cash [Tessssttt]", pref:"browser.sessionhistory.max_total_viewers", strValues:"0,,,0"},
  //{nodeName:"menu", pref:"image.animation_mode", key:'i', userChoice:"none", strValues:"normal,,,Анимация картинок вкл.,,,|||none,,,Анимация картинок выкл.,,,"},
  //{nodeName:"menu", pref:"network.cookie.cookieBehavior", key:'k', userChoice:"1", strValues:"2,,,Не принимать куки с сайтов,,,|||0,,,Принимать куки со сторонних сайтов всегда,,,|||3,,,Принимать куки со сторонних посещённых сайтов,,,|||1,,,Принимать куки со сторонних сайтов никогда,,,"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", pref:"general.useragent.locale", key:'l', restart:"", strValues:"en-US,,,English,,,e|||ru,,,Русский,,,r"},
  //{nodeName:"menu", name:"language", pref:"intl.accept_languages", strValues:"en-US, en;q=0.5,,,en-US, en;q=0.5,,,e|||en-US, en, ru-RU, ru,,,en-US, en, ru-RU, ru,,,r"},
  //{nodeName:"menu", pref:"browser.display.document_color_use", key:'c', userChoice:"0", strValues:"0,,,Automatic,,,0|||1,,,Always,,,1|||2,,,Never,,,2"},
  //{nodeName:"menu", pref:"CB.TEST", key:'t', userChoice:"C:\\Downloads\\TEST1", strValues:"C:\\Downloads\\TEST1,,,TEST1,,,1|||C:\\Downloads\\TEST2,,,TEST2,,,2"}
  //{nodeName:"menuseparator"},
  //{nodeName:"menuitem", name:"Откл. инфу начало/конец загрузки стр", pref:"dom.enable_performance", userChoice:"false"},
  //{nodeName:"menu", name:"Вкл/Выкл Referer", pref:"network.http.sendRefererHeader", strValues:"0,,,0"},
  //{nodeName:"menuitem", name:"В качестве реферера корень сайта", pref:"network.http.referer.spoofSource", userChoice:"true"},
  //{nodeName:"menu", name:"referer.trimmingPolicy", pref:"network.http.referer.trimmingPolicy", strValues:"2,,,2"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", name:"On/Off Image", pref:"permissions.default.image", userChoice:1, strValues:"2,,,Off"},

  //{nodeName:"menuitem", name:"On/Off javascript", pref:"javascript.enabled", key:'j', userChoice:"true"},
  {nodeName:"menuitem", name:"On/Off useragentS", pref:"general.useragent.site_specific_overrides", userChoice:"true"},
  //{nodeName:"menuitem", pref:"dom.workers.enabled", key:'w', userChoice:"false"},
  //{nodeName:"menu", name:"Stopautoplay", pref:"media.autoplay.default", userChoice:0, strValues:"0,,,Stop,,,0|||1,,,Play,,,1"},
  //{nodeName:"menuitem", pref:"xpinstall.signatures.required"},                       //Check is compatibility
  //{nodeName:"menuitem", pref:"browser.bookmarks.autoExportHTML"},                    //BookmarksHtml [false=places.sqlite]
  //{nodeName:"menuitem", pref:"media.peerconnection.enabled"},                        //WebRTC false=off!

  {nodeName:"menuitem", name:"Drag&Drop(Safe) !Manual restart required!", pref:"browser.launcherProcess.enabled", userChoice:"true"},   //Drag&Drop(Safe) Manual restart required! - forum.mozilla-russia.org/viewtopic.php?pid=774980#p774980
  {nodeName:"menuitem", name:"On/Off media.play-stand-alone", pref:"media.play-stand-alone"},   //сразу скачивать медиафайлы, без перехода на новую страницу.
  {nodeName:"menuseparator"},
  {nodeName:"menu", name:"On/Off DoH", pref:"network.trr.mode", strValues:"3,,,3"},
  {nodeName:"menu", name:"Configure Proxies", pref:"network.proxy.type", userChoice:5, strValues:"1,,,httpP,,,1|||2,,,AutomaticP,,,2|||5,,,Use systemP,,,5"},
  {nodeName:"menu", name:"AutomaticP", pref:"network.proxy.autoconfig_url", strValues:"resource://FF/..pac,,,resource://FF/..pac,,,1|||https://antizapret.prostovpn.org/proxy.pac,,,https://antizapret.prostovpn.org/proxy.pac,,,2"},
  {nodeName:"menuseparator"}, 
  {nodeName:"menu", name:"User Agent", pref:"general.useragent.override", key:'u', strValues:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0,,,Firefox 60/MacOSX 10.13|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36,,,Chrome 66/MacOSX 10.13.5|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36,,,Chrome 57/MacOSX|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30,,,Safari Generic/MacOSX|||Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36,,,Chrome57/W7|||Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12 Version/12.16,,,Opera12/W8|||Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36,,,Chrome61/W10|||Mozilla/5.0 (Linux; Android 7.0; PLUS Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36,,,Chrome61/Android7|||Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html),,,GoogleBot|||Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots),,,YandexBot|||Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp),,,YahooBot|||Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm),,,BingBot|||DuckDuck bot/1.0; (+http://duckduckgo.com/duckduckbot.html),,,DuckDuckBot|||Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html),,,BaiduspiderBot|||ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com),,,AlexaCrawlerBot|||Mozilla/5.0 (Linux; Android 5.1.1; SM-G928X Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36,,,Samsung Galaxy S6 Edge Plus|||Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Microsoft Lumia 950|||Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Xbox One|||Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73 (KHTML, like Gecko),,,Playstation 4|||,,,Пустое значение"},
]

.forEach(function(m){var mItem=document.createElementNS(xulns,m.nodeName);var browserRestart='';
if("restart"in m)browserRestart='if(custombuttons.confirmBox(null,"Restart?","Yes","Cancel"))Services.startup.quit(Services.startup.eAttemptQuit|Services.startup.eRestart);';
if("name"in m) mItem.setAttribute('name',m.name);
if("pref"in m){mItem.setAttribute('closemenu','none');
mItem.setAttribute('oncontextmenu','event.preventDefault();custombuttons.clearPrefs("'+m.pref+'");'+browserRestart);}
if("key"in m)  mItem.setAttribute('accesskey',m.key);
if(m.nodeName==="menuitem"){mItem.setAttribute('type','checkbox');
mItem.setAttribute('oncommand','custombuttons.setPrefs("'+m.pref+'",!custombuttons.getPrefs("'+m.pref+'"));if(event.shiftKey&&event.keyCode==event.DOM_VK_RETURN){event.preventDefault();custombuttons.clearPrefs("'+m.pref+'")};'+browserRestart);}
if(m.nodeName==="menu"){mItem.setAttribute('class','menu-iconic');

var subMenu=mItem.appendChild(document.createXULElement("menupopup"));

for (var value of m.strValues.split('|||')){var submItem=document.createXULElement("menuitem");
var smVal=value.split(',,,')[0];
var smValConv=convertFromUnicode("UTF-8",smVal);
var smName=value.split(',,,')[1];
var key=value.split(',,,')[2];

key&&submItem.setAttribute('accesskey',key);submItem.setAttribute('type','radio');
submItem.setAttribute('label',smName);submItem.setAttribute('tooltiptext',smVal);
submItem.setAttribute('closemenu','none');
submItem.setAttribute('oncommand','try{custombuttons.setPrefs("'+m.pref+'","'+smValConv.replace(/\\/g,'\\\\')+'")}catch(e){Services.prefs.setIntPref("'+m.pref+'","'+smValConv+'")};'+browserRestart);
subMenu.appendChild(submItem);}}
menuPopup.appendChild(mItem);

  // Листенеры отслеживающие переключение параметров
  // и устанавливающие соответствующие названия и чекбоксы для пунктов меню при открытии меню и кликах
  for (var type of ['command','popupshowing','contextmenu']){addEventListener(type,(e)=>{setTimeout(()=>{if ("pref" in m){var val,def;
   def=Services.prefs.prefHasUserValue(m.pref);
   try {val=Services.prefs.getComplexValue(m.pref,Ci.nsISupportsString).data;} catch(e) {
   if (Services.prefs.getPrefType(m.pref)==64) val=custombuttons.getPrefs(m.pref).toString();else val=custombuttons.getPrefs(m.pref);}
   def ? mItem.style.setProperty('font-weight', 'bold', 'important') : mItem.style.removeProperty('font-weight');}

     if (m.nodeName==='menuitem'){mItem.setAttribute('checked',val);mItem.label=(mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref)+' - "'+val+'"';
     if ("userChoice" in m){try {var usrChc=(val.toString()===m.userChoice)} catch(e) {usrChc=false};

     mItem.setAttribute('user-choice',usrChc);usrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color','orangered','important');}}
     if (subMenu){for (var smitem of subMenu.getElementsByTagName('menuitem')) {var smval=smitem.getAttribute('tooltiptext');smitem.setAttribute('checked',(val===smval) ? true : false);}}
     if (m.nodeName==="menu") {var vname;
     try {vname=subMenu.getElementsByAttribute('checked','true')[0].getAttribute('label');} catch(e) {if (!Services.prefs.prefHasUserValue(m.pref)) vname='Default';else vname='Other';}

     mItem.setAttribute('label',(mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref)+' - "'+vname+'"');
     mItem.setAttribute('tooltiptext',val || 'This preferences has null value or does not exist.');

     if ("userChoice" in m) {var smUsrChc=(val===m.userChoice.toString());mItem.setAttribute('user-choice',smUsrChc);
     smUsrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color','orangered','important');}}

     if ("userChoice" in m) {var hasNotUserChoice=menuPopup.getElementsByAttribute('user-choice','false')[0];custombuttons.setPrefs(s,hasNotUserChoice ? true : false);}}, 0)},false,menuPopup)}});

// Листенер позволяющий сброс параметров с субменю по Shift+Enter||За код спасибо Dumby
addEventListener("popupshown",{handleEvent:function(e){this[e.type](e);},
  popupshown:function(e){if(e.target!=menuPopup)return;menuPopup.addEventListener   ("popuphidden",this,false);window.addEventListener   ("keydown",this,true);},
 popuphidden:function(e){if(e.target!=menuPopup)return;menuPopup.removeEventListener("popuphidden",this,false);window.removeEventListener("keydown",this,true);},
popupshowing:function(e){e.target.parentNode.removeEventListener("popupshowing",this,false);e.preventDefault();},get old(){delete this.old;
this.e=new MouseEvent("contextmenu",{});return this.old=parseInt(Services.appinfo.platformVersion)<25;},get prop(){delete this.prop;
if("key"in KeyboardEvent.prototype)this.prop="key",this.val="Enter";else this.prop="keyCode",this.val=KeyboardEvent.DOM_VK_RETURN;return this.prop;},
keydown:function(e){if(!e.shiftKey||e.ctrlKey||e.altKey||e[this.prop]!=this.val)return;var target=menuPopup.querySelector("menu[_moz-menuactive]:not([open])");
if(!target)return;this.old ? target.addEventListener("popupshowing",this,false) : e.stopPropagation();target.dispatchEvent(this.e);menuPopup.dispatchEvent(this.e);}},false,menuPopup);

// Открыть меню кнопки по сочетанию клавиш Alt + M (не зависит от текущей раскладки клавиатуры)
addEventListener("keydown",e=>{if(e.altKey&&e.code=="KeyM"&&!e.shiftKey&&!e.ctrlKey)e.preventDefault(),self.open=true},false,window);

// Конвертировать текст в юникод .............
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();};

Отредактировано func4ptch4 (29-01-2020 09:38:25)

Отсутствует

 

№1413026-01-2020 08:27:40

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

Re: Custom Buttons

shadow_user для сплошного теста в окне перевода пробуйте

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

Выделить код

Код:

/*Initialization Code*/

var lc = navigator.lastClick = {};
addEventListener("mouseup", e => {
    if (e.button) return;
    lc.X = e.screenX - mozInnerScreenX;
    lc.Y = e.screenY - mozInnerScreenY;
}, false, gBrowser.tabpanels || 1);

var createWindow = function(text, status, title, id, pos, size){
var win = window, 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.createElementNS(xhtmlns, 'div');
     w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#eaeaea;padding-top:0px;border-radius:4px;box-shadow:0 0 15px 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.addEle = function(str, style){
        var ele = doc.createElementNS(xhtmlns, '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);
    };
     w.addEle1 = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'textarea');
        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.createElementNS(xhtmlns, 'div');
    img.setAttribute('style', 'display:block;float:right;width:16px;height:16px;padding:0;margin-top:2px;margin-right:1px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVR4Xm2SPUhbURTHfzfNJ4nU0Axx7CJCN2kQtIgVCtq6OdQuBUftWIQqFNsKDo6iHTqIqN3a0kklUKTS2AZrcOjioFtRjFWUfH+803cS9GHwB4dzcu75/+8L9xgaSEDbLXhaASzAyXAMn5/DHxwwjeJgKLRxd3Q0atxuLhGgWqmQmp9PJ7LZJ5Ow3WhQFweDG20LC1FfRwc3kUsm+T48fPIzl3s8VTdxxLt+/2FhdlZkc1MkmdR8Pba2ajlrz3z1+9OvIOaIfb7DwsSEyNKSyM6OSLksEo/rbw2ttadntV7Gnv3k86VfqskvmDzv7hZ580Zkelrk4kJqFIsii4satVrRs+rYmBQHBuRvS4u8g/fuCmDOz+HgAIWpKRgfh3AYhoZQ8Hqxjo4o9PdT3d1FcQEl8KoBnJ7C/j6KZkZGYG4OIhEUFed7erD29q69jGrd1qVBqcQVKgwEuMSEQhjtXRk4JvW/kM1i2WGMga4uzMoKBIOIfbNiolEC6+uU+/qQRALFA1QBlwVYxmBcLmhuxqytQSgEKu7t1dBavwKvbeINh/Has2IMqnXpem4bky6qWLdvZgaOj2FwEHNyoqG19vRMZ8jZs1+NOfsNcZS3EFvzeNL51laRe/dEYrFadsLpZeyZDx7P6QN4Btwx1OE1xO4HAquP2tsjAZ+Pm8gWi3xMpc6W8/kXPyAO/DM4oOsZa2pafdjZGXF7PAgOpXKZL4nE2XImcyUGMDSg63kbhgvgtYCq8+akIL4J3y7Fyn+DokZOnLlMyQAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
        title.onclick = e => {
        e.preventDefault();
        var url = e.target.href;
        // Здесь открываем url как хотим.
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
        doc.getElementById(wId).closeWin();    
    }
    var cnt = w.addEle1(text, 'display:block;border:1px solid #aaa;padding-bottom:3px;padding-left:3px;background-color:#fafcfe;color:#000;font:16px Times New Roman;width:310px;height:160px;overflow:auto;cursor:text;-moz-user-focus:normal;-moz-user-select:text;');
    cnt.contentEditable="true";
    cnt.context="contentAreaContextMenu";
    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
    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 = 80*i+'px';
                cnt.style.width = 160*i+'px';
            }
            else break;
        }
    };

    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? 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);
    return w;
};

var getHash = function (txt) {
    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
    function sM(a) {
        var b;
        if (null !== yr)
            b = yr;
        else {
            b = wr(String.fromCharCode(84));
            var c = wr(String.fromCharCode(75));
            b = [b(), b()];
            b[1] = c();
            b = (yr = window[b.join(c())] || "") || ""
        }
        var d = wr(String.fromCharCode(116))
            , c = wr(String.fromCharCode(107))
            , d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var l = a.charCodeAt(g);
            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                e[f++] = l >> 18 | 240,
                e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                e[f++] = l >> 6 & 63 | 128),
                e[f++] = l & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++)
            a += e[f],
                a = xr(a, "+-a^+6");
        a = xr(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    }

    var yr = null;
    var wr = function(a) {
        return function() {
            return a
        }
    }
        , xr = function(a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2)
                , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
                , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    }; 

    return sM(txt);
}; 
 
  
 
var ujs_google_translate = function (dir){
    var lng = window.navigator.language.slice(0, 2), txt = gContextMenu.selectionInfo.fullText , l = dir.split('|');
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
        var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        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').replace(/\\n/g, "").replace(/\\r/g, ""));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:#009;font:16px Times New Roman;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
         xhr.send('q=' + encodeURIComponent(txt));
    } else {
        var urlt = gBrowser.currentURI.spec;  
        var url = "http://translate.google.com/translate?u="+encodeURIComponent(urlt)+"&hl="+lng+"&langpair="+dir+"&tbb=1";
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
    };
};

var contextMenu = document.getElementById("contentAreaContextMenu");
var nextEleMenu = document.getElementById("context-inspect");

var menuId = "context-ext-google-translate";
var menuItem = document.getElementById(menuId);
if (menuItem) {
    contextMenu.removeChild(menuItem.nextElementSibling);
    contextMenu.removeChild(menuItem.nextElementSibling);
    contextMenu.removeChild(menuItem);
};

menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("id", menuId);
menuItem.setAttribute("label", "Перевести на русский");
menuItem.setAttribute("class", "menuitem-iconic");
menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABBUlEQVR4Ac2RMU4DMRREB2MqihQpAkUaqnAduuQw4Sx03CGcJYIiDYqQ0lCsZ77535ZFcgAkRuPvV7zd/dLiz3N1PFb8hmRckrfELZrF9ONQ1B6Yz0MyM7S0O6zGkVprh/3+Kw/JzkHSpRpJKZkpr9fYbOx0cjVsCbWG31oHBM9mtt0q73ZcrdLhAMlYQKkUI22aqsNo8HKZAMQhvVaKSHWj2Q2aPU3mJQFY7nuHyvYFduP83WF3AJRfcPNYnr/Lp1G1uK4m9sno1LaUbnX/htf8BNzoneUD5NhjvLCMhURQSQ93QCZwXYjFwg3I0NZKrvoknQPMIHkt/jRAQKMeG2yX89/mB4EJbKbZxIhFAAAAAElFTkSuQmCC");
menuItem.addEventListener("command", function(){ujs_google_translate('auto|ru')}, false);
contextMenu.insertBefore(menuItem, nextEleMenu);

menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("label", "Перевести на английский");
menuItem.setAttribute("class", "menuitem-iconic");
menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAAB5UlEQVR4AWOgPZg0c9+Oq2+qpx9LaQaiw4mNB27efbs2uXFNQh2Q4Zm9zSNth23MhqjGnXMC86vnHmUS4udxv7OvOd2yPE7PTlfCTk9GVVEoyJA7WI8dyPA0k3U1l+jJMV7CeThpTZeoKDdDUsvBPSff/V+6/P/Bvf///2+bdvU/EKRm/k9IBNIlfZe+LFrzvbsbyJ636pKkyQyQhoUb7tZNvPpw3/0/TfX/ISAm5n94BIiRm/n/xYsLd946ei4vajoiqDuRAejQf//+o4PQ0P9+fmhiQGVnrr1kXJNYG2zEzXDxDsPv3wy/fkFJoOTPn39+/fr/69e/37//AUX+/mXRkO458wWHDba2f8wswCyQ3N+/f//8/fP7z5+TV18w2Mdt6plzPiptx5Wr7/+/ffMzOR6kysjkt74hWMPfp06O+2dulZCeFZKwnkE4m8E8bN3i9aCQ+dxY96GrK6bkGJD9R1v3l6Y20NVW9kt+/v//ZdbcFwkxTVPPMQimM8XEqkb7a/zoqLxkH9v4zVyI5+///wyMmtKMmhJAnbLqQjHxaw5r2orOmZN5uj470Zahat6BKS7JzpmLBHXm8GhM5lCdcP7ai1ZpixZxk9NXXjKIFzOIFjAI54oY1vXuue5qmscw+AAAW0tKxtPoicEAAAAASUVORK5CYII=");
menuItem.addEventListener("command", function(){ujs_google_translate('auto|en')}, false);
contextMenu.insertBefore(menuItem, nextEleMenu);

contextMenu.insertBefore(document.createXULElement("menuseparator"), nextEleMenu);

Отсутствует

 

№1413126-01-2020 09:51:53

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 68.0

Re: Custom Buttons

Andrey_Krropotkin пишет

для сплошного теста в окне перевода пробуйте

Спасибо, работает. После правки t->gtx качество перевода улучшилось, стало 1:1 с Simple Translate.

Отсутствует

 

№1413226-01-2020 13:36:10

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

Re: Custom Buttons

solombala пишет

Дай код полностью! И проверим..

Скопировать из первоисточника сюда?
Как-то ... . Но, если поможет

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

Выделить код

Код:

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

// Undo Close Tabs button for Custom Buttons
// (code for "initialization" section)

// (c) Infocatcher 2009-2015, 2017-2018
// version 0.3.3.1 - 2018-08-01

var options = {
    menuTemplate: [
        "closedWindows",
        "separator",
        "restoreClosedWindows",
        "clearClosedWindows",
        "separator",
        "closedTabs",
        "separator",
        "restoreClosedTabs",
        "clearClosedTabs",
        "separator",
        "clearAll",
        "separator",
        "restoreLastSession",
        "separator",
        "buttonMenu"
    ],
    showInTabContextMenu: false,
    /*
    menuTemplateTabContext: [ // like menuTemplate
        "closedTabs",
        "separator",
        "restoreClosedTabs",
        "clearClosedTabs"
    ],
    */
    windowItemTemplate: "(%count) %title",
    windowSelectedTabPrefix: "*",
    buttonTipTemplate: ["header", "title", "url", "closedAt"],
    itemTipTemplate: ["title", "url", "closedAt"],
    hideRestoreAllForSingleEntry: false,
    allowDeleteEntries: true,
    accesskeys: { // Empty string ("") to disable or string with possible values ("0123...", "abcd...")
        closedTabs: "",
        closedWindows: ""
    },
    accesskeyPostfix: " ", // <accesskey><postfix><label>
    openMenuOnMouseover: false,
    useMenu: false,
    rightClickToUndoCloseTab: false // Useful with "useMenu: true"
};

function _localize(sid) {
    var strings = {
        en: {
            restoreTab: "Restore the most recently closed tab",

            restoreAllTabs: "Restore all tabs",
            restoreAllTabsAccesskey: "t",
            clearTabsHistory: "Clear history of closed tabs",
            clearTabsHistoryAccesskey: "b",

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

            clearAllHistory: "Clear all history",
            clearAllHistoryAccesskey: "C",

            restoreLastSession: "Restore last session",
            restoreLastSessionAccesskey: "s",

            deleteUndoEntry: "Delete",

            buttonMenu: "Button menu",
            buttonMenuAccesskey: "m",

            tabContextMenu: "Recently Closed Tabs",
            tabContextMenuAccesskey: "y",

            itemTip: "%ago ago, %date",
            day: "d"
        },
        ru: {
            restoreTab: "Восстановить последнюю закрытую вкладку",

            restoreAllTabs: "Восстановить все вкладки",
            restoreAllTabsAccesskey: "л",
            clearTabsHistory: "Очистить историю закрытых вкладок",
            clearTabsHistoryAccesskey: "д",

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

            clearAllHistory: "Очистить всю историю",
            clearAllHistoryAccesskey: "ч",

            restoreLastSession: "Восстановить последнюю сессию",
            restoreLastSessionAccesskey: "с",

            deleteUndoEntry: "Удалить",

            buttonMenu: "Меню кнопки",
            buttonMenuAccesskey: "М",

            tabContextMenu: "Недавно закрытые вкладки",
            tabContextMenuAccesskey: "о",

            itemTip: "%ago назад, %date",
            day: "д"
        }
    };
    var locale = (function() {
        if("Services" in window && "locale" in Services) {
            var locales = Services.locale.requestedLocales // Firefox 64+
                || Services.locale.getRequestedLocales && Services.locale.getRequestedLocales();
            if(locales)
                return locales[0];
        }
        var prefs = "Services" in window && Services.prefs
            || Components.classes["@mozilla.org/preferences-service;1"]
                .getService(Components.interfaces.nsIPrefBranch);
        function pref(name, type) {
            return prefs.getPrefType(name) != prefs.PREF_INVALID ? prefs["get" + type + "Pref"](name) : undefined;
        }
        if(!pref("intl.locale.matchOS", "Bool")) { // Also see https://bugzilla.mozilla.org/show_bug.cgi?id=1414390
            var locale = pref("general.useragent.locale", "Char");
            if(locale && locale.substr(0, 9) != "chrome://")
                return locale;
        }
        return Components.classes["@mozilla.org/chrome/chrome-registry;1"]
            .getService(Components.interfaces.nsIXULChromeRegistry)
            .getSelectedLocale("global");
    })().match(/^[a-z]*/)[0];
    _localize = function(sid) {
        return strings[locale] && strings[locale][sid] || strings.en[sid] || sid;
    };
    return _localize.apply(this, arguments);
}

var JSON = "JSON" in window
    ? window.JSON
    : "nsIJSON" in Components.interfaces
        ? {
            parse: function(s) {
                return Components.classes["@mozilla.org/dom/json;1"]
                    .createInstance(Components.interfaces.nsIJSON)
                    .decode(s);
            }
        }
        : {
            parse: function(s) {
                return Components.utils.evalInSandbox("(" + s + ")", new Components.utils.Sandbox("about:blank"));
            }
        };

this.onclick = function(e) {
    if(e.target != this)
        return;
    if(e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey))
        this.undoCloseTabsList.clearAllLists();
    else if(
        e.button == 0
        || e.button == 2 && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
            && this.undoCloseTabsList.options.rightClickToUndoCloseTab
    ) {
        if(
            e.button == 0 && !this.undoCloseTabsList.options.useMenu
            || e.button == 2 && this.undoCloseTabsList.options.rightClickToUndoCloseTab
        ) {
            if(this.undoCloseTabsList.closedTabCount)
                this.undoCloseTabsList.undoCloseTab();
            else
                this.undoCloseTabsList.drawUndoList() && this.undoCloseTabsList.showMenu(e);
        }
        // Allow use "command" section only from hotkey:
        e.preventDefault();
        e.stopPropagation();
    }
};
if(!this.hasOwnProperty("defaultContextId"))
    this.defaultContextId = this.getAttribute("context") || "custombuttons-contextpopup";
this.onmousedown = function(e) {
    if(e.target != this)
        return;
    if(this.undoCloseTabsList.options.useMenu) {
        if(e.button == 0)
            this.undoCloseTabsList.drawUndoList();
    }
    else if(e.button == 2) {
        var showCbMenu = e.ctrlKey || e.shiftKey || e.altKey || e.metaKey || !this.undoCloseTabsList.drawUndoList();
        this.setAttribute(
            "context",
            showCbMenu
                ? this.defaultContextId
                : this.undoCloseTabsList.mpId
        );
    }
};
this.onmouseover = function(e) {
    if(e.target != this)
        return;
    if(!this.disabled)
        this.undoCloseTabsList.updUI();
    this.undoCloseTabsList.options.useMenu && Array.prototype.some.call(
        this.parentNode.getElementsByTagName("*"),
        function(node) {
            if(
                node != this
                && node.namespaceURI == xulns
                // See https://github.com/Infocatcher/Custom_Buttons/issues/28
                //&& node.boxObject
                //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject
                && "open" in node
                && node.open
                && node.getElementsByTagName("menupopup").length
                && this.undoCloseTabsList.drawUndoList()
            ) {
                node.open = false;
                this.open = true;
                return true;
            }
            return false;
        },
        this
    );
    if(
        this.undoCloseTabsList.options.openMenuOnMouseover
        && this.undoCloseTabsList.drawUndoList()
    )
        this.undoCloseTabsList.openMenu();
};

this.undoCloseTabsList = {
    button: this,
    options: options,
    mpId: this.id + "-context",
    cmId: this.id + "-contextSub",
    tcmId: this.id + "-tabContextMenu",
    tipId: this.id + "-tooltip",
    errPrefix: "[Custom Buttons :: Undo Close Tabs List]: ",
    get mp() {
        var btn = this.button;
        var mp = btn.getElementsByTagName("menupopup");
        mp = mp.length && mp[0];
        mp && mp.parentNode.removeChild(mp);
        mp = this.createElement("menupopup", {
            id: this.mpId,
            onclick: "this.parentNode.undoCloseTabsList.checkForMiddleClick(event);",
            onpopupshowing: "if(event.target == this) document.popupNode = this.parentNode;",
            onpopuphidden: "if(event.target == this) document.popupNode = null;"
        });
        if(this.cm)
            mp.setAttribute("context", this.cmId);
        var tb = btn.parentNode;
        if(
            this.options.useMenu
            && tb.getAttribute("orient") == "vertical"
        ) {
            // https://addons.mozilla.org/firefox/addon/vertical-toolbar/
            var isRight = tb.parentNode.getAttribute("placement") == "right";
            mp.setAttribute("position", isRight ? "start_before" : "end_before");
        }
        delete this.mp;
        return this.mp = btn.appendChild(mp);
    },
    get useCentextMenu() {
        delete this.useCentextMenu;
        return this.useCentextMenu = this.options.allowDeleteEntries
            && ("forgetClosedTab" in this.ss || "forgetClosedWindow" in this.ss);
    },
    get cm() {
        delete this.cm;
        if(!this.useCentextMenu)
            return this.cm = null;
        var cm = document.getElementById(this.cmId);
        cm && cm.parentNode.removeChild(cm);
        cm = this.createElement("menupopup", {
            id: this.cmId,
            onpopupshowing: "return this.undoCloseTabsList.canDeleteUndoEntry(this.triggerNode || document.popupNode);"
        });
        var mi = this.createElement("menuitem", {
            oncommand: "this.parentNode.undoCloseTabsList.deleteUndoEntry(this.parentNode.triggerNode || document.popupNode);",
            label: _localize("deleteUndoEntry"),
            closemenu: "single"
        });
        cm.appendChild(mi);
        cm.undoCloseTabsList = this;
        return this.cm = document.getElementById("mainPopupSet").appendChild(cm);
    },
    get cbMenu() {
        var cbPopup = document.getElementById(this.button.defaultContextId);
        if(!cbPopup) {
            Components.utils.reportError(this.errPrefix + "cb menu not found");
            return this.cbMenu = null;
        }
        cbPopup = cbPopup.cloneNode(true);
        var id = "-" + this.button.id.match(/\d*$/)[0] + "-cloned";
        cbPopup.id += id;
        Array.prototype.slice.call(cbPopup.getElementsByAttribute("id", "*")).forEach(function(node) {
            node.id += id;
        });
        var menu = this.createElement("menu", {
            label: _localize("buttonMenu"),
            accesskey: _localize("buttonMenuAccesskey")
        });
        menu.appendChild(cbPopup);
        cbPopup.setAttribute(
            "onpopupshowing",
            '\
            var btn = document.popupNode = this.parentNode.parentNode.parentNode\n\
                .undoCloseTabsList.button;\n\
            custombutton.setContextMenuVisibility(btn);'
        );
        delete this.cbMenu;
        return this.cbMenu = menu;
    },
    get ss() {
        delete this.ss;
        return this.ss = "nsISessionStore" in Components.interfaces
            ? (
                Components.classes["@mozilla.org/browser/sessionstore;1"]
                || Components.classes["@mozilla.org/suite/sessionstore;1"]
            ).getService(Components.interfaces.nsISessionStore)
            : SessionStore; // Firefox 61+ https://bugzilla.mozilla.org/show_bug.cgi?id=1450559
    },
    get appInfo() {
        delete this.appInfo;
        return this.appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
            .getService(Components.interfaces.nsIXULAppInfo);
    },
    get appVersion() {
        delete this.appVersion;
        return this.appVersion = parseFloat(this.appInfo.version);
    },
    get appName() {
        delete this.appName;
        return this.appName = this.appInfo.name;
    },

    init: function() {
        window.addEventListener("TabClose",       this, false);
        window.addEventListener("SSTabRestoring", this, false);
        window.addEventListener("unload",         this, false);
        if(this.appName == "SeaMonkey") // No SSTab* events in SeaMonkey
            window.addEventListener("TabOpen", this, false);
        setTimeout(function(_this) {
            _this.mp.addEventListener("DOMMenuItemActive",   _this, false);
            _this.mp.addEventListener("DOMMenuItemInactive", _this, false);
            _this.initTooltip();
        }, 50, this);
        this.addPbExitObserver(true);
        this.updUIGlobal();
        if(this.options.showInTabContextMenu) setTimeout(function(_this) {
            _this.initTabContext();
        }, 100, this);
    },
    initTabContext: function() {
        var origMi = this.tabContextUndoClose;
        if(!origMi) {
            LOG("Can't find \"Undo Close Tab\" item in tab context menu");
            return;
        }
        var menu = document.getElementById(this.tcmId);
        menu && menu.parentNode.removeChild(menu); // For SeaMonkey
        menu = this.createElement("menu", {
            id: this.tcmId,
            label: _localize("tabContextMenu"),
            accesskey: _localize("tabContextMenuAccesskey"),
            tooltip: this.tipId,
            popupsinherittooltip: "true"
        });
        menu.undoCloseTabsList = this;
        menu.onclick = function(e) {
            if(e.target != this)
                return;
            if(e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey)) {
                if(this.undoCloseTabsList.closedTabCount) {
                    this.undoCloseTabsList.undoCloseTab();
                    closeMenus(this);
                }
            }
        };
        var origMp = this.mp;
        var mp = origMp.cloneNode(true);
        mp.id = this.button.id + "-tabContext";
        var _this = this;
        function drawUndoList() {
            var ok = false;
            var opts = _this.options;
            var origTemplate = opts.menuTemplate;
            opts.menuTemplate = opts.menuTemplateTabContext || origTemplate;
            _this.mp = mp;
            try {
                ok = _this.drawUndoList();
            }
            catch(e) {
                Components.utils.reportError(e);
            }
            opts.menuTemplate = origTemplate;
            _this.mp = origMp;
            return ok;
        }
        function updMenu() {
            if(drawUndoList())
                menu.removeAttribute("disabled");
            else
                menu.setAttribute("disabled", "true");
        }
        mp._updatePopup = function(e) {
            if(e.target != this)
                return;
            document.popupNode = _this.button;
            drawUndoList();
        };
        mp.setAttribute("onpopupshowing", "this._updatePopup(event);");
        mp.onclick = function(e) {
            _this.checkForMiddleClick(e, updMenu);
        };
        menu.appendChild(mp);
        addEventListener("popupshown", function(e) {
            if(e.target == e.currentTarget)
                setTimeout(updMenu, 0); // Pseudo async
        }, false, origMi.parentNode);
        addEventListener("DOMMenuItemActive",   this, false, mp);
        addEventListener("DOMMenuItemInactive", this, false, mp);
        origMi.parentNode.insertBefore(menu, origMi.nextSibling);
        origMi.setAttribute("hidden", "true");
    },
    initTooltip: function() {
        var tip = document.getElementById(this.tipId);
        tip && tip.parentNode.removeChild(tip);
        tip = this.tip = this.createElement("tooltip", {
            id: this.tipId,
            orient: "vertical",
            onpopupshowing: "return this.undoCloseTabsList.updTooltip(this, document.tooltipNode);",
            onpopuphiding: "this.cancelUpdateTimer();",
            style: "padding: 0;"
        });
        tip.undoCloseTabsList = this;
        tip._updateTimer = 0;
        tip.initUpdateTimer = function(fn, context) {
            if(this._updateTimer)
                clearInterval(this._updateTimer);
            this._updateTimer = setInterval(function() {
                fn.call(context);
            }, 1000);
        };
        tip.cancelUpdateTimer = function() {
            if(this._updateTimer) {
                clearInterval(this._updateTimer);
                this._updateTimer = 0;
            }
        };
        var btn = this.button;
        btn.removeAttribute("tooltiptext");
        btn.setAttribute("tooltip", this.tipId);
        btn.setAttribute("popupsinherittooltip", "true");
        document.getElementById("mainPopupSet").appendChild(tip);
        if(this.appVersion >= 61 && "getAnonymousElementByAttribute" in document) {
            var label = document.getAnonymousElementByAttribute(tip, "class", "tooltip-label");
            label && label.remove();
        }
    },
    _hasPbExitObserver: false,
    addPbExitObserver: function(add) {
        if(add == this._hasPbExitObserver || !("Services" in window))
            return;
        this._hasPbExitObserver = add;
        if(add)
            Services.obs.addObserver(this, "last-pb-context-exited", false);
        else
            Services.obs.removeObserver(this, "last-pb-context-exited");
    },
    destroy: function() {
        window.removeEventListener("TabClose",       this, false);
        window.removeEventListener("SSTabRestoring", this, false);
        window.removeEventListener("unload",         this, false);
        if(this.appName == "SeaMonkey")
            window.removeEventListener("TabOpen", this, false);
        this.mp.removeEventListener("DOMMenuItemActive",   this, false);
        this.mp.removeEventListener("DOMMenuItemInactive", this, false);
        this.addPbExitObserver(false);
        var menu = document.getElementById(this.tcmId);
        if(menu) {
            menu.parentNode.removeChild(menu);
            this.tabContextUndoClose.removeAttribute("hidden");
        }
        var tip = this.tip;
        tip && tip.parentNode && tip.parentNode.removeChild(tip);
    },
    handleEvent: function(e) {
        switch(e.type) {
            case "TabClose":
            case "SSTabRestoring":
            case "TabOpen":
                setTimeout(function(_this) {
                    _this.updUI();
                }, 0, this);
            break;
            case "DOMMenuItemActive":
            case "DOMMenuItemInactive":
                if(!("XULBrowserWindow" in window))
                    break;
                XULBrowserWindow.setOverLink(
                    e.type == "DOMMenuItemActive"
                        ? (e.target.getAttribute("cb_urlDecoded") || "")
                            .replace(/ \n/g, ", ")
                        : "",
                    null
                );
            break;
            case "unload":
                this.updUIGlobal();
                this.destroy();
        }
    },
    observe: function(subject, topic, data) {
        if(topic == "last-pb-context-exited") {
            setTimeout(function(_this) {
                _this.updUI();
            }, 25, this);
        }
    },

    createElement: function(name, attrs) {
        var node = document.createElementNS(xulns, name);
        if(attrs) for(var attrName in attrs) if(attrs.hasOwnProperty(attrName))
            node.setAttribute(attrName, attrs[attrName]);
        return node;
    },
    get tabContextUndoClose() {
        return document.getElementById("context_undoCloseTab")
            || document.getElementById("tabContextUndoCloseTab") // Firefox 2.0
            || document.getAnonymousElementByAttribute(gBrowser, "tbattr", "tabbrowser-undoclosetab"); // SeaMonkey
    },
    get closedWindowCount() {
        if(!("getClosedWindowCount" in this.ss)) {
            delete this.closedWindowCount;
            return this.closedWindowCount = 0;
        }
        this.__defineGetter__("closedWindowCount", function() {
            return this.ss.getClosedWindowCount();
        });
        return this.closedWindowCount;
    },
    get closedTabCount() {
        return this.ss.getClosedTabCount(window);
    },
    undoCloseTab: function(i) {
        if("undoCloseTab" in window) // Firefox 2.0+
            undoCloseTab(i);
        else // SeaMonkey
            gBrowser.undoCloseTab(i);
    },
    clearUndoTabsList: function() {
        var closedTabCount = this.closedTabCount;
        if(!closedTabCount)
            return;
        if("forgetClosedTab" in this.ss) // Gecko 1.9.2+
            while(closedTabCount--)
                this.ss.forgetClosedTab(window, 0);
        else {
            // Doesn't work in SeaMonkey
            const pName = "browser.sessionstore.max_tabs_undo";
            let val = cbu.getPrefs(pName);
            cbu.setPrefs(pName, 0);
            cbu.setPrefs(pName, val);
        }
        this.updUIGlobal();
    },
    clearUndoWindowsList: function() {
        var closedWindowCount = this.closedWindowCount;
        if(!closedWindowCount)
            return;
        if("forgetClosedWindow" in this.ss) // Gecko 1.9.2+
            while(closedWindowCount--)
                this.ss.forgetClosedWindow(0);
        else
            this.ss.setWindowState(window, '{"windows":[{}],"_closedWindows":[]}', false);
        this.updUIGlobal();
    },
    clearAllLists: function() {
        this.clearUndoTabsList();
        this.clearUndoWindowsList();
    },
    canDeleteUndoEntry: function(mi) {
        switch(mi.getAttribute("cb_type")) {
            case "tab":    return "forgetClosedTab"    in this.ss;
            case "window": return "forgetClosedWindow" in this.ss;
        }
        return false;
    },
    deleteUndoEntry: function(mi) {
        var i = +mi.getAttribute("cb_index");
        if(mi.getAttribute("cb_type") == "window") {
            this.ss.forgetClosedWindow(i);
            this.updUIGlobal();
        }
        else {
            this.ss.forgetClosedTab(window, i);
            this.updUI();
        }
        this.drawUndoList();
    },
    showMenu: function(e, isContext, mp) {
        var btn = this.button;
        document.popupNode = btn.ownerDocument.popupNode = btn;
        if(!mp)
            mp = this.mp;
        if("openPopupAtScreen" in mp)
            mp.openPopupAtScreen(e.screenX, e.screenY, isContext);
        else
            mp.showPopup(btn, e.screenX, e.screenY, isContext ? "context" : "popup", null, null);
    },
    openMenu: function() {
        var mp = this.mp;
        if("openPopup" in mp)
            mp.openPopup(this.button, "after_start");
        else
            mp.showPopup(this.button, -1, -1, "popup", "bottomleft", "topleft");
    },
    drawUndoList: function() {
        var mp = this.mp;

        var wc = this.closedWindowCount;
        var tc = this.closedTabCount;
        var ss = this.ss;
        var canRestoreLastSession = "restoreLastSession" in ss && ss.canRestoreLastSession
        if(!wc && !tc && !canRestoreLastSession) {
            mp.textContent = "";
            mp.hidePopup();
            return false;
        }

        this._undoWindowItems = wc && JSON.parse(ss.getClosedWindowData());
        this._undoTabItems    = tc && JSON.parse(ss.getClosedTabData(window));
        var df = document.createDocumentFragment();

        this.options.menuTemplate.forEach(function(sid, indx, arr) {
            switch(sid) {
                case "closedWindows":
                    wc && this.addUndoWindowsList(df);
                break;
                case "restoreClosedWindows":
                    wc > this.options.hideRestoreAllForSingleEntry
                    && df.appendChild(this.createElement("menuitem", {
                        label: _localize("restoreAllWindows"),
                        accesskey: _localize("restoreAllWindowsAccesskey"),
                        oncommand: "for(var i = 0; i < " + this._undoWindowItems.length + "; ++i) undoCloseWindow();"
                    }));
                break;
                case "clearClosedWindows":
                    wc && df.appendChild(this.createElement("menuitem", {
                        label: _localize("clearWindowsHistory"),
                        accesskey: _localize("clearWindowsHistoryAccesskey"),
                        oncommand: "this.parentNode.parentNode.undoCloseTabsList.clearUndoWindowsList();"
                    }));
                break;
                case "closedTabs":
                    tc && this.addUndoTabsList(df);
                break;
                case "restoreClosedTabs":
                    tc > this.options.hideRestoreAllForSingleEntry
                    && df.appendChild(this.createElement("menuitem", {
                        label: _localize("restoreAllTabs"),
                        accesskey: _localize("restoreAllTabsAccesskey"),
                        oncommand: "for(var i = 0; i < " + this._undoTabItems.length + "; ++i) this.parentNode.parentNode.undoCloseTabsList.undoCloseTab();"
                    }));
                break;
                case "clearClosedTabs":
                    tc && df.appendChild(this.createElement("menuitem", {
                        label: _localize("clearTabsHistory"),
                        accesskey: _localize("clearTabsHistoryAccesskey"),
                        oncommand: "this.parentNode.parentNode.undoCloseTabsList.clearUndoTabsList();"
                    }));
                break;
                case "clearAll":
                    (
                        wc && tc
                        || wc && arr.indexOf("clearClosedWindows") == -1
                        || tc && arr.indexOf("clearClosedTabs") == -1
                    )
                    && df.appendChild(this.createElement("menuitem", {
                        label: _localize("clearAllHistory"),
                        accesskey: _localize("clearAllHistoryAccesskey"),
                        oncommand: "this.parentNode.parentNode.undoCloseTabsList.clearAllLists();"
                    }));
                break;
                case "restoreLastSession": // Gecko 2.0+
                    canRestoreLastSession && df.appendChild(this.createElement("menuitem", {
                        label: _localize("restoreLastSession"),
                        accesskey: _localize("restoreLastSessionAccesskey"),
                        oncommand: "this.parentNode.parentNode.undoCloseTabsList.ss.restoreLastSession();"
                    }));
                break;
                case "buttonMenu":
                    let cbMenu = this.cbMenu;
                    if(cbMenu)
                        df.appendChild(cbMenu);
                break;
                case "separator":
                    if(df.hasChildNodes() && df.lastChild.localName != "menuseparator")
                        df.appendChild(document.createElementNS(xulns, "menuseparator"));
                break;
                default:
                    Components.utils.reportError(this.errPrefix + 'Invalid template entry: "' + sid + '"');
            }
        }, this);

        while(df.hasChildNodes() && df.lastChild.localName == "menuseparator")
            df.removeChild(df.lastChild);

        this._undoWindowItems = this._undoTabItems = null;

        mp.textContent = "";
        if(!df.hasChildNodes()) {
            mp.hidePopup();
            return false;
        }
        mp.appendChild(df);
        return true;
    },
    addUndoWindowsList: function(undoPopup) {
        // Based on code from chrome://browser/content/browser.js
        // Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.3a1pre) Gecko/20090824 Minefield/3.7a1pre

        var keys = this.options.accesskeys.closedWindows;
        this._undoWindowItems.forEach(function(undoItem, i) {
            var tabs = undoItem.tabs;
            var [key, keyPrefix] = this.getKey(keys, i);
            var title = undoItem.title;
            var selectedTab = tabs[undoItem.selected - 1];
            var urls = [];
            tabs.forEach(function(tab) {
                if(!tab.entries || !tab.entries.length) // Can be [] for about:blank
                    return;
                var url = this.convertURI(tab.entries[tab.index - 1].url, 120);
                var selectedPrefix = tab == selectedTab && tabs.length > 1
                    ? this.options.windowSelectedTabPrefix
                    : "";
                urls.push(selectedPrefix + url);
            }, this);
            var url = urls.join(" \n");
            var mi = this.createElement("menuitem", {
                label: keyPrefix + this.options.windowItemTemplate
                    .replace("%title", title)
                    .replace("%count", tabs.length),
                accesskey: key,
                "class": "menuitem-iconic bookmark-item menuitem-with-favicon",
                oncommand: "undoCloseWindow(" + i + ");",
                cb_url: url,
                cb_urlDecoded: this.convertURI(url),
                cb_closedAt: undoItem.closedAt || 0,
                cb_index: i,
                cb_type: "window"
            });
            if(this.cm)
                mi.setAttribute("context", this.cmId);
            var icon = selectedTab.image || selectedTab.attributes && selectedTab.attributes.image;
            if(icon)
                mi.setAttribute("image", this.cachedIcon(icon));
            if(i == 0)
                mi.setAttribute("key", "key_undoCloseWindow");
            undoPopup.appendChild(mi);
        }, this);
    },
    addUndoTabsList: function(undoPopup) {
        // Based on code from chrome://browser/content/browser.js
        // Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.3a1pre) Gecko/20090824 Minefield/3.7a1pre

        var keys = this.options.accesskeys.closedTabs;
        this._undoTabItems.forEach(function(undoItem, i) {
            var state = undoItem.state;
            var [key, keyPrefix] = this.getKey(keys, i);
            var title = undoItem.title;
            var url = state && state.entries && state.entries[state.index - 1].url || "";
            var mi = this.createElement("menuitem", {
                label: keyPrefix + title,
                accesskey: key,
                class: "menuitem-iconic bookmark-item menuitem-with-favicon",
                oncommand: "this.parentNode.parentNode.undoCloseTabsList.undoCloseTab(" + i + ");",
                cb_url: url,
                cb_urlDecoded: this.convertURI(url),
                cb_closedAt: undoItem.closedAt || 0,
                cb_index: i,
                cb_type: "tab"
            });
            if(
                state
                && "attributes" in state
                && "privateTab-isPrivate" in state.attributes
            ) // https://addons.mozilla.org/addon/private-tab/
                mi.setAttribute("privateTab-isPrivate", "true");
            if(this.cm)
                mi.setAttribute("context", this.cmId);
            var image = undoItem.image // Firefox
                || state && state.attributes && state.attributes.image // SeaMonkey
                || state && state.xultab
                    && /(?:^| )image=(\S+)/.test(state.xultab)
                    && decodeURI(RegExp.$1); // Only Firefox 2.0 ?
            if(image)
                mi.setAttribute("image", this.cachedIcon(image));
            if(i == 0)
                mi.setAttribute("key", "key_undoCloseTab");
            undoPopup.appendChild(mi);
        }, this);
    },
    getKey: function(keys, i) {
        var key = keys && keys.charAt(i % keys.length);
        var keyPrefix = keys && (key + this.options.accesskeyPostfix);
        return [key, keyPrefix];
    },
    checkForMiddleClick: function(e, upd) {
        var mi = e.target;
        if(
            "doCommand" in mi
            && e.button == 1
            && mi.parentNode == e.currentTarget
        ) {
            mi.doCommand();
            if(upd)
                upd();
            else
                this.drawUndoList();
        }
    },
    crop: function(s, crop) {
        if(crop == undefined)
            crop = 500;
        if(s.length <= crop)
            return s;
        var start = Math.round(crop*0.6);
        return s.substr(0, start) + "…" + s.substr(start - crop);
    },
    convertURI: function(uri, crop) {
        if(!uri || uri.indexOf("\n") != -1)
            return uri;
        try {
            uri = "losslessDecodeURI" in window
                ? losslessDecodeURI(makeURI(uri))
                : decodeURI(uri);
        }
        catch(e) {
            Components.utils.reportError(e);
        }
        return this.crop(uri, crop);
    },
    cachedIcon: function(src) {
        src = src.replace(/[&#]-moz-resolution=\d+,\d+$/, ""); // Firefox 22+
        if(
            !/^https?:/.test(src)
            // IDN, see https://bugzilla.mozilla.org/show_bug.cgi?id=311045
            || /^https?:\/\/[^.:\/]+\.[^a-z0-9-]+(?:\/|$)/.test(src)
            || this.appName == "SeaMonkey" && this.appVersion <= 2
            || this.appName == "Firefox"   && this.appVersion <= 3.5
        )
            return src;
        return "moz-anno:favicon:" + src; // https://bugzilla.mozilla.org/show_bug.cgi?id=467828
    },
    updUI: function() {
        var tabsCount = this.closedTabCount;
        var dis = !tabsCount && !this.closedWindowCount;
        if(
            dis
            && this.options.useMenu
            && this.options.menuTemplate.indexOf("restoreLastSession") != -1
            && "restoreLastSession" in this.ss && this.ss.canRestoreLastSession
        )
            dis = false;
        this.button.disabled = dis;
    },
    updTooltip: function(tip, tn) {
        var template, header, title, url, closedAt;
        if(tn == this.button) {
            template = this.options.buttonTipTemplate;
            header = _localize("restoreTab");
            let undoTabItems = JSON.parse(this.ss.getClosedTabData(window));
            if(undoTabItems.length) {
                let lastItem = undoTabItems[0];
                title = lastItem.title;
                url = lastItem.state && lastItem.state.entries
                    && lastItem.state.entries[lastItem.state.index - 1].url;
                closedAt = lastItem.closedAt || 0;
            }
        }
        else if(tn.hasAttribute("cb_index")) {
            template = this.options.itemTipTemplate;
            title = tn.getAttribute("label");
            url = tn.getAttribute("cb_url");
            closedAt = +tn.getAttribute("cb_closedAt");
        }
        else {
            return false;
        }

        var tipData = this.getTooltipData(template, header, title, url, closedAt);
        tip.textContent = "";
        tip.appendChild(tipData);
        if(closedAt && template.indexOf("closedAt") != -1) {
            tip.initUpdateTimer(function() {
                var tipData = this.getTooltipData(template, header, title, url, closedAt);
                if(tipData.textContent != tip.textContent) {
                    tip.textContent = "";
                    tip.appendChild(tipData);
                }
            }, this);
        }
        return tip.hasChildNodes();
    },
    getTooltipData: function(template, header, title, url, closedAt) {
        var df = document.createDocumentFragment();
        var hasHeader = header && template.indexOf("header") != -1;
        function item(key, val) {
            var lbl = document.createElementNS(xulns, "label");
            lbl.className = "cb-" + key;
            //lbl.setAttribute("value", val);
            lbl.textContent = val;
            lbl.setAttribute("maxwidth", "450"); // Trick to restore right border for long lines
            if(key == "closedAt" || hasHeader && key != "header")
                lbl.style.color = "grayText";
            return df.appendChild(lbl);
        }
        template.forEach(function(key) {
            switch(key) {
                case "header":
                    if(header)
                        item(key, header);
                break;
                case "title":
                    if(title && title != url)
                        item(key, title);
                break;
                case "url":
                    if(url)
                        item(key, this.convertURI(url));
                break;
                case "closedAt":
                    if(!closedAt)
                        break;
                    let dt = Math.round(Math.max(0, Date.now() - closedAt)/1000);
                    let days = Math.floor(dt/24/3600);
                    dt -= days*24*3600;
                    let d = new Date((dt + new Date(dt).getTimezoneOffset()*60)*1000);
                    let m = d.getMinutes();
                    let ts = d.getHours() + ":" + (m > 9 ? m : "0" + m);
                    if(days)
                        ts = days + _localize("day") + " " + ts;
                    let tsTip = _localize("itemTip")
                        .replace("%ago", ts)
                        .replace("%date", new Date(closedAt).toLocaleString());
                    item(key, tsTip);
            }
        }, this);
        return df;
    },
    get wm() {
        delete this.wm;
        return this.wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
            .getService(Components.interfaces.nsIWindowMediator);
    },
    updUIGlobal: function() {
        var isSeaMonkey = this.appName == "SeaMonkey";
        var ws = this.wm.getEnumerator(isSeaMonkey ? null : "navigator:browser");
        const id = this.button.id;
        while(ws.hasMoreElements()) {
            let win = ws.getNext();
            if(!isSeaMonkey || this.isBrowserWindow(win)) {
                let btn = win.document.getElementById(id);
                if(btn && "undoCloseTabsList" in btn) {
                    let ucl = btn.undoCloseTabsList;
                    ucl.ensureSessionsInitialized(ucl.updUI, ucl);
                }
            }
        }
    },
    isBrowserWindow: function(win) {
        var loc = window.location.href;
        return loc == "chrome://browser/content/browser.xul"
            || loc == "chrome://navigator/content/navigator.xul";
    },
    ensureSessionsInitialized: function(callback, context) {
        var _this = this;
        var stopTime = Date.now() + 3e3;
        (function ensureInitialized() {
            try {
                _this.ss.getClosedTabCount(window);
                callback.call(context);
                return;
            }
            catch(e) {
                if(Date.now() > stopTime) {
                    Components.utils.reportError(
                        _this.errPrefix
                        + "Can't initialize: nsISessionStore.getClosedTabCount() failed"
                    );
                    Components.utils.reportError(e);
                    return;
                }
            }
            setTimeout(ensureInitialized, 50);
        })();
    }
};

if(!this.undoCloseTabsList.options.useMenu && this.undoCloseTabsList.useCentextMenu) {
    this.oncontextmenu = function(e) {
        if(
            e.target != this
            || e.ctrlKey || e.shiftKey || e.altKey || e.metaKey
            || !this.undoCloseTabsList.mp.hasChildNodes()
        )
            return;
        e.preventDefault();
        this.undoCloseTabsList.showMenu(e); // Show menu without "context" flag
    };
}
if(this.undoCloseTabsList.options.rightClickToUndoCloseTab) {
    this.oncontextmenu = function(e) {
        if(e.target == this && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey)
            e.preventDefault();
    };
}

this.disabled = true;
setTimeout(function(_this) {
    _this.undoCloseTabsList.init();
}, 0, this);

//===================
// Styles
// Used icons from Undo Closed Tabs Button extension

// Styles can't override hardcoded icon
if( // Remove icon only if nsIStyleSheetService works on-the-fly (Firefox 3.0+)
    !Components.ID("{41d979dc-ea03-4235-86ff-1e3c090c5630}")
        .equals(Components.interfaces.nsIStyleSheetService)
) {
    let icon = this.icon
        || this.ownerDocument.getAnonymousElementByAttribute(this, "class", "toolbarbutton-icon");
    if(icon)
        icon.src = "";
    else
        this.image = "";
}

var cssStr = '\
    @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");\n\
    @-moz-document url("%windowURL%") {\n\
        %button% {\n\
            list-style-image: url("data:image/png;base64,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") !important;\n\
            -moz-image-region: rect(0, 24px, 24px, 0) !important;\n\
        }\n\
        %button%:hover {\n\
            -moz-image-region: rect(0, 48px, 24px, 24px) !important;\n\
        }\n\
        %button%[disabled="true"] {\n\
            -moz-image-region: rect(0, 72px, 24px, 48px) !important;\n\
        }\n\
        toolbar[iconsize="small"] %button% {\n\
            -moz-image-region: rect(24px, 16px, 40px, 0) !important;\n\
        }\n\
        toolbar[iconsize="small"] %button%:hover {\n\
            -moz-image-region: rect(24px, 32px, 40px, 16px) !important;\n\
        }\n\
        toolbar[iconsize="small"] %button%[disabled="true"] {\n\
            -moz-image-region: rect(24px, 48px, 40px, 32px) !important;\n\
        }\n\
    }'
    .replace(/%windowURL%/g, window.location.href)
    .replace(/%button%/g, "#" + this.id);
var cssURI = this.cssURI = Components.classes["@mozilla.org/network/io-service;1"]
    .getService(Components.interfaces.nsIIOService)
    .newURI("data:text/css," + encodeURIComponent(cssStr), null, null);
var sss = this.sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
    .getService(Components.interfaces.nsIStyleSheetService);
if(!sss.sheetRegistered(cssURI, sss.USER_SHEET))
    sss.loadAndRegisterSheet(cssURI, sss.USER_SHEET);


this.onDestroy = function(reason) {
    this.undoCloseTabsList.destroy();
    if(reason == "update" || reason == "delete") {
        let sss = this.sss;
        let cssURI = this.cssURI;
        if(sss.sheetRegistered(cssURI, sss.USER_SHEET))
            sss.unregisterSheet(cssURI, sss.USER_SHEET);
    }
};
if(this.undoCloseTabsList.options.useMenu) {
    this.type = "menu";
    this.orient = "horizontal";
}

Andrey_Krropotkin пишет

подправь пожалуйста (срабатывает только со второго раза)

Замысел непонятен. Если типа для всех findbar'ов вообще,
то примерно так, а если только для открытых двойным СКМ,
то нужно описание.

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

Выделить код

Код:

(obj => {
    for(var findbar of gBrowser.tabpanels.getElementsByTagName("findbar"))
        obj.initFindBar(findbar);
    addEventListener("TabFindInitialized",
        e => obj.initFindBar(e.target._findBar)
    , false, gBrowser.tabContainer || 1);
    addDestructor(() => Array.from(
        document.getElementsByClassName("clearFindbar-button")
    ).forEach(obj.destroyFindBar, obj));
})({
    initFindBar(findbar) {
        var btn = document.importNode(this.btn);
        btn.style; // ???
        btn.onclick = this.click;
        (btn.findbar = findbar).getElement("highlight").before(btn);
        findbar.onwheel = this.wheel;
        findbar.getElement("find-closebutton")
            .setAttribute("style", "-moz-box-ordinal-group: 0 !important;");
    },
    destroyFindBar(btn) {
        btn.findbar.getElement("find-closebutton").removeAttribute("style");
        btn.findbar = btn.findbar.onwheel = null;
        btn.remove();
    },
    click(e) {
        if (e.button == 1) return;
        this.findbar._findField.value = e.button ? "" : gClipboard.read().trim();
        this.findbar.onFindAgainCommand();
    },
    wheel(e) {
        this.onFindAgainCommand(e.deltaY < 0);
    },
    get btn() {
        delete this.btn;
        var btn = MozXULElement.parseXULToFragment(`<toolbarbutton
            type="button"
            style="margin: 0 6px !important;"
            class="toolbarbutton-1 clearFindbar-button"
            tooltiptext="ЛКМ - вставить из буфера.&#xA;ПКМ - очистить поиск."
            image="data:image/x-icon;base64,AAABAAEADhAAAAEAIADoAwAAFgAAACgAAAAOAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXn/eXl5/3l5ef95eXn/eXl5/3l5ef95eXn/eXl5/ylTda0pU3X/KVN1/ylTdf8pU3X/HTpS/4WFhf/w8PL/8fHz//Hx8//x8fP/8fHz//Hx8/+FhYX/KVN1/yRJaP8jSGf/I0dl/yNHZP8YMEX/j4+P//Hx8//x8vP/8fLz//Hy8//x8vP/8fLz/4+Pj/8pU3X/JUxr/yVLav8kSmn/JElo/xkyR/+cnJz/8vLz//Ly9P/y8vT/8vL0//Ly9P/y8vT/nJyc/ylTdf8nTm3/Jk1t/yVMa/8lSmn/GjNJ/6urq//y8vT/8/P1//Pz9f/z8/X/8/P1//Pz9f+rq6v/KVN1/ydPb/8nTm7/Jk1t/yZMa/8aNEr/srKy//X19v/19vf/9fb3//X29//19vf/9fb3/7Kysv8pU3X/J1Bx/ydQb/8nTm//Jk1t/xs2S/+8vLz/+fr6//r7+//6+/v/ubm5/7e3t/+3t7f/ubm5/ylTdf8oUXP/KFBx/ydQcf8nT2//GzZN/76+vv/6+/v/+/v8//v7/P/ExMT/9vb2/7e3t/na2tpfKVN1/ylTdP8pUXP/KFBy/yhPcP8bN03/v7+///v7/P/7/Pz/+/z8/8rKyv+3t7f/4OLgaQAAAAApU3X/KVN1/yhSdP8oUnT/KFJy/xw4UP+/v7//v7+//7+/v/+/v7//uru7/2OBmf8AAAAAAAAAAClTdf8pU3X/KVN1/ylSdP8pUnT/JEpn/yRIZv8kSGX/I0dk/yNGY/8jRWL/KVN1/wAAAAAAAAAAKVN1/ylTdf8lS2n/IztO/yM7Tv8jO07/IztO/yM7Tv8jO07/JUtp/ydOb/8lS2n/AAAAAAAAAAApU3X/K2GQ/yhahv91dXX/XV1d/11dXf9dXV3/XV1d/4B/f/8oWob/Kmad/ylTdf8AAAAAAAAAAClTda0pU3X/KVN1/7O0tP/h4eD/3t7f/97f3//g4OD/s7S0/ylTdf8pU3X/KVN1rQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1yds1dXFv1XVxb9Wxxdc8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUwFASZMCwAlTAsAI00LIys1CxcXFsEYFxbCJS01DAAlTQsAJk0LASZNCwAlTQUAAAAAAAAAAPwArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAASsQQAMrEEADKxBAAysQQAMrEEADKxB8PysQQAMrEE="
        />`).firstChild;
        btn.remove();
        return this.btn = btn;
    }
});

func4ptch4 пишет

проверял кнопку, интересно он работает только после правки, а так после запуска [firefox] не работает.

Не получается воспроизвести. Можно так попробовать
this.onmouseover = e => custombuttons.initAutoPopup(this) && this.onmouseover(e);

Отсутствует

 

№1413326-01-2020 14:03:15

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
UA: Firefox 72.0

Re: Custom Buttons

Dumby
Как это? Заработало! Ну, ты и Magic , в натуре.

Отсутствует

 

№1413426-01-2020 14:03:52

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

Re: Custom Buttons

Dumby спасибо, да именно то что нужно

Отсутствует

 

№1413526-01-2020 18:52:36

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

Re: Custom Buttons

Andrey_Krropotkin
А открытие FindBar двойным СКМ появилось?

Отсутствует

 

№1413626-01-2020 19:25:37

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 557
UA: Firefox 72.0

Re: Custom Buttons

а есть (можно ли сделать) кнопка, которая закрывает вкладку по клавише Esc?

Отсутствует

 

№1413726-01-2020 19:51:43

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

Re: Custom Buttons

voqabuhe этот  код - отдельное добавление не связан с СКМ

Отсутствует

 

№1413826-01-2020 20:00:36

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 68.0

Re: Custom Buttons

Andrey_Krropotkin
Все варианты кнопки перевода добавляют в низ окна с переводом пустые строки, бесполезно увеличивая тем самым площадь окна на 20-30%. Может, это можно пофиксить?
1.1580057867.png

Отсутствует

 

№1413926-01-2020 20:04:26

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

Re: Custom Buttons

sonyas75 пишет

а есть (можно ли сделать) кнопка, которая закрывает вкладку по клавише Esc?

Попробуйте так:

Выделить код

Код:

// Закрыть активную вкладку по Escape .....
document.onkeydown=function(e) {
  if (e.which == 27) { gBrowser.removeCurrentTab(); }
}

«The Truth Is Out There»

Отсутствует

 

№1414026-01-2020 20:08:57

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

Re: Custom Buttons

shadow_user попробуй поэкспериментируй вот здесь
cnt.style.height = 50*i+'px';
cnt.style.width = 100*i+'px';
и наверно пропорция окна width:240px;height:120px

Отредактировано Andrey_Krropotkin (26-01-2020 20:32:05)

Отсутствует

 

№1414126-01-2020 20:15:07

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

Re: Custom Buttons

Andrey_Krropotkin пишет

этот  код - отдельное добавление не связан с СКМ

Для чего этот я понял. Я спрашивал вообще, что-нибудь появилось для СКМ, чтоб не пропустить?

Добавлено 26-01-2020 20:19:57

unter_officer пишет

Попробуйте так:

Прикольная фишка получилась, спасибо.

Отредактировано voqabuhe (26-01-2020 20:20:30)

Отсутствует

 

№1414226-01-2020 20:24:22

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 557
UA: Firefox 72.0

Re: Custom Buttons

unter_officer
да! спасибо :)

Отсутствует

 

№1414326-01-2020 20:34:47

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

Re: Custom Buttons

voqabuhe нет, как раньше дал Dumby код по СКМ, больше изменений не было.

Отсутствует

 

№1414426-01-2020 21:58:54

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 68.0

Re: Custom Buttons

unter_officer пишет

кнопка, которая закрывает вкладку по клавише Esc?

voqabuhe пишет

Прикольная фишка получилась, спасибо.

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

Andrey_Krropotkin пишет

shadow_user попробуй поэкспериментируй вот здесь

Не помогло. Ну да ладно, это уже чисто эстетика.

Отсутствует

 

№1414526-01-2020 22:43:45

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

Re: Custom Buttons

shadow_user пишет

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

Не могу заценить, у меня нет никаких окон перевода.  А для перевода давно понял, что для меня пока нет ничего удобнее QTranslate.

Добавлено 26-01-2020 22:49:07
А возможность осталась любым способом восстановить адресную строку в окне добавления закладок через звёздочку и сделать всегда развёрнутым окошко дерева закладок там же?

Отредактировано voqabuhe (26-01-2020 22:50:06)

Отсутствует

 

№1414627-01-2020 01:05:15

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
UA: Firefox 72.0

Re: Custom Buttons

Кто там хотел "Перевод" с идеальным окном ?

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

Выделить код

Код:

/*Initialization Code*/

var lc = navigator.lastClick = {};
addEventListener("mouseup", e => {
    if (e.button) return;
    lc.X = e.screenX - mozInnerScreenX;
    lc.Y = e.screenY - mozInnerScreenY;
}, false, gBrowser.tabpanels || 1);

var createWindow = function(text, status, title, id, pos, size){
var win = window, 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.createElementNS(xhtmlns, 'div');
     w.setAttribute('style', 'position:fixed;display:block;visibility:hidden;left:0;top:0;width:auto;height:auto;border:1px solid gray;padding:2px;margin:0;z-index:99999;overflow:hidden;cursor:move;'+(typeof w.style.borderRadius === 'string' ? 'background-color:#eaeaea;padding-top:0px;border-radius:4px;box-shadow:0 0 15px 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.addEle = function(str, style){
        var ele = doc.createElementNS(xhtmlns, '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);
    };
     w.addEle1 = function(str, style){
        var ele = doc.createElementNS(xhtmlns, 'textarea');
        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.createElementNS(xhtmlns, 'div');
    img.setAttribute('style', 'display:block;float:right;width:15px;height:15px;padding:0;margin-top:3px;margin-right:2px;border:none;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAACwklEQVR42i2TW0hVeRjFf98+aloWQUbkedBCIkgKusAxRCiiBy3yrZJuxEB0Bh/moemh6EoXkuhGSQ9dToHVW3XwKS1qhnFmcIIEmTNQYD3UoIWdtDJt76+1j/5hbfbe//196/+ttbah9adQLNwWmqFpLtTlYcwg8Q3C6VD6H/y9HR66vokRCPaPLt/jG2EMttXPmXPbWlvh0ycoKtKmdmfNYvTcOTL5fHoPtOstw3HNX7pEwjjsqK+szAQPHkRUVFihXyIh3pAC2fv3nm9qCi4NDv68D650TBUXiXFrw8yZt8hkQubNCzAzhoddzCZmZ/ZsUxNnaCj6sGtX4uTISHotXLNH0NgAnSVtbSHJZEBjo6nY6e42Xr+GqipYs8YpKTE6O51cLsodOpQ4Ay3WCydWrF69n1QqKDDs3u2eTJq9fSslJWUqhVdWYn19zvHjRm+v+8BAeAFu2B9wsC6ZPMbKlcbXr051tZFO40uX4jq9RRH25Alqysc3b1wq26g0uCnh7Dc4XD9t2hEWLtQrmZCXSVu2ELadJfF5BC8vx5qbyWezBTtjceUD1+Pip2JeDsfKi4stmpjwIJUy2tuhtpZIVgWxVc+fw86djOZyLhtsRDRX4+JnmnkV7FfXILF4sZHNutfUmD2Ld07AgQPQIElfvXI2bLDvaiB3osLMl2Gjth7WzpgRat6A+/eN8XGnpcX8xQts2TLo6HB0MjZtcjngXV++BFfgF3usZP4OP22W8YtqakLmzw8oKzP6+13JMiXNWbJkUsx376Kely8TF+HUXbhgGQ2/blKA9Da4XF1XFyoQAaWlsd+TIo6NudLmfT09wWkV3oHzGmbQ4vBNCAoibbB3h06QXL8eMVFYcXFZGf92dXHU/eQ9MW5VYdXU/8CQUDH18KuiukiZ+qiesbJq7KVQ0g39WbirH+l/pYsFwg9RIBTyj1ZRogAAAABJRU5ErkJggg==");background:-o-skin("Caption Close Button Skin");');
    img.title = (win.navigator.language.indexOf('ru') == 0) ? '\u0417\u0430\u043A\u0440\u044B\u0442\u044C' : 'Close';
    img.addEventListener('click', function(){this.parentNode.closeWin()}, false);
    w.appendChild(img);
    var title = w.addEle(title, 'display:table;color:#000;font:17px Times New Roman;width:auto;height:auto;padding:0;margin:0 2px;cursor:text;');
        title.onclick = e => {
        e.preventDefault();
        var url = e.target.href;
        // Здесь открываем url как хотим.
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
        doc.getElementById(wId).closeWin();    
    }
    var cnt = w.addEle1(text, 'display:block;border:1px solid #aaa;padding-bottom:3px;padding-left:3px;background-color:#fafcfe;color:#000;font:17px Times New Roman;width:260px;height:100px;overflow:auto;cursor:text;-moz-user-focus:normal;');
    cnt.contentEditable="true";
    cnt.context="contentAreaContextMenu";
    w.addEle(status, 'display:table;font:12px Times New Roman;font-weight:bold;color:blue;width:auto;height:auto;padding-top:2px;margin:0 3px;cursor:pointer;');
    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 = 40*i+'px';
        cnt.style.width = 130*i+'px';
    }
    else{
        for(var i = 3; i < 10; i++){
            if(cnt.scrollHeight > cnt.offsetHeight || cnt.scrollWidth > cnt.offsetWidth){
                cnt.style.height = 40*i+'px';
                cnt.style.width = 130*i+'px';
            }
            else break;
        }
    };

    var docEle = (doc.compatMode == 'CSS1Compat' && win.postMessage) ? 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);
    return w;
};

var getHash = function (txt) {
    TKK=eval('((function(){var a\x3d817046147;var b\x3d-335196159;return 410049+\x27.\x27+(a+b)})())');
    function sM(a) {
        var b;
        if (null !== yr)
            b = yr;
        else {
            b = wr(String.fromCharCode(84));
            var c = wr(String.fromCharCode(75));
            b = [b(), b()];
            b[1] = c();
            b = (yr = window[b.join(c())] || "") || ""
        }
        var d = wr(String.fromCharCode(116))
            , c = wr(String.fromCharCode(107))
            , d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var l = a.charCodeAt(g);
            128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
                e[f++] = l >> 18 | 240,
                e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
                e[f++] = l >> 6 & 63 | 128),
                e[f++] = l & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++)
            a += e[f],
                a = xr(a, "+-a^+6");
        a = xr(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    }

    var yr = null;
    var wr = function(a) {
        return function() {
            return a
        }
    }
        , xr = function(a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2)
                , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
                , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    }; 

    return sM(txt);
}; 
 
  
 
var ujs_google_translate = function (dir){
    var lng = window.navigator.language.slice(0, 2), txt = gContextMenu.selectionInfo.fullText, l = dir.split('|');
    var encTxt = encodeURIComponent(txt);
    var winWait = function(lng){createWindow('', (lng == 'ru' ? 'Подождите идет перевод' : 'Wait, is going Translating')+'\u2026', 'Google Translate', '_gt', window.navigator.lastClick)};
    if (txt) {
    winWait(lng);
        var xhr = new XMLHttpRequest();
         var url = 'https://translate.google.com/translate_a/single?client=gtx&sl=' + l[0] + '&tl=' + l[1] + '&hl=' + lng + '&eotf=0&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t' + getHash(txt);
        var urlt = "http://translate.google.com/translate_t?text="+encTxt+"&sl='  + langFrom_google_text + '&tl=' + langTo_google_text +'&hl=' + lng + '&eotf=0&ujs=gtt";
      
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
        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').replace(/\\n/g, "<br />"));
                    for(var i = 0, n; n = tmp[0][i]; i++){
                        if(n[0])result += n[0].toString();
                    };
                    status = tmp[8][0][0].toUpperCase() + ' -\u203A ' + l[1].toUpperCase();
                     createWindow(result, status, '<a href="'+urlt.replace(/&/g,'&amp;')+'" target="_blank" style="display:inline;padding:0;margin:0;text-decoration:none;border:none;color:blue;font:17px Arian;">Google Translate</a>', '_gt', window.navigator.lastClick);
                }
            } catch (x){LOG(x)};
        };
        xhr.send('q=' + encodeURIComponent(txt));
    } else {
        var urlt = gBrowser.currentURI.spec;  
        var url = "http://translate.google.com/translate?u="+encodeURIComponent(urlt)+"&hl="+lng+"&langpair="+dir+"&tbb=1";
        var ctabpos = gBrowser.selectedTab._tPos +1;
        gBrowser.moveTabTo(gBrowser.selectedTab = gBrowser.addWebTab(url), ctabpos);
    };
};

var contextMenu = document.getElementById("contentAreaContextMenu");
var nextEleMenu = document.getElementById("context-inspect");

var menuId = "context-ext-google-translate";
var menuItem = document.getElementById(menuId);
if (menuItem) {
    contextMenu.removeChild(menuItem.nextElementSibling);
    contextMenu.removeChild(menuItem.nextElementSibling);
    contextMenu.removeChild(menuItem);
};

menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("id", menuId);
menuItem.setAttribute("label", "Перевести на русский");
menuItem.setAttribute("class", "menuitem-iconic");
menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABBUlEQVR4Ac2RMU4DMRREB2MqihQpAkUaqnAduuQw4Sx03CGcJYIiDYqQ0lCsZ77535ZFcgAkRuPvV7zd/dLiz3N1PFb8hmRckrfELZrF9ONQ1B6Yz0MyM7S0O6zGkVprh/3+Kw/JzkHSpRpJKZkpr9fYbOx0cjVsCbWG31oHBM9mtt0q73ZcrdLhAMlYQKkUI22aqsNo8HKZAMQhvVaKSHWj2Q2aPU3mJQFY7nuHyvYFduP83WF3AJRfcPNYnr/Lp1G1uK4m9sno1LaUbnX/htf8BNzoneUD5NhjvLCMhURQSQ93QCZwXYjFwg3I0NZKrvoknQPMIHkt/jRAQKMeG2yX89/mB4EJbKbZxIhFAAAAAElFTkSuQmCC");
menuItem.addEventListener("command", function(){ujs_google_translate('auto|ru')}, false);
contextMenu.insertBefore(menuItem, nextEleMenu);

menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("label", "Перевести на английский");
menuItem.setAttribute("class", "menuitem-iconic");
menuItem.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAAB5UlEQVR4AWOgPZg0c9+Oq2+qpx9LaQaiw4mNB27efbs2uXFNQh2Q4Zm9zSNth23MhqjGnXMC86vnHmUS4udxv7OvOd2yPE7PTlfCTk9GVVEoyJA7WI8dyPA0k3U1l+jJMV7CeThpTZeoKDdDUsvBPSff/V+6/P/Bvf///2+bdvU/EKRm/k9IBNIlfZe+LFrzvbsbyJ636pKkyQyQhoUb7tZNvPpw3/0/TfX/ISAm5n94BIiRm/n/xYsLd946ei4vajoiqDuRAejQf//+o4PQ0P9+fmhiQGVnrr1kXJNYG2zEzXDxDsPv3wy/fkFJoOTPn39+/fr/69e/37//AUX+/mXRkO458wWHDba2f8wswCyQ3N+/f//8/fP7z5+TV18w2Mdt6plzPiptx5Wr7/+/ffMzOR6kysjkt74hWMPfp06O+2dulZCeFZKwnkE4m8E8bN3i9aCQ+dxY96GrK6bkGJD9R1v3l6Y20NVW9kt+/v//ZdbcFwkxTVPPMQimM8XEqkb7a/zoqLxkH9v4zVyI5+///wyMmtKMmhJAnbLqQjHxaw5r2orOmZN5uj470Zahat6BKS7JzpmLBHXm8GhM5lCdcP7ai1ZpixZxk9NXXjKIFzOIFjAI54oY1vXuue5qmscw+AAAW0tKxtPoicEAAAAASUVORK5CYII=");
menuItem.addEventListener("command", function(){ujs_google_translate('auto|en')}, false);
contextMenu.insertBefore(menuItem, nextEleMenu);

contextMenu.insertBefore(document.createXULElement("menuseparator"), nextEleMenu);

Отсутствует

 

№1414727-01-2020 04:14:07

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 69.0

Re: Custom Buttons

unter_officer
А можно сделать, чтобы "Закрыть активную вкладку по Escape ....." не закрывала вкладку в Полноэкранном режиме? Из него выход же тоже по Esc. А то уже три раза по ошибке фильм закрывал, приходится потом искать откуда смотреть. :)

Отсутствует

 

№1414827-01-2020 07:46:28

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

Re: Custom Buttons

voqabuhe пишет

А можно сделать, чтобы "Закрыть активную вкладку по Escape ....." не закрывала вкладку в Полноэкранном режиме?

Попробуйте так:

Выделить код

Код:

document.onkeydown=function(e) {
  if (e.which == 27 && window.fullScreen) {
    window.fullScreen = !window.fullScreen;
  }
  else if (e.which == 27) {
    gBrowser.removeCurrentTab();
  }
}

Отредактировано unter_officer (27-01-2020 08:43:41)


«The Truth Is Out There»

Отсутствует

 

№1414927-01-2020 08:52:58

shadow_user
Участник
 
Группа: Members
Зарегистрирован: 14-02-2007
Сообщений: 244
UA: Firefox 68.0

Re: Custom Buttons

voqabuhe пишет

Не могу заценить, у меня нет никаких окон перевода.

Речь об обсуждаемом контекстном (из конт. меню) переводе от Andrey_Krropotkin.

solombala пишет

Кто там хотел "Перевод" с идеальным окном ?

Теперь получше. Плюсы: иногда совсем нет пустых строк, примерно один раз из пяти; количество пустых строк уменьшилось. Минусы: в большинстве случаев пустые строки все же есть.

Отсутствует

 

№1415027-01-2020 08:54:12

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

Re: Custom Buttons

unter_officer пишет

Попробуйте так:

Во, теперь просто здорово. Спасибо.

Отсутствует

 

Board footer

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