Created
January 24, 2011 16:02
-
-
Save bwg/793426 to your computer and use it in GitHub Desktop.
plugin for widgetparent that uses an async-queue to render children
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
YUI.add('sm-widget-parent-renderqueue', function(Y) { | |
/** | |
* Plugin for WidgetParent that uses an async-queue to render children | |
* | |
* @module widget-parent-render-queue | |
*/ | |
var NAME = 'renderqueue', | |
HOST = 'host', | |
BOUNDING_BOX = 'boundingBox', | |
PARENT = 'parent', | |
RENDERED = 'rendered', | |
TIMEOUT = 'timeout', | |
WIDGET_RENDER_FN = Y.Widget.prototype._defRenderFn; | |
/** | |
* Plugin for WidgetParent providing async-queue functionality for | |
* rendering child widgets | |
* | |
* @class WidgetParentRenderQueue | |
* @constructor | |
* @extends Plugin.Base | |
* @param config {Object} User configuration object | |
*/ | |
function RenderQueue(config) { | |
RenderQueue.superclass.constructor.apply(this, arguments); | |
} | |
/** | |
* Static property provides a string to identify the class. | |
* | |
* @property WidgetParentRenderQueue.NAME | |
* @type String | |
* @static | |
*/ | |
RenderQueue.NAME = NAME; | |
/** | |
* Static property provides a string to identify the namespace. | |
* | |
* @property WidgetParentRenderQueue.NS | |
* @type String | |
* @static | |
*/ | |
RenderQueue.NS = NAME; | |
/** | |
* Static property used to define the default attribute | |
* configuration for the WidgetParentRenderQueue. | |
* | |
* @property WidgetParentRenderQueue.ATTRS | |
* @type Object | |
* @static | |
*/ | |
RenderQueue.ATTRS = { | |
/** | |
* Queue execution timer | |
* | |
* @attribute timeout | |
* @default Y.AsyncQueue.defaults.timeout (currently 10ms) | |
*/ | |
timeout: { | |
value: Y.AsyncQueue.defaults.timeout | |
} | |
}; | |
Y.extend(RenderQueue, Y.Plugin.Base, { | |
/** | |
* the async queue instance | |
* | |
* @property _queue | |
* @private | |
*/ | |
_queue: new Y.AsyncQueue(), | |
/** | |
* Initializer lifecycle method for the plugin. | |
* | |
* @method initializer | |
* @protected | |
*/ | |
initializer: function(cfg) { | |
var host = this.get(HOST), | |
q = this._queue; | |
// set the defaults for the queue | |
q.defaults.context = host; | |
q.defaults.timeout = this.get(TIMEOUT); | |
// add the plugin as a bubble target for queue events | |
q.addTarget(this); | |
this.on(TIMEOUT + 'Change', function(e) { | |
q.defaults.timeout = e.newVal; | |
}); | |
//this.beforeHostMethod('_uiAddChild', this._uiAddChild, host); | |
this.onHostEvent('addChild', this._onAddChild); | |
}, | |
/** | |
* Destructor lifecycle implementation for the plugin. Resets all | |
* child widgets to their default state | |
* | |
* @method destructor | |
* @protected | |
*/ | |
destructor: function() { | |
var host = this.get(HOST), | |
q = this._queue; | |
// HostMethod/Event listeners are automatically | |
// detached by plugin base destructor | |
// return the default renderFn for children | |
// back to its...um...default | |
host.each(function(child) { | |
child._defRenderFn = WIDGET_RENDER_FN; | |
}); | |
//clean up all events on the queue | |
q.detachAll(); | |
}, | |
/** | |
* This is the same _uiAddChild method copied from Widget | |
* YUI v3.3.0 | |
* | |
* Modifications: | |
* Added check for nextSibling.get(RENDERED) and | |
* prevSibling.get(RENDERED) because with queued rendering | |
* a sibling may exist that is not yet rendered into the DOM. | |
* Return Y.Do.Prevent to prevent original method from executing | |
* | |
* Note: I will be filing a bug about this, as assuming the | |
* sibling is rendered is kinda reckless anyways. When that | |
* behavior changes in YUI core, this method can be removed | |
* | |
* @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. | |
*/ | |
_uiAddChild: function(child, parentNode) { | |
child.render(parentNode); | |
// TODO: Ideally this should be in Child's render UI. | |
var childBB = child.get(BOUNDING_BOX), | |
siblingBB, | |
nextSibling = child.next(false), | |
prevSibling; | |
// Insert or Append to last child. | |
// Avoiding index, and using the current sibling | |
// state (which should be accurate), means we don't have | |
// to worry about decorator elements which may be added | |
// to the _childContainer node. | |
if (nextSibling && nextSibling.get(RENDERED)) { | |
siblingBB = nextSibling.get(BOUNDING_BOX); | |
siblingBB.insert(childBB, "before"); | |
} else { | |
prevSibling = child.previous(false); | |
if (prevSibling && prevSibling.get(RENDERED)) { | |
siblingBB = prevSibling.get(BOUNDING_BOX); | |
siblingBB.insert(childBB, "after"); | |
} | |
} | |
return new Y.Do.Prevent(); | |
}, | |
/** | |
* Resets the childs render event defaultFn | |
* | |
* @method _onAddChild | |
* @see _onChildRender | |
* @private | |
* @param event {EventFacade} The Event object | |
*/ | |
_onAddChild: function(event) { | |
var child = event.child; | |
/** | |
* Reassign the _defRenderFn to the plugin renderFn | |
* Because a plugin could be added at any point in | |
* an objects lifecycle, doing a reassignment instead | |
* of using an event listener or AOP is the most reliable. | |
* We dont have to worry about any other listeners that | |
* may have been already added or where the new listener | |
* would be in the event bubble chain. We also wont be | |
* creating a new event for every child | |
*/ | |
child._defRenderFn = this._childRender; | |
}, | |
/** | |
* This is the new default handler for child render events | |
* It adds the old default child renderFn (_defRenderFn) | |
* to the plugin render queue. | |
* | |
* @method _childRender | |
* @private | |
* @param event {EventFacade} The Event object | |
*/ | |
_childRender: function(event) { | |
var child = event.target, | |
q = child.get(PARENT)[NAME]._queue, | |
// get the defaultFn so we can add it to the queue | |
fn = WIDGET_RENDER_FN, | |
// arguments we want to pass on to the default fn | |
args = event.details; | |
// add the default fn to our render queue | |
q.add({ | |
fn: fn, | |
args: args, | |
context: child | |
}); | |
q.run(); | |
} | |
}); | |
Y.namespace('SM.Plugin').WidgetParentRenderQueue = RenderQueue; | |
}, '110122183848' ,{'requires': ['plugin', 'async-queue']}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment