NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / widget-child / widget-child.js
blob6bc1c15e2963840fb71c20a1899c32b817d9b4f2
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('widget-child', function (Y, NAME) {
10 /**
11  * Extension enabling a Widget to be a child of another Widget.
12  *
13  * @module widget-child
14  */
16 var Lang = Y.Lang;
18 /**
19  * Widget extension providing functionality enabling a Widget to be a
20  * child of another Widget.
21  *
22  * @class WidgetChild
23  * @param {Object} config User configuration object.
25 function Child() {
27     //  Widget method overlap
28     Y.after(this._syncUIChild, this, "syncUI");
29     Y.after(this._bindUIChild, this, "bindUI");
33 Child.ATTRS = {
35     /**
36      * @attribute selected
37      * @type Number
38      * @default 0
39      *
40      * @description Number indicating if the Widget is selected.  Possible
41      * values are:
42      * <dl>
43      * <dt>0</dt> <dd>(Default) Not selected</dd>
44      * <dt>1</dt> <dd>Fully selected</dd>
45      * <dt>2</dt> <dd>Partially selected</dd>
46      * </dl>
47     */
48     selected: {
49         value: 0,
50         validator: Lang.isNumber
51     },
54     /**
55      * @attribute index
56      * @type Number
57      * @readOnly
58      *
59      * @description Number representing the Widget's ordinal position in its
60      * parent Widget.
61      */
62     index: {
63         readOnly: true,
64         getter: function () {
66             var parent = this.get("parent"),
67                 index = -1;
69             if (parent) {
70                 index = parent.indexOf(this);
71             }
73             return index;
75         }
76     },
79     /**
80      * @attribute parent
81      * @type Widget
82      * @readOnly
83      *
84      * @description Retrieves the parent of the Widget in the object hierarchy.
85     */
86     parent: {
87         readOnly: true
88     },
91     /**
92      * @attribute depth
93      * @type Number
94      * @default -1
95      * @readOnly
96      *
97      * @description Number representing the depth of this Widget relative to
98      * the root Widget in the object heirarchy.
99      */
100     depth: {
101         readOnly: true,
102         getter: function () {
104             var parent = this.get("parent"),
105                 root = this.get("root"),
106                 depth = -1;
108             while (parent) {
110                 depth = (depth + 1);
112                 if (parent == root) {
113                     break;
114                 }
116                 parent = parent.get("parent");
118             }
120             return depth;
122         }
123     },
125     /**
126      * @attribute root
127      * @type Widget
128      * @readOnly
129      *
130      * @description Returns the root Widget in the object hierarchy.  If the
131      * ROOT_TYPE property is set, the search for the root Widget will be
132      * constrained to parent Widgets of the specified type.
133      */
134     root: {
135         readOnly: true,
136         getter: function () {
138             var getParent = function (child) {
140                 var parent = child.get("parent"),
141                     FnRootType = child.ROOT_TYPE,
142                     criteria = parent;
144                 if (FnRootType) {
145                     criteria = (parent && Y.instanceOf(parent, FnRootType));
146                 }
148                 return (criteria ? getParent(parent) : child);
150             };
152             return getParent(this);
154         }
155     }
159 Child.prototype = {
161     /**
162      * Constructor reference used to determine the root of a Widget-based
163      * object tree.
164      * <p>
165      * Currently used to control the behavior of the <code>root</code>
166      * attribute so that recursing up the object heirarchy can be constrained
167      * to a specific type of Widget.  Widget authors should set this property
168      * to the constructor function for a given Widget implementation.
169      * </p>
170      *
171      * @property ROOT_TYPE
172      * @type Object
173      */
174     ROOT_TYPE: null,
176     /**
177      * Returns the node on which to bind delegate listeners.
178      *
179      * Override of Widget's implementation of _getUIEventNode() to ensure that
180      * all event listeners are bound to the Widget's topmost DOM element.
181      * This ensures that the firing of each type of Widget UI event (click,
182      * mousedown, etc.) is facilitated by a single, top-level, delegated DOM
183      * event listener.
184      *
185      * @method _getUIEventNode
186      * @for Widget
187      * @protected
188      */
189     _getUIEventNode: function () {
190         var root = this.get("root"),
191             returnVal;
193         if (root) {
194             returnVal = root.get("boundingBox");
195         }
197         return returnVal;
198     },
200     /**
201     * @method next
202     * @description Returns the Widget's next sibling.
203     * @param {Boolean} circular Boolean indicating if the parent's first child
204     * should be returned if the child has no next sibling.
205     * @return {Widget} Widget instance.
206     */
207     next: function (circular) {
209         var parent = this.get("parent"),
210             sibling;
212         if (parent) {
213             sibling = parent.item((this.get("index")+1));
214         }
216         if (!sibling && circular) {
217             sibling = parent.item(0);
218         }
220         return sibling;
222     },
225     /**
226     * @method previous
227     * @description Returns the Widget's previous sibling.
228     * @param {Boolean} circular Boolean indicating if the parent's last child
229     * should be returned if the child has no previous sibling.
230     * @return {Widget} Widget instance.
231     */
232     previous: function (circular) {
234         var parent = this.get("parent"),
235             index = this.get("index"),
236             sibling;
238         if (parent && index > 0) {
239             sibling = parent.item([(index-1)]);
240         }
242         if (!sibling && circular) {
243             sibling = parent.item((parent.size() - 1));
244         }
246         return sibling;
248     },
251     //  Override of Y.WidgetParent.remove()
252     //  Sugar implementation allowing a child to remove itself from its parent.
253     remove: function (index) {
255         var parent,
256             removed;
258         if (Lang.isNumber(index)) {
259             removed = Y.WidgetParent.prototype.remove.apply(this, arguments);
260         }
261         else {
263             parent = this.get("parent");
265             if (parent) {
266                 removed = parent.remove(this.get("index"));
267             }
269         }
271         return removed;
273     },
276     /**
277     * @method isRoot
278     * @description Determines if the Widget is the root Widget in the
279     * object hierarchy.
280     * @return {Boolean} Boolean indicating if Widget is the root Widget in the
281     * object hierarchy.
282     */
283     isRoot: function () {
284         return (this == this.get("root"));
285     },
288     /**
289     * @method ancestor
290     * @description Returns the Widget instance at the specified depth.
291     * @param {number} depth Number representing the depth of the ancestor.
292     * @return {Widget} Widget instance.
293     */
294     ancestor: function (depth) {
296         var root = this.get("root"),
297             parent;
299         if (this.get("depth") > depth)  {
301             parent = this.get("parent");
303             while (parent != root && parent.get("depth") > depth) {
304                 parent = parent.get("parent");
305             }
307         }
309         return parent;
311     },
314     /**
315      * Updates the UI to reflect the <code>selected</code> attribute value.
316      *
317      * @method _uiSetChildSelected
318      * @protected
319      * @param {number} selected The selected value to be reflected in the UI.
320      */
321     _uiSetChildSelected: function (selected) {
323         var box = this.get("boundingBox"),
324             sClassName = this.getClassName("selected");
326         if (selected === 0) {
327             box.removeClass(sClassName);
328         }
329         else {
330             box.addClass(sClassName);
331         }
333     },
336     /**
337      * Default attribute change listener for the <code>selected</code>
338      * attribute, responsible for updating the UI, in response to
339      * attribute changes.
340      *
341      * @method _afterChildSelectedChange
342      * @protected
343      * @param {EventFacade} event The event facade for the attribute change.
344      */
345     _afterChildSelectedChange: function (event) {
346         this._uiSetChildSelected(event.newVal);
347     },
350     /**
351      * Synchronizes the UI to match the WidgetChild state.
352      * <p>
353      * This method is invoked after bindUI is invoked for the Widget class
354      * using YUI's aop infrastructure.
355      * </p>
356      *
357      * @method _syncUIChild
358      * @protected
359      */
360     _syncUIChild: function () {
361         this._uiSetChildSelected(this.get("selected"));
362     },
365     /**
366      * Binds event listeners responsible for updating the UI state in response
367      * to WidgetChild related state changes.
368      * <p>
369      * This method is invoked after bindUI is invoked for the Widget class
370      * using YUI's aop infrastructure.
371      * </p>
372      * @method _bindUIChild
373      * @protected
374      */
375     _bindUIChild: function () {
376         this.after("selectedChange", this._afterChildSelectedChange);
377     }
381 Y.WidgetChild = Child;
384 }, '3.13.0', {"requires": ["base-build", "widget"]});