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

Хотите узнать больше о расширениях? Посмотрите ролики, рассказывающие о работе с расширениями Firefox.

№1540106-04-2021 12:01:50

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby
Здравсвуйте, по поводу контейнеров
Вы бы не могли пожалуйста еще сделать кнопку в контекстном меню папки закладок "Открыть всё в контейнере"

Отсутствует

 

№1540206-04-2021 16:30:47

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

Re: Custom Buttons

Давно хотел задать вопрос тем, кто заливает картинки на directupload.net . У меня по клику открывается https и не работает. Если в адресной строке потом заменить на http  и обновить, то всё открывается. Может, кто подскажет решение или какая у меня проблема?

Отсутствует

 

№1540306-04-2021 17:59:59

bezuma
Участник
 
Группа: Members
Откуда: Москва
Зарегистрирован: 26-01-2014
Сообщений: 256
UA: Chrome 86.0

Re: Custom Buttons

xrun1
Есть там аккаунт - все ОК по https, проблемы были месяца три назад, сейчас все ровно, проверял на ФФ 87 и Центе. А тогда так бесило, что хотел акк удалить - картинки не открывались

Отредактировано bezuma (06-04-2021 18:06:39)

Отсутствует

 

№1540406-04-2021 22:26:27

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

Re: Custom Buttons

Dumby приветствую, давно не был в теме, не слежу давно, что происходит, извини за это. Подскажи, что подправить, все связано с боковой панелью, не отображаются в боковой панели:
1.

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

Выделить код

Код:

/*Initialization Code*/
gCBClipboardViewer = this; // global obj
this.label="Clipboard Viewer";



((g, name, id) => {
    var obj = g[name] || (g[name] = ({
        topic: "quit-application-granted",
        init() {
            var pv = parseInt(Services.appinfo.platformVersion);
         var url = `data:application/${pv >= 73 ? "xhtm" : "vnd.mozilla.xu"}l+xml,${encodeURIComponent(self.Help)}`; 
            if (pv >= 69 && Services.appinfo.browserTabsRemoteAutostart) {
            this.url = `chrome://custombuttons/content/cbdialog${Date.now()}.xul`;
            this.helper = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup).registerChrome(
                    Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)), [["override", this.url, url]]
                );
                url = this.url;
               } 
            (this.obs = Services.obs).addObserver(this, this.topic, false);
            return this;
        },
        observe() {
            delete g[name];
            this.obs.removeObserver(this, this.topic);
            this.helper.destruct();
        }
    }).init());

 var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                   .getService(Components.interfaces.nsIWindowWatcher);
 var em = ww.getWindowEnumerator();
 var winName = "clipview";
 var index = 1;
 while (em.hasMoreElements()) {
  let win = em.getNext();
  if(win.name == winName) {
    win.focus();
    return;
  }
  index++
 }

    this.onclick = e => {
       if (e.button == 0  )  {
         var pv = parseInt(Services.appinfo.platformVersion);
         var url = `data:application/${pv >= 73 ? "xhtm" : "vnd.mozilla.xu"}l+xml,${encodeURIComponent(self.Help)}`;  
        if (pv >= 69 && Services.appinfo.browserTabsRemoteAutostart) {
        var chromeURL = `chrome://custombuttons/content/cbdialog${Date.now()}.xul`;
        Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup).registerChrome(
        Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)), [["override", chromeURL, url]]
    );
    url = chromeURL;
}
        window.openDialog(url, winName, "chrome, centerscreen, minimizable, resizable");
        }
       if (e.button == 1 && e.ctrlKey)  return gBrowser.selectedTab = gBrowser.addTrustedTab(obj.url);
       if (e.button == 1) SidebarUI.toggle(id);
          }

    addDestructor(reason => reason[5] == "e" && name in g && g[name].observe());
    for(var tab of gBrowser.tabs) {
        if (!tab.linkedPanel || tab.closing) continue;
        var br = tab.linkedBrowser;
        !br.isRemoteBrowser && br.currentURI.spec == obj.url &&
        br.contentDocument.documentURI.startsWith("about:neterror?e=fileNotFound") && br.reload();
    }

    var label = "Clipboard Viewer";
    var url = "chrome://browser/content/webext-panels.xhtml?" + id;
    var icon = this.image;
    var defaultURL = obj.url; 

     var e = (name, attrs, node, append) => {
        var elm = document.createXULElement(name);
        for(var a in attrs) elm.setAttribute(a, attrs[a]);
        append ? node.append(elm) : node.before(elm);
        return elm;
    }
    var menuitem = e("menuitem", {
        label,
        type: "checkbox",
        id: "menu_CBClipboardLoader",
        oncommand: `SidebarUI.toggle("${id}");`,
    }, document.getElementById("viewSidebarMenu"), true);

    var btn = e("toolbarbutton", {
        label,
        type: "checkbox",
        oncommand: "handleCommand();",
        id: "sidebar-switcher-CBClipboardLoader",
        class: "subviewbutton subviewbutton-iconic"
    }, document.querySelector('toolbarbutton[id^="sidebar-switcher-"] + toolbarseparator'));

    SidebarUI.sidebars.set(id, {
        url,
        title: label,
        buttonId: btn.id,
        menuId: menuitem.id,
    });
    var css = `\
        #${btn.id} > .toolbarbutton-icon,
        #sidebar-box[sidebarcommand="${id}"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
            width: 16px;
            height: 16px;
            opacity: 0.8;
            fill: currentColor;
            -moz-context-properties: fill;
            list-style-image: url(${icon});
        }`;
    var str = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
    windowUtils.loadSheetUsingURIString(str, type);

    addDestructor(() => {
        btn.remove(); menuitem.remove();
        SidebarUI.sidebars.delete(id);
        windowUtils.removeSheetUsingURIString(str, type);
    });
    var isActive = () => SidebarUI.isOpen && SidebarUI.currentID == id;

    if (isActive()) {
        SidebarUI.selectMenuItem(id);
        var doc = SidebarUI.browser.contentDocument;
        if (doc.readyState != "complete") return;
        var br = doc.getElementById("webext-panels-browser");
        if (br) defaultURL = br.currentURI.spec;
    }
    btn.handleCommand = () => {
        if (!btn.hasAttribute("checked")) {
            SidebarUI._switcherPanel.hidePopup();
            btn.setAttribute("checked", true);
        }
        loadURL(gBrowser.currentURI.spec);
    }

    addEventListener("load", e =>
        e.target.documentURI == url && load(defaultURL)
    , true, SidebarUI.browser);

    var loadURL = url => {
        defaultURL = defaultURL;
        isActive() ? load(url) : SidebarUI.show(id);  
    }

    var principal = {triggeringPrincipal: document.nodePrincipal};
    var config = {browserStyle: false, extension: {remote: false}};

        var e10sFox69 = Services.appinfo.browserTabsRemoteAutostart
        && parseInt(Services.appinfo.platformVersion) >= 69;
    var load = async url => {
        if (e10sFox69) {
            config.uri = url;
            config.extension.remote = E10SUtils.getRemoteTypeForURI(url, true) != E10SUtils.NOT_REMOTE;
        }
        var win = SidebarUI.browser.contentWindow;
        var br = win.document.getElementById("webext-panels-browser");
        if (br) {
            if (br.currentURI.spec === url) return;
            br.parentNode.remove();
        }
        var br = await win.getBrowser(config);
        win.onunload = () => defaultURL = br.currentURI.spec;
        br.loadURI(url, principal);
    }
                 // Обработчик следит за изменениями табов и меняет название и иконку нужного таба ......................................................
gBrowser.tabContainer.addEventListener("TabAttrModified", function(event) {
         // очистить адресную строку если это Clipboard Viewer ....
    var defaultURL1 = "chrome://custombuttons/content/some-unique-name.xhtml";
         if ( gBrowser.currentURI.spec == defaultURL1) gURLBar.value = "Clipboard Viewer"; 
}, true);

})(Cu.import("resource://gre/modules/Services.jsm", {}), "some-unique-name", "viewCBClipboardLoader");



this.info = "ЛКМ: открыть в окне\n\n\
СКМ: открыть в Sidebar\n\n\
Ctrl+СКМ: открыть в новой вкладке";


this.checkForCBWindow = function() {
  var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                     .getService(Components.interfaces.nsIWindowWatcher);
  var em = ww.getWindowEnumerator();
  var winName = "clipview";
  var index = 1;
  while (em.hasMoreElements()) {
    let win = em.getNext();
    if(win.name == winName) {
      win.focus();
      return true;
    }
    index++
  }
  return false;
};

(css => {
    this.setAttribute("tooltip", "_child");
    var tooltip = this.appendChild(document.createXULElement("tooltip"));
    this.onmouseover = () => tooltip.label = (gClipboard.read() || this.info);
    css = `#${_id} > tooltip {${css.replace(/;/g, " !important;")}}`;
    var args = ["data:text/css;charset=utf-8," + encodeURIComponent(css), windowUtils.AGENT_SHEET];
    windowUtils.loadSheetUsingURIString(...args);
    addDestructor(() => windowUtils.removeSheetUsingURIString(...args));
})(`
    -moz-appearance: none;
    border: 1px solid black;
    max-width: none;
    background: #ebf1f9;
    color: black;
    font-family: monospace;
    opacity: 0.9;
    border-radius: 5px;
    font-size: 16px;
    padding: 4px 8px;
`);


скрытый текст
Справка

Выделить код

Код:

<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://global/skin/menu.css" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/popup.css" type="text/css"?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        xmlns:html="http://www.w3.org/1999/xhtml"
        id="clipboard-viewer"
        width="800" height="600"
        title="Clipboard viewer"
        buttons="extra1, extra2, cancel"
        buttonlabelextra1="Правка"
        buttonlabelextra2="Очистить"
        buttonlabelcancel="Закрыть"
        buttonaccesskeyextra1="E"
        buttonaccesskeyextra2="r"
        buttonaccesskeycancel="C"
        onfocus="loadFromClipboard();">

  <keyset><key keycode="VK_F5" oncommand="loadFromClipboard();" /></keyset>
  <script src="chrome://global/content/globalOverlay.js"/>
  <script src="chrome://global/content/editMenuOverlay.js"/>
  <html:textarea  id="textbox"   contentEditable="true"  style="height: 600pt; "/>
  <script type="application/x-javascript"><![CDATA[

  var dialogEvents = Object.entries({dialogextra1: edit, dialogextra2: clearClipboard, dialogcancel: closeDialog});
for(let args of dialogEvents) document.addEventListener(...args);
addEventListener("unload", () => dialogEvents.forEach(args => document.removeEventListener(...args)), {once: true});
const Cc = Components.classes;
const Ci = Components.interfaces;

const gTextbox = document.getElementById("textbox");

function getMainwin() {
  if (window.frameElement) {
    return window.frameElement.ownerDocument.defaultView;
  } else if (window.opener) {
    return window.opener;
  } else {
    return Cc["@mozilla.org/appshell/window-mediator;1"].
           getService().QueryInterface(Ci.nsIWindowMediator).
           getMostRecentWindow("navigator:browser")
  }
}

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

function loadFromClipboard() {
  var string = readFromClipboard();
  if (gTextbox.value != string) {
    if (!string) {
      gTextbox.value = "";
    } else {
      gTextbox.value = string;
    }
  }
  gTextbox.selectionStart = 0;
  gTextbox.selectionEnd = 0;
}

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

function clearClipboard() {
  copyToClipboard("");
  gTextbox.value = "";
}

function edit() {
  edittarget(gTextbox);
}

function closeDialog() {
  getMainwin().gCBClipboardViewer.opened = false;
  if (window.frameElement) {
    switch (window.frameElement.id) {
    case "sidebar":
      getMainwin().gCBClipboardViewer.toggleSidebar();
      break;
    default:
      getMainwin().gCBClipboardViewer.togglePanel();
    }
  } else {
    window.close();
  }
}

function popupShowing(aEvent) {
  var children = aEvent.target.childNodes;
  for (var i = 0; i < children.length; i++) {
    var command = children[i].getAttribute("cmd");
    if (command) {
      var controller = document.commandDispatcher
                               .getControllerForCommand(command);
      var enabled = controller.isCommandEnabled(command);
      if (enabled) {
        children[i].removeAttribute("disabled");
      } else {
        children[i].setAttribute("disabled", "true");
      }
    }
  }
}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////// External Editor //////////////////////////////
/////////////////////////////////////////////////////////////////////////////

var _tmpdir=null,_dir_separator,_os;
var _ext,_encode,_target=[];

function editinit() {
  if (window.navigator.platform.toLowerCase().indexOf("win") != -1) {
    // Windows OS
    _dir_separator = "\\";
    _os = "win";
  } else {
    // UNIX/Linux OS
    _dir_separator = "/";
    _os = "unix";
  }

  _ext = "txt";
  _encode = "UTF-8";
  _target = [];

  window.addEventListener("unload", edituninit, false);
  window.addEventListener("unload", function() {
    document.removeEventListener("focus", checkfocus_window, true);
  }, false);
}

function getEditor() {
  var pref = Cc["@mozilla.org/preferences-service;1"].
             getService(Ci.nsIPrefService).
             getBranch("custombuttons.ClipboardViewer.");
  var editor = null;
  try {
    editor = pref.getCharPref("external_editor");
  } catch(ex) {
    var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                  getService(Ci.nsIPromptService);

    var ask = prompts.confirm(null, "Clipboard Viewer",
                              "Вы должны сначала выбрать текстовый редактор.\nНажмите OK для продолжения.");
    if (!ask) return false;

    var nsIFilePicker = Ci.nsIFilePicker;
    var filePicker = Cc["@mozilla.org/filepicker;1"].
                     createInstance(nsIFilePicker);
    filePicker.init(window, "Select editor", nsIFilePicker.modeOpen);
    filePicker.appendFilters(nsIFilePicker.filterApplication);
    filePicker.appendFilters(nsIFilePicker.filterAll);
    filePicker.open(res => {
                   if (res == nsIFilePicker.returnOK) 
      if (filePicker.file.exists() && filePicker.file.isExecutable()) {
        pref.setCharPref("external_editor", filePicker.file.path);
        editor = filePicker.file.path;
      }
      });
    }
  return editor;
}

function edituninit() {
  if (_tmpdir == null) return;
  var windowType = "navigator:browser";
  var windowManager = Cc["@mozilla.org/appshell/window-mediator;1"].
                      getService();
  var windowManagerInterface = windowManager.
                               QueryInterface(Ci.nsIWindowMediator);
  var enumerator = windowManagerInterface.getEnumerator(windowType);
  if (enumerator.hasMoreElements()) {
    return;
  }

  var file = Cc["@mozilla.org/file/local;1"].
             createInstance(Ci.nsIFile);
  file.initWithPath(_tmpdir);
  var entries = file.directoryEntries;
  while (entries.hasMoreElements()) {
    var entry = entries.getNext().QueryInterface(Ci.nsIFile);
    if (/^custombuttons\./i.test(entry.leafName)) {
      try {
        entry.remove(false);
      } catch(e) {
      }
    }
  }

  try {
    if (file.exists() == true ) {
      file.remove(false);
    }
  } catch(e) {
  }

  _tmpdir = null;
}

function checkfocus_window() {
  var target, filename, timestamp, encode,
      file, inst, sstream, utf, textBoxText;

  if (_target.length<=0) return;

  file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  istr = Cc["@mozilla.org/network/file-input-stream;1"].
         createInstance(Ci.nsIFileInputStream);

  // FileInputStream's read is [noscript].
  sstream = Cc["@mozilla.org/scriptableinputstream;1"].
            createInstance(Ci.nsIScriptableInputStream);
  utf = Cc["@mozilla.org/intl/utf8converterservice;1"].
        createInstance(Ci.nsIUTF8ConverterService);

  for (var i=0; i < _target.length;i++) {
    target = _target[i];
    if (!target.hasAttribute("filename")) continue;
    filename = target.getAttribute("filename");
    timestamp = target.getAttribute("timestamp");
    file.initWithPath(filename);
    if (!file.exists() || !file.isReadable()) continue;
    if (file.lastModifiedTime <= timestamp) continue;

    target.setAttribute("timestamp", file.lastModifiedTime);

    istr.init(file, 1, 0x400, false);
    sstream.init(istr);

    textBoxText  = sstream.read(sstream.available());
    encode = target.getAttribute("encode");
    if (textBoxText.length) {
      copyToClipboard(utf.convertStringToUTF8(textBoxText, encode, true, false));
      target.value = utf.convertStringToUTF8(textBoxText, encode, true, false);
    } else {
      clearClipboard();
      target.value = "";
    }
    sstream.close();
    istr.close();
    try {
      file.remove(false);
    } catch(e) {
    }
  }
}

function editfile(target,filename) {
  // Figure out what editor to use.
  var editor = getEditor();
  //var editor = "C:\\Program Files\\AkelPad\\AkelPad.exe";
  if (!editor) return false;

  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  file.initWithPath(editor);
  if (!file.exists()) {
    alert("Error_invalid_Editor_file");
    return false;
  }
  if (!file.isExecutable()) {
    alert("Error_Editor_not_executable");
    return false;
  }
  target.setAttribute("filename", filename);
  target.setAttribute("timestamp", file.lastModifiedTime);

  // Run the editor.
  var process = Cc["@mozilla.org/process/util;1"].
                createInstance(Ci.nsIProcess);
  process.init(file);
  var args = [filename];
  process.run(false, args, args.length);  // don't block
  document.addEventListener("focus", checkfocus_window, true);
  return true;
}

function edittarget(target) {
  var textBoxText = target.value;
  // Get filename.
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  if (target.hasAttribute("filename")) {
    var filename = target.getAttribute("filename");
    file.initWithPath(filename);
    try {
      if(file.exists()) file.remove(false);
    } catch(e) {
    }
  } else {
    var filename = TmpFilenameTextarea();
  }
  file.initWithPath(filename);    
  file.create(file.NORMAL_FILE_TYPE, 0x180);

  // Write the data to the file.
  var ostr = Cc["@mozilla.org/network/file-output-stream;1"].
             createInstance(Ci.nsIFileOutputStream);
  ostr.init(file, 2, 0x200, false);

  if(navigator.platform == "Win32") {
    // Convert Unix newlines to standard network newlines
    textBoxText = textBoxText.replace(/\n/g, "\r\n");
  }
  var conv = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  try {
        conv.charset = 'utf-8';
	textBoxText = conv.ConvertFromUnicode(textBoxText);
    
  } catch(e) {
    textBoxText = "";
  }
  ostr.write(textBoxText, textBoxText.length);

  ostr.flush();
  ostr.close();

  // setup target info
  target.setAttribute("encode", _encode);

  // Edit the file.
  if (editfile(target,file.path)) {
    _target.push(target);  // Editting target array
  }
}

//Compose temporary filename out of
function TmpFilenameTextarea() {
  var TmpFilename;
  _tmpdir = gettmpDir();
  do {
    TmpFilename = _tmpdir + _dir_separator + "clipboard." +
                  Math.floor(Math.random() * 100000) + "." + _ext;
  } while (!ExistsFile(TmpFilename))
    return TmpFilename;
}

//Function returns true if given filename exists
function ExistsFile(filename) {
  try {
    var file = Cc["@mozilla.org/file/local;1"].
               createInstance(Ci.nsIFile);
    file.initWithPath(filename);
    return true;
  } catch(e) {
    return false;
  }
}

/**
* Returns the directory where we put files to edit.
* @returns nsILocalFile The location where we should write editable files.
*/
function gettmpDir() {
  /* Where is the directory that we use. */
  var fobj = Cc["@mozilla.org/file/directory_service;1"].
             getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
  fobj.append("Clipboard_Viewer");
  if (!fobj.exists()) {
    fobj.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0700", 8));
  }
  if (!fobj.isDirectory()) {
    alert("Возникли проблемы с поиском или создать каталог: "+ fobj.path);
  }
  return fobj.path;
}

//////////////////////////////////////////////

function onLoad() {
  getMainwin().gCBClipboardViewer.opened = true;
  editinit();
  gTextbox.focus();
}

window.addEventListener("load", onLoad, false);
window.removeEventListener("unload", onLoad, false);

  ]]></script>

</dialog>


2.
скрытый текст

Выделить код

Код:

// Добавить новый пункт "Открыть в боковой панели" в контекстное меню вкладки ........................................................................................
( {
    var label = "CB Site Loader";
    var url = "chrome://browser/content/webext-panels.xhtml?" + id;
    var icon = "chrome://devtools/skin/images/dock-side-left.svg";
    var defaultURL = "data:text/html;charset=utf-8,<center><h1>Заглушка</h1></center>";
    var currentURL;

    var e = (name, attrs, node, append) => {
        var elm = document.createXULElement(name);
        for(var a in attrs) elm.setAttribute(a, attrs[a]);
        append ? node.append(elm) : node.before(elm);
        return elm;
    }
    var menuitem = e("menuitem", {
        label,
        type: "checkbox",
        id: "menu_CBSiteLoader",
        oncommand: "handleCommand1();",
    }, document.getElementById("viewSidebarMenu"), true);


        handleCommand1 = () => loadURL(
        TabContextMenu.contextTab.linkedBrowser.currentURI.spec
    );

    var btn = e("toolbarbutton", {
        label,
        type: "checkbox",
        oncommand: "handleCommand();",
        id: "sidebar-switcher-CBSidebarLoader",
        class: "subviewbutton subviewbutton-iconic"
    }, document.querySelector('toolbarbutton[id^="sidebar-switcher-"] + toolbarseparator'));

    SidebarUI.sidebars.set(id, {
        url,
        title: label,
        buttonId: btn.id,
        menuId: menuitem.id,
    });
    var css = `\
        #${btn.id} > .toolbarbutton-icon,
        #sidebar-box[sidebarcommand="${id}"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
            width: 16px;
            height: 16px;
            opacity: 0.8;
            fill: currentColor;
            -moz-context-properties: fill;
            list-style-image: url(${icon});
        }`;
    var str = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
    windowUtils.loadSheetUsingURIString(str, type);

    addDestructor(() => {
        btn.remove(); menuitem.remove();
        SidebarUI.sidebars.delete(id);
        windowUtils.removeSheetUsingURIString(str, type);
    });
    var isActive = () => SidebarUI.isOpen && SidebarUI.currentID == id;

    if (isActive()) {
        SidebarUI.selectMenuItem(id);
        var doc = SidebarUI.browser.contentDocument;
        if (doc.readyState != "complete") return;
        var br = doc.getElementById("webext-panels-browser");
        if (br) currentURL = br.currentURI.spec;
    }
    btn.handleCommand = () => {
        if (!btn.hasAttribute("checked")) {
            SidebarUI._switcherPanel.hidePopup();
            btn.setAttribute("checked", true);
        }
        loadURL(gBrowser.currentURI.spec);
    }
    
    if ( document.getElementById("TabCBSite") ) return;
 
  var tabContext = document.getElementById("tabContextMenu");
 
   var mItem = document.createXULElement("menuitem");                 
   mItem.setAttribute("id", "TabCBSite");
   mItem.setAttribute("label", "Открыть в боковой панели");
   mItem.setAttribute("oncommand", "handleCommand1()" );
   mItem.setAttribute("class", "menuitem-iconic");
   mItem.setAttribute("image", icon);
   tabContext.insertBefore( mItem, tabContext.firstChild.nextSibling ); // как первый пункт

 
    addEventListener("load", e =>
        e.target.documentURI == url && load(currentURL || defaultURL)
    , true, SidebarUI.browser);

    var loadURL = url => {
        currentURL = url;
        isActive() ? load(url) : SidebarUI.show(id);    
    }
    var principal = {triggeringPrincipal: document.nodePrincipal};
    var config = {browserStyle: false, extension: {remote: false}};
    //var load = async url => {
        var e10sFox69 = Services.appinfo.browserTabsRemoteAutostart
        && parseInt(Services.appinfo.platformVersion) >= 69;
    var load = async url => {
        if (e10sFox69) {
            config.uri = url;
            config.extension.remote = E10SUtils.getRemoteTypeForURI(url, true) != E10SUtils.NOT_REMOTE;
        }
        var win = SidebarUI.browser.contentWindow;
        var br = win.document.getElementById("webext-panels-browser");
        if (br) {
            if (br.currentURI.spec === url) return;
            br.parentNode.remove();
        }
        var br = await win.getBrowser(config);
        win.onunload = () => currentURL = br.currentURI.spec;
        br.loadURI(url, principal);
    }
})("viewCBSiteLoader");

Отредактировано Andrey_Krropotkin (06-04-2021 22:31:34)

Отсутствует

 

№1540507-04-2021 00:39:53

toxa
Участник
 
Группа: Members
Зарегистрирован: 11-04-2012
Сообщений: 261
UA: Firefox 85.0

Re: Custom Buttons

Dumby пишет
toxa пишет

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

Ну флаг можно поставить куда-нибудь,
в окно или иное подобное надёжное место.
Если флаг есть, то не добавляем листенер, иначе добавляем.

А как поставить флаг в окно? И какие есть еще места, куда можно поставить флаг?

Отсутствует

 

№1540607-04-2021 02:18:49

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 388
UA: Firefox 84.0

Re: Custom Buttons

Dumby спасибо за кнопку QuickToggleAboutSettings!
Дополнил кнопку: выбор шрифтов, подсказки, умолчания, Zoom, графика, Hotkeys, запоминание путей сохранения файлов и картинок и прочее…

Выделить код

Код:

// Quick Toggle Быстрое переключение параметров about:config для custom_script.js

(async (name, id, func) => { // https://forum.mozilla-russia.org/viewtopic.php?pid=789824#p789824
	if (name == "Object") return CustomizableUI.createWidget(func());
	var win = name == "Window", g = Cu.import("resource://gre/modules/Services.jsm", {});
	if (g[id]) {if (win) return;} else g[id] = func(); if (win) return CustomizableUI.createWidget(g[id]);
	addDestructor(r => r[5] == "e" && delete g[id]); g[id].onCreated(this);	// BEGIN QuickToggle…
})(this.constructor.name, "ToggleAboutConfig", () => { var help =

`ПКМ	Меню быстрых настроек 
։нажать	Краткая справка ✍
…+Alt	Опции about:config\n
ЛКМ	Боковая панель: Журнал
։нажать	Антизапрет proxy
…+Alt	Пипетка: захват цвета
…Shift	★ Библиотека закладок\n
СКМ	± Zoom Текст/Страница
։нажать	Консоль браузера\n
- тире ⟳ Обновить ↯ Перезапуск
СКМ ролик мыши, :нажать ≥ 1 сек`, // :нажать - удержание кнопки мыши около секунды. свободные hotkeys: ЛКМ+Alt+⇧

help_ucf = ['chrome://user_chrome_files/content/help.html', 'http://forum.puppyrus.org/index.php?topic=22762'],

// Ctrl+Click или правый клик - сброс параметра по-умолчанию
// клик по параметру с Shift блокирует авто-закрытие меню
// строки с userAlt имеют шрифт italic
//	refresh: false - reload current tab,	true - reload current tab skip cache
//	restart: false - restart browser,		true - restart browser with confirm
// Разделитель: Имя меню "—,⟳,↯" Опция, ⟳ обновить страницу, ↯ перезапуск браузера
// иконки равны ключам: userChoice:зелёный, userAlt:жёлтый, userPro:серый, нет userChoice:серый, ни один:красный

	{prefs, dirsvc} = Services, db = prefs.getDefaultBranch(""), my_vpn = "https://antizapret.prostovpn.org/proxy.pac", icon_vpn = "hue-rotate(270deg) brightness(95%)", menuactive = (AppConstants.platform == "macosx") ? '#e8e8e8' : '#124', // текст, подсвеченный курсором
	xul_ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
	fonts = ["Arial","Cantarell","DejaVu Sans","Roboto","PT Serif","Segoe UI","Ubuntu","Cambria","Fira Sans","Georgia","Noto Sans","Calibri","Times","системный"],
	font_pref = (font) => { return font.map(function(name) { // массив с вложениями
		return (name == font[font.length -1]) ? ["", name,,, `prefs.setIntPref("browser.display.use_document_fonts", 1)`] : [name, name,,, `prefs.setIntPref("browser.display.use_document_fonts", 0)`]; });
	},
	fontserif = font_pref(fonts), fontsans = [["PT Sans","PT Sans"], ...fontserif], dw; // путь загрузки
	try {dw = prefs.getComplexValue("browser.download.dir",Ci.nsIFile);} catch {dw = dirsvc.get("DfltDwnld", Ci.nsIFile);};

	var secondary = [{ // pref … [apref, lab, akey, hint, js-code]
			pref: ["dom.disable_open_during_load", "Блокировать всплывающие окна"], userChoice: 2, userAlt: true,
	},{
			pref: ["browser.safebrowsing.downloads.remote.block_dangerous", "Опасные файлы, сайты",,"browser.safebrowsing.downloads.remote.block_dangerous_host"], userChoice: true, userAlt: false,
			values: [[true, "Запретить",,,`prefs.setBoolPref('browser.safebrowsing.downloads.remote.block_dangerous_host',true)`], [false, "Загружать",,,`prefs.setBoolPref('browser.safebrowsing.downloads.remote.block_dangerous_host',false)`]]
	},{
			pref: ["permissions.default.image", "Загрузка графики"], userChoice: 1, userAlt: 3, refresh: true,
			values: [[1, "Разрешена"], [3, "Только с сайта"], [2, "Отключить"]]
	},{
			pref: ["ucf_save.dirs", `Сайт|Графика`,,`\nПути сохранения страниц | графики\n[Загрузки] — папка по-умолчанию${dw ? ":\n"+ dw.path : ""}`], userChoice: "_Сайты||_Картинки|1", userAlt: "", userPro: "_Web||_Images|1",
			values: [
				["", "папка [Загрузки]"], // subdir: пусто | 0 заголовок | 1 домен
				[`_Сайты||_Картинки|1`, "_Сайты|_Картинки/имя"], // _Web/host|_Pics/title
				[`_Web||_Images|`, "_Web|_Images"],
				[`_Web||_Images|1`, "_Web|_Images/имя"],
				[`_Web||_Pics|1`, "_Web|_Pics/имя"],
				[`_Web|1|_Pics|0`, "_Web/сайт|_Pics/имя"],
				[`_Web|1|_Pics|`, "_Web/сайт|_Pics"],
				[`_Web|1|_Images|0`, "ввести свои пути"]] // здесь нужно открыть about:config
	},null,{
			pref: ["network.proxy.autoconfig_url", "Прокси (VPN) URL", "п"],
			userChoice: my_vpn, userAlt: "127.0.0.1", userPro: "", refresh: true,
			values: [
				["", "сброшен", ""],
				[my_vpn, "АнтиЗапрет", "1", "\nНадёжный доступ на заблокированные сайты\n«Режим прокси» меняется на 2", `prefs.setIntPref('network.proxy.type', 2); node.parentNode.parentNode.style.filter = icon_vpn;`],
				["https://git.io/ac-anticensority-pac", "ac-anticensority", "2"],
				// ["localhost", "Tor Browser", "4", "Только для Linux, MacOS\nУстановите сервис: «tor»"],
				[prefs.getStringPref("user.pacfile", "file:///etc/proxy.pac"), "user .pac файл", "3"], // нужен диалог выбора pac-файла
				["127.0.0.1", "local host", "0",, `prefs.setIntPref('network.proxy.type', 0); node.parentNode.parentNode.style.filter = '';`]]
	},{
			pref: ["network.proxy.type", "Режим прокси", "р"], userChoice: 0, userAlt: 2, refresh: true,
			values: [
				[0, "Без прокси", "0", "по-умолчанию"],
				[5, "Системные (из IE)", "5"],
				[2, "Автонастройка", "2", "about:config - user.pacfile"],
				[1, "Ручная настройка", "1", "Используется network.proxy.autoconfig_url"],
				[4, "Автоопределение", "4"] ]
	},{
			pref: ["network.proxy.share_proxy_settings", "Все протоколы через прокси"], userAlt: true, refresh: true,
			values: [[true, "Да", "", "Прокси для всех протоколов при ручной настройке"], [false, "Нет"]]
	},{
			pref: ["network.trr.mode", "DNS поверх HTTPS",, "\nШифрование DNS-трафика для\nзащиты персональных данных"], userChoice: 1, userAlt: 2, userPro: 5, refresh: true,
			values: [
				[0, "по-умолчанию", "0"], [1, "автоматически", "1", "используется DNS или DoH, в зависимости от того, что быстрее"], [2, "DoH, затем DNS", "2"], [3, "только DoH", "3"], [4, "DNS и DoH", "4"], [5, "отключить DoH", "5"] ]
	},null,{
			pref: ["browser.zoom.full", "Масштабировать"], userChoice: false, userAlt: true,
			values: [[true, "всю страницу"], [false, "только текст"]]
	},{
			pref: ["font.name.sans-serif.x-cyrillic", "Шрифт без засечек ",,"\nТакже влияет на всплывающие подсказки\nСистемный: загрузка шрифтов документа"], userAlt: "", values: fontsans
	},{
			pref: ["font.name.serif.x-cyrillic", "Шрифт с засечками"], userAlt: "", values: fontserif
	},{
			pref: ["image.animation_mode", "Анимация изображений"], userChoice: "none", userAlt: "normal", refresh: true,
			values: [["none", "Выключена"], ["normal", "По циклу"], ["once", "Единожды"]]
	},null,{
			pref: ["media.autoplay.default", "Авто-play аудио/видео"], userChoice: 0, userAlt: 2, userPro: 5, refresh: true,
			values: [
				[0, "Разрешить", "0"], [2, "Спрашивать", "2"], [1, "Запретить", "1"], [5, "Блокировать", "5"]]
	},{
			pref: ["media.autoplay.blocking_policy", "Автозапуск (политика)"], userChoice: 1, userAlt: 2, refresh: true,
			values: [[1, "Временная", "1"], [2, "По действию", "2"], [0, "Постоянная", "0"]]
	},{
			pref: ["gfx.webrender.all", "Аппаратное ускорение графики"], userChoice: true, refresh: true,
			values: [[true, "Да"], [false, "Нет"]]
	},{
			pref: ["gfx.webrender.force-disabled", "Web render disabled", , "gfx.webrender.compositor.force-enabled\n\nАппаратная отрисовка страниц видеокартой.\nотключите при разных проблемах с графикой"],
			userChoice: false, restart: true, values: [
			[true, "Да",,, `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", false)`],
			[false, "Нет",,, `prefs.setBoolPref("gfx.webrender.compositor.force-enabled", true)`]]
	},null,{
			pref: ["network.cookie.cookieBehavior", "Получать куки",, "\nПерсональные настройки посещённых сайтов"], userChoice: 3, userAlt: 0, userPro: 4, refresh: false,
			values: [[0, "со всех сайтов"], [3, "кроме не посещённых"], [4, "кроме трекеров"], [1, "кроме сторонних"], [2, "никогда"]]
	},{
			pref: ["network.http.sendRefererHeader", "Referer: для чего"], userChoice: 2, userAlt: 1,
			values: [[0, "Ни для чего", "0"], [1, "Только ссылки", "1"], [2, "Ссылки, графика", "2"]]
	},{
			pref: ["dom.storage.enabled", "Локальное хранилище",, "\nСохранение персональных данных, по\nкоторым вас можно идентифицировать"],
			userChoice: false, userAlt: true,
			values: [[true, "Разрешить"], [false, "Запретить"]]
	},{
			pref: ["privacy.resistFingerprinting", "Изоляция Firstparty-Fingerprint", ,"privacy.firstparty.isolate\n\nЗащита данных пользователя также\nзапрещает запоминать размер окна"], userChoice: false,
			values: [[true, "Да", , "Защита от слежки",`prefs.setBoolPref('privacy.firstparty.isolate', true);`], [false, "Нет", , "Защита от слежки",`prefs.setBoolPref('privacy.firstparty.isolate', false);`]]
	},{
			pref: ["media.peerconnection.enabled", "WebRTC ваш реальный IP"], userChoice: false,
			values: [[true, "Выдать"], [false, "Скрыть"]]
	},null,{
			pref: ["browser.tabs.remote.force-enable", "Многопоточный режим вкладок"], userChoice: null, userAlt: true, userPro: false,
			values: [[true, "Да"], [false, "Нет"]]
	},{
			pref: ["javascript.enabled", "Выполнять скрипты Java",,"\nПоддержка интерактивных сайтов (и рекламы)"], userChoice: true, refresh: true,
			values: [[true, "Да"], [false, "Нет"]]
	},{
			pref: ["browser.cache.disk.capacity", "Кэш браузера",,"browser.cache.memory.enable"], userChoice: 1048576, userAlt: 0,
			values: [
			[1048576, "Диск и Память",,, `prefs.setBoolPref("browser.cache.memory.enable", true); prefs.setBoolPref("browser.cache.disk.enable", true)`],
			[0, "только Память",,, 		`prefs.setBoolPref("browser.cache.memory.enable", true); prefs.setBoolPref("browser.cache.disk.enable", false)`],
			[2097152, "только Диск",,, `prefs.setBoolPref("browser.cache.memory.enable", false); prefs.setBoolPref("browser.cache.disk.enable", true)`]]
	},{
			pref: ["dom.enable_performance", "Статус загрузки страницы",,"\nПередача данных разрешит определять\nфакт использования прокси-сервера"], userAlt: true
	},{
			pref: ["general.useragent.override", "User Agent"],
			userChoice: null, userAlt: "Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0", userPro: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0", refresh: true,
			values: [
				(arr => {
					var pref = "general.useragent.override";
					var has = prefs.prefHasUserValue(pref);
					if (has) {
						var val = prefs.getStringPref(pref);
						prefs.clearUserPref(pref);
					}
					var ua = Cc["@mozilla.org/network/protocol;1?name=http"]
						.getService(Ci.nsIHttpProtocolHandler).userAgent; // текущий юзерагент
					has && prefs.setStringPref(pref, val);

					var find = node => node.pref && node.pref.pref == pref;
					var redef = (doc, hint) => {
						var popup = doc.getElementById("ToggleAboutConfig-secondaryPopup");
						var menuitem = Array.from(popup.children).find(find).menupopup.firstChild;
						menuitem.tooltipText = hint ? ua + "\n" + hint : ua;
						menuitem.setAttribute("oncommand",
							`event.stopPropagation();
							this.closest("toolbarbutton").linkedObject.contextmenu({
								preventDefault: Boolean,
								target: this.parentNode.parentNode
							});`
						);
					}
					Object.defineProperty(arr, "0", {enumerable: true, get() {
						if (Components.stack.formattedStack.includes("createRadios")) {
							var win = Services.wm.getMostRecentWindow("navigator:browser");
							win.setTimeout(redef, 0, win.document, this[3]);
						}
						else return "";
					}});
					return arr;
				})([null, "По-умолчанию"]),
				["Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0", "Firefox Android9"],
				["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0", "Firefox 68 MacOSX"],
				["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36", "Chrome61 Win10"],
				["Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0", "Firefox 56"],
				["Mozilla/5.0 (X11; Linux x86_64; rv:56.0) Gecko/20100101 Firefox/56.0", "Firefox 56 Linux"],
				["Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)", "MSIE 6.0 Windows"],
				["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 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", "Safari 6 MacOSX"],
				["Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12 Version/12.16", "Opera12 W8"],
				["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"],
				["Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73 (KHTML, like Gecko)", "Playstation 4"],
				["Xbox (Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", "Xbox One (mobile)"],
				["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 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; GT-I8350)", "Windows Phone"],
				["Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "GoogleBot"]]
	},{
			pref: ["browser.sessionstore.restore_on_demand", "Загружать неактивные вкладки", , "\nПри запуске загружаются все вкладки,\nэто может замедлить работу браузера."], userAlt: false,
			values: [[false, "Да"], [true, "Нет"]]
	}];
	return {
		label: "Quick Toggle Settings",
		id: "ToggleAboutConfig",
		tooltiptext: help, localized: false,
		image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADhUlEQVR4AaWUIYzsNhCG91WVelKfqoWrpwMLFxQYGhoGBgYGBgYGGhoGBhoGGhoaBhoaGhqcdIFhf+dGt2n09rpq1ZE+2bHl+eyxd0993yVjNIwxq9F6/WjtaNd5nBnq85g2PMeMo8EwDEUI0Z7+jm/EY2it87ZtuAf1EUqAzZZZcuCxnyOlBFoLkuhnkgdBjBG36YqzP+EaTqgmSckyjrGuK8paWGythVLKfv/9t/O/OkEIC6pZoskCfanQuQYLSTm2/ZQkjSil8Pc8z6iqyp/P58tn2l92wWjGnEuG9gO6uUVtaygnMOQaU+nR+hotjfeugwmaHNv9pJzYOYcQAp+kbVv3cBJrbA45QIQLVLyizRI6t5R8gC0aY+nQZYWK5lT4E3nNn2XaiJX5PAmLXl9fuweBz54X97mCoYR21SwYc8+yjsbrKKGCvAu4TDnne3IO7z2oTP1RwCVKJXGJ+rlHaxu0ocZQahLWaO4lmjtov5eI7yDZFnFqWXQUPL1kFzwaV3GpmqQo+cMlc1li9MBCyacbUnC74MePy3NBiAukFRDLBTd/QWUVUk44BJclx5lMPVYvEJ3e7+CZYN+dSw5TmpiQA1/oPTYip4SV5gANRIloa5Ku/LKeCqhljrHmhLzMSIFYPGLw3N/KCMAAuUYeBUkXLDE9vCIW0K45MbXYoW/aFZdiyxYoM9Y0oiwGaxyBjcAElAHFCETTw40T6tvVXP749eUfBe/v78xdlJaAvNwTGmo1YYiRIME6YosGxWnEaUDQbXFt5adazKO6DEcBX97b29tRAq4tl0XzpZKAkzJFEx31iY1bYuANIBtkW6engl1CRD6JAYrh5Mg90QBRAYsgbkAkksS2VJvT0jXqUj0R7HzOrViCQ1kGILZAUAQl9AxLVl/BDTI24tyK1+/8n/SVYOexVDMlaQAvAHdjOHmQLPS6grxe9ZeviDgKuM/jzIZM38kbbE4ekguGBV7CDwLXy1k/vKJtPf4ODmAPFhbf74mLa5DmFltQwCKJCskIiPNpprTi42+bRcaYTIv3Z/oVhcgpUrIOm1NYbIvZWtjJIliSLgpIFdZZohMvgQRqFyilRimFF0I4+QXik7ZR3vRqqSsRpJSO1jEf/bFXGUsNhAq2uWS63eb0X+NjN/uuforb9UXYXjqEBkkLyMupP85/I/53fDzLsZV6am8zCdR9/C+4MZTbZ2zc/gAAAABJRU5ErkJggg==",
		onCreated(btn) {
			btn.setAttribute("image", this.image);
			var doc = btn.ownerDocument;

			btn.btn = true;
			btn.domParent = null;
			btn.popups = new btn.ownerGlobal.Array();
			this.createPopup(doc, btn, "secondary", secondary);
			this.createCloseMenusOption(doc, btn);

			if (prefs.getIntPref('network.proxy.type') == 2)
				btn.style.filter = icon_vpn; // btn.style.cssText = "background-image: -moz-linear-gradient(#c0c8c0, #c0c8c0, #c0c8c0) !important";

			btn.linkedObject = this;
			for(var type of ["command", "contextmenu", "mousedown", "auxclick"]) // события
				btn.setAttribute("on" + type, `linkedObject.${type}(event)`);
			this.addSheet(btn);
		},
		addSheet(btn) {
			var cb = Array.isArray(btn._destructors);
			var id = cb ? btn.id : "ToggleAboutConfig";
			var css = `#${id} menu[_moz-menuactive] {
				color: ${menuactive} !important;
			}`;
			var args = [
				"data:text/css;charset=utf-8," + encodeURIComponent(css),
				Ci.nsIDOMWindowUtils.USER_SHEET
			];
			if (cb) var destructor = function() {
				this.removeSheetUsingURIString(...args);
			}
			var add = b => b.ownerGlobal.windowUtils.loadSheetUsingURIString(...args);
			(this.addSheet = !cb ? add : btn => {
				add(btn);
				btn._destructors.push({destructor, context: btn.ownerGlobal.windowUtils});
			})(btn);
		},
		createPopup(doc, btn, name, data) {
			var popup = doc.createElementNS(xul_ns, "menupopup");
			var prop = name + "Popup";
			btn.popups.push(btn[prop] = popup);
			popup.id = this.id + "-" + prop;
			for (var type of ["popupshowing", "click"])
				popup.setAttribute("on" + type, `parentNode.linkedObject.${type}(event)`);
			for(var obj of data) popup.append(this.createElement(doc, obj));
			btn.append(popup);
		},
		map: {b: "Bool", n: "Int", s: "String"},
		createElement(doc, obj) {
			if (!obj) return doc.createElementNS(xul_ns, "menuseparator");
			var pref = doc.ownerGlobal.Object.create(null), node, img, bool;
			for(var [key, val] of Object.entries(obj)) {
				if (key == "pref") {
					var [apref, lab, akey, hint] = val;
					pref.pref = apref; pref.lab = lab || apref;
					if (hint) pref.hint = hint;
				}
				else if (key == "image") img = val, pref.img = true;
				else if (key != "values") pref[key] = val;
				else pref.hasVals = true;
			}
			var type = prefs.getPrefType(pref.pref);
			var str = this.map[type == prefs.PREF_INVALID
				? obj.values ? (typeof obj.values[0][0])[0] : "b"
				: type == prefs.PREF_BOOL ? "b" : type == prefs.PREF_INT ? "n" : "s"
			];
			pref.get = prefs[`get${str}Pref`];
			var map, set = prefs[`set${str}Pref`];
			if (pref.hasVals) {
				for(var [val, , , , code] of obj.values)
					code && (map || (map = new Map())).set(val, code);
				if (map) pref.set = (key, val) => {
					set(key, val);
					map.has(val) && eval(map.get(val)); // выполнить код
				}
			}
			if (!map) pref.set = set;

			node = doc.createElementNS(xul_ns, "menu");
			node.className = "menu-iconic";
			node.setAttribute("closemenu", "none");
			img && node.setAttribute("image", img);
			akey && node.setAttribute("accesskey", akey);
			(node.pref = pref).vals = doc.ownerGlobal.Object.create(null);
			this.createRadios(doc,
				str.startsWith("B") && !pref.hasVals ? [[true, "true"], [false, "false"]] : obj.values,
				node.appendChild(doc.createElementNS(xul_ns, "menupopup"))
			);
			if ("userChoice" in obj) pref.noAlt = !("userAlt" in obj);
			return node;
		},
		createCloseMenusOption(doc, btn) {
			var pn = this.closePref = "ToggleAboutConfig.closeMenus";
			var data = [null, {
				pref: [pn, "Закрывать меню этой кнопки"], values: [[true, "Да"], [false, "Нет"]]
			}];
			var setCloseMenus = (e, trg = e.target) => {
				e.stopPropagation();
				var {pref, val} = trg, updPopup = true, clear;
				switch(e.type) {
					case "command": pref = (trg = trg.closest("menu")).pref; updPopup = false; break;
					case "click": if (e.button) return; break;
					case "contextmenu": e.preventDefault(); clear = pref;
				}
				if (!pref) return;
				if (clear) prefs.clearUserPref(pn);
				else if (!updPopup && val === pref.val) return;
				else pref.set(pn, val !== undefined ? val : !pref.val);
				this.upd(trg);
				updPopup && this.popupshowing(null, trg.querySelector("menupopup"));
			}
			(this.createCloseMenusOption = (doc, btn) => {
				for(var obj of data)
					btn.secondaryPopup.append(this.createElement(doc, obj));
				var m = btn.secondaryPopup.lastChild;
				m.style.cssText = "fill: lightblue !important; list-style-image: url(chrome://browser/skin/menu.svg) !important;";
				m.setAttribute("oncommand", "setCloseMenus(event)");
				m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus;
			})(doc, btn);
		},
		UserImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAe1BMVEUAAAB1dXV1dXV1dXV1dXV1dXV1dXV1dXV8fHyRkZGfn5+oqKipqamqqqqysrKzs7O6urq8vLy9vb3ExMTFxcXHx8fNzc3Ozs7Pz8/Q0NDY2NjZ2dna2tre3t7g4ODi4uLj4+Pk5OTl5eXn5+fs7Ozv7+/w8PDx8fHy8vLK4aRZAAAACHRSTlMAGFiAiNDw+LBTincAAACRSURBVBgZBcFBTsMADAAwJ20pqjgM+P8TgQua2Nok2AAAAiIzdfcgkOv2/ub357yaIF8+jwgz969nS7He9pnumf22hrSse1d1V/W+LlIc3d1V3d1HCPsHkWjj+5FUTVdVTdcQtmMNkXrMdT/Dur0KYYy/8wqx7QugHucE+bIFmPPZArkuS+qqqwmIzNTdAwAA/zI6Uy+Vzu5KAAAAAElFTkSuQmCC", // серый
		UserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABGElEQVR4AWKgPgAQSmbgEsNQFB53GHz43GGcioPF4mCxGCwWi8FiMBgMBoPFYOzOPWf2/cv3Z/3P7Wo2W2VQolIJ59zb/grvlfLnO1lWJ7lmwDn2cEbnY3jciF0XSTUqSfKZRCLP4NB9c9tlyrOE4iXUwMAd2OMZHLiPj2O0uUZcWcQXp3jKsQTAuSeODlxm7grEIRmxZZal2EuhOxjEGR24yNwXqHOe5MQsdtVCq72He+DiIfNQYMxGwJRHhdIzPLs4zwViGw4ypF5MGsiYIBLML/t04D49gja7kz4eyEB6yiQCnhG4zDx/xsa30sUL3RMtgXP5jO9+JApt2L+DZ3C+/o2sbv9l5xsNtYBz7B0HS8qUZSZqAwCSaKMMRS9J3wAAAABJRU5ErkJggg==", // зелёный
		notUserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABDElEQVR4Aa2TK3CEQBBEt6JwdxKJRJ48GRkZiURGxqt4dV5FnkQikSdXIpHIweE6+8KKyf+7Va92qqe770v493MOoUw8JGJizcSslV+Fm3NRWLxrZUMnzaOAGY0dng/DXVnK+kdpGhKXFI4CZjR2ePC+edu0W3eSYieNPQEPGjvhwUuG7FXuuK+b691uX4Sw2obBmkHbwIOXjC+4qY61D+d5Bq89g5eML6hpxvQd8JLxBXk5uxsM3p05vmBcJhfmnrkzbmaHl4wv6KfL5IKuZHbFecZLxhecxiEuiwVX4nBhPHjJvP0j7QtZe5TaWmqqdG8wo7HD8+m/MWHxUMluDym0wYzGDs/fHqb/Pk9WVkDcHStz1AAAAABJRU5ErkJggg==", // красный
		UserAltImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABAklEQVR4Aa2TKVDEQBREx3sRiUQi8Wpl5MqVSCQyMhIZGYlciVy5cmQkEhk5runHNQf3kapX9ev36w97hX9/xk3ozGCiScDMjuyr8va6D+syd9LdIOkgYGZHhvNhed4FyxdSmswsaQ/M7MiEg9uWO65r6aV1MCOFCnZkOLh0ygPjMgXpvjc7i5f50HORHRkOLp3yQNSR131uYZMPFbAjw8GlUx5IWk5kLJwiGeQMOzIcoFMfiEEFz+IZMHsHOW8PRO0dHMyxIEK9w8FtX8IYBwe3gPQeOcel0377Vt1w/XNwcOm8/SJtLcxI70OG8+m3kevxKihNucjMjgznbz+m/34eAEg4sZItNtjUAAAAAElFTkSuQmCC", // жёлтый
		regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/,
		upd(node) {
			var {pref} = node, def = false, user = false, val;
			if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) {
				var pn = pref.pref;
				try {val = pref.defVal = db[pref.get.name](pn); def = true}
				catch(ex) {def = false;}
				var user = prefs.prefHasUserValue(pn);
				if (user) try {val = pref.get(pn, undefined);} catch(ex) {}
			}
			if (val == pref.val && def == pref.def && user == pref.user) return;
			pref.val = val; pref.def = def; pref.user = user;
			var exists = def || user;

			var hint = exists ? val : "Эта опция не указана";
			if (hint === "") hint = "[ пустая строка ]";
			hint += "\n" + pref.pref;
			if (pref.hint) hint += "\n" + pref.hint;
			node.tooltipText = hint;

			var img, alt = "userAlt" in pref && val == pref.userAlt, pro = "userPro" in pref && val == pref.userPro;
			if (alt) img = this.UserAltImg;
			if (pro) img = this.UserImg;
			if ("userChoice" in pref)
				if (val == pref.userChoice)
					node.style.removeProperty("color"),
					img = this.UserChoiceImg;
				else {
					node.style.setProperty("color", "#804040", "important");
					if (!alt && !pro) img = this.notUserChoiceImg;
				}
			node.nextSibling && node.setAttribute("image", img || this.UserImg); // серый значок, если нет userChoice
			user
				? node.style.setProperty("font-style", "italic", "important")
				: node.style.removeProperty("font-style");

			var {lab} = pref;
			if (exists && pref.hasVals) {
				if (val in pref.vals) var sfx = pref.vals[val] || val;
				else var sfx = user ? "другое" : "стандарт";
				lab += ` ${"restart" in pref ? "↯-" : "refresh" in pref ? "-⟳" : "—"} ${sfx}`;
			}
			lab = exists ? lab : '['+ lab +']'; // имя = [имя] если преф не существует
			node.setAttribute("label", lab);
		},
		createRadios(doc, vals, popup) {
			for(var arr of vals) {
				if (!arr) {
					popup.append(doc.createElementNS(xul_ns, "menuseparator"));
					continue;
				}
				var [val, lab, key, hint] = arr;
				var menuitem = doc.createElementNS(xul_ns, "menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("closemenu", "none");
				menuitem.style.setProperty("font-style", "italic", "important"),
				menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab);
				key && menuitem.setAttribute("accesskey", key);
				var tip = menuitem.val = val;
				if (hint) tip += "\n" + hint;
				menuitem.tooltipText = tip;
				popup.append(menuitem);
			}
		},
		openPopup(popup) {
			var btn = popup.parentNode;
			if (btn.domParent != btn.parentNode) {
				btn.domParent = btn.parentNode;
				if (btn.matches(".widget-overflow-list > :scope"))
					var pos = "after_start";
				else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} =
					btn.closest("toolbar").getBoundingClientRect(), pos = width > height
						? `${win.innerHeight - bottom > top ? "after" : "before"}_start`
						: `${win.innerWidth - right > left ? "end" : "start"}_before`;
				for(var p of btn.popups) p.setAttribute("position", pos);
			}
			popup.openPopup(btn);
		},
		maybeRestart(node, conf) {
			if (conf && !Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) return;
			var cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
			Services.obs.notifyObservers(cancel, "quit-application-requested", "restart");
			return cancel.data ? Services.prompt.alert(null, this.label, "Запрос на выход отменён.") : this.restart();
		},
		async restart() {
			var meth = Services.appinfo.inSafeMode ? "restartInSafeMode" : "quit";
			Services.startup[meth](Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
		},
		maybeRe(node, fe) {
			var {pref} = node;
			if ("restart" in pref) {
				if (this.maybeRestart(node, pref.restart)) return;
			}
			else this.popupshowing(fe, node.parentNode);
			if ("refresh" in pref) {
				var win = node.ownerGlobal;
				if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh
					? win.BrowserReloadSkipCache() : win.BrowserReload();
			}
		},
		maybeClosePopup(e, trg) {
			!e.shiftKey && prefs.getBoolPref(this.closePref, undefined)
				&& trg.parentNode.hidePopup();
		},
		eyedropper(trg) { // Пипетка - захват цвета
			var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm")
				.require("devtools/client/menus").menuitems
				.find(menuitem => menuitem.id == "menu_eyedropper");
			(this.eyedropper = target => obj.oncommand({target}))(trg);
		},
		auxclick(e) { // CKM
			if (e.button != 1 || !e.target.btn) return;
			e.view.ZoomManager.toggleZoom();
		},
		command(e) { // нажатия левой кнопки мыши
			var trg = e.target, win = e.view;
			if (trg.btn) { // LMB
				if (e.shiftKey) e.altKey
					? e.view.alert("Press Alt+Shift") // Alt+Shift
					: e.view.PlacesCommandHook.showPlacesOrganizer("BookmarksToolbar"); // Shift Библиотека Панель закладок
				else if (e.altKey)
					this.eyedropper(trg); // Alt Пипетка
				else {  // LMB Click
					var bar = trg.ownerDocument.getElementById("add-additional-vertical-bar");
					if (bar) {
						win.setToolbarVisibility(bar, bar.collapsed);
						bar.collapsed ? win.SidebarUI.hide() : win.SidebarUI.show("viewHistorySidebar");
					} else
						win.SidebarUI.toggle("viewHistorySidebar");
				}
				return;
			}
			var menu = trg.closest("menu"), newVal = trg.val;
			this.maybeClosePopup(e, menu);
			if (newVal != menu.pref.val)
				menu.pref.set(menu.pref.pref, newVal),
				this.maybeRe(menu, true);
		},
		popupshowing(e, trg = e.target) {
			if (trg.state == "closed") return;
			if (trg.id) {
				for(var node of trg.children) {
					if (node.nodeName.endsWith("r")) continue;
					this.upd(node);
					!e && node.open && this.popupshowing(null, node.querySelector("menupopup"));
				}
				return;
			}
			var {pref} = trg.closest("menu"), findChecked = true;

			var findDef = "defVal" in pref;
			var checked = trg.querySelector("[checked]");
			if (checked) {
				if (checked.val == pref.val) {
					if (findDef) findChecked = false;
					else return;
				}
				else checked.removeAttribute("checked");
			}
			if (findDef) {
				var def = trg.querySelector("menuitem:not([style*=font-style]");
				if (def)
					if (def.val == pref.defVal) {
						if (findChecked) findDef = false;
						else return;
					}
					else def.style.setProperty("font-style", "italic", "important");
			}
			for(var node of trg.children) if ("val" in node) {
				if (findChecked && node.val == pref.val) {
					node.setAttribute("checked", true);
					if (findDef) findChecked = false;
					else break;
				}
				if (findDef && node.val == pref.defVal) {
					node.style.removeProperty("font-style");
					if (findChecked) findDef = false;
					else break;
				}
			}
		},
		contextmenu(e) { // RMB
			var trg = e.target, win = e.view;
			if (trg.btn) {
				if (e.ctrlKey || e.shiftKey) return;
				if (e.detail == 2) return trg.secondaryPopup.hidePopup(); // меню быстрых настроек
				! e.altKey ? this.openPopup(trg.secondaryPopup) : this.switchToTab("about:config", e);
			}
			else if ("pref" in trg) {
				this.maybeClosePopup(e, trg);
				if (trg.pref.user)
					prefs.clearUserPref(trg.pref.pref),
					this.maybeRe(trg);
			}
			e.preventDefault();
		},
		click(e) {
			if (e.button) return;
			var trg = e.target, {pref} = trg;
			if (!pref) return;
		},
		mousedown(e) {
			var reset = e => e.target.linkedObject = this;
			var id, lo = {command: reset, mousedown: reset, auxclick: e => e.button != 1 || reset(e)};
			var lin = /macos|linux/.test(e.view.AppConstants.platform);
			var stop = e => reset(e) && e.preventDefault();
			lo.contextmenu = lin
				? e => e.ctrlKey || e.shiftKey ? dsp(e) : stop(e) : stop;
			var context = lin
				? e => e.button == 2 && e.type.endsWith("p") && this.contextmenu(e) : () => {};
			var dsp = (e, timeout) => {
				var trg = e.target;
				trg.onmouseup = trg.onmouseleave = null;
				if (timeout) return this.londPress(e);
				e.view.clearTimeout(id);
				reset(e);
				context(e);
			}
			(this.mousedown = e => { var trg = e.target;
				if (!trg.btn) return;
				trg.linkedObject = lo;
				trg.onmouseup = trg.onmouseleave = dsp;
				id = e.view.setTimeout(dsp, 500, e, true);
			})(e);
		},
		showInStatusPanel(info, ms = 5000) {
			var win = Services.wm.getMostRecentWindow("navigator:browser"); StatusPanel = win.StatusPanel;
			if (StatusPanel.update.tid)
				clearTimeout(StatusPanel.update.tid)
			else {
				var {update} = StatusPanel;
				StatusPanel.update = () => {};
				StatusPanel.update.ret = () => {
					StatusPanel.update = update;
					StatusPanel.update();
				}
			}
			StatusPanel.update.tid = setTimeout(StatusPanel.update.ret, ms);
			StatusPanel._label = info;
		},
		Notify(title, text, ms = 3000){
			Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService).showAlertNotification(null, title, text, false, '', null, ms);
		},
		switchToTab(url, e = this) { // открыть вкладку | закрыть, если открыта
			for(var tab of e.view.gBrowser.tabs)
				if ( tab.linkedBrowser.currentURI.spec == url ) {e.view.gBrowser.removeTab(tab); return;}; // вкладка найдена, закрыть
			e.view.switchToTabHavingURI(url, true, {relatedToCurrent: true, triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
		},
		switchProxy(e, pac) {
			if (prefs.getIntPref('network.proxy.type') == 2) { // выключить
				prefs.setIntPref('network.proxy.type', 0);
				prefs.setStringPref("network.proxy.autoconfig_url", "127.0.0.1");
				e.target.style.removeProperty("filter");
				this.showInStatusPanel("\u{1F6A6} Настройки сети - работа без прокси"); // символ Светофор
			} else {
				prefs.setIntPref('network.proxy.type', 2);
				prefs.setStringPref("network.proxy.autoconfig_url", pac);
				e.target.style.setProperty("filter", icon_vpn, "important");
				this.showInStatusPanel("\u{1F6A6} Заблокированные сайты через «АнтиЗапрет»");
				// this.Notify('Proxy', 'Работаем через VPN Антизапрет');
			}
		},
		londPress(e) { // удержание кнопки мыши. на второй долгий клик при отпускании сработает действие на обычный клик этой кнопки
			var trg = e.target, win = e.view;
			if (e.button == 0) this.switchProxy(e, my_vpn);
			if (e.button == 1) trg.ownerDocument.getElementById("key_browserConsole").doCommand(); // Консоль браузера
			if (e.button == 2) { // RMB Long
				var newURI = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).convertChromeURL(Services.io.newURI(help_ucf[0])); // .spec = file:///
				(newURI.QueryInterface(Ci.nsIFileURL).file.exists()) ? this.switchToTab(help_ucf[0], e) : this.switchToTab(help_ucf[1], e);
			}
		}
	};
}); // END ToggleAboutConfig

Отредактировано Dobrov (23-05-2021 17:38:22)

Отсутствует

 

№1540707-04-2021 21:50:41

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

Re: Custom Buttons

Stkvsky пишет

в контекстном меню папки закладок "Открыть всё в контейнере"

Для custom_script.js

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

Выделить код

Код:

(async (sel, self) => ({
	init(topic) {
		Services.obs.addObserver(self = this, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(mm, topic);
			Services.obs.removeObserver(quit, t);
		}, "quit-application-granted");
	},
	observe(doc) {
		var list = doc.querySelectorAll(sel);
		list.length && new this.listener(Array.from(list));
	},
	listener: class {
		constructor(list) {
			var popup = this.popup = (this.list = list)[0].parentNode;
			popup.addEventListener("popupshowing", this);
			popup.ownerGlobal.addEventListener("unload",
				() => popup.removeEventListener("popupshowing", this)
			, {once: true});
		}
		get shouldHide() {
			return (this.ind = this.list.findIndex(this.find)) == -1;
		}
		find(node) {
			return !node.hidden && !node.disabled;
		}
		handleEvent() {
			if (this.shouldHide) return;
			var doc = this.popup.ownerDocument;
			var menu = this.menu = doc.createXULElement("menu");
			menu.setAttribute("label", "Открыть всё в контейнере");
			var popup = menu.appendChild(doc.createXULElement("menupopup"));
			popup.setAttribute("oncommand", "lst.cmd(event)");
			(this.sub = popup).lst = this;
			(this.list[1] || this.list[0]).after(menu);
			/\/browser\.x(?:u|htm)l$/.test(doc.documentURI)
				|| self.stylify(doc.ownerGlobal.windowUtils);
			this.handleEvent = self.popupshowing;
		}
		cmd(e) {
			self.redef(e.target.getAttribute("data-usercontextid"), e.view);
			this.list[this.ind].doCommand();
		}
	},
	redef(id, w) {
		var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow;
		(this.redef = (id, w) => {
			var gb = gbw(w).gBrowser, lt = gb.loadTabs;
			gb.loadTabs = (urls, opts) => {
				opts.userContextId = id;
				(gb.loadTabs = lt).call(gb, urls, opts);
			}
		})(id, w);
	},
	popupshowing(e) {
		if (e.target == this.popup) this.menu.hidden = this.shouldHide;
		else if (e.target == this.sub)
			e.stopImmediatePropagation(),
			e.view.createUserContextMenu(e, {isContextMenu: true});
	},
	stylify(wu) {
		var url = "chrome://browser/content/usercontext/usercontext.css";
		var css = Cu.readUTF8URI(Services.io.newURI(url));
		url = "data:text/css;charset=utf-8," + encodeURIComponent(
			css.replace(/list-style-image.+?\)/, "$& !important")
		);
		(this.stylify = wu => wu.loadSheetUsingURIString(url, wu.USER_SHEET))(wu);
	}
}).init("chrome-document-loaded"))(
	"#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs"
);

Andrey_Krropotkin пишет

все связано с боковой панелью, не отображаются в боковой панели

«1.» там наворочено какой-то жути.
Вот, совсем не многим лучше, но это к тому, что webext-panels.xhtml там не нужен.

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

Выделить код

Код:

((g, id) => {
	var name = id + "Helper";
	var obj = g[name] || (g[name] = ({
		wids: new Set(),
		url: `chrome://custombuttons/content/${id}.xhtml`,
		reg(code) {
			var muri = Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile));
			var ams = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
			(this.reg = code => {
				this.ts = Cu.now();
				var url = "data:application/xhtml+xml;charset=utf-8," + encodeURIComponent(this.code = code);
				this.helper = ams.registerChrome(muri, [["override", this.url, url]]);
			})(code);
		},
		init(btn) {
			this.reg(btn.Help);
			this.init = btn => {
				if (Cu.now() - this.ts < 500) return;
				var code = btn.Help;
				if (this.code == code) return;
				this.helper.destruct();
				Services.obs.notifyObservers(null, "chrome-flush-caches");
				this.reg(code);
			}
		}
	}));
	obj.init(this);

	window.gCBClipboardViewer = {toggleSidebar: () => SidebarUI.toggle(id)};

	var {url} = obj, winName = "clipview";
	var find = win => win.name == winName;

	this.onclick = e => {
		if (e.button == 1) return e.ctrlKey
			? gBrowser.selectedTab = gBrowser.addTrustedTab(url) : SidebarUI.toggle(id);
		if (e.button) return;
		var win = Array.from(Services.wm.getEnumerator(null)).find(find);
		if (win) return win.focus();
		openDialog(url, winName, "chrome,centerscreen,minimizable,resizable");
	}

	var label = this.label = "Clipboard Viewer";
	var icon = this.image;

	var e = (name, attrs, node, append) => {
		var elm = document.createXULElement(name);
		for(var a in attrs) elm.setAttribute(a, attrs[a]);
		append ? node.append(elm) : node.before(elm);
		return elm;
	}
	var menuitem = e("menuitem", {
		label,
		type: "checkbox",
		id: "menu_CBClipboardLoader",
		oncommand: `SidebarUI.toggle("${id}");`,
	}, document.getElementById("viewSidebarMenu"), true);

	var btn = e("toolbarbutton", {
		label,
		type: "checkbox",
		oncommand: `SidebarUI.show("${id}")`,
		id: "sidebar-switcher-CBClipboardLoader",
		class: "subviewbutton subviewbutton-iconic"
	}, document.querySelector('toolbarbutton[id^="sidebar-switcher-"] + toolbarseparator'));
	SidebarUI.isOpen && SidebarUI.currentID == id && btn.setAttribute("checked", true);

	SidebarUI.sidebars.set(id, {
		url,
		title: label,
		buttonId: btn.id,
		menuId: menuitem.id,
	});

	var info = [
		"ЛКМ: открыть в окне",
		"СКМ: открыть в Sidebar",
		"Ctrl+СКМ: открыть в новой вкладке"
	].join("\n\n");

	this.setAttribute("tooltip", "_child");
	var tooltip = this.appendChild(document.createXULElement("tooltip"));
	this.onmouseover = () => tooltip.label = gClipboard.read() || info;

	var css = `\
		#${_id} > tooltip {
			-moz-appearance: none;
			border: 1px solid black;
			max-width: none;
			background: #ebf1f9;
			color: black;
			font-family: monospace;
			opacity: 0.9;
			border-radius: 5px;
			font-size: 16px;
			padding: 4px 8px;
		}
		#${btn.id} > .toolbarbutton-icon,
		#sidebar-box[sidebarcommand="${id}"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
			width: 16px;
			height: 16px;
			opacity: 0.8;
			fill: currentColor;
			-moz-context-properties: fill;
			list-style-image: url(${icon});
		}`
		.replace(/;$/gm, " !important;");

	var str = "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
	windowUtils.loadSheetUsingURIString(str, type);

	addDestructor(reason => {
		btn.remove(); menuitem.remove();
		SidebarUI.sidebars.delete(id);
		windowUtils.removeSheetUsingURIString(str, type);
		if (reason[5] == "e") obj.code = "";
	});

	var wid = window.docShell.outerWindowID;
	if (obj.wids.has(wid)) return;

	obj.wids.add(wid);
	var maybeReload = br => !br.isRemoteBrowser && br.currentURI.spec == url &&
		br.contentDocument.documentURI.startsWith("about:neterror?e=fileNotFound") && br.reload();
	for(var tab of gBrowser.tabs)
		tab.linkedPanel && !tab.closing && maybeReload(tab.linkedBrowser);
	var su = SidebarUI;
	su._box && su.lastOpenedId == id && (!su.isOpen || !su.browser.src) && su.show(id);

})(Cu.import("resource://gre/modules/Services.jsm", {}), "viewCBClipboardLoader");


А в «2.» — вторая строка битая, и код #TabCBSite
режет своим return'ом поперёк, неужели в конце разместить сложно было.


А по сути отвала, консоль ведь подсказывает, что не хватает
policy.browsingContextGroupId
Можно попробовать от CB подсунуть, если paxmod, иначе вписать id
от другого заведомо установленного и включённого WebExtensions.

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

Выделить код

Код:

/*
    var config = {browserStyle: false, extension: {remote: false}};
*/
    var config = {browserStyle: false, extension: {remote: false, policy: {
        browsingContextGroupId: WebExtensionPolicy
            .getByID("custombuttons@xsms.org").browsingContextGroupId
    }}};

toxa пишет

А как поставить флаг в окно? И какие есть еще места, куда можно поставить флаг?

С помощью оператора присваивания, очевидно же.
Место, ну, например, объект custombuttons, чтоб окно не засорять.
А вообще листенеры удалять принято.

Отсутствует

 

№1540808-04-2021 03:36:51

Пострел
Участник
 
Группа: Members
Зарегистрирован: 08-04-2021
Сообщений: 51
UA: Firefox 87.0

Re: Custom Buttons

Здравствуйте. Можно ли адаптировать кнопку
"При повторном открытии боковой панели закладок, все открытые папки автоматически сворачиваются"
для 87 версии Fierfox?

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

Выделить код

Код:

gBrowser.currentURI == "about:customizing" || (() => {

    var func = PlacesTreeView.prototype.toggleOpenState;
    func = eval("(" + String.replace(func, /\s+if \(!this._c([\s\S]+)}\s+}/, "") + ")");

    addEventListener("pageshow", e => {
        if (e.target.location != "chrome://browser/content/bookmarks/bookmarksPanel.xul") return;
        var view = e.target.getElementById("bookmarks-view").view;
        view.toggleOpenState = func.bind(view);

    }, false, document.getElementById("sidebar"));
})();

Отсутствует

 

№1540908-04-2021 04:50:55

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby пишет

Для custom_script.js

Прекрасно работает, спасибо
Блин извиняюсь, а можно две поправки внести?
Чтобы контейнер не выбирать из списка, а создавался новый?
И можно ли указать чтобы вкладки не загружались?

Отредактировано Stkvsky (08-04-2021 07:49:28)

Отсутствует

 

№1541008-04-2021 09:25:33

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

Re: Custom Buttons

Dumby
В 88 по-моему опять не работает кнопка по правому клику
https://forum.mozilla-russia.org/viewtopic.php?pid=789677#p789677
Посмотрите, пожалуйста.

Отредактировано Garalf (08-04-2021 18:37:49)

Отсутствует

 

№1541108-04-2021 11:02:45

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 388
UA: Firefox 87.0

Re: Custom Buttons

Dumby
ваша кнопка: Консоль в сайдбаре хорошая, но как открыть обычную консоль браузера, которая в меню «Web-разработка» ?


Пробовал напрямую, но эта команда не работает: e.openBrowserConsole();
может имитировать клик по пункту меню, наподобии клика по urlbar?
document.getAnonymousElementByAttribute(document.getElementById('urlbar'),"class","textbox-input-box urlbar-input-box").click();


Вторая просьба: добавить дополнительный клик на стандартную кнопку «Загрузки» (для user_chrome_files), чтобы по Right или Middle-click запускался код сохранения страницы SaveHTML:
для старого FF я делал так:

Выделить код

Код:

addEventListener("click", function(event) {
			e.view.alert("downloads-button");
		}
	event.preventDefault(); event.stopPropagation();
	}
}, false, document.getElementById("downloads-button") );

Отредактировано Dobrov (08-04-2021 11:18:15)

Отсутствует

 

№1541208-04-2021 16:32:48

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 332
UA: Firefox 87.0

Re: Custom Buttons

del

Отредактировано ВВП (08-04-2021 22:31:29)

Отсутствует

 

№1541308-04-2021 22:53:54

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

Re: Custom Buttons

Пострел пишет

Здравствуйте. Можно ли адаптировать кнопку
"При повторном открытии боковой панели закладок, все открытые папки автоматически сворачиваются"
для 87 версии Fierfox?

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

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

Выделить код

Код:

(sb => {
	var gv = () => sb.contentDocument
		?.getElementById("bookmarks-view")?.view;
	var func = function(row) {
		var node = this._rows[row];
		node.containerOpen = !node.containerOpen;
	}
	var set = () => {
		var view = gv();
		if (view) view.toggleOpenState = func;
	}
	set();
	addEventListener("pageshow", set, false, sb);
	addDestructor(() => {
		var view = gv();
		if (view) delete view.toggleOpenState;
	});
})(document.getElementById("sidebar"));

Stkvsky пишет

а можно две поправки внести?
Чтобы контейнер не выбирать из списка, а создавался новый?
И можно ли указать чтобы вкладки не загружались?

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

Выделить код

Код:

(async (sel, self) => ({

	icon: "circle",
	color: "turquoise",

	init(topic) {
		Services.obs.addObserver(self = this, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(mm, topic);
			Services.obs.removeObserver(quit, t);
		}, "quit-application-granted");
	},
	observe(doc) {
		var list = doc.querySelectorAll(sel);
		if (!list.length) return;

		var menuitem = doc.createXULElement("menuitem");
		for(var args of Object.entries({
			selectiontype: "single",
			oncommand: "cmd(window)",
			nodetype: "folder|query",
			selection: "folder|query",
			label: "Открыть всё в контейнере",
			id: "placesContext_openContainer:tabs:newUsercontext"
		}))
			menuitem.setAttribute(...args);
		menuitem.cmd = this.cmd;
		menuitem.rnd = menuitem.constructor.prototype.render;
		menuitem.render = this.render;
		var [m1, m2] = menuitem.list = Array.from(list);
		(m2 || m1).after(menuitem);
	},
	async render() {
		this.rnd();
		await new Promise(this.ownerGlobal.requestAnimationFrame);
		this.hidden || (this.hidden = this.list.every(self.every));
	},
	every(node) {
		return node.disabled || node.hidden;
	},
	cmd(win) {
		var view = this.parentNode._view;
		var node = win.document.popupNode;
		node = node._placesView && node._placesView.result.root;
		self.open(win, node || view.selectedNode || view.result.root);
	},
	open(win, node) {
		var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow;
		var w = gbw(win);
		this.pu = w.PlacesUIUtils;
		this.fs = w.PlacesUtils.favicons;
		this.cis = w.ContextualIdentityService;
		this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
		this.pad = {pad: false};
		(this.open = (win, node) => this.openURLs(
			gbw(win), win.PlacesUtils.getURLsForContainerNode(node)
		))(w, node);
	},
	async openURLs(win, urls) {
		var {userContextId} = this.cis.create(
			`[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.color
		);
		var pos = win.gBrowser.selectedTab._tPos;
		var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win);
		for(var {uri, title, isBookmark} of urls) try {
			if (mark) isBookmark
				? this.pu.markPageAsFollowedBookmark(uri)
				: this.pu.markPageAsTyped(uri);

			var state = {entries: [{
				url: uri,
				title: title || uri,
				triggeringPrincipal_base64: this.sysp
			}]};
			var [,, data, mime] = await new Promise(
				resolve => this.fs.getFaviconDataForPage(
					Services.io.newURI(uri), (...args) => resolve(args), 16
				)
			);
			if (data.length) state.image = `data:${
				mime || "image/x-icon"
			};base64,${
				btoa(String.fromCharCode(...data))
			}`;
			var tab = win.gBrowser.addTrustedTab(null, {index: ++pos, userContextId});
			win.SessionStore.setTabState(tab, state);
		} catch {};
	}
}).init("chrome-document-loaded"))(
	"#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs"
);

Garalf пишет

В 88 по-моему опять не работает кнопка по правому клику
https://forum.mozilla-russia.org/viewtopic.php?pid=789677#p789677
Посмотрите, пожалуйста.

На 89.0a1 не вижу. Синтетический STR в студию.


Dobrov пишет

но как открыть обычную консоль браузера, которая в меню «Web-разработка» ?

Пробовал напрямую, но эта команда не работает: e.openBrowserConsole();
может имитировать клик по пункту меню, наподобии клика по urlbar?
document.getAnonymousElementByAttribute(document.getElementById('urlbar'),"class","textbox-input-box urlbar-input-box").click();

Клик не подойдёт, потому что пункта меню может ещё не быть,
больше подходит <key> — document.getElementById("key_browserConsole").doCommand();


Dobrov пишет

для старого FF я делал так

Ну так в чём проблема, если кнопка вытащена, конечно.

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

Выделить код

Код:

(async id => {
	await window.delayedStartupPromise;
	var btn = document.getElementById("downloads-button");
	if (!btn) return;

	var listener = e => {
		if (e.button == 1) {

			alert("Middle-click");

		} else if (e.button == 2) {
			if (e.metaKey || e.ctrlKey || e.shiftKey) return;
			e.preventDefault();

			alert("Right-click");
		}
	}
	btn.addEventListener("click", listener);
	var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win;
	ucf[id] = {destructor: () => btn.removeEventListener("click", listener)};
	ucf.unloadlisteners.push(id);
})("downloads-button-click-listener");

Отредактировано Dumby (08-04-2021 22:58:27)

Отсутствует

 

№1541409-04-2021 00:39:39

Пострел
Участник
 
Группа: Members
Зарегистрирован: 08-04-2021
Сообщений: 51
UA: Firefox 87.0

Re: Custom Buttons

Dumby

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

Отсутствует

 

№1541509-04-2021 01:26:37

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby
Это фантастика, спасибо)
Только вот блин все контейнеры в одном цвете открываются
Можно ли указать чтобы разных цветов были?

Отсутствует

 

№1541609-04-2021 01:30:54

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 388
UA: Firefox 84.0

Re: Custom Buttons

Dumby пишет

как открыть обычную консоль браузера, которая в меню «Web-разработка» ?
document.getElementById("key_browserConsole").doCommand();

Dumby - да, работает на МакОС в браузере Basilisk, (он называется Serpent), но ничего не происходит в Firefox 84.0.2

Uncaught ReferenceError: window is not defined
    command chrome://user_chrome_files/content/custom_scripts/QuickToggle.js:465
    oncommand chrome://browser/content/browser.xhtml:1

Отсутствует

 

№1541709-04-2021 22:12:51

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

Re: Custom Buttons

Stkvsky пишет

Можно ли указать чтобы разных цветов были?

Допустим в коде, в массиве colors: [...], перебор по кругу.

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

Выделить код

Код:

(async (sel, self) => ({

	icon: "circle",
	colors: [
		"mediumseagreen",
		"silver",
		"crimson",
		"blue",
		"peru",
	],

	initColors() {
		var colorName = "ucf-gen";
		var css = "@-moz-document url(about:preferences#containers),"
			+ " url-prefix(chrome://browser/content/browser.x) {\n";
		this.colors.forEach((color, ind) => {
			var [ic, tc] = color.split(/\s*\|\s*/);
			css += `\t.identity-color-${colorName}${ind} {\n`
				+ `\t\t--identity-tab-color: ${tc || ic};\n`
				+ `\t\t--identity-icon-color: ${ic};\n\t}\n`
		});
		var url = "data:text/css;charset=utf-8," + encodeURIComponent(css + "}");
		var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
			.getService(Ci.nsIStyleSheetService);
		sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET);

		var len = this.colors.length;
		var pref = "ucf.openInGeneratedContainer.lastColor";
		var ind = Math.min(Services.prefs.getIntPref(pref, -1), len - 1);
		this.nextColor = () => {
			var next = ind + 1;
			Services.prefs.setIntPref(pref, ind = next == len ? 0 : next);
			return colorName + ind;
		}
	},
	init(topic) {
		Services.obs.addObserver(self = this, topic);
		Services.obs.addObserver(function quit(s, t) {
			Services.obs.removeObserver(self, topic);
			Services.obs.removeObserver(quit, t);
		}, "quit-application-granted");
		this.initColors();
	},
	observe(doc) {
		var list = doc.querySelectorAll(sel);
		if (!list.length) return;

		var menuitem = doc.createXULElement("menuitem");
		for(var args of Object.entries({
			selectiontype: "single",
			oncommand: "cmd(window)",
			nodetype: "folder|query",
			selection: "folder|query",
			label: "Открыть всё в контейнере",
			id: "placesContext_openContainer:tabs:newUsercontext"
		}))
			menuitem.setAttribute(...args);
		menuitem.cmd = this.cmd;
		menuitem.rnd = menuitem.constructor.prototype.render;
		menuitem.render = this.render;
		var [m1, m2] = menuitem.list = Array.from(list);
		(m2 || m1).after(menuitem);
	},
	async render() {
		this.rnd();
		await new Promise(this.ownerGlobal.requestAnimationFrame);
		this.hidden || (this.hidden = this.list.every(self.every));
	},
	every(node) {
		return node.disabled || node.hidden;
	},
	cmd(win) {
		var view = this.parentNode._view;
		var node = win.document.popupNode;
		node = node._placesView && node._placesView.result.root;
		self.open(win, node || view.selectedNode || view.result.root);
	},
	open(win, node) {
		var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow;
		var w = gbw(win);
		this.pu = w.PlacesUIUtils;
		this.fs = w.PlacesUtils.favicons;
		this.cis = w.ContextualIdentityService;
		this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
		(this.open = (win, node) => this.openURLs(
			gbw(win), win.PlacesUtils.getURLsForContainerNode(node)
		))(w, node);
	},
	async openURLs(win, urls) {
		var {userContextId} = this.cis.create(
			`[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.nextColor()
		);
		var pos = win.gBrowser.selectedTab._tPos;
		var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win);
		for(var {uri, title, isBookmark} of urls) try {
			if (mark) isBookmark
				? this.pu.markPageAsFollowedBookmark(uri)
				: this.pu.markPageAsTyped(uri);

			var state = {userContextId, entries: [{
				url: uri,
				title: title || uri,
				triggeringPrincipal_base64: this.sysp
			}]};
			var [,, data, mime] = await new Promise(
				resolve => this.fs.getFaviconDataForPage(
					Services.io.newURI(uri), (...args) => resolve(args), 16
				)
			);
			if (data.length) state.image = `data:${
				mime || "image/x-icon"
			};base64,${
				btoa(String.fromCharCode(...data))
			}`;
			var tab = win.gBrowser.addTrustedTab(null, {index: ++pos, userContextId});
			win.SessionStore.setTabState(tab, state);
		} catch {};
	}
}).init("chrome-document-loaded"))(
	"#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs"
);

Dobrov пишет

Uncaught ReferenceError: window is not defined
    command chrome://user_chrome_files/content/custom_scripts/QuickToggle.js:465

Откуда в QuickToggle.js в command() взялось window?
Хорошо бы на весь код command(e) {...} посмотреть.

Отсутствует

 

№1541809-04-2021 23:52:43

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby пишет

Допустим в коде, в массиве colors: [...], перебор по кругу.

Понял, супер, спасибо

Отредактировано Stkvsky (10-04-2021 15:34:11)

Отсутствует

 

№1541910-04-2021 00:52:11

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 388
UA: Firefox 84.0

Re: Custom Buttons

Dumby пишет

Откуда в QuickToggle.js в command() взялось window?
Хорошо бы на весь код command(e) {...} посмотреть.

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

command(e)

Выделить код

Код:

command(e) { // LMB
	var trg = e.target;
	if (trg.btn) {
		if(e.shiftKey) { // +Shift
			e.view.PlacesCommandHook.showPlacesOrganizer("History"); // Переключить боковую панель
		} else if (e.altKey) { // Control
			// e.openBrowserConsole(); // не работает
			// document.getElementById('menu_eyedropper').doCommand(); // Линза
			e.view.alert("Press " + trg.btn);
		} else {
			var win = e.target.ownerDocument.defaultView;
			var bar = e.target.ownerDocument.querySelector("#add-additional-vertical-bar");
			// if (bar)
				win.setToolbarVisibility(bar, bar.collapsed);
			bar.collapsed ? win.SidebarUI.hide('viewHistorySidebar') : win.SidebarUI.show('viewHistorySidebar');
			return;
		}
	}
	var menu = trg.closest("menu"), newVal = trg.val;
	this.maybeClosePopup(e, menu);
	if (newVal != menu.pref.val)
		menu.pref.set(menu.pref.pref, newVal),
		this.maybeRe(menu, true);
},


Второй вопрос: greasyfork скрипт mhtml-reader не открывает mht-файл.
в меню Violentmonkey есть пункт: "Open MHTML file", но при его выборе ничего не происходит, а должен быть диалог открытия файла…

Отредактировано Dobrov (10-04-2021 05:09:23)

Отсутствует

 

№1542010-04-2021 12:26:42

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 332
UA: Firefox 87.0

Re: Custom Buttons

Dumby
Сразу при переходе в подробности , кнопка "опции"  такая ,а просто белая?  aboutaddons.js - рихтовать?
ia4jcm4i.png
Ну, да пришлось это убрать  this.optionsButton = this.card.querySelector(".more-options-button");

Отредактировано ВВП (10-04-2021 12:44:27)

Отсутствует

 

№1542110-04-2021 15:36:47

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby пишет

Допустим в коде, в массиве colors: [...], перебор по кругу.

Можно вас еще попросить добавить в этот код чтобы просле открытия папки закладок она удалялась?

Отредактировано Stkvsky (10-04-2021 21:10:50)

Отсутствует

 

№1542210-04-2021 21:20:03

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

Re: Custom Buttons

Dobrov пишет

command(e)

Ну и нет никакого «window is not defined».


SidebarUI.hide() — не зачищен, return — не на своём месте,
и что, разве на Mac #menu_eyedropper есть,
пока субменю «Веб-разработка» не откроешь?


Кстати, когда-то спрашивали про пипетку,
код сохранился, вот — вписал, на всякий случай.

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

Выделить код

Код:

...
		eyedropper(trg) {
			var obj = ChromeUtils.import("resource://devtools/shared/Loader.jsm")
				.require("devtools/client/menus").menuitems
				.find(menuitem => menuitem.id == "menu_eyedropper");
			(this.eyedropper = target => obj.oncommand({target}))(trg);
		},
		command(e) {
			var trg = e.target;
			if (trg.btn) {
				if (e.shiftKey) e.altKey
					? this.eyedropper(trg) // Shift+Alt — Пипетка
					: e.view.PlacesCommandHook.showPlacesOrganizer("History"); // Shift — Библиотека (журнал)

				else if (e.altKey)
					trg.ownerDocument.getElementById("key_browserConsole").doCommand(); // Alt — Консоль браузера
				else {
					var bar = trg.ownerDocument.getElementById("add-additional-vertical-bar");
					if (!bar) return; // включите вертикальную панель user_chrome_files

					var bc = bar.collapsed, win = e.view, su = win.SidebarUI;
					win.setToolbarVisibility(bar, bc);
					bc ? su.show("viewHistorySidebar") : su.hide();
				}
				return;
			}
			var menu = trg.closest("menu"), newVal = trg.val;
			this.maybeClosePopup(e, menu);
			if (newVal != menu.pref.val)
				menu.pref.set(menu.pref.pref, newVal),
				this.maybeRe(menu, true);
		},

Dobrov пишет

в меню Violentmonkey есть пункт: "Open MHTML file", но при его выборе ничего не происходит, а должен быть диалог открытия файла…

Наверно всплывающие окна не разрешены. Букмарклет должен работать.


Stkvsky пишет

добавить чтобы просле открытия папки закладок она удалялась

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

Выделить код

Код:

/*
		(this.open = (win, node) => this.openURLs(
			gbw(win), win.PlacesUtils.getURLsForContainerNode(node)
		))(w, node);
*/
		(this.open = (win, node) => {
			this.openURLs(gbw(win), win.PlacesUtils.getURLsForContainerNode(node));
			node.bookmarkGuid && this.pu.doCommand(win, "placesCmd_delete");
		})(win, node);

Отсутствует

 

№1542310-04-2021 22:08:04

Stkvsky
Участник
 
Группа: Members
Зарегистрирован: 26-06-2012
Сообщений: 1699
UA: Firefox 68.0

Re: Custom Buttons

Dumby
Класс, работает как часы, спасибо большое

Отсутствует

 

№1542411-04-2021 02:50:55

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 388
UA: Firefox 84.0

Re: Custom Buttons

Dumby - спасибо за помощь! Ещё просьба – нужна функция, которая открывает вкладку с url
(если его нет) и закрывает вкладку, если такая уже открыта в браузере. То есть, переключатель вкладки - открыть/закрыть.
Не могу исправить ошибку - код напрямую в кнопке работает, а обёрнутый в функцию нет!

Выделить код

Код:

switchToTab(url, e){
	var e = e || this; // аргумент функции не указан
	e.view.switchToTabHavingURI(url, true, {
	    relatedToCurrent: true,
	    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
	});
};
Выделить код

Код:

command(e) { // нажатия мыши
	switchToTab('about:config', e);  // так вкладка не открывается
e.view.switchToTabHavingURI(url, true, { // а так открывается
	    relatedToCurrent: true,
	    triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()…

Отсутствует

 

№1542511-04-2021 06:49:31

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 559
UA: Firefox 86.0

Re: Custom Buttons

Dobrov

Dobrov пишет

Второй вопрос: greasyfork скрипт mhtml-reader не открывает mht-файл.
в меню Violentmonkey есть пункт: "Open MHTML file", но при его выборе ничего не происходит, а должен быть диалог открытия файла…

Объясни как должен работать этот скрипт. У меня ни скрипт ни Букмарклет не работает при попытке открыть локальный MHTML file.

Отсутствует

 

Board footer

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