widget-parent.js revision 0891d75cb3cc23db8fc2846447c429a4015a7afb
/**
* Extension enabling a Widget to be a parent of another Widget.
*
* @module widget-parent
*/
/**
* Widget extension providing functionality enabling a Widget to be a
* parent of another Widget.
*
* @class WidgetParent
* @param {Object} config User configuration object.
*/
// TO DO: look at DataType for event facade documentation
/**
* Fires when a Widget is add as a child. The event object will have a
* 'child' property that returns a reference to the child Widget, as well
* as an 'index' property that returns a reference to the index specified
* when the add() method was called.
* <p>
* Subscribers to the "on" moment of this event, will be notified
* before a child is added.
* </p>
* <p>
* Subscribers to the "after" moment of this event, will be notified
* after a child is added.
* </p>
*
* @event childAdded
* @preventable _defAddChildFn
* @param {EventFacade} e The Event Facade
*/
this.publish("addChild", {
defaultTargetOnly: true,
defaultFn: this._defAddChildFn
});
/**
* Fires when a child Widget is removed. The event object will have a
* 'child' property that returns a reference to the child Widget, as well
* as an 'index' property that returns a reference child's ordinal position.
* <p>
* Subscribers to the "on" moment of this event, will be notified
* before a child is removed.
* </p>
* <p>
* Subscribers to the "after" moment of this event, will be notified
* after a child is removed.
* </p>
*
* @event childRemoved
* @preventable _defRemoveChildFn
* @param {EventFacade} e The Event Facade
*/
this.publish("removeChild", {
defaultTargetOnly: true,
defaultFn: this._defRemoveChildFn
});
// TO DO: Document ability to populate children via the constructor
this._items = [];
var children,
});
}
// Widget method overlap
}
/**
* @attribute defaultChildType
* @type {String|Object}
*
* @description String representing the default type of the children
* managed by this Widget. Can also supply default type as a constructor
* reference.
*/
}
return returnVal;
}
},
/**
* @attribute activeItem
* @type Widget
* @readOnly
*
* @description Returns the Widget's currently focused descendant Widget.
*/
activeItem: {
readOnly: true
},
/**
* @attribute multiple
* @type Boolean
* @default false
* @writeOnce
*
* @description Boolean indicating if multiple children can be selected at
* once. Whether or not multiple selection is enabled is always delegated
* to the value of the <code>multiple</code> attribute of the root widget
* in the object hierarchy.
*/
multiple: {
value: false,
writeOnce: true,
}
},
/**
* @attribute selection
* @type {Y.ArrayList|Widget}
* @readOnly
*
* @description Returns the currently selected child Widget. If the
* <code>mulitple</code> attribte is set to <code>true</code> will
* return an Y.ArrayList instance containing the currently selected
* children. If no children are selected, will return null.
*/
selection: {
readOnly: true,
setter: "_setSelection",
return selection;
}
},
selected: {
// Enforces selection behavior on for parent Widgets. Parent's
// selected attribute can be set to the following:
// 0 - Not selected
// 1 - Fully selected (all children are selected). In order for
// all children to be selected, multiple selection must be
// enabled. Therefore, you cannot set the "selected" attribute
// on a parent Widget to 1 unless multiple selection is enabled.
// 2 - Partially selected, meaning one ore more (but not all)
// children are selected.
}
return returnVal;
}
}
};
/**
* Destroy event listener for each child Widget, responsible for removing
* the destroyed child Widget from the parent's internal array of children
* (_items property).
*
* @method _afterDestroyChild
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_afterDestroyChild: function (event) {
}
},
/**
* Attribute change listener for the <code>selection</code>
* attribute, responsible for setting the value of the
* parent's <code>selected</code> attribute.
*
* @method _afterSelectionChange
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_afterSelectionChange: function (event) {
if (selection) {
}
}
}
},
/**
* Attribute change listener for the <code>activeItem</code>
* attribute, responsible for setting the value of the
* parent's <code>activeItem</code> attribute.
*
* @method _afterSelectionChange
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_afterActiveItemChange: function (event) {
var parent;
if (parent) {
}
}
},
/**
* Attribute change listener for the <code>selected</code>
* attribute, responsible for syncing the selected state of all children to
* match that of their parent Widget.
*
*
* @method _afterParentSelectedChange
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_afterParentSelectedChange: function (event) {
// Specify the source of this change as the parent so that
// value of the parent's "selection" attribute isn't
// recalculated
}, this);
}
},
/**
* Default setter for <code>selection</code> attribute changes.
*
* @method _setSelection
* @protected
* @param child {Widget|Array} Widget or Array of Widget instances.
* @return {Widget|Array} Widget or Array of Widget instances.
*/
_setSelection: function (child) {
var selection = null,
selected = [];
this.each(function (v) {
}
});
}
}
else {
}
}
return selection;
},
/**
* Attribute change listener for the <code>selected</code>
* attribute of child Widgets, responsible for setting the value of the
* parent's <code>selection</code> attribute.
*
* @method _updateSelection
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_updateSelection: function (event) {
// Deselect the previously selected child.
// Set src equal to the current context to prevent
// unnecessary re-calculation of the selection.
}
}
}
}
},
/**
* Attribute change listener for the <code>focused</code>
* attribute of child Widgets, responsible for setting the value of the
* parent's <code>activeItem</code> attribute.
*
* @method _updateActiveItem
* @protected
* @param {EventFacade} event The event facade for the attribute change.
*/
_updateActiveItem: function (event) {
val = null;
}
}
},
/**
* Creates an instance of a child Widget using the specified configuration.
* By default Widget instances will be created of the type specified
* by the <code>defaultChildType</code> attribute. Types can be explicitly
* defined via the <code>type</code> property of the configuration object
* literal.
*
* @method _createChild
* @protected
* @param config {Object} Object literal representing the configuration
* used to create an instance of a Widget.
*/
_createChild: function (config) {
Fn,
if (altType) {
FnConstructor = Fn;
}
}
else if (defaultType) {
}
if (FnConstructor) {
}
else {
Y.error("Could not create a child instance because its constructor is either undefined or invalid.");
}
return child;
},
/**
* Default childAdded handler
*
* @method _defAddChildFn
* @protected
* @param event {EventFacade} The Event object
* @param child {Widget} The Widget instance, or configuration
* object for the Widget to be added as a child.
* @param index {Number} Number representing the position at
* which the child will be inserted.
*/
_defAddChildFn: function (event) {
}
}
else {
}
// TO DO: Remove in favor of using event bubbling
//child.after("focusedChange", Y.bind(this._updateActiveItem, this));
},
/**
* Default childRemoved handler
*
* @method _defRemoveChildFn
* @protected
* @param event {EventFacade} The Event object
* @param child {Widget} The Widget instance to be removed.
* @param index {Number} Number representing the index of the Widget to
* be removed.
*/
_defRemoveChildFn: function (event) {
}
}
child.removeTarget(this);
},
/**
* @method _add
* @protected
* @param child {Widget|Object} The Widget instance, or configuration
* object for the Widget to be added as a child.
* @param child {Array} Array of Widget instances, or configuration
* objects for the Widgets to be added as a children.
* @param index {Number} (Optional.) Number representing the position at
* which the child should be inserted.
* @description Adds a Widget as a child. If the specified Widget already
* has a parent it will be removed from its current parent before
* being added as a child.
* @return {Widget|Array} Successfully added Widget or Array containing the
* successfully added Widget instance(s). If no children where added, will
* will return undefined.
*/
var children,
children = [];
if (oChild) {
}
}, this);
}
}
else {
}
else {
}
}
}
return returnVal;
},
/**
* @method add
* @param child {Widget|Object} The Widget instance, or configuration
* object for the Widget to be added as a child.
* @param child {Array} Array of Widget instances, or configuration
* objects for the Widgets to be added as a children.
* @param index {Number} (Optional.) Number representing the position at
* which the child should be inserted.
* @description Adds a Widget as a child. If the specified Widget already
* has a parent it will be removed from its current parent before
* being added as a child.
* @return {Y.ArrayList} Y.ArrayList containing the successfully added
* Widget instance(s). If no children where added, will return an empty
* Y.ArrayList instance.
*/
add: function () {
},
/**
* @method remove
* @param index {Number} (Optional.) Number representing the index of the
* child to be removed.
* @description Removes the Widget from its parent. Optionally, can remove
* a child by specifying its index.
* @return {Widget} Widget instance that was successfully removed, otherwise
* undefined.
*/
}
return returnVal;
},
/**
* @method removeAll
* @description Removes all of the children from the Widget.
* @return {Y.ArrayList} Y.ArrayList instance containing Widgets that were
* successfully removed. If no children where removed, will return an empty
* Y.ArrayList instance.
*/
removeAll: function () {
var removed = [],
if (child) {
}
}, this);
},
/**
* Selects all children.
*
* @method selectAll
*/
selectAll: function () {
},
/**
* Deselects all children.
*
* @method deselectAll
*/
deselectAll: function () {
},
/**
* Updates the UI in response to a child being added.
*
* @method _uiAddChild
* @protected
* @param child {Widget} The child Widget instance to render.
* @param parentNode {Object} The Node under which the
* child Widget is to be rendered.
* @param index {Number} Number representing the position at
* which the child Widget will be inserted.
*/
// TO DO: Better way to handle inserts? Perhaps Widget's
// render() method should be able to accept an optional index.
}
},
/**
* Updates the UI in response to a child being removed.
*
* @method _uiRemoveChild
* @protected
* @param child {Widget} The child Widget instance to render.
*/
_uiRemoveChild: function (child) {
},
_afterAddChild: function (event) {
}
},
_afterRemoveChild: function (event) {
this._uiRemoveChild(child);
}
},
/**
* Sets up DOM and CustomEvent listeners for the parent widget.
* <p>
* This method in invoked after bindUI is invoked for the Widget class
* using YUI's aop infrastructure.
* </p>
*
* @method _bindUIParent
* @protected
*/
_bindUIParent: function () {
},
/**
* Renders all child Widgets for the parent.
* <p>
* This method in invoked after renderUI is invoked for the Widget class
* using YUI's aop infrastructure.
* </p>
* @method _renderChildren
* @protected
*/
_renderChildren: function () {
});
},
/**
* Destroys all child Widgets for the parent.
* <p>
* This method is invoked before the destructor is invoked for the Widget
* class using YUI's aop infrastructure.
* </p>
* @method _destroyChildren
* @protected
*/
_destroyChildren: function () {
// Detach the handler responsible for removing children in
// response to destroying them since:
// 1) It is unnecessary/inefficient at this point since we are doing
// a batch destroy of all children.
// 2) Removing each child will affect our ability to iterate the
// children since the size of _items will be changing as we
// iterate.
this._hDestroyChild.detach();
// Need to clone the _items array since
});
}
};
Y.WidgetParent = Parent;