2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
8 YUI.add('widget-child', function(Y) {
11 * Extension enabling a Widget to be a child of another Widget.
13 * @module widget-child
19 * Widget extension providing functionality enabling a Widget to be a
20 * child of another Widget.
23 * @param {Object} config User configuration object.
27 // Widget method overlap
28 Y.after(this._syncUIChild, this, "syncUI");
29 Y.after(this._bindUIChild, this, "bindUI");
40 * @description Number indicating if the Widget is selected. Possible
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>
50 validator: Lang.isNumber
59 * @description Number representing the Widget's ordinal position in its
66 var parent = this.get("parent"),
70 index = parent.indexOf(this);
84 * @description Retrieves the parent of the Widget in the object hierarchy.
97 * @description Number representing the depth of this Widget relative to
98 * the root Widget in the object heirarchy.
102 getter: function () {
104 var parent = this.get("parent"),
105 root = this.get("root"),
112 if (parent == root) {
116 parent = parent.get("parent");
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.
136 getter: function () {
138 var getParent = function (child) {
140 var parent = child.get("parent"),
141 FnRootType = child.ROOT_TYPE,
145 criteria = (parent && Y.instanceOf(parent, FnRootType));
148 return (criteria ? getParent(parent) : child);
152 return getParent(this);
162 * Constructor reference used to determine the root of a Widget-based
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.
171 * @property ROOT_TYPE
177 // Override of Widget's implementation of _getUIEventNode() to ensure that
178 // all event listeners are bound to the Widget's topmost DOM element.
179 // This ensures that the firing of each type of Widget UI event (click,
180 // mousedown, etc.) is facilitated by a single, top-level, delegated DOM
182 _getUIEventNode: function () {
184 var root = this.get("root"),
188 returnVal = root.get("boundingBox");
198 * @description Returns the Widget's next sibling.
199 * @param {Boolean} circular Boolean indicating if the parent's first child
200 * should be returned if the child has no next sibling.
201 * @return {Widget} Widget instance.
203 next: function (circular) {
205 var parent = this.get("parent"),
209 sibling = parent.item((this.get("index")+1));
212 if (!sibling && circular) {
213 sibling = parent.item(0);
223 * @description Returns the Widget's previous sibling.
224 * @param {Boolean} circular Boolean indicating if the parent's last child
225 * should be returned if the child has no previous sibling.
226 * @return {Widget} Widget instance.
228 previous: function (circular) {
230 var parent = this.get("parent"),
231 index = this.get("index"),
234 if (parent && index > 0) {
235 sibling = parent.item([(index-1)]);
238 if (!sibling && circular) {
239 sibling = parent.item((parent.size() - 1));
247 // Override of Y.WidgetParent.remove()
248 // Sugar implementation allowing a child to remove itself from its parent.
249 remove: function (index) {
254 if (Lang.isNumber(index)) {
255 removed = Y.WidgetParent.prototype.remove.apply(this, arguments);
259 parent = this.get("parent");
262 removed = parent.remove(this.get("index"));
274 * @description Determines if the Widget is the root Widget in the
276 * @return {Boolean} Boolean indicating if Widget is the root Widget in the
279 isRoot: function () {
280 return (this == this.get("root"));
286 * @description Returns the Widget instance at the specified depth.
287 * @param {number} depth Number representing the depth of the ancestor.
288 * @return {Widget} Widget instance.
290 ancestor: function (depth) {
292 var root = this.get("root"),
295 if (this.get("depth") > depth) {
297 parent = this.get("parent");
299 while (parent != root && parent.get("depth") > depth) {
300 parent = parent.get("parent");
311 * Updates the UI to reflect the <code>selected</code> attribute value.
313 * @method _uiSetChildSelected
315 * @param {number} selected The selected value to be reflected in the UI.
317 _uiSetChildSelected: function (selected) {
319 var box = this.get("boundingBox"),
320 sClassName = this.getClassName("selected");
322 if (selected === 0) {
323 box.removeClass(sClassName);
326 box.addClass(sClassName);
333 * Default attribute change listener for the <code>selected</code>
334 * attribute, responsible for updating the UI, in response to
337 * @method _afterChildSelectedChange
339 * @param {EventFacade} event The event facade for the attribute change.
341 _afterChildSelectedChange: function (event) {
342 this._uiSetChildSelected(event.newVal);
347 * Synchronizes the UI to match the WidgetChild state.
349 * This method is invoked after bindUI is invoked for the Widget class
350 * using YUI's aop infrastructure.
353 * @method _syncUIChild
356 _syncUIChild: function () {
357 this._uiSetChildSelected(this.get("selected"));
362 * Binds event listeners responsible for updating the UI state in response
363 * to WidgetChild related state changes.
365 * This method is invoked after bindUI is invoked for the Widget class
366 * using YUI's aop infrastructure.
368 * @method _bindUIChild
371 _bindUIChild: function () {
372 this.after("selectedChange", this._afterChildSelectedChange);
377 Y.WidgetChild = Child;
380 }, '3.3.0' ,{requires:['base-build', 'widget']});