browser/devtools/shared/widgets/BreadcrumbsWidget.jsm

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     1 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 "use strict";
     8 const Ci = Components.interfaces;
     9 const Cu = Components.utils;
    11 const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
    13 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
    14 Cu.import("resource://gre/modules/devtools/event-emitter.js");
    16 this.EXPORTED_SYMBOLS = ["BreadcrumbsWidget"];
    18 /**
    19  * A breadcrumb-like list of items.
    20  *
    21  * Note: this widget should be used in tandem with the WidgetMethods in
    22  * ViewHelpers.jsm.
    23  *
    24  * @param nsIDOMNode aNode
    25  *        The element associated with the widget.
    26  */
    27 this.BreadcrumbsWidget = function BreadcrumbsWidget(aNode) {
    28   this.document = aNode.ownerDocument;
    29   this.window = this.document.defaultView;
    30   this._parent = aNode;
    32   // Create an internal arrowscrollbox container.
    33   this._list = this.document.createElement("arrowscrollbox");
    34   this._list.className = "breadcrumbs-widget-container";
    35   this._list.setAttribute("flex", "1");
    36   this._list.setAttribute("orient", "horizontal");
    37   this._list.setAttribute("clicktoscroll", "true")
    38   this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
    39   this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
    40   this._parent.appendChild(this._list);
    42   // By default, hide the arrows. We let the arrowscrollbox show them
    43   // in case of overflow.
    44   this._list._scrollButtonUp.collapsed = true;
    45   this._list._scrollButtonDown.collapsed = true;
    46   this._list.addEventListener("underflow", this._onUnderflow.bind(this), false);
    47   this._list.addEventListener("overflow", this._onOverflow.bind(this), false);
    50   // These separators are used for CSS purposes only, and are positioned
    51   // off screen, but displayed with -moz-element.
    52   this._separators = this.document.createElement("box");
    53   this._separators.className = "breadcrumb-separator-container";
    54   this._separators.innerHTML =
    55                     "<box id='breadcrumb-separator-before'></box>" +
    56                     "<box id='breadcrumb-separator-after'></box>" +
    57                     "<box id='breadcrumb-separator-normal'></box>";
    58   this._parent.appendChild(this._separators);
    60   // This widget emits events that can be handled in a MenuContainer.
    61   EventEmitter.decorate(this);
    63   // Delegate some of the associated node's methods to satisfy the interface
    64   // required by MenuContainer instances.
    65   ViewHelpers.delegateWidgetAttributeMethods(this, aNode);
    66   ViewHelpers.delegateWidgetEventMethods(this, aNode);
    67 };
    69 BreadcrumbsWidget.prototype = {
    70   /**
    71    * Inserts an item in this container at the specified index.
    72    *
    73    * @param number aIndex
    74    *        The position in the container intended for this item.
    75    * @param nsIDOMNode aContents
    76    *        The node displayed in the container.
    77    * @return nsIDOMNode
    78    *         The element associated with the displayed item.
    79    */
    80   insertItemAt: function(aIndex, aContents) {
    81     let list = this._list;
    82     let breadcrumb = new Breadcrumb(this, aContents);
    83     return list.insertBefore(breadcrumb._target, list.childNodes[aIndex]);
    84   },
    86   /**
    87    * Returns the child node in this container situated at the specified index.
    88    *
    89    * @param number aIndex
    90    *        The position in the container intended for this item.
    91    * @return nsIDOMNode
    92    *         The element associated with the displayed item.
    93    */
    94   getItemAtIndex: function(aIndex) {
    95     return this._list.childNodes[aIndex];
    96   },
    98   /**
    99    * Removes the specified child node from this container.
   100    *
   101    * @param nsIDOMNode aChild
   102    *        The element associated with the displayed item.
   103    */
   104   removeChild: function(aChild) {
   105     this._list.removeChild(aChild);
   107     if (this._selectedItem == aChild) {
   108       this._selectedItem = null;
   109     }
   110   },
   112   /**
   113    * Removes all of the child nodes from this container.
   114    */
   115   removeAllItems: function() {
   116     let list = this._list;
   118     while (list.hasChildNodes()) {
   119       list.firstChild.remove();
   120     }
   122     this._selectedItem = null;
   123   },
   125   /**
   126    * Gets the currently selected child node in this container.
   127    * @return nsIDOMNode
   128    */
   129   get selectedItem() {
   130     return this._selectedItem;
   131   },
   133   /**
   134    * Sets the currently selected child node in this container.
   135    * @param nsIDOMNode aChild
   136    */
   137   set selectedItem(aChild) {
   138     let childNodes = this._list.childNodes;
   140     if (!aChild) {
   141       this._selectedItem = null;
   142     }
   143     for (let node of childNodes) {
   144       if (node == aChild) {
   145         node.setAttribute("checked", "");
   146         this._selectedItem = node;
   147       } else {
   148         node.removeAttribute("checked");
   149       }
   150     }
   151   },
   153   /**
   154    * Returns the value of the named attribute on this container.
   155    *
   156    * @param string aName
   157    *        The name of the attribute.
   158    * @return string
   159    *         The current attribute value.
   160    */
   161   getAttribute: function(aName) {
   162     if (aName == "scrollPosition") return this._list.scrollPosition;
   163     if (aName == "scrollWidth") return this._list.scrollWidth;
   164     return this._parent.getAttribute(aName);
   165   },
   167   /**
   168    * Ensures the specified element is visible.
   169    *
   170    * @param nsIDOMNode aElement
   171    *        The element to make visible.
   172    */
   173   ensureElementIsVisible: function(aElement) {
   174     if (!aElement) {
   175       return;
   176     }
   178     // Repeated calls to ensureElementIsVisible would interfere with each other
   179     // and may sometimes result in incorrect scroll positions.
   180     setNamedTimeout("breadcrumb-select", ENSURE_SELECTION_VISIBLE_DELAY, () => {
   181       if (this._list.ensureElementIsVisible) {
   182         this._list.ensureElementIsVisible(aElement);
   183       }
   184     });
   185   },
   187   /**
   188    * The underflow and overflow listener for the arrowscrollbox container.
   189    */
   190   _onUnderflow: function({ target }) {
   191     if (target != this._list) {
   192       return;
   193     }
   194     target._scrollButtonUp.collapsed = true;
   195     target._scrollButtonDown.collapsed = true;
   196     target.removeAttribute("overflows");
   197   },
   199   /**
   200    * The underflow and overflow listener for the arrowscrollbox container.
   201    */
   202   _onOverflow: function({ target }) {
   203     if (target != this._list) {
   204       return;
   205     }
   206     target._scrollButtonUp.collapsed = false;
   207     target._scrollButtonDown.collapsed = false;
   208     target.setAttribute("overflows", "");
   209   },
   211   window: null,
   212   document: null,
   213   _parent: null,
   214   _list: null,
   215   _selectedItem: null
   216 };
   218 /**
   219  * A Breadcrumb constructor for the BreadcrumbsWidget.
   220  *
   221  * @param BreadcrumbsWidget aWidget
   222  *        The widget to contain this breadcrumb.
   223  * @param nsIDOMNode aContents
   224  *        The node displayed in the container.
   225  */
   226 function Breadcrumb(aWidget, aContents) {
   227   this.document = aWidget.document;
   228   this.window = aWidget.window;
   229   this.ownerView = aWidget;
   231   this._target = this.document.createElement("hbox");
   232   this._target.className = "breadcrumbs-widget-item";
   233   this._target.setAttribute("align", "center");
   234   this.contents = aContents;
   235 }
   237 Breadcrumb.prototype = {
   238   /**
   239    * Sets the contents displayed in this item's view.
   240    *
   241    * @param string | nsIDOMNode aContents
   242    *        The string or node displayed in the container.
   243    */
   244   set contents(aContents) {
   245     // If there are already some contents displayed, replace them.
   246     if (this._target.hasChildNodes()) {
   247       this._target.replaceChild(aContents, this._target.firstChild);
   248       return;
   249     }
   250     // These are the first contents ever displayed.
   251     this._target.appendChild(aContents);
   252   },
   254   window: null,
   255   document: null,
   256   ownerView: null,
   257   _target: null
   258 };

mercurial