Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

javascript - Firefox SDK Add-on with a sidebar on both the right and left at the same time

I'm programming a Firefox Add-on SDK based extension. I need to use both a left and a right-side sidebar, at the same time. By default, I can display one on the left side. I've already read about changing between having the ui/sidebar on the left and the right by using the CSS:

@namespace url(http://www.mozilla.org/keymaster/gat...re.is.only.xul);
hbox#browser { 
    direction: rtl !important;
}         
hbox#browser > vbox {
    direction: ltr !important; 
}

But, that seems to be something of the old-school, because I didn't define .xul files.

Do you know any to have a sidebar on both the left and right of the browser at the same time?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your question is not clear as to exactly what you want. Thus, I have made some assumptions.

Ultimately, there is no officially supported way to have more than one "sidebar" displayed at a time. By default, only a single "sidebar" exist within the Firefox Browser windows. While there is no supported API which provides you with more than one sidebar, it is possible to create multiple sidebars (interface panels) by modifying the XUL DOM for the Firefox Browser windows.

The code below creates user interface panels (side-bars, top-bars, bottom-bars and windows) which are on the top, bottom, left, right, of the browser window, or in a separate window. The interface panels can be created such that they are with respect to the window (they stay visible when you switch tabs; like a bookmarks/history sidebar), or are with respect to the tab (they on only visible when the tab in which they were created is displayed; like the developer tools).

The createInterfacePanelIframe() method creates an interface panel containing an <iframe> (or <browser>) for which you can supply the URL and all attributes. The elements for the <iframe> and the <splitter> are returned to the caller so you can perform other operations on them, or remove them from the Firefox window's DOM to delete/hide them. This method creates <iframe> and calls createInterfacePanel() to insert it into the Firefox browser in the location specified.

The createInterfacePanel() method will put the XUL element that you pass to it (use a Document Fragment to pass multiple elements) into the Firefox Browser window's DOM, along with a <splitter> in the location specified (left, right, top, bottom, window and relative to either the window or the tab). You can specify the window and/or tab you desire the interface panel to be within, or, by default, the interface panel is inserted in the current window/tab. If an interface panel already exists where you are specifying one to be inserted, another panel will be created adjacent to the existing one. There is no inherent limit to the number you can create (e.g. you could have 10 panels on the right, if you wanted).

In addition, a demo Firefox Add-on SDK extension is below which adds 6 different buttons. The first 5 buttons create or destroy interface panels. The badge indicates which panel the button will affect (left, right, top, bottom, and window). A green badge indicates an interface panel will be created. A red badge indicates clicking will destroy the already existing panel. The sixth button toggles the other buttons between Tab relative interface panels, and Window relative interface panels. If you create all the panels your will have 8 panels (4 for the Window and 4 for the current tab) along with two separate windows (per Browser Window).

The following is what the demo add-on looks like. The panels shown in the image below are narrow and/or short to allow them to be displayed on this page. The code below allows you to make the panels whatever size you desire and for the user to be able to resize them.
Demo Add-on in action

This is the code which creates the sidebars (interface panels):

sidebars.js:

/**
 * createInterfacePanelIframe(location,options)
 *   Creates an <iframe> based panel within the current tab, within the
 *   current window, or opens a window, for use as an user interface
 *   box.  If it is not a window, it is associated with the current
 *   browser tab, or the current browser window depending on the
 *   byWindow option.

 * @param location 
 *   Placement of the panel [right|left|top|bottom|window]
 *   The default location is 'right'.
 * @param options
 *   An Object containing optional parameters. 
 *     height
 *       The height of a top or bottom sidebar
 *       Default is 200.
 *     width
 *       The width of a left or right sidebar
 *       Default is 200.
 *     size
 *       Width if on left or right. Height if top or bottom.
 *       Both width and height if location='window' unless
 *       features is a string. 
 *       Default is 200.
 *     id
 *       The ID to assign to the iframe. Default is
 *       'makyen-interface-panel'
 *       The <splitter> will be assigned the
 *       ID = id + '-splitter'
 *     url
 *       This is the chrome://  URL to use for the contents
 *       of the iframe or the window.
 *       the default is:
 *       'chrome://devtools/content/framework/toolbox.xul'
 *     iframeAttributes
 *       An Object
 *       Contains key/value pairs which are applies as attributes
 *       of the iframe. These will override any defaults or other
 *       attributes derived from other options (e.g. id, height,
 *       width, type, etc.). If the value of the property is null
 *       then that attribute will be removed.
 *     useBrowser
 *       If true, a <browser> element is used instead of an <iframe>.
 *     byWindow
 *       If true then the created sidebar is for the window
 *       not the tab.
 *     tab
 *       The tab for which to create the sidebar. If not
 *       specified, the current tab is used.
 *     window
 *       The window for which to create the sidebar. If not
 *       specified, the current window is used.
 *     features
 *       The features string for the window. See:
 *       https://developer.mozilla.org/en-US/docs/Web/API/Window.open
 *
 * returns [splitterEl, iframeEl]
 *   The elements for the <splitter> and <iframe>.
 *
 * Copyright 2014-2016 by Makyen.
 * Released under the MPL 2.0. http://mozilla.org/MPL/2.0/.
 **/
function createInterfacePanelIframe(location,options){
    //options
    let size,width,height,id,chromeUrl;
    if(typeof options === 'object'){
        size = options.size;
        width = options.width;
        height = options.height;
        id = options.id;
        chromeUrl = options.url;
    }
    if(!width && !height && size){
        width = size;
        height = size;
    }
    [width,height] = getSizeWithDefaults(location,width,height);

    //defaults
    id = typeof id !== 'string' ? 'makyen-interface-panel' : id;
    chromeUrl = typeof chromeUrl !== 'string'
        ? 'chrome://devtools/content/framework/toolbox.xul'
        : chromeUrl;

    //Create some common variables if they do not exist.
    //This gets the currently active Firefox XUL window.
    //  Add/remove a '/' to comment/un-comment the code appropriate for your add-on type.
    //* Add-on SDK:
    let activeWindow = options.window ?
            options.window : require('sdk/window/utils').getMostRecentBrowserWindow();
    //*/
    /* Overlay and bootstrap (from almost any context/scope):
    Components.utils.import('resource://gre/modules/Services.jsm');//Services
    let activeWindow = options.window ?
            options.window : Services.wm.getMostRecentWindow('navigator:browser');
    //*/
    let mainDocument = activeWindow.document;

    //Create the <iframe> use
    //mainDocument for the XUL namespace.
    let iframeEl;
    if(options.useBrowser){
        iframeEl = mainDocument.createElement('browser');
    } else {
        iframeEl = mainDocument.createElement('iframe');
    }
    iframeEl.id = id;
    iframeEl.setAttribute('src',chromeUrl);
    iframeEl.setAttribute("tooltip", "aHTMLTooltip");
    iframeEl.setAttribute("autocompleteenabled", true);
    iframeEl.setAttribute("autocompletepopup", "PopupAutoComplete");
    iframeEl.setAttribute("disablehistory",true);
    iframeEl.setAttribute('type', 'content');
    if(typeof height === 'number'){
        iframeEl.setAttribute('height', height.toString());
    }
    if(typeof width === 'number'){
        iframeEl.setAttribute('width', width.toString());
    }
    if(typeof options.iframeAttributes === 'object'){
        let attrs = options.iframeAttributes;
        for(let attr in attrs){
            if(attrs.hasOwnProperty(attr)) {
                if(attrs[attr]===null){
                    iframeEl.removeAttribute(attr);
                }else{
                    iframeEl.setAttribute(attr, attrs[attr]);
                }
            }
        }
    }

    //Call createInterfacePanel
    let splitterEl;
    let newOptions = {};
    if(height) {
        newOptions.height = height;
    }
    if(width) {
        newOptions.width = width;
    }
    newOptions.url = chromeUrl;
    if(options.tab){
        newOptions.tab = options.tab;
    }
    if(options.window){
        newOptions.window = options.window;
    }
    if(options.features){
        newOptions.features = options.features;
    }
    if(options.byWindow){
        newOptions.byWindow = options.byWindow;
    }
    newOptions.id = id + '-splitter';
    splitterEl = createInterfacePanel(location, iframeEl, newOptions)
    return [splitterEl, iframeEl];
}

/**
 * createInterfacePanel(location,objectEl,options)
 *   Creates a panel within the current tab, or opens a window, for use as a
 *   user interface box. If not a window, it is associated with the current
 *   browser tab.
 * @param location 
 *   Placement of the panel [right|left|top|bottom|window]
 *   The default location is 'right'.
 * @param objectEl
 *   The element of an XUL object that will be inserted into
 *   the DOM such that it is within the current tab.
 *   Some examples of possible objects are <iframe>,
 *   <browser>, <box>, <hbox>, <vbox>, etc.
 *   If the location='window' and features is not a string
 *   and this is a number then it is used as the width of the
 *   window.
 * @param options
 *   An Object containing optional parameters. 
 *     height
 *       The height of a top or bottom sidebar
 *       Default is 200.
 *     width
 *       The width of a left or right sidebar
 *       Default is 200.
 *     size
 *       Width if on left or right. Height if top or bottom.
 *       Both width and height if location='window' unless
 *       features is a string. 
 *       Default is 200.
 *       If none of height, width or size is specified, then the
 *       size of the sidebar should be specified within the XUL
 *       elements referenced by objectEl.
 *     sizeEl
 *       The element that is to contain attributes of 'width' and 
 *       'height'. If location=='left'|'right' then the 
 *       'height' attribute is removed prior to the objectEl
 *       being inserted into the DOM.
 *       This is an optional spearate reference for the size element
 *       in case the objectEl is a documentFragment containing
 *       multiple elements. However, normal usage is for
 *       objectEl === sizeEl (which is default if unspecified)
 *       when location != 'window'.
 *       When location == 'window' and features is not a string,
 *       and sizeEl is a number then it is used as the height
 *       of the window.
 *       If features is a string, it is assumed the height is
 *       set in that, or elsewhere (e.g. in the XUL).
 *     id
 *       The ID to assign to the <splitter>. The default is:
 *       'makyen-interface-panel-splitter'.
 *     url
 *       This is the chrome://  URL to use for the contents
 *       of the window.
 *       the default is:
 *       'chrome://devtools/content/framework/toolbox.xul'
 *     byWindow
 *       If true then t

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...