src/cm/media/js/lib/yui/yui3-3.15.0/build/tree-selectable/tree-selectable.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('tree-selectable', function (Y, NAME) {
       
     2 
       
     3 /*jshint expr:true, onevar:false */
       
     4 
       
     5 /**
       
     6 Extension for `Tree` that adds the concept of selection state for nodes.
       
     7 
       
     8 @module tree
       
     9 @submodule tree-selectable
       
    10 @main tree-selectable
       
    11 **/
       
    12 
       
    13 var Do = Y.Do;
       
    14 
       
    15 /**
       
    16 Extension for `Tree` that adds the concept of selection state for nodes.
       
    17 
       
    18 @class Tree.Selectable
       
    19 @constructor
       
    20 @extensionfor Tree
       
    21 **/
       
    22 
       
    23 /**
       
    24 Fired when a node is selected.
       
    25 
       
    26 @event select
       
    27 @param {Tree.Node} node Node being selected.
       
    28 @preventable _defSelectFn
       
    29 **/
       
    30 var EVT_SELECT = 'select';
       
    31 
       
    32 /**
       
    33 Fired when a node is unselected.
       
    34 
       
    35 @event unselect
       
    36 @param {Tree.Node} node Node being unselected.
       
    37 @preventable _defUnselectFn
       
    38 **/
       
    39 var EVT_UNSELECT = 'unselect';
       
    40 
       
    41 function Selectable() {}
       
    42 
       
    43 Selectable.prototype = {
       
    44     // -- Protected Properties -------------------------------------------------
       
    45 
       
    46     /**
       
    47     Mapping of node ids to node instances for nodes in this tree that are
       
    48     currently selected.
       
    49 
       
    50     @property {Object} _selectedMap
       
    51     @protected
       
    52     **/
       
    53 
       
    54     // -- Lifecycle ------------------------------------------------------------
       
    55     initializer: function () {
       
    56         this.nodeExtensions = this.nodeExtensions.concat(Y.Tree.Node.Selectable);
       
    57         this._selectedMap   = {};
       
    58 
       
    59         Do.after(this._selectableAfterDefAddFn, this, '_defAddFn');
       
    60         Do.after(this._selectableAfterDefClearFn, this, '_defClearFn');
       
    61         Do.after(this._selectableAfterDefRemoveFn, this, '_defRemoveFn');
       
    62 
       
    63         this._selectableEvents = [
       
    64             this.after('multiSelectChange', this._afterMultiSelectChange)
       
    65         ];
       
    66     },
       
    67 
       
    68     destructor: function () {
       
    69         (new Y.EventHandle(this._selectableEvents)).detach();
       
    70 
       
    71         this._selectableEvents = null;
       
    72         this._selectedMap      = null;
       
    73     },
       
    74 
       
    75     // -- Public Methods -------------------------------------------------------
       
    76 
       
    77     /**
       
    78     Returns an array of nodes that are currently selected.
       
    79 
       
    80     @method getSelectedNodes
       
    81     @return {Tree.Node.Selectable[]} Array of selected nodes.
       
    82     **/
       
    83     getSelectedNodes: function () {
       
    84         return Y.Object.values(this._selectedMap);
       
    85     },
       
    86 
       
    87     /**
       
    88     Selects the specified node.
       
    89 
       
    90     @method selectNode
       
    91     @param {Tree.Node.Selectable} node Node to select.
       
    92     @param {Object} [options] Options.
       
    93         @param {Boolean} [options.silent=false] If `true`, the `select` event
       
    94             will be suppressed.
       
    95         @param {String} [options.src] Source of the change, to be passed along
       
    96             to the event facade of the resulting event. This can be used to
       
    97             distinguish between changes triggered by a user and changes
       
    98             triggered programmatically, for example.
       
    99     @chainable
       
   100     **/
       
   101     selectNode: function (node, options) {
       
   102         // Instead of calling node.isSelected(), we look for the node in this
       
   103         // tree's selectedMap, which ensures that the `select` event will fire
       
   104         // in cases such as a node being added to this tree with its selected
       
   105         // state already set to true.
       
   106         if (!this._selectedMap[node.id]) {
       
   107             this._fireTreeEvent(EVT_SELECT, {
       
   108                 node: node,
       
   109                 src : options && options.src
       
   110             }, {
       
   111                 defaultFn: this._defSelectFn,
       
   112                 silent   : options && options.silent
       
   113             });
       
   114         }
       
   115 
       
   116         return this;
       
   117     },
       
   118 
       
   119     /**
       
   120     Unselects all selected nodes.
       
   121 
       
   122     @method unselect
       
   123     @param {Object} [options] Options.
       
   124         @param {Boolean} [options.silent=false] If `true`, the `unselect` event
       
   125             will be suppressed.
       
   126         @param {String} [options.src] Source of the change, to be passed along
       
   127             to the event facade of the resulting event. This can be used to
       
   128             distinguish between changes triggered by a user and changes
       
   129             triggered programmatically, for example.
       
   130     @chainable
       
   131     **/
       
   132     unselect: function (options) {
       
   133         for (var id in this._selectedMap) {
       
   134             if (this._selectedMap.hasOwnProperty(id)) {
       
   135                 this.unselectNode(this._selectedMap[id], options);
       
   136             }
       
   137         }
       
   138 
       
   139         return this;
       
   140     },
       
   141 
       
   142     /**
       
   143     Unselects the specified node.
       
   144 
       
   145     @method unselectNode
       
   146     @param {Tree.Node.Selectable} node Node to unselect.
       
   147     @param {Object} [options] Options.
       
   148         @param {Boolean} [options.silent=false] If `true`, the `unselect` event
       
   149             will be suppressed.
       
   150         @param {String} [options.src] Source of the change, to be passed along
       
   151             to the event facade of the resulting event. This can be used to
       
   152             distinguish between changes triggered by a user and changes
       
   153             triggered programmatically, for example.
       
   154     @chainable
       
   155     **/
       
   156     unselectNode: function (node, options) {
       
   157         if (node.isSelected() || this._selectedMap[node.id]) {
       
   158             this._fireTreeEvent(EVT_UNSELECT, {
       
   159                 node: node,
       
   160                 src : options && options.src
       
   161             }, {
       
   162                 defaultFn: this._defUnselectFn,
       
   163                 silent   : options && options.silent
       
   164             });
       
   165         }
       
   166 
       
   167         return this;
       
   168     },
       
   169 
       
   170     // -- Protected Methods ----------------------------------------------------
       
   171     _selectableAfterDefAddFn: function (e) {
       
   172         // If the node is marked as selected, we need go through the select
       
   173         // flow.
       
   174         if (e.node.isSelected()) {
       
   175             this.selectNode(e.node);
       
   176         }
       
   177     },
       
   178 
       
   179     _selectableAfterDefClearFn: function () {
       
   180         this._selectedMap = {};
       
   181     },
       
   182 
       
   183     _selectableAfterDefRemoveFn: function (e) {
       
   184         delete e.node.state.selected;
       
   185         delete this._selectedMap[e.node.id];
       
   186     },
       
   187 
       
   188     // -- Protected Event Handlers ---------------------------------------------
       
   189     _afterMultiSelectChange: function () {
       
   190         this.unselect();
       
   191     },
       
   192 
       
   193     _defSelectFn: function (e) {
       
   194         if (!this.get('multiSelect')) {
       
   195             this.unselect();
       
   196         }
       
   197 
       
   198         e.node.state.selected = true;
       
   199         this._selectedMap[e.node.id] = e.node;
       
   200     },
       
   201 
       
   202     _defUnselectFn: function (e) {
       
   203         delete e.node.state.selected;
       
   204         delete this._selectedMap[e.node.id];
       
   205     }
       
   206 };
       
   207 
       
   208 Selectable.ATTRS = {
       
   209     /**
       
   210     Whether or not to allow multiple nodes to be selected at once.
       
   211 
       
   212     @attribute {Boolean} multiSelect
       
   213     @default false
       
   214     **/
       
   215     multiSelect: {
       
   216         value: false
       
   217     }
       
   218 };
       
   219 
       
   220 Y.Tree.Selectable = Selectable;
       
   221 /**
       
   222 @module tree
       
   223 @submodule tree-selectable
       
   224 **/
       
   225 
       
   226 /**
       
   227 `Tree.Node` extension that adds methods useful for nodes in trees that use the
       
   228 `Tree.Selectable` extension.
       
   229 
       
   230 @class Tree.Node.Selectable
       
   231 @constructor
       
   232 @extensionfor Tree.Node
       
   233 **/
       
   234 
       
   235 function NodeSelectable() {}
       
   236 
       
   237 NodeSelectable.prototype = {
       
   238     /**
       
   239     Returns `true` if this node is currently selected.
       
   240 
       
   241     @method isSelected
       
   242     @return {Boolean} `true` if this node is currently selected, `false`
       
   243         otherwise.
       
   244     **/
       
   245     isSelected: function () {
       
   246         return !!this.state.selected;
       
   247     },
       
   248 
       
   249     /**
       
   250     Selects this node.
       
   251 
       
   252     @method select
       
   253     @param {Object} [options] Options.
       
   254         @param {Boolean} [options.silent=false] If `true`, the `select` event
       
   255             will be suppressed.
       
   256         @param {String} [options.src] Source of the change, to be passed along
       
   257             to the event facade of the resulting event. This can be used to
       
   258             distinguish between changes triggered by a user and changes
       
   259             triggered programmatically, for example.
       
   260     @chainable
       
   261     **/
       
   262     select: function (options) {
       
   263         this.tree.selectNode(this, options);
       
   264         return this;
       
   265     },
       
   266 
       
   267     /**
       
   268     Unselects this node.
       
   269 
       
   270     @method unselect
       
   271     @param {Object} [options] Options.
       
   272         @param {Boolean} [options.silent=false] If `true`, the `unselect` event
       
   273             will be suppressed.
       
   274         @param {String} [options.src] Source of the change, to be passed along
       
   275             to the event facade of the resulting event. This can be used to
       
   276             distinguish between changes triggered by a user and changes
       
   277             triggered programmatically, for example.
       
   278     @chainable
       
   279     **/
       
   280     unselect: function (options) {
       
   281         this.tree.unselectNode(this, options);
       
   282         return this;
       
   283     }
       
   284 };
       
   285 
       
   286 Y.Tree.Node.Selectable = NodeSelectable;
       
   287 
       
   288 
       
   289 }, '@VERSION@', {"requires": ["tree"]});