Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}, '3.18.1', {"requires": ["tree"]});