"Fossies" - the Fresh Open Source Software Archive

Member "firefox-69.0.1/dom/html/HTMLMenuBuilder.jsm" (17 Sep 2019, 3324 Bytes) of package /linux/www/firefox-69.0.1.source.tar.xz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "HTMLMenuBuilder.jsm": 68.0.2_vs_69.0.

    1 /* This Source Code Form is subject to the terms of the Mozilla Public
    2  * License, v. 2.0. If a copy of the MPL was not distributed with this
    3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    4 
    5 // This component is used to build the menus for the HTML contextmenu attribute.
    6 
    7 // A global value that is used to identify each menu item. It is
    8 // incremented with each one that is found.
    9 var gGeneratedId = 1;
   10 
   11 function HTMLMenuBuilder() {
   12   this.currentNode = null;
   13   this.root = null;
   14   this.items = {};
   15   this.nestedStack = [];
   16 }
   17 
   18 // Building is done in two steps:
   19 // The first generates a hierarchical JS object that contains the menu structure.
   20 // This object is returned by toJSONString.
   21 //
   22 // The second step can take this structure and generate a XUL menu hierarchy or
   23 // other UI from this object. The default UI is done in PageMenu.jsm.
   24 //
   25 // When a multi-process browser is used, the first step is performed by the child
   26 // process and the second step is performed by the parent process.
   27 
   28 HTMLMenuBuilder.prototype = {
   29   classID: Components.ID("{51c65f5d-0de5-4edc-9058-60e50cef77f8}"),
   30   QueryInterface: ChromeUtils.generateQI([Ci.nsIMenuBuilder]),
   31 
   32   currentNode: null,
   33   root: null,
   34   items: {},
   35   nestedStack: [],
   36 
   37   toJSONString: function() {
   38     return JSON.stringify(this.root);
   39   },
   40 
   41   openContainer: function(aLabel) {
   42     if (!this.currentNode) {
   43       this.root = {
   44         type: "menu",
   45         children: [],
   46       };
   47       this.currentNode = this.root;
   48     } else {
   49       let parent = this.currentNode;
   50       this.currentNode = {
   51         type: "menu",
   52         label: aLabel,
   53         children: [],
   54       };
   55       parent.children.push(this.currentNode);
   56       this.nestedStack.push(parent);
   57     }
   58   },
   59 
   60   addItemFor: function(aElement, aCanLoadIcon) {
   61     // Since we no longer type check this at the IDL level, make sure we've got
   62     // the right element type here.
   63     if (ChromeUtils.getClassName(aElement) !== "HTMLMenuItemElement") {
   64       return;
   65     }
   66     if (!("children" in this.currentNode)) {
   67       return;
   68     }
   69 
   70     let item = {
   71       type: "menuitem",
   72       label: aElement.label,
   73     };
   74 
   75     let elementType = aElement.type;
   76     if (elementType == "checkbox" || elementType == "radio") {
   77       item.checkbox = true;
   78 
   79       if (aElement.checked) {
   80         item.checked = true;
   81       }
   82     }
   83 
   84     let icon = aElement.icon;
   85     if (icon.length > 0 && aCanLoadIcon) {
   86       item.icon = icon;
   87     }
   88 
   89     if (aElement.disabled) {
   90       item.disabled = true;
   91     }
   92 
   93     item.id = gGeneratedId++;
   94     this.currentNode.children.push(item);
   95 
   96     this.items[item.id] = aElement;
   97   },
   98 
   99   addSeparator: function() {
  100     if (!("children" in this.currentNode)) {
  101       return;
  102     }
  103 
  104     this.currentNode.children.push({ type: "separator" });
  105   },
  106 
  107   undoAddSeparator: function() {
  108     if (!("children" in this.currentNode)) {
  109       return;
  110     }
  111 
  112     let children = this.currentNode.children;
  113     if (children.length && children[children.length - 1].type == "separator") {
  114       children.pop();
  115     }
  116   },
  117 
  118   closeContainer: function() {
  119     this.currentNode = this.nestedStack.length
  120       ? this.nestedStack.pop()
  121       : this.root;
  122   },
  123 
  124   click: function(id) {
  125     let item = this.items[id];
  126     if (item) {
  127       item.click();
  128     }
  129   },
  130 };
  131 
  132 var EXPORTED_SYMBOLS = ["HTMLMenuBuilder"];