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

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

№782609-06-2014 12:22:23

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 29.0

Re: Custom Buttons

okkamas_knife и bunda1 спасибо за помощь, а то я немного запутался. :)

Вот фрагмент работоспособного кода, может кому то пригодиться

Из кнопки  — Page Navigation

Выделить код

Код:

var IncDecPage = 1; //Только целое число!!!
var delay = 600; // Задержка для Long Right
this.onmousedown = function(event) {this._mouseDownTime = Date.now();};

//....................
//Вверх по странице
this.rightclick = function(event) {
  if ((Date.now() - this._mouseDownTime) > delay)
     {
       gShowPopup(this);
       return;
     }
  var scroller = this.scroller;
  if(!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
    event.preventDefault();
        event.stopPropagation();
        content.scrollByPages(-IncDecPage);
        }
};

//....................
this.setAttribute('onclick', 'custombuttons.gQuot.mHandler(event, this)');
this.setAttribute('ondblclick', 'custombuttons.gQuot.mHandler(event, this)');


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№782710-06-2014 04:54:45

difabor
Участник
 
Группа: Members
Зарегистрирован: 21-09-2013
Сообщений: 539
UA: Firefox 28.0
Веб-сайт

Re: Custom Buttons

bunda1 пишет

Вопрос знающим людям :blush:
Как отсортировать массив объектов placesList по свойству uri так что бы объекты с одинаковыми доменами uri.split(/\/+/g)[1] были по группам в массиве, а эти группы были отсортированы по свойству title в алфавитном порядке placesList.sort(function(a, b) a.title.localeCompare(b.title, {sensitivity: "base"}));

Мучаюсь с этим уже который час и не могу придумать решение :(

Я, конечно, человек не знающий, но что если:
1. Отсортировать исходный массив по свойству uri в алфавитном порядке.
2. Отсортированный массив распихать по группам с одинаковыми доменами.
    (Просто при прохождении массива текущий домен сравнивать с предыдущим.
     Если равны - переписывать в ту же группу, если нет - создавать новую и записывать туда)
3. Каждую такую группу отсортировать по свойству title в алфавитном порядке.

Отредактировано difabor (10-06-2014 18:55:49)


Хорошо, когда у человека есть выбор, но плохо, когда он перед ним стоит ©

Отсутствует

 

№782810-06-2014 10:08:04

Mishania
Забанен
 
Группа: Members
Откуда: Usa
Зарегистрирован: 22-10-2011
Сообщений: 357
UA: Firefox 30.0

Re: Custom Buttons

Сегодня обновил браузер до 30. Перестала работать "//Добавление в меню расширений дополнительных пунктов".  Поправьте, пожалуйста.

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

Выделить код

Код:

//Добавление в меню расширений дополнительных пунктов
(function(){
    var iconURL = null;  
    
    let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
    Cu.import("resource://gre/modules/Services.jsm");
    Cu.import("resource://gre/modules/AddonManager.jsm");
    Cu.import("resource://gre/modules/XPIProvider.jsm");

    const usoRegx = /^https?:\/\/userscripts.org\/scripts\/source\/\d+.\w+.js$/;

    window.AMD_Helper = {
        init: function(){
            document.addEventListener("DOMContentLoaded", this, false);
            this.addHomePageForScriptish();
        },

        handleEvent: function(event){
            switch(event.type){
                case "DOMContentLoaded":
                   var doc = event.target;
                    var win = doc.defaultView;
                    if (["about:addons","chrome://mozapps/content/extensions/extensions.xul"].indexOf(doc.URL) == -1)
                        return;
                    this.addPopupMenu(doc);

                    win.AMD_Helper = AMD_Helper;
                    this.win = win;

                    var observer = new MutationObserver(function(e) {
                        e = e[e.length-1];
                        if(e.attributeName == "loading") {
                            var doc = e.target.ownerDocument;
                        }
                    });
                    observer.observe(doc.getElementById("detail-view"), {attributes: true});
                    break;
                    case "popupshowing":
                    this.getAddon(this.win.document.popupNode.value,
                                  this.setItemsAttributes,
                                  event);
                    break;
            }
        },
        addHomePageForScriptish: function(){
            if(!window.Scriptish_config) return;
            Scriptish_config.scripts.forEach(function(script){
                if(!script.homepageURL && script.updateURL){
                    if(usoRegx.test(script.updateURL)){
                        script.homepageURL = script.updateURL.replace(/source/, "show").replace(/.\w+.js$/, "");
                    }
                }
            });
        },
   
       //Создаем меню
       addPopupMenu: function(doc){

         var mainicon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAB3RJTUUH1wcREBAg9OD7NAAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAARnQU1BAACxjwv8YQUAAAH6SURBVHjaxVNBaxNBFP4mGRNp06bSaGu9qXhRLOSQX6Dg0d48SMWC4Mmbv8AfYA7Sgp6UgteCF29CKahBsKKWglgam4rRxGxiks3u7Mz6zZIlSVHRk7N8vLcz7/vemzczwP8eorSCgtLJJeXpUGtMBQHgK5RptxbuYJUx5o8CL5bx+OzCkyuZ2cLIwtPihbVW9a1GiCyFQyusFD4S2zfv4x5DtI2TAphOZk8zbXFE4NKt5ctInDmY8OLd6zNrtI+IlhURG0Xs55dezZXXF9Gq7CA9NQvNbAH19W/wo+6gWXeaN1aQkybEXLv2Bb36Z+SvfUAynYLgB9Y+GLEv6Sl4HTdcvX0yy4kZqdkit1nFWC4Pme4ydvMXxNiOwwTfIVP5OCBlK0Cv8Y4C5xnXYM+bB0ixTwjWHwpUdzbh+ijZSWlYQefrcxwrLJJcIZxRAWM33qP1KTCOwJ9ErbyLno8trvqRgOrsITV5ik6pT2IXvbZdINmjVr8CmYMx09h7/8wKMBtUtIWgu4/DE8e5lxob4pLsDkhhvxJrjYfE2Am065/Et1ZUQRAJTBxJIDQJZrgKZDiRwYA03AlxCF1Ho92oYGM7ElCS5/qmVjXzLx+cg71tMex5D/8Pw+ng4etd2GYpER0ucJRI26v9l2/Ivg82CI2YIP+BPCyifwI91AzKs/qQkQAAAABJRU5ErkJggg==";
         var mainicon1="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABVUlEQVQ4y2P4//8/AyWYoALpQsb9ftPM/4tnM+4nywCQ5s5jRf8d+7T+k2VAxHzH/TUHkv57TDMgzgWyJYz74xZ6/E9Y4vU/ZaXv/9Jd0f/LDkb+j13v8N9xmtp/oy6J/xqN/P+5Ihj2YzUApHnxtb7/My83/e8+W/C/9nj8//yD/v+T99j/D99u8N9nk/J/h9Vi/+Vq2P5jNQBkMz7NTuvE/1ut5v0vV8+M3QCQs3Fptlsh+l93Ktd/pTaW/wKpjAgDYFEFCjCQn3HZDNLME8tYANLDEcrgADcAFlWg0AYFGC5nK3ew/McaC6BEAopnUFSBQhubZpMVbP81JrFgdwEyBkUVup9BNoM0681hBdMYYYCMQfGMzc8gGqQZ5BIQxhkLoEQCimeQs0E2IcuB+CDNxkvZ/ktX4jAAlMJAiQRkA8iZML+CaBAfJA7SDOTvJyovEMIAruB4gKjNkYMAAAAASUVORK5CYII=";
         var mainicon2="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAwAAAP8AAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAD/AAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAA/wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAP8AAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAAAAAAD/AAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAA8wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAPAAAAD/AAAA/wAAAPAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAAAAAAAAAAAAAHsAAAD/AAAAkAAAAAAAAADwAAAA/wAAAP8AAADwAAAA/wAAAP8AAAD/AAAA/wAAAP8AAADwAAAAAAAAAIQAAAD/AAAAjQAAAAAAAAB1AAAA/wAAAP8AAAD/AAAA8AAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAAAIoAAAD/AAAAigAAAAAAAABpAAAAAAAAAAAAAAB7AAAA/wAAAIcAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAigAAAAAAAAB7AAAA8AAAAAAAAACEAAAA/wAAAIcAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAhwAAAAAAAACBAAAA/wAAAPAAAACKAAAA/wAAAIcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAAA/wAAAP8AAAD/AAAA/wAAAIcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAIQAAAAAAAAAAAAAAAAAAAAAAB8AAAAfAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAxAAAAIgAAAAWAAAAJEAAAEDAAD+BwAA+A8AAA==";
            
            var ins = doc.getElementById("menuitem_uninstallItem");
            if(!ins) return;
             ins = ins.nextSibling;
            var popup = ins.parentNode;
            var menuitem = $C("menuseparator", {
                id: "AMD-separator-1"
            });
            popup.insertBefore(menuitem, ins);

            menuitem = $C("menuitem", {
                id: "AMD-browse-dir",
                class: "menu-iconic",
                image: mainicon,
                label: "Место установки",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.browseDir);"
            });
            popup.insertBefore(menuitem, ins);
           
            menuitem = $C("menuitem", {
                id: "AMD-browse-Folder",
                class: "menu-iconic",
                image: mainicon1,
                label: "Папка установки",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.Folder);"
            });
            popup.insertBefore(menuitem, ins);
           
            menuitem = $C("menuitem", {
                id: "AMD-browse-goHome",
                label: "Домашняя страница",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.goHome);"
            });
           popup.insertBefore(menuitem, ins); 
             
           menuitem = $C("menuitem", {
                id: "AMD-browse-goAMO",
                label: "Страница на AMO",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.goAMO);"
            });
           popup.insertBefore(menuitem, ins); 
          
           menuitem = $C("menuitem", {
                id: "AMD-browse-support",
                label: "Страница поддержки",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.support);"
            });    
           popup.insertBefore(menuitem, ins);
         
            var menu = $C("menu", {
                id: "AMD-menu",
                class: "menu-iconic",
                image: mainicon2,
                label: "Копировать",
            });
            popup.insertBefore(menu, ins);
            var menuPopup = $C("menupopup", {
                id: "AMD-menupopup",
            });
            menu.appendChild(menuPopup);
            
            menuitem = $C("menuitem", {
                id: "AMD-copy-name",
                label: "Копировать имя",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyName);"
            });
            menuPopup.appendChild(menuitem);

             menuitem = $C("menuitem", {
                id: "AMD-copy-version",
                label: "Копировать версию",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyVersion);"
            });
            menuPopup.appendChild(menuitem);
            
            menuitem = $C("menuitem", {
                id: "AMD-copy-NameVersion",
                label: "Копировать имя и версию",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyNameVersion);"
            });
            menuPopup.appendChild(menuitem);
           
            menuitem = $C("menuitem", {
                id: "AMD-copy-id",
                label: "Копировать id",
                oncommand: "AMD_Helper.getAddon(AMD_Helper.getPopupNode(this).value, AMD_Helper.copyID);"
            });
            menuPopup.appendChild(menuitem);
            
            menuitem = $C("menuitem", {
                id: "AMD-go-uso",
                class: "greasemonkey",
                hidden: true,
                label: "Страница на Userscripts.org",
                oncommand: "openURL(this.tooltipText);"
            });
            popup.appendChild(menuitem);

            menuitem = $C("menuitem", {
                id: "AMD-find-uso",
                class: "greasemonkey",
                hidden: true,
                label: "Поиск по Userscripts.org",
                oncommand: "openURL(this.getAttribute('find-on-uso'));"
            });
            popup.appendChild(menuitem);
            
            popup.addEventListener("popupshowing", this, true);
        },

        //Указываем где и когда показывать элементы меню
            setItemsAttributes: function(aAddon, event){
            var popup = event.target;
            var doc = popup.ownerDocument;

            var isExtension = (aAddon.type == "extension");
            var isTheme = (aAddon.type == "theme");
            var isPlugin = (aAddon.type == "plugin");
            var isUserStyle = (aAddon.type == "userstyle");
            var isScriptish = (aAddon.type == "userscript");
            var isUserScript = (aAddon.type == "user-script") || // Greasemonkey
                               (aAddon.type == "userscript") ||  // Scriptish
                               (aAddon.type == "greasemonkey-user-script"); // Greasemonkey 1.7+
            var isCustomButton = (aAddon.type == "custombuttons");
            var isService = (aAddon.type == "service");
            
            var browseDirItem = doc.getElementById("AMD-browse-dir");
            browseDirItem.hidden = isUserStyle || isUserScript || isCustomButton || isService;

            var browseFolderItem = doc.getElementById("AMD-browse-Folder");
            browseFolderItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService;
            
            var copyNameItem = doc.getElementById("AMD-copy-name");
            copyNameItem.tooltipText = aAddon.name;
            copyNameItem.className = isUserScript
                                    ? isScriptish
                                      ? ""
                                      : "greasemonkey"
                                    : "";
                                    
            var copyNameVersionItem = doc.getElementById("AMD-copy-NameVersion");
            copyNameVersionItem.hidden = isUserStyle || isCustomButton || isService;
            copyNameVersionItem.tooltipText = aAddon.name + " " + aAddon.version;
            copyNameVersionItem.className = isUserScript
                                    ? isScriptish
                                      ? ""
                                      : "greasemonkey"
                                    : "";
                                    
            var copyIDItem = doc.getElementById("AMD-copy-id");
            copyIDItem.tooltipText = "ID: " + aAddon.id;
            copyIDItem.className = isUserScript
                                    ? isScriptish
                                      ? ""
                                      : "greasemonkey"
                                    : "";
            
             var copyVersionItem = doc.getElementById("AMD-copy-version");
             copyVersionItem.tooltipText = aAddon.version;
             copyVersionItem.hidden = isUserStyle || isCustomButton || isService;
             copyVersionItem.className = isUserScript
                                    ? isScriptish
                                      ? ""
                                      : "greasemonkey"
                                    : "";
                                    
            var opengoAMOItem = doc.getElementById("AMD-browse-goAMO");
            opengoAMOItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService;
            var amoURL = aAddon.reviewURL
                 ? aAddon.reviewURL.replace(/\/reviews\//, "/")
                 : null;
            opengoAMOItem.tooltipText = amoURL;
            opengoAMOItem.hidden = !amoURL || /addons.mozilla.org/.test(aAddon.homepageURL);
            
            var opengoHomeItem = doc.getElementById("AMD-browse-goHome");
            opengoHomeItem.hidden = isUserScript || isCustomButton || isPlugin;
               if (aAddon.homepageURL) {
                   opengoHomeItem.tooltipText = aAddon.homepageURL;
                   } else if (aAddon.reviewURL) {
                    opengoHomeItem.tooltipText = amoURL;
                   }
           opengoHomeItem.hidden = !(aAddon.homepageURL || aAddon.reviewURL);

           var opensupportItem = doc.getElementById("AMD-browse-support");
           opensupportItem.hidden = isUserStyle || isUserScript || isCustomButton || isPlugin || isService;
           opensupportItem.tooltipText = aAddon.supportURL;
           opensupportItem.hidden = !aAddon.supportURL;

            if(isUserScript && !isScriptish){
                var usoURL = "";
                if (aAddon._script) {
                    var usDownloadURL = aAddon._script._downloadURL;
                    var usUpdateURL = aAddon._script._updateURL;
                    if (usoRegx.test(usDownloadURL)) {
                        usoURL = usDownloadURL;
                    } else if (usoRegx.test(usUpdateURL)) {
                        usoURL = usUpdateURL;
                    }
                }

                var usoItem = doc.getElementById("AMD-go-uso");
                usoItem.disabled = !usoRegx.test(usoURL);
                usoItem.className = isUserScript ? usoItem.disabled ? "" : "greasemonkey" : "";
                usoItem.tooltipText = usoURL.replace(/source/, "show")
                    .replace(/.\w+.js$/, "");

                var fusoItem = doc.getElementById("AMD-find-uso");
                fusoItem.disabled = usoRegx.test(usoURL);
                fusoItem.className = isUserScript ? fusoItem.disabled ? "" : "greasemonkey" : "";
                fusoItem.setAttribute("find-on-uso",
                    "http://userscripts.org/scripts/search?q=" +
                    encodeURIComponent(aAddon.name));
            }
        },

        getPopupNode: function (aNode) {
            var doc = aNode.ownerDocument;
            return "triggerNode" in aNode.parentNode ? aNode.parentNode.triggerNode : doc.popupNode;
        },
        getAddon: function (aId, aCallback, aEvent) {
            var self = this;

            if (this.win.gDetailView._addon) {
                aCallback.apply(this, [this.win.gDetailView._addon, aEvent]);
                return;
            }

            AddonManager.getAllAddons(function(aAddons) {
                for (var i = 0; i < aAddons.length; i++) {
                    if (aAddons[i].id == aId) {
                        aCallback.apply(self, [aAddons[i], aEvent]);
                        return;
                    }
                }
            });
        },

    //Домашняя страница
     goHome: function (aAddon) {
        var url = aAddon.homepageURL;
        if (!url) {
        if (aAddon.reviewURL) {
        url = aAddon.reviewURL.replace(/\/reviews\/.*$/, "/");
        } else {
        url = "https://addons.mozilla.org/search/?q="
            + encodeURIComponent(aAddon.name);
         }
        }
       openURL(url);
       },
   //Страница на АМО
   
   goAMO: function (aAddon) {
        var sourceTracker = "/?src=external-Add-ons_Manager_Context_Menu-extension";
    if (aAddon.reviewURL) {
      var amoURL = aAddon.reviewURL.replace(/\/reviews\//, "/")
                             .replace(/\/(firefox|seamonkey|thunderbird|android)/, "")
                             .replace(/\/\?src\=api/, sourceTracker);
    }
    if (/personas.mozilla.org$/.test(aAddon.id)) {
      amoURL = "https://addons.mozilla.org/addon/" + aAddon.id.match(/\d+/) + sourceTracker;
      }
       openURL(amoURL);
       },
       
   //Страница поддержки
    support: function (aAddon) {
       openURL(aAddon.supportURL);
       },
     
    //Открыть место установки   
    browseDir: function (aAddon) {
            switch(aAddon.type){
                case "plugin":
                    var pathes = aAddon.pluginFullpath;
                    for (var i = 0; i < pathes.length; i++) {
                        this.revealPath(pathes[i]);
                    }
                    return;
                 }
            var gecko = parseInt(Services.appinfo.platformVersion);
            var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile",
                "initWithPath");
            var dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
            dir.append("extensions");
            dir.append(aAddon.id);
            var fileOrDir = dir.path + (dir.exists() ? "" : ".xpi");
            try {
                (new nsLocalFile(fileOrDir)).reveal();
            } catch (ex) {
                var addonDir = /.xpi$/.test(fileOrDir) ? dir.parent : dir;
                try {
                    if (addonDir.exists()) {
                        addonDir.launch();
                      }
                } catch (ex) {
                    var uri = Services.io.newFileURI(addonDir);
                    var protSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                    getService(Ci.nsIExternalProtocolService);
                    protSvc.loadUrl(uri);
                }
            }
        },
    //Открыть папку установки    
    Folder: function (aAddon) {
            var gecko = parseInt(Services.appinfo.platformVersion);
            var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", (gecko >= 14) ? "nsIFile" : "nsILocalFile",
                "initWithPath");
            var dir = Services.dirsvc.get("ProfD", Ci.nsIFile); 
                        dir.append('extensions');
                        dir.append(aAddon.id);
                            if ( dir.exists() ) dir.launch();
 
                            var file = Components.classes['@mozilla.org/file/directory_service;1']
                                      .getService(Components.interfaces.nsIProperties)
                                     .get('ProfD', Components.interfaces.nsILocalFile);       
                            file.append('extensions');
                            file.append( aAddon.id + '.xpi' )             
                            if ( file.exists() ) file.launch(); 
                            return;
          },
    //Копировать имя     
    copyName: function (aAddon) {
            this.copyToClipboard(aAddon.name);
        },
    //Копировать ID 
    copyID: function (aAddon) {
            this.copyToClipboard("ID: " + aAddon.id);
        },
    //Копировать версию 
    copyVersion: function (aAddon) {
            this.copyToClipboard(aAddon.version);
        },
    //Копировать имя и версию
    copyNameVersion: function (aAddon) {
           this.copyToClipboard(aAddon.name + " " + aAddon.version);
        },
 
     //Вспомогательные функции
       revealPath: function(path){
            var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
            file.initWithPath(path);
            if(file.exists())
                file.reveal();
        },
        copyToClipboard: function (aString) {
            Cc["@mozilla.org/widget/clipboardhelper;1"].
                getService(Ci.nsIClipboardHelper).copyString(aString);
        }
    };

     AMD_Helper.init();
     function $C(name, attr) {
        var el = document.createElement(name);
       if (attr) Object.keys(attr).forEach(function(n) el.setAttribute(n, attr[n]));
        return el;
    }
   
})();

Отредактировано Mishania (10-06-2014 10:19:15)

Отсутствует

 

№782910-06-2014 12:30:14

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

Re: Custom Buttons

Mishania пишет

Cu.import("resource://gre/modules/XPIProvider.jsm");

https://blog.mozilla.org/addons/2014/05 … irefox-30/

Move some addon-private JSM’s to a subdirectory. A large number of number of JS modules used in the Add-ons Manager were moved to a different path. They include AddonRepository.jsm, LightweightThemeImageOptimizer.jsm, XPIProvider.jsm, AddonUpdateChecker.jsm, AddonLogging.jsm, PluginProvider.jsm, AddonRepository_SQLiteMigrator.jsm, XPIProviderUtils.js and SpellCheckDictionaryBootstrap.js. The new path is resource://gre/modules/addons/MODULE.jsm.


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

Отсутствует

 

№783010-06-2014 13:05:27

Mishania
Забанен
 
Группа: Members
Откуда: Usa
Зарегистрирован: 22-10-2011
Сообщений: 357
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher
Я в этих шаманских штучках не понимаю совсем. :( Мне желательно на русском и с картинками.

Отсутствует

 

№783110-06-2014 13:54:41

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

Re: Custom Buttons

Mishania
Как минимум, надо заменить

Выделить код

Код:

Cu.import("resource://gre/modules/XPIProvider.jsm");

на

Выделить код

Код:

Cu.import("resource://gre/modules/addons/XPIProvider.jsm");

Или (чтобы универсально) на

Выделить код

Код:

try {
    Cu.import("resource://gre/modules/XPIProvider.jsm");
}
catch(e) {
    Cu.import("resource://gre/modules/addons/XPIProvider.jsm");
}

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

Отсутствует

 

№783210-06-2014 19:28:45

Mishania
Забанен
 
Группа: Members
Откуда: Usa
Зарегистрирован: 22-10-2011
Сообщений: 357
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher
Спасибо, заработало, но очень странно.

скрытый текст
79108fb547bf2646f93d3c3ca0e1adac.jpeg

PS/ Хотя если перегрузить браузер, какое-то время отображается правильно, но потом опять меню разрастается. Но лучше так, чем никак. :)

Отредактировано Mishania (10-06-2014 19:31:41)

Отсутствует

 

№783310-06-2014 20:32:05

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

Re: Custom Buttons

Mishania пишет

Хотя если перегрузить браузер, какое-то время отображается правильно, но потом опять меню разрастается.

Можно попробовать заменить

Выделить код

Код:

document.addEventListener("DOMContentLoaded", this, false);

на

Выделить код

Код:

addEventListener("DOMContentLoaded", this, false, document);

и

Выделить код

Код:

popup.addEventListener("popupshowing", this, true);

на

Выделить код

Код:

addEventListener("popupshowing", this, true, popup);

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

Отсутствует

 

№783410-06-2014 20:33:51

Uxapb
Участник
 
Группа: Members
Зарегистрирован: 25-01-2012
Сообщений: 137
UA: Firefox 30.0

Re: Custom Buttons

Отсутствует

 

№783510-06-2014 21:15:27

Mishania
Забанен
 
Группа: Members
Откуда: Usa
Зарегистрирован: 22-10-2011
Сообщений: 357
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher
Спасибо, всё отлично заработало. Может выложите исправленный код в соответствующей теме?

Отсутствует

 

№783610-06-2014 21:21:22

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

Re: Custom Buttons

Mishania
Это лучше к автору, чтобы не было кучи дублей.
Я так понимаю, вот это оригинал: https://forum.mozilla-russia.org/viewto … 33#p632733


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

Отсутствует

 

№783710-06-2014 21:47:08

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

difabor пишет

1. Отсортировать исходный массив по свойству uri в алфавитном порядке.
2. Отсортированный массив распихать по группам с одинаковыми доменами.
    (Просто при прохождении массива текущий домен сравнивать с предыдущим.
     Если равны - переписывать в ту же группу, если нет - создавать новую и записывать туда)
3. Каждую такую группу отсортировать по свойству title в алфавитном порядке.

Спасибо за отзывчивость.

Отсутствует

 

№783811-06-2014 06:30:57

Mishania
Забанен
 
Группа: Members
Откуда: Usa
Зарегистрирован: 22-10-2011
Сообщений: 357
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher
Хорошо. Написал ему в ПМ.

Отсутствует

 

№783911-06-2014 09:02:39

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher Вопрос к тебе, т.к. кнопка твоя - Custom_Buttons/Bookmarks_Folder at master · Infocatcher/Custom_Buttons · GitHub

Правда после модификаций она стала немного иной, но все они, модификации, даны тобой

Вот код (обе секции)

Выделить код

Код:

/*CODE*/ 

if(!event.target && !this.disabled) // Button's hotkey pressed
    this.open = true;

и

Выделить код

Код:

/*Initialization Code*/

// http://infocatcher.ucoz.net/js/cb/bookmarksFolder.js
// https://github.com/Infocatcher/Custom_Buttons/tree/master/Bookmarks_Folder

// Bookmarks Folder button for Custom Buttons
// (code for "initialization" section)

// (c) Infocatcher 2011-2013
// version 0.1.0 - 2013-01-26

// Compatibility: Firefox 4.0+, SeaMonkey 2.1+

// Icon by FatCow Web Hosting: http://www.iconfinder.com/icondetails/36059/16/

// Hidden feature: you can manually set extensions.custombuttons.button<N>.bookmarkFolder
// preference to any place: URI https://developer.mozilla.org/en-US/docs/Places_query_URIs
// (and press OK in button editor or reopen window or restart browser)

/*
//Описание иконок для подпапок
menu.bookmark-item[label="Форум Mozilla Россия"] {
    list-style-image: url("https://forum.mozilla-russia.org/style/img/Moz-infinity/pun_icon_unactive.png") !important;
    -moz-image-region: auto !important;
}
*/

setTimeout(function() {
 //---------------------------
 // ----- Массив описания подпапок с иконками --------
     var icons = {
        "Форум Mozilla Россия": "data:image/png;base64,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",
        "Мозилла код": "data:image/png;base64,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"
    };
    var rules = [];
    for(var label in icons) if(icons.hasOwnProperty(label)) {
        rules.push('\
            %button% menu.bookmark-item[label="' + label + '"] {\n\
                list-style-image: url("' + icons[label] + '") !important;\n\
                -moz-image-region: auto !important;\n\
            }'
        );
    }
    var cssStr = ('\
        @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");\n\
        @-moz-document url("' + document.documentURI + '") {\n' + rules.join("\n") + '\n\
        }')
        .replace(/%button%/g, "#" + self.id);
 //---------------------------       
        
    var cssURI = Services.io.newURI("data:text/css," + encodeURIComponent(cssStr), null, null);
    var 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);
    addDestructor(function(reason) {
        if(reason == "update" || reason == "delete") {
            if(sss.sheetRegistered(cssURI, sss.USER_SHEET))
                sss.unregisterSheet(cssURI, sss.USER_SHEET);
        }
    });
}, 50);



var hideDropMarker = true;

function _localize(s, key) {
    var strings = {
        "Select folder": {
            ru: "Выберите папку"
        },
        "Root folder": {
            ru: "Корневая папка"
        }
    };
    var locale = (cbu.getPrefs("general.useragent.locale") || "en").match(/^[a-z]*/)[0];
    _localize = !locale || locale == "en"
        ? function(s) {
            return s;
        }
        : function(s) {
            return strings[s] && strings[s][locale] || s;
        };
    return _localize.apply(this, arguments);
}

this.onclick = function(e) {
    if(e.target != this)
        return;
        //if(e.button == 2 && !e.ctrlKey &&!e.shiftKey && !e.altKey && !e.metaKey) {
        // Действие при клике ПКМ без модификаторов
        //this.bookmarks.changeFolder();
                //event.preventDefault();
            //event.stopPropagation();
   // }        
    if(e.button != 2 && !this.bookmarks.initialized)
        this.bookmarks.init();
    else if(e.button == 1 || e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey))
        this.bookmarks.changeFolder();
};

this.onmousedown = function(e) {
    if(e.target == this && e.button == 0 && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey))
        e.preventDefault();
};
this.onmouseover = function(e) {
    if(e.target != this)
        return;
    Array.some(
        this.parentNode.getElementsByTagName("*"),
        function(node) {
            if(
                node != this
                && node.namespaceURI == xulns
                && node.boxObject
                && node.boxObject instanceof Components.interfaces.nsIMenuBoxObject
                && node.open
            ) {
                node.open = false;
                this.open = true;
                return true;
            }
            return false;
        },
        this
    );
};
this.bookmarks = {
    button: this,
    get pref() {
        delete this.pref;
        return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder";
    },
    get folder() {
        return cbu.getPrefs(this.pref) || "";
    },
    set folder(val) {
        cbu.setPrefs(this.pref, String(val));
    },
    get wm() {
        delete this.wm;
        return this.wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
            .getService(Components.interfaces.nsIWindowMediator);
    },
    initialized: false,
    init: function() {
        var folder = this.folder;
        if(!folder) {
            folder = this.selectFolder();
            if(!folder)
                return;
            this.folder = folder;
        }
        var btn = this.button;
        btn.setAttribute("ondragenter", "PlacesMenuDNDHandler.onDragEnter(event);");
        btn.setAttribute("ondragover",  "PlacesMenuDNDHandler.onDragOver(event);");
        btn.setAttribute("ondragexit",  "PlacesMenuDNDHandler.onDragExit(event);");
        //btn.setAttribute("ondrop",      "PlacesMenuDNDHandler.onDrop(event);");
        btn.setAttribute("ondrop",      "this.bookmarks.onDrop(event);");
        var mp = btn.getElementsByTagName("menupopup");
        mp.length && mp[0].parentNode.removeChild(mp[0]);
        mp = document.createElement("menupopup");
        mp.setAttribute("context", "placesContext");
        mp.setAttribute("placespopup", "true");
        var placeURI = folder.substr(0, 6) == "place:"
            ? folder
            : "place:folder=" + folder + "&excludeItems=0&expandQueries=0";
        placeURI = placeURI
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;");
        mp.setAttribute(
            "onpopupshowing",
            'this.parentNode.bookmarks.initMenu(event, "' + placeURI + '");'
        );
        mp.setAttribute("oncommand", "BookmarksEventHandler.onCommand(event, this.parentNode._placesView);");
        mp.setAttribute("onclick", "BookmarksEventHandler.onClick(event, this.parentNode._placesView);");
        mp.setAttribute("tooltip", "bhTooltip");
        mp.setAttribute("popupsinherittooltip", "true");
        btn.appendChild(mp);

        this.initialized = true;
    },
    initMenu: function(event, placeURI) {
        var btn = this.button;
        if("_placesView" in btn)
            return;
        btn._placesMenu = new PlacesMenu(event, placeURI);
        // Add "Open All in Tabs" menuitem
        PlacesViewBase.prototype._mayAddCommandsItems(btn.firstChild);
    },
    destroy: function() {
        var btn = this.button;
        if(!("_placesMenu" in btn))
            return;
        try {
            btn._placesMenu.uninit();
        }
        catch(e) {
            Components.utils.reportError(e);
        }
        delete btn._placesView;
        delete btn._placesMenu;
    },
    initWithFolder: function(folder) {
        this.destroy();
        this.folder = folder;
        var mp = this.button.firstChild;
        mp.setAttribute(
            "onpopupshowing",
            mp.getAttribute("onpopupshowing")
                .replace(/(place:folder=)\w+/, "$1" + folder)
        );
    },
    selectFolder: function() {
        var winType = this.button.id + ":dialog";
        var win = this.wm.getMostRecentWindow(winType);
        if(win) {
            win.focus();
            return null;
        }
        // https://developer.mozilla.org/en/Displaying_Places_information_using_views
        var rootFolder = PlacesUIUtils.allBookmarksFolderId;
        var placesOverlay = Application.name == "SeaMonkey"
            ? '\n\
            <?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks.css"?>\n\
            <?xml-stylesheet href="chrome://communicator/content/places/places.css"?>\n\
            <?xul-overlay href="chrome://communicator/content/bookmarks/placesOverlay.xul"?>'
            : '\n\
            <?xml-stylesheet href="chrome://browser/content/places/places.css"?>\n\
            <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>\n\
            <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>';
        // Note: <property name="view"> from chrome://communicator/content/places/tree.xml#places-tree
        // are null sometimes.
        // We are trying to re-apply binding as a workaround.
        var winSrc = '\
            <?xml version="1.0"?>\n\
            <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>'
            + placesOverlay + '\n\
            <dialog xmlns="' + xulns + '"\n\
                id="' + this.button.id + "-dialog" + '"\n\
                windowtype="' + winType + '"\n\
                title="' + _localize("Select folder") + '"\n\
                buttons="accept,cancel"\n\
                onload="init();"\n\
                ondialogaccept="return dialogCallback();"\n\
                width="400"\n\
                height="350">\n\
                <keyset>\n\
                    <key id="key-accept" keycode="VK_RETURN" modifiers="control"\n\
                        oncommand="document.documentElement.acceptDialog();" />\n\
                </keyset>\n\
                <tree id="tree" type="places"\n\
                    place="place:excludeItems=1&amp;excludeQueries=1&amp;folder=' + rootFolder + '"\n\
                    hidecolumnpicker="true" seltype="single" flex="1"\n\
                    onselect="onSelect();">\n\
                    <treecols>\n\
                        <treecol id="title" flex="1" primary="true" hideheader="true" />\n\
                    </treecols>\n\
                    <treechildren />\n\
                </tree>\n\
                <checkbox id="root" label="' + _localize("Root folder") + '" oncommand="onSelect();" />\n\
                <script type="application/javascript"><![CDATA[\n\
                var [folderId, rootFolder, callback, context] = window.arguments;\n\
                var tree = document.getElementById("tree");\n\
                var root = document.getElementById("root");\n\
                function init() {\n\
                    if(!ensurePlacesBinding(init, this, arguments))\n\
                        return;\n\
                    if(folderId == rootFolder)\n\
                        root.checked = true;\n\
                    else if(folderId != undefined) {\n\
                        tree.selectItems([folderId]);\n\
                        var i = tree.view.selection.currentIndex;\n\
                        if(i != -1) {\n\
                            setTimeout(function() {\n\
                                tree.treeBoxObject.ensureRowIsVisible(i);\n\
                            }, 0);\n\
                        }\n\
                    }\n\
                    onSelect();\n\
                }\n\
                function onSelect(dis) {\n\
                    if(!ensurePlacesBinding(onSelect, this, arguments))\n\
                        return;\n\
                    if(!arguments.length)\n\
                        dis = !root.checked && !tree.view.selection.getRangeCount();\n\
                    document.documentElement.getButton("accept").disabled = dis;\n\
                    disableTree(root.checked);\n\
                }\n\
                function ensurePlacesBinding(func, context, args) {\n\
                    if(tree.view && tree.selectItems)\n\
                        return true;\n\
                    \// Try re-apply binding, hack for SeaMonkey\n\
                    tree.removeAttribute("type");\n\
                    setTimeout(function() {\n\
                        tree.setAttribute("type", "places");\n\
                        setTimeout(function() {\n\
                            func.apply(context, args);\n\
                        }, 0);\n\
                    }, 0);\n\
                    return false;\n\
                }\n\
                function disableTree(dis) {\n\
                    var treechildren = tree.getElementsByTagName("treechildren")[0];\n\
                    if(dis) {\n\
                        treechildren.style.opacity = "0.6";\n\
                        tree.setAttribute("disabled", "true");\n\
                    }\n\
                    else {\n\
                        treechildren.style.opacity = "";\n\
                        tree.removeAttribute("disabled");\n\
                    }\n\
                }\n\
                function dialogCallback() {\n\
                    if(root.checked)\n\
                        var id = rootFolder;\n\
                    else {\n\
                        var view = tree.view;\n\
                        var i = view.selection.currentIndex;\n\
                        if(i == -1)\n\
                            return false;\n\
                        var item = view.nodeForTreeIndex(i);\n\
                        if(item) {\n\
                            var id = /place:folder=(\\w+)/.test(item.uri)\n\
                                ? RegExp.$1\n\
                                : item.itemId;\n\
                        }\n\
                    }\n\
                    callback.call(context, id);\n\
                    return true;\n\
                }\n\
                onSelect(false);\n\
                ]]></script>\n\
            </dialog>';
        var folder;
        var callback = function(folderId) {
            folder = folderId;
        };
        var folderId = this.getFolderId(this.folder);
        window.openDialog(
            "data:application/vnd.mozilla.xul+xml," + encodeURIComponent(winSrc.replace(/^\s+/, "")),
            "_blank",
            "chrome,all,resizable,centerscreen,modal",
            folderId, rootFolder, callback, this
        );
        return folder;
    },
    changeFolder: function() {
        if(!this.initialized) {
            this.init();
            return;
        }
        var folder = this.selectFolder();
        if(!folder)
            return;
        this.initWithFolder(folder);

        var ws = this.wm.getEnumerator("navigator:browser");
        while(ws.hasMoreElements()) {
            let w = ws.getNext();
            if(w == window)
                continue;
            let btn = w.document.getElementById(this.button.id);
            btn && btn.bookmarks.initWithFolder(folder);
        }
    },
    getFolderId: function(folder) {
        if(/^\d+$/.test(folder))
            return Number(folder);
        var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
            .getService(Components.interfaces.nsINavBookmarksService);
        switch(folder) {
            case "BOOKMARKS_MENU":    return bmsvc.bookmarksMenuFolder;
            case "TOOLBAR":           return bmsvc.toolbarFolder;
            case "UNFILED_BOOKMARKS": return bmsvc.unfiledBookmarksFolder;
        }
        return undefined;
    },
    placesDrop: function(event, folder) {
        // Based on PlacesMenuDNDHandler.onDrop(event) function
        try {
            var ip = new InsertionPoint(folder, PlacesUtils.bookmarks.DEFAULT_INDEX, Ci.nsITreeView.DROP_ON);
            PlacesControllerDragHelper.onDrop(ip, event.dataTransfer);
            event.stopPropagation();
        }
        catch(e) {
            Components.utils.reportError(e);
        }
    },
    onDrop: function(e) {
        var folder = this.folder;
        if(e.target != this.button || !folder) {
            PlacesMenuDNDHandler.onDrop(e);
            return;
        }
        var folderId = this.getFolderId(folder);
        if(folderId)
            this.placesDrop(e, folderId);
        else
            PlacesMenuDNDHandler.onDrop(e);
    }
};

this.type = "menu";
this.orient = "horizontal";
if(hideDropMarker) {
    let btn = this;
    let doc = btn.ownerDocument;
    let stopTime = Date.now() + 500;
    setTimeout(function hideDropMarker() { // Wait for menu XBL binding
        var dm = doc.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-menu-dropmarker");
        if(dm) {
            dm.hidden = true;
            let icon = doc.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-icon");
            if(icon) {
                let s = doc.defaultView.getComputedStyle(icon, null);
                if(s.paddingRight != s.paddingLeft) // Hack for Firefox 19 and large icons
                    icon.style.paddingLeft = icon.style.paddingRight = s.paddingLeft;
            }
        }
        else if(Date.now() < stopTime)
            setTimeout(hideDropMarker, 10);
    }, 0);
}

setTimeout(function(_this) { // Don't show modal "Select folder" dialog during initialization
    _this.bookmarks.init();
}, 0, this);
this.onDestroy = function() {
    this.bookmarks.destroy();
};

/*
this. onmouseover = function (event)
{
    this. open = true;
 };
[/spoiler]

this. onmouseout = function (event)
{
    setTimeout(function() {this. open = true;},1250);
    this. open = false;
     
 };
*/
 
 
//code_snippets/autoOpenCloseMenu.js
// https://github.com/Infocatcher/Custom_Buttons/blob/master/code_snippets/autoOpenCloseMenu.js
// Automatically open menu on mouse over (and hide it on mouse out)
// (code for "initialization" section)

// Dummy menu
this.type = "menu";
this.orient = "horisontal";
this.appendChild(parseXULFromString(
    '<menupopup xmlns="' + xulns + '" oncommand="alert(event.target.getAttribute(\'label\'));">\
        <menuitem label="Item 1" />\
        <menuitem label="Item 2" />\
        <menuitem label="Item 3" />\
    </menupopup>'
));
function parseXULFromString(xul) {
    xul = xul.replace(/>\s+</g, "><");
    return new DOMParser().parseFromString(xul, "application/xml").documentElement;
}

// Autoopen/close feature
var openDelay = 200;
var closeDelay = 350;

var _openTimer = 0;
var _closeTimer = 0;
this.onmouseover = function(e) {
    clearTimeout(_closeTimer);
    if(e.target == this && closeOtherMenus()) {
        this.open = true;
        return;
    }
    _openTimer = setTimeout(function() {
        self.open = true;
    }, openDelay);
};
this.onmouseout = function(e) {
    clearTimeout(_openTimer);
    _closeTimer = setTimeout(function() {
        if(!isContextOpened())
            self.open = false;
    }, closeDelay);
};
function closeOtherMenus() {
    return Array.some(
        self.parentNode.getElementsByTagName("*"),
        function(node) {
            if(
                node != self
                && node.namespaceURI == xulns
                && node.boxObject
                && node.boxObject instanceof Components.interfaces.nsIMenuBoxObject
                && node.open
            ) {
                node.open = false;
                return true;
            }
            return false;
        }
    );
}
function isContextOpened() {
    return inBtn(document.popupNode);
}
function inBtn(node) {
    for(; node; node = node.parentNode)
        if(node == self)
            return true;
    return false;
}


Теперь Вопрос: Как отключить автозапрос папки при создании новой кнопки?
Данный вопрос сводится к  Вопросу — Как в каждой кнопке "намертво" прописать имя папки с которой она работает?

Просто я иногда сохраняю кнопки в HTML-файле и иногда нужно что то восстановить, но вот твоя кнопка ведёт себя немного прикольно, то выдаёт запрос, то ссылается на пустую папку, а то и на другую произвольную  — мне надо от этого избавится... ну просто неудобно каждый раз прописывать каждой кнопке соответствующую ей папку.

P.S. Надеюсь, я всё верно изложил.

Отредактировано Indomito (11-06-2014 09:17:42)


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№784011-06-2014 13:15:03

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

Re: Custom Buttons

Indomito пишет

Теперь Вопрос: Как отключить автозапрос папки при создании новой кнопки?
Данный вопрос сводится к  Вопросу — Как в каждой кнопке "намертво" прописать имя папки с которой она работает?

Просто я иногда сохраняю кнопки в HTML-файле и иногда нужно что то восстановить, но вот твоя кнопка ведёт себя немного прикольно, то выдаёт запрос, то ссылается на пустую папку, а то и на другую произвольную  — мне надо от этого избавится... ну просто неудобно каждый раз прописывать каждой кнопке соответствующую ей папку.

Во-первых, кнопку можно обновить. :)
Во-вторых, от «// Dummy menu» и до «// Autoopen/close feature» пример меню, он нужен только для полноценной демонстрации и тут не лишний.

Идентификатор папки сохраняется в about:config:

Выделить код

Код:

get pref() {
        delete this.pref;
        return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder";
    },
    get folder() {
        return Application.prefs.getValue(this.pref, "");
    },
    set folder(val) {
        Application.prefs.setValue(this.pref, String(val));
    },

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

Выделить код

Код:

get pref() {
        delete this.pref;
        return this.pref = "extensions.custombuttons.buttonMisc.bookmarkFolder";
    },

И можно вписать идентификатор прямо в код:

Выделить код

Код:

get folder() {
        return "12345"; // Идентификатор папки
    },
    set folder(val) {
        // Сохранение больше не будет работать
    },

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

Отсутствует

 

№784111-06-2014 13:44:03

>ORG@niZM<
Участник
 
Группа: Members
Зарегистрирован: 20-08-2013
Сообщений: 66
UA: Firefox 30.0

Re: Custom Buttons

Установил кнопу на чистом профиле, истыкал её вдоль и поперёк (согласно подсказок), но так и не увидел полезных свойств. Работают только Left Long, Right и Right Long. В консоли соотвественно реакция

TypeError: pt is null

на неработающие клики и ссылается на 52 строку

var pt_hideAttr = pt.getAttribute("type") == "menubar" ? "autohide" : "collapsed";

Отредактировано >ORG@niZM< (11-06-2014 13:45:33)

Отсутствует

 

№784211-06-2014 15:34:44

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher Значит в фрагменте

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

Выделить код

Код:

this.bookmarks = {
    button: this,
        get pref() {
        delete this.pref;
        return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder";
    },
    get folder() {
        return cbu.getPrefs(this.pref) || "";
    },
    set folder(val) {
        cbu.setPrefs(this.pref, String(val));
    },


Делаем так
скрытый текст

Выделить код

Код:

this.bookmarks = {
    button: this,
         get folder() {
         return "12345"; // Идентификатор папки
      },
       set folder(val) {
           // Сохранение больше не будет работать
      },    
        /*
    get pref() {
        delete this.pref;
        return this.pref = "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder";
    },
    get folder() {
        return cbu.getPrefs(this.pref) || "";
    },
    set folder(val) {
        cbu.setPrefs(this.pref, String(val));
    }, */


Я что то упустил?

Добавлено 11-06-2014 15:52:20


>ORG@niZM< пишет

Установил кнопу на чистом профиле, истыкал её вдоль и поперёк (согласно подсказок), но так и не увидел полезных свойств. Работают только Left Long, Right и Right Long. В консоли соотвественно реакция

TypeError: pt is null

на неработающие клики и ссылается на 52 строку

var pt_hideAttr = pt.getAttribute("type") == "menubar" ? "autohide" : "collapsed";

проблема ID панели - HideShowPanel(тут написан ID панели как строковая или можно переменную задать);

У всех много разных панелей и отловить все это надо сканировать prefs.js текущего профиля, но нет гарантии что все будут найдены.

Проще взять кнопку Attributes_Inspector и прописать нужный для тебя ID панели на конкретное действие мыши.

P.S. Я учту твои замечания и создам блок в коде с описанием ID-панелей, что бы избежать путаницы.

Отредактировано Indomito (11-06-2014 16:04:03)


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№784312-06-2014 17:50:08

Xant1k
Забанен
 
Группа: Members
Зарегистрирован: 22-10-2011
Сообщений: 49
UA: Chrome 35.0
Веб-сайт

Re: Custom Buttons

del

Отредактировано Xant1k (11-02-2017 13:57:21)

Отсутствует

 

№784412-06-2014 21:25:46

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher после замены фрагмента исходного на твой... пришлось править таблицу кнопок в ручную, т.к. при наведении на модифицированную кнопку происходит глобальное зависание мозиллы :D
Про правку я написал в посте №8755 - может что то ещё надо сделать, а?


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№784512-06-2014 22:37:57

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

Re: Custom Buttons

Indomito
Идентификаторы папок при втором варианте, когда все в коде, надо получать вручную.
Или смотреть, что сохраняет оригинальная версия кнопки в about:config.


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

Отсутствует

 

№784613-06-2014 20:43:13

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher пишет

Indomito
Идентификаторы папок при втором варианте, когда все в коде, надо получать вручную.
Или смотреть, что сохраняет оригинальная версия кнопки в about:config.

плиз поясни
1. "Надо получать вручную" - что ты под этим имел, т.е. что писать то?
2. "Оригинальная версия" - тоже проблематично, т.к. не понятно по какому признаку искать.

Если можно немного подробнее напиши.

Отредактировано Indomito (13-06-2014 20:44:05)


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№784713-06-2014 21:44:36

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

Re: Custom Buttons

Indomito пишет

плиз поясни
1. "Надо получать вручную" - что ты под этим имел, т.е. что писать то?
2. "Оригинальная версия" - тоже проблематично, т.к. не понятно по какому признаку искать.

Что писать – зависит от выбора папки, у каждой свой уникальный идентификатор.
Оригинальная кнопка записывает этот идентификатор в about:config, в настройку "extensions.custombuttons.button" + this.button.id.match(/\d*$/)[0] + ".bookmarkFolder", this.button.id.match(/\d*$/)[0] – номер из идентификатора кнопки.

Можно заменить вот так:

Выделить код

Код:

get folder() {
        return null;
    },
    set folder(val) {
        alert("Folder id: " + val);
    },

Работать будет не совсем корректно, но после выбора папки ее идентификатор выведет alert'ом. Его нужно скопировать и заменить «null» на «"идентификатор"», кавычки обязательны.


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

Отсутствует

 

№784814-06-2014 06:07:02

Indomito
Участник
 
Группа: Members
Откуда: Москва-Север
Зарегистрирован: 27-08-2009
Сообщений: 426
UA: Firefox 30.0

Re: Custom Buttons

Infocatcher Я верно понял:

Выделить код

Код:

get folder() {
        return null; //заменяем на 
       //return  "идентификатор";
    },
    set folder(val) {
        alert("Folder id: " + val);
    },

Так?

Что то ещё в коде менять нужно?
Просто не хочется чистить в ручную, из-за подвисаний FireFox, файл buttonsoverlay.xul


"Никогда не выявляйте в программе ошибки, если не знаете, что с ними дальше делать." Штейнбах

Отсутствует

 

№784914-06-2014 12:09:54

Dgonix
Участник
 
Группа: Members
Зарегистрирован: 12-06-2014
Сообщений: 18
UA: Firefox 33.0

Re: Custom Buttons

Друзья, поясните пожалуйста чайнику суть данной кнопочкм?

Отсутствует

 

№785014-06-2014 14:31:23

Dgonix
Участник
 
Группа: Members
Зарегистрирован: 12-06-2014
Сообщений: 18
UA: Firefox 33.0

Re: Custom Buttons

okkamas_knife пишет

намёк ясен?

Спасибо, вы очень любезны.

Отсутствует

 

Board footer

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