diff -r d334a616c023 -r e16a97fb364a src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-base/widget-base-debug.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-base/widget-base-debug.js Mon Mar 10 15:19:48 2014 +0100 @@ -0,0 +1,1293 @@ +YUI.add('widget-base', function (Y, NAME) { + +/** + * Provides the base Widget class, with HTML Parser support + * + * @module widget + * @main widget + */ + +/** + * Provides the base Widget class + * + * @module widget + * @submodule widget-base + */ +var L = Y.Lang, + Node = Y.Node, + + ClassNameManager = Y.ClassNameManager, + + _getClassName = ClassNameManager.getClassName, + _getWidgetClassName, + + _toInitialCap = Y.cached(function(str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + }), + + // K-Weight, IE GC optimizations + CONTENT = "content", + VISIBLE = "visible", + HIDDEN = "hidden", + DISABLED = "disabled", + FOCUSED = "focused", + WIDTH = "width", + HEIGHT = "height", + BOUNDING_BOX = "boundingBox", + CONTENT_BOX = "contentBox", + PARENT_NODE = "parentNode", + OWNER_DOCUMENT = "ownerDocument", + AUTO = "auto", + SRC_NODE = "srcNode", + BODY = "body", + TAB_INDEX = "tabIndex", + ID = "id", + RENDER = "render", + RENDERED = "rendered", + DESTROYED = "destroyed", + STRINGS = "strings", + DIV = "
", + CHANGE = "Change", + LOADING = "loading", + + _UISET = "_uiSet", + + EMPTY_STR = "", + EMPTY_FN = function() {}, + + TRUE = true, + FALSE = false, + + UI, + ATTRS = {}, + UI_ATTRS = [VISIBLE, DISABLED, HEIGHT, WIDTH, FOCUSED, TAB_INDEX], + + WEBKIT = Y.UA.webkit, + + // Widget nodeid-to-instance map. + _instances = {}; + +/** + * A base class for widgets, providing: + *+ * Currently used to apply class identifiers to the bounding box + * and to classify events fired by the widget. + *
+ * + * @property NAME + * @type String + * @static + */ +Widget.NAME = "widget"; + +/** + * Constant used to identify state changes originating from + * the DOM (as opposed to the JavaScript model). + * + * @property UI_SRC + * @type String + * @static + * @final + */ +UI = Widget.UI_SRC = "ui"; + +/** + * Static property used to define the default attribute + * configuration for the Widget. + * + * @property ATTRS + * @type Object + * @static + */ +Widget.ATTRS = ATTRS; + +// Trying to optimize kweight by setting up attrs this way saves about 0.4K min'd + +/** + * @attribute id + * @writeOnce + * @default Generated using guid() + * @type String + */ + +ATTRS[ID] = { + valueFn: "_guid", + writeOnce: TRUE +}; + +/** + * Flag indicating whether or not this Widget + * has been through the render lifecycle phase. + * + * @attribute rendered + * @readOnly + * @default false + * @type boolean + */ +ATTRS[RENDERED] = { + value:FALSE, + readOnly: TRUE +}; + +/** + * @attribute boundingBox + * @description The outermost DOM node for the Widget, used for sizing and positioning + * of a Widget as well as a containing element for any decorator elements used + * for skinning. + * @type String | Node + * @writeOnce + */ +ATTRS[BOUNDING_BOX] = { + valueFn:"_defaultBB", + setter: "_setBB", + writeOnce: TRUE +}; + +/** + * @attribute contentBox + * @description A DOM node that is a direct descendant of a Widget's bounding box that + * houses its content. + * @type String | Node + * @writeOnce + */ +ATTRS[CONTENT_BOX] = { + valueFn:"_defaultCB", + setter: "_setCB", + writeOnce: TRUE +}; + +/** + * @attribute tabIndex + * @description Number (between -32767 to 32767) indicating the widget's + * position in the default tab flow. The value is used to set the + * "tabIndex" attribute on the widget's bounding box. Negative values allow + * the widget to receive DOM focus programmatically (by calling the focus + * method), while being removed from the default tab flow. A value of + * null removes the "tabIndex" attribute from the widget's bounding box. + * @type Number + * @default null + */ +ATTRS[TAB_INDEX] = { + value: null, + validator: "_validTabIndex" +}; + +/** + * @attribute focused + * @description Boolean indicating if the Widget, or one of its descendants, + * has focus. + * @readOnly + * @default false + * @type boolean + */ +ATTRS[FOCUSED] = { + value: FALSE, + readOnly:TRUE +}; + +/** + * @attribute disabled + * @description Boolean indicating if the Widget should be disabled. The disabled implementation + * is left to the specific classes extending widget. + * @default false + * @type boolean + */ +ATTRS[DISABLED] = { + value: FALSE +}; + +/** + * @attribute visible + * @description Boolean indicating whether or not the Widget is visible. + * @default TRUE + * @type boolean + */ +ATTRS[VISIBLE] = { + value: TRUE +}; + +/** + * @attribute height + * @description String with units, or number, representing the height of the Widget. If a number is provided, + * the default unit, defined by the Widgets DEF_UNIT, property is used. + * @default EMPTY_STR + * @type {String | Number} + */ +ATTRS[HEIGHT] = { + value: EMPTY_STR +}; + +/** + * @attribute width + * @description String with units, or number, representing the width of the Widget. If a number is provided, + * the default unit, defined by the Widgets DEF_UNIT, property is used. + * @default EMPTY_STR + * @type {String | Number} + */ +ATTRS[WIDTH] = { + value: EMPTY_STR +}; + +/** + * @attribute strings + * @description Collection of strings used to label elements of the Widget's UI. + * @default null + * @type Object + */ +ATTRS[STRINGS] = { + value: {}, + setter: "_strSetter", + getter: "_strGetter" +}; + +/** + * Whether or not to render the widget automatically after init, and optionally, to which parent node. + * + * @attribute render + * @type boolean | Node + * @writeOnce + */ +ATTRS[RENDER] = { + value:FALSE, + writeOnce:TRUE +}; + +/** + * The css prefix which the static Widget.getClassName method should use when constructing class names + * + * @property CSS_PREFIX + * @type String + * @default Widget.NAME.toLowerCase() + * @private + * @static + */ +Widget.CSS_PREFIX = _getClassName(Widget.NAME.toLowerCase()); + +/** + * Generate a standard prefixed classname for the Widget, prefixed by the default prefix defined + * by theY.config.classNamePrefix attribute used by ClassNameManager and
+ * Widget.NAME.toLowerCase() (e.g. "yui-widget-xxxxx-yyyyy", based on default values for
+ * the prefix and widget class name).
+ * + * The instance based version of this method can be used to generate standard prefixed classnames, + * based on the instances NAME, as opposed to Widget.NAME. This method should be used when you + * need to use a constant class name across different types instances. + *
+ * @method getClassName + * @param {String*} args* 0..n strings which should be concatenated, using the default separator defined by ClassNameManager, to create the class name + */ +Widget.getClassName = function() { + // arguments needs to be array'fied to concat + return _getClassName.apply(ClassNameManager, [Widget.CSS_PREFIX].concat(Y.Array(arguments), true)); +}; + +_getWidgetClassName = Widget.getClassName; + +/** + * Returns the widget instance whose bounding box contains, or is, the given node. + *+ * In the case of nested widgets, the nearest bounding box ancestor is used to + * return the widget instance. + *
+ * @method getByNode + * @static + * @param node {Node | String} The node for which to return a Widget instance. If a selector + * string is passed in, which selects more than one node, the first node found is used. + * @return {Widget} Widget instance, or null if not found. + */ +Widget.getByNode = function(node) { + var widget, + widgetMarker = _getWidgetClassName(); + + node = Node.one(node); + if (node) { + node = node.ancestor("." + widgetMarker, true); + if (node) { + widget = _instances[Y.stamp(node, true)]; + } + } + + return widget || null; +}; + +Y.extend(Widget, Y.Base, { + + /** + * Returns a class name prefixed with the the value of the + *YUI.config.classNamePrefix attribute + the instances NAME property.
+ * Uses YUI.config.classNameDelimiter attribute to delimit the provided strings.
+ * e.g.
+ *
+ *
+ * // returns "yui-slider-foo-bar", for a slider instance
+ * var scn = slider.getClassName('foo','bar');
+ *
+ * // returns "yui-overlay-foo-bar", for an overlay instance
+ * var ocn = overlay.getClassName('foo','bar');
+ *
+ *
+ *
+ * @method getClassName
+ * @param {String} [classnames*] One or more classname bits to be joined and prefixed
+ */
+ getClassName: function () {
+ return _getClassName.apply(ClassNameManager, [this._cssPrefix].concat(Y.Array(arguments), true));
+ },
+
+ /**
+ * Initializer lifecycle implementation for the Widget class. Registers the
+ * widget instance, and runs through the Widget's HTML_PARSER definition.
+ *
+ * @method initializer
+ * @protected
+ * @param config {Object} Configuration object literal for the widget
+ */
+ initializer: function(config) {
+ Y.log('initializer called', 'life', 'widget');
+
+ var bb = this.get(BOUNDING_BOX);
+
+ if (bb instanceof Node) {
+ this._mapInstance(Y.stamp(bb));
+ }
+
+ /**
+ * Notification event, which widget implementations can fire, when
+ * they change the content of the widget. This event has no default
+ * behavior and cannot be prevented, so the "on" or "after"
+ * moments are effectively equivalent (with on listeners being invoked before
+ * after listeners).
+ *
+ * @event widget:contentUpdate
+ * @preventable false
+ * @param {EventFacade} e The Event Facade
+ */
+ },
+
+ /**
+ * Utility method used to add an entry to the boundingBox id to instance map.
+ *
+ * This method can be used to populate the instance with lazily created boundingBox Node references.
+ *
+ * @method _mapInstance
+ * @param {String} The boundingBox id
+ * @protected
+ */
+ _mapInstance : function(id) {
+ _instances[id] = this;
+ },
+
+ /**
+ * Destructor lifecycle implementation for the Widget class. Purges events attached
+ * to the bounding box and content box, removes them from the DOM and removes
+ * the Widget from the list of registered widgets.
+ *
+ * @method destructor
+ * @protected
+ */
+ destructor: function() {
+ Y.log('destructor called', 'life', 'widget');
+
+ var boundingBox = this.get(BOUNDING_BOX),
+ bbGuid;
+
+ if (boundingBox instanceof Node) {
+ bbGuid = Y.stamp(boundingBox,true);
+
+ if (bbGuid in _instances) {
+ delete _instances[bbGuid];
+ }
+
+ this._destroyBox();
+ }
+ },
+
+ /**
+ * + * Destroy lifecycle method. Fires the destroy + * event, prior to invoking destructors for the + * class hierarchy. + * + * Overrides Base's implementation, to support arguments to destroy + *
+ *+ * Subscribers to the destroy + * event can invoke preventDefault on the event object, to prevent destruction + * from proceeding. + *
+ * @method destroy + * @param destroyAllNodes {Boolean} If true, all nodes contained within the Widget are + * removed and destroyed. Defaults to false due to potentially high run-time cost. + * @return {Widget} A reference to this object + * @chainable + */ + destroy: function(destroyAllNodes) { + this._destroyAllNodes = destroyAllNodes; + return Widget.superclass.destroy.apply(this); + }, + + /** + * Removes and destroys the widgets rendered boundingBox, contentBox, + * and detaches bound UI events. + * + * @method _destroyBox + * @protected + */ + _destroyBox : function() { + + var boundingBox = this.get(BOUNDING_BOX), + contentBox = this.get(CONTENT_BOX), + deep = this._destroyAllNodes, + same; + + same = boundingBox && boundingBox.compareTo(contentBox); + + if (this.UI_EVENTS) { + this._destroyUIEvents(); + } + + this._unbindUI(boundingBox); + + if (contentBox) { + if (deep) { + contentBox.empty(); + } + contentBox.remove(TRUE); + } + + if (!same) { + if (deep) { + boundingBox.empty(); + } + boundingBox.remove(TRUE); + } + }, + + /** + * Establishes the initial DOM for the widget. Invoking this + * method will lead to the creating of all DOM elements for + * the widget (or the manipulation of existing DOM elements + * for the progressive enhancement use case). + *+ * This method should only be invoked once for an initialized + * widget. + *
+ *+ * It delegates to the widget specific renderer method to do + * the actual work. + *
+ * + * @method render + * @chainable + * @final + * @param parentNode {Object | String} Optional. The Node under which the + * Widget is to be rendered. This can be a Node instance or a CSS selector string. + *+ * If the selector string returns more than one Node, the first node will be used + * as the parentNode. NOTE: This argument is required if both the boundingBox and contentBox + * are not currently in the document. If it's not provided, the Widget will be rendered + * to the body of the current document in this case. + *
+ */ + render: function(parentNode) { + if (this.get(DESTROYED)) { Y.log("Render failed; widget has been destroyed", "error", "widget"); } + + if (!this.get(DESTROYED) && !this.get(RENDERED)) { + /** + * Lifecycle event for the render phase, fired prior to rendering the UI + * for the widget (prior to invoking the widget's renderer method). + *+ * Subscribers to the "on" moment of this event, will be notified + * before the widget is rendered. + *
+ *+ * Subscribers to the "after" moment of this event, will be notified + * after rendering is complete. + *
+ * + * @event render + * @preventable _defRenderFn + * @param {EventFacade} e The Event Facade + */ + this.publish(RENDER, { + queuable:FALSE, + fireOnce:TRUE, + defaultTargetOnly:TRUE, + defaultFn: this._defRenderFn + }); + + this.fire(RENDER, {parentNode: (parentNode) ? Node.one(parentNode) : null}); + } + return this; + }, + + /** + * Default render handler + * + * @method _defRenderFn + * @protected + * @param {EventFacade} e The Event object + * @param {Node} parentNode The parent node to render to, if passed in to therender method
+ */
+ _defRenderFn : function(e) {
+ this._parentNode = e.parentNode;
+
+ this.renderer();
+ this._set(RENDERED, TRUE);
+
+ this._removeLoadingClassNames();
+ },
+
+ /**
+ * Creates DOM (or manipulates DOM for progressive enhancement)
+ * This method is invoked by render() and is not chained
+ * automatically for the class hierarchy (unlike initializer, destructor)
+ * so it should be chained manually for subclasses if required.
+ *
+ * @method renderer
+ * @protected
+ */
+ renderer: function() {
+ // kweight
+ var widget = this;
+
+ widget._renderUI();
+ widget.renderUI();
+
+ widget._bindUI();
+ widget.bindUI();
+
+ widget._syncUI();
+ widget.syncUI();
+ },
+
+ /**
+ * Configures/Sets up listeners to bind Widget State to UI/DOM
+ *
+ * This method is not called by framework and is not chained
+ * automatically for the class hierarchy.
+ *
+ * @method bindUI
+ * @protected
+ */
+ bindUI: EMPTY_FN,
+
+ /**
+ * Adds nodes to the DOM
+ *
+ * This method is not called by framework and is not chained
+ * automatically for the class hierarchy.
+ *
+ * @method renderUI
+ * @protected
+ */
+ renderUI: EMPTY_FN,
+
+ /**
+ * Refreshes the rendered UI, based on Widget State
+ *
+ * This method is not called by framework and is not chained
+ * automatically for the class hierarchy.
+ *
+ * @method syncUI
+ * @protected
+ *
+ */
+ syncUI: EMPTY_FN,
+
+ /**
+ * @method hide
+ * @description Hides the Widget by setting the "visible" attribute to "false".
+ * @chainable
+ */
+ hide: function() {
+ return this.set(VISIBLE, FALSE);
+ },
+
+ /**
+ * @method show
+ * @description Shows the Widget by setting the "visible" attribute to "true".
+ * @chainable
+ */
+ show: function() {
+ return this.set(VISIBLE, TRUE);
+ },
+
+ /**
+ * @method focus
+ * @description Causes the Widget to receive the focus by setting the "focused"
+ * attribute to "true".
+ * @chainable
+ */
+ focus: function () {
+ return this._set(FOCUSED, TRUE);
+ },
+
+ /**
+ * @method blur
+ * @description Causes the Widget to lose focus by setting the "focused" attribute
+ * to "false"
+ * @chainable
+ */
+ blur: function () {
+ return this._set(FOCUSED, FALSE);
+ },
+
+ /**
+ * @method enable
+ * @description Set the Widget's "disabled" attribute to "false".
+ * @chainable
+ */
+ enable: function() {
+ return this.set(DISABLED, FALSE);
+ },
+
+ /**
+ * @method disable
+ * @description Set the Widget's "disabled" attribute to "true".
+ * @chainable
+ */
+ disable: function() {
+ return this.set(DISABLED, TRUE);
+ },
+
+ /**
+ * @method _uiSizeCB
+ * @protected
+ * @param {boolean} expand
+ */
+ _uiSizeCB : function(expand) {
+ this.get(CONTENT_BOX).toggleClass(_getWidgetClassName(CONTENT, "expanded"), expand);
+ },
+
+ /**
+ * Helper method to collect the boundingBox and contentBox and append to the provided parentNode, if not
+ * already a child. The owner document of the boundingBox, or the owner document of the contentBox will be used
+ * as the document into which the Widget is rendered if a parentNode is node is not provided. If both the boundingBox and
+ * the contentBox are not currently in the document, and no parentNode is provided, the widget will be rendered
+ * to the current document's body.
+ *
+ * @method _renderBox
+ * @private
+ * @param {Node} parentNode The parentNode to render the widget to. If not provided, and both the boundingBox and
+ * the contentBox are not currently in the document, the widget will be rendered to the current document's body.
+ */
+ _renderBox: function(parentNode) {
+
+ // TODO: Performance Optimization [ More effective algo to reduce Node refs, compares, replaces? ]
+
+ var widget = this, // kweight
+ contentBox = widget.get(CONTENT_BOX),
+ boundingBox = widget.get(BOUNDING_BOX),
+ srcNode = widget.get(SRC_NODE),
+ defParentNode = widget.DEF_PARENT_NODE,
+
+ doc = (srcNode && srcNode.get(OWNER_DOCUMENT)) || boundingBox.get(OWNER_DOCUMENT) || contentBox.get(OWNER_DOCUMENT);
+
+ // If srcNode (assume it's always in doc), have contentBox take its place (widget render responsible for re-use of srcNode contents)
+ if (srcNode && !srcNode.compareTo(contentBox) && !contentBox.inDoc(doc)) {
+ srcNode.replace(contentBox);
+ }
+
+ if (!boundingBox.compareTo(contentBox.get(PARENT_NODE)) && !boundingBox.compareTo(contentBox)) {
+ // If contentBox box is already in the document, have boundingBox box take it's place
+ if (contentBox.inDoc(doc)) {
+ contentBox.replace(boundingBox);
+ }
+ boundingBox.appendChild(contentBox);
+ }
+
+ parentNode = parentNode || (defParentNode && Node.one(defParentNode));
+
+ if (parentNode) {
+ parentNode.appendChild(boundingBox);
+ } else if (!boundingBox.inDoc(doc)) {
+ Node.one(BODY).insert(boundingBox, 0);
+ }
+ },
+
+ /**
+ * Setter for the boundingBox attribute
+ *
+ * @method _setBB
+ * @private
+ * @param {Node|String} node
+ * @return Node
+ */
+ _setBB: function(node) {
+ return this._setBox(this.get(ID), node, this.BOUNDING_TEMPLATE, true);
+ },
+
+ /**
+ * Setter for the contentBox attribute
+ *
+ * @method _setCB
+ * @private
+ * @param {Node|String} node
+ * @return Node
+ */
+ _setCB: function(node) {
+ return (this.CONTENT_TEMPLATE === null) ? this.get(BOUNDING_BOX) : this._setBox(null, node, this.CONTENT_TEMPLATE, false);
+ },
+
+ /**
+ * Returns the default value for the boundingBox attribute.
+ *
+ * For the Widget class, this will most commonly be null (resulting in a new
+ * boundingBox node instance being created), unless a srcNode was provided
+ * and CONTENT_TEMPLATE is null, in which case it will be srcNode.
+ * This behavior was introduced in @VERSION@ to accomodate single-box widgets
+ * whose BB & CB both point to srcNode (e.g. Y.Button).
+ *
+ * @method _defaultBB
+ * @protected
+ */
+ _defaultBB : function() {
+ var node = this.get(SRC_NODE),
+ nullCT = (this.CONTENT_TEMPLATE === null);
+
+ return ((node && nullCT) ? node : null);
+ },
+
+ /**
+ * Returns the default value for the contentBox attribute.
+ *
+ * For the Widget class, this will be the srcNode if provided, otherwise null (resulting in
+ * a new contentBox node instance being created)
+ *
+ * @method _defaultCB
+ * @protected
+ */
+ _defaultCB : function(node) {
+ return this.get(SRC_NODE) || null;
+ },
+
+ /**
+ * Helper method to set the bounding/content box, or create it from
+ * the provided template if not found.
+ *
+ * @method _setBox
+ * @private
+ *
+ * @param {String} id The node's id attribute
+ * @param {Node|String} node The node reference
+ * @param {String} template HTML string template for the node
+ * @param {boolean} isBounding true if this is the boundingBox, false if it's the contentBox
+ * @return {Node} The node
+ */
+ _setBox : function(id, node, template, isBounding) {
+
+ node = Node.one(node);
+
+ if (!node) {
+ node = Node.create(template);
+
+ if (isBounding) {
+ this._bbFromTemplate = true;
+ } else {
+ this._cbFromTemplate = true;
+ }
+ }
+
+ if (!node.get(ID)) {
+ node.set(ID, id || Y.guid());
+ }
+
+ return node;
+ },
+
+ /**
+ * Initializes the UI state for the Widget's bounding/content boxes.
+ *
+ * @method _renderUI
+ * @protected
+ */
+ _renderUI: function() {
+ this._renderBoxClassNames();
+ this._renderBox(this._parentNode);
+ },
+
+ /**
+ * Applies standard class names to the boundingBox and contentBox
+ *
+ * @method _renderBoxClassNames
+ * @protected
+ */
+ _renderBoxClassNames : function() {
+ var classes = this._getClasses(),
+ cl,
+ boundingBox = this.get(BOUNDING_BOX),
+ i;
+
+ boundingBox.addClass(_getWidgetClassName());
+
+ // Start from Widget Sub Class
+ for (i = classes.length-3; i >= 0; i--) {
+ cl = classes[i];
+ boundingBox.addClass(cl.CSS_PREFIX || _getClassName(cl.NAME.toLowerCase()));
+ }
+
+ // Use instance based name for content box
+ this.get(CONTENT_BOX).addClass(this.getClassName(CONTENT));
+ },
+
+ /**
+ * Removes class names representative of the widget's loading state from
+ * the boundingBox.
+ *
+ * @method _removeLoadingClassNames
+ * @protected
+ */
+ _removeLoadingClassNames: function () {
+
+ var boundingBox = this.get(BOUNDING_BOX),
+ contentBox = this.get(CONTENT_BOX),
+ instClass = this.getClassName(LOADING),
+ widgetClass = _getWidgetClassName(LOADING);
+
+ boundingBox.removeClass(widgetClass)
+ .removeClass(instClass);
+
+ contentBox.removeClass(widgetClass)
+ .removeClass(instClass);
+ },
+
+ /**
+ * Sets up DOM and CustomEvent listeners for the widget.
+ *
+ * @method _bindUI
+ * @protected
+ */
+ _bindUI: function() {
+ this._bindAttrUI(this._UI_ATTRS.BIND);
+ this._bindDOM();
+ },
+
+ /**
+ * @method _unbindUI
+ * @protected
+ */
+ _unbindUI : function(boundingBox) {
+ this._unbindDOM(boundingBox);
+ },
+
+ /**
+ * Sets up DOM listeners, on elements rendered by the widget.
+ *
+ * @method _bindDOM
+ * @protected
+ */
+ _bindDOM : function() {
+ var oDocument = this.get(BOUNDING_BOX).get(OWNER_DOCUMENT),
+ focusHandle = Widget._hDocFocus;
+
+ // Shared listener across all Widgets.
+ if (!focusHandle) {
+ focusHandle = Widget._hDocFocus = oDocument.on("focus", this._onDocFocus, this);
+ focusHandle.listeners = {
+ count: 0
+ };
+ }
+
+ focusHandle.listeners[Y.stamp(this, true)] = true;
+ focusHandle.listeners.count++;
+
+ // Fix for Webkit:
+ // Document doesn't receive focus in Webkit when the user mouses
+ // down on it, so the "focused" attribute won't get set to the
+ // correct value. Keeping this instance based for now, potential better performance.
+ // Otherwise we'll end up looking up widgets from the DOM on every mousedown.
+ if (WEBKIT){
+ this._hDocMouseDown = oDocument.on("mousedown", this._onDocMouseDown, this);
+ }
+ },
+
+ /**
+ * @method _unbindDOM
+ * @protected
+ */
+ _unbindDOM : function(boundingBox) {
+
+ var focusHandle = Widget._hDocFocus,
+ yuid = Y.stamp(this, true),
+ focusListeners,
+ mouseHandle = this._hDocMouseDown;
+
+ if (focusHandle) {
+
+ focusListeners = focusHandle.listeners;
+
+ if (focusListeners[yuid]) {
+ delete focusListeners[yuid];
+ focusListeners.count--;
+ }
+
+ if (focusListeners.count === 0) {
+ focusHandle.detach();
+ Widget._hDocFocus = null;
+ }
+ }
+
+ if (WEBKIT && mouseHandle) {
+ mouseHandle.detach();
+ }
+ },
+
+ /**
+ * Updates the widget UI to reflect the attribute state.
+ *
+ * @method _syncUI
+ * @protected
+ */
+ _syncUI: function() {
+ this._syncAttrUI(this._UI_ATTRS.SYNC);
+ },
+
+ /**
+ * Sets the height on the widget's bounding box element
+ *
+ * @method _uiSetHeight
+ * @protected
+ * @param {String | Number} val
+ */
+ _uiSetHeight: function(val) {
+ this._uiSetDim(HEIGHT, val);
+ this._uiSizeCB((val !== EMPTY_STR && val !== AUTO));
+ },
+
+ /**
+ * Sets the width on the widget's bounding box element
+ *
+ * @method _uiSetWidth
+ * @protected
+ * @param {String | Number} val
+ */
+ _uiSetWidth: function(val) {
+ this._uiSetDim(WIDTH, val);
+ },
+
+ /**
+ * @method _uiSetDim
+ * @private
+ * @param {String} dim The dimension - "width" or "height"
+ * @param {Number | String} val The value to set
+ */
+ _uiSetDim: function(dimension, val) {
+ this.get(BOUNDING_BOX).setStyle(dimension, L.isNumber(val) ? val + this.DEF_UNIT : val);
+ },
+
+ /**
+ * Sets the visible state for the UI
+ *
+ * @method _uiSetVisible
+ * @protected
+ * @param {boolean} val
+ */
+ _uiSetVisible: function(val) {
+ this.get(BOUNDING_BOX).toggleClass(this.getClassName(HIDDEN), !val);
+ },
+
+ /**
+ * Sets the disabled state for the UI
+ *
+ * @method _uiSetDisabled
+ * @protected
+ * @param {boolean} val
+ */
+ _uiSetDisabled: function(val) {
+ this.get(BOUNDING_BOX).toggleClass(this.getClassName(DISABLED), val);
+ },
+
+ /**
+ * Sets the focused state for the UI
+ *
+ * @method _uiSetFocused
+ * @protected
+ * @param {boolean} val
+ * @param {string} src String representing the source that triggered an update to
+ * the UI.
+ */
+ _uiSetFocused: function(val, src) {
+ var boundingBox = this.get(BOUNDING_BOX);
+ boundingBox.toggleClass(this.getClassName(FOCUSED), val);
+
+ if (src !== UI) {
+ if (val) {
+ boundingBox.focus();
+ } else {
+ boundingBox.blur();
+ }
+ }
+ },
+
+ /**
+ * Set the tabIndex on the widget's rendered UI
+ *
+ * @method _uiSetTabIndex
+ * @protected
+ * @param Number
+ */
+ _uiSetTabIndex: function(index) {
+ var boundingBox = this.get(BOUNDING_BOX);
+
+ if (L.isNumber(index)) {
+ boundingBox.set(TAB_INDEX, index);
+ } else {
+ boundingBox.removeAttribute(TAB_INDEX);
+ }
+ },
+
+ /**
+ * @method _onDocMouseDown
+ * @description "mousedown" event handler for the owner document of the
+ * widget's bounding box.
+ * @protected
+ * @param {EventFacade} evt The event facade for the DOM focus event
+ */
+ _onDocMouseDown: function (evt) {
+ if (this._domFocus) {
+ this._onDocFocus(evt);
+ }
+ },
+
+ /**
+ * DOM focus event handler, used to sync the state of the Widget with the DOM
+ *
+ * @method _onDocFocus
+ * @protected
+ * @param {EventFacade} evt The event facade for the DOM focus event
+ */
+ _onDocFocus: function (evt) {
+ var widget = Widget.getByNode(evt.target),
+ activeWidget = Widget._active;
+
+ if (activeWidget && (activeWidget !== widget)) {
+ activeWidget._domFocus = false;
+ activeWidget._set(FOCUSED, false, {src:UI});
+
+ Widget._active = null;
+ }
+
+ if (widget) {
+ widget._domFocus = true;
+ widget._set(FOCUSED, true, {src:UI});
+
+ Widget._active = widget;
+ }
+ },
+
+ /**
+ * Generic toString implementation for all widgets.
+ *
+ * @method toString
+ * @return {String} The default string value for the widget [ displays the NAME of the instance, and the unique id ]
+ */
+ toString: function() {
+ // Using deprecated name prop for kweight squeeze.
+ return this.name + "[" + this.get(ID) + "]";
+ },
+
+ /**
+ * Default unit to use for dimension values
+ *
+ * @property DEF_UNIT
+ * @type String
+ */
+ DEF_UNIT : "px",
+
+ /**
+ * Default node to render the bounding box to. If not set,
+ * will default to the current document body.
+ *
+ * @property DEF_PARENT_NODE
+ * @type String | Node
+ */
+ DEF_PARENT_NODE : null,
+
+ /**
+ * Property defining the markup template for content box. If your Widget doesn't
+ * need the dual boundingBox/contentBox structure, set CONTENT_TEMPLATE to null,
+ * and contentBox and boundingBox will both point to the same Node.
+ *
+ * @property CONTENT_TEMPLATE
+ * @type String
+ */
+ CONTENT_TEMPLATE : DIV,
+
+ /**
+ * Property defining the markup template for bounding box.
+ *
+ * @property BOUNDING_TEMPLATE
+ * @type String
+ */
+ BOUNDING_TEMPLATE : DIV,
+
+ /**
+ * @method _guid
+ * @protected
+ */
+ _guid : function() {
+ return Y.guid();
+ },
+
+ /**
+ * @method _validTabIndex
+ * @protected
+ * @param {Number} tabIndex
+ */
+ _validTabIndex : function (tabIndex) {
+ return (L.isNumber(tabIndex) || L.isNull(tabIndex));
+ },
+
+ /**
+ * Binds after listeners for the list of attributes provided
+ *
+ * @method _bindAttrUI
+ * @private
+ * @param {Array} attrs
+ */
+ _bindAttrUI : function(attrs) {
+ var i,
+ l = attrs.length;
+
+ for (i = 0; i < l; i++) {
+ this.after(attrs[i] + CHANGE, this._setAttrUI);
+ }
+ },
+
+ /**
+ * Invokes the _uiSet=ATTR NAME> method for the list of attributes provided
+ *
+ * @method _syncAttrUI
+ * @private
+ * @param {Array} attrs
+ */
+ _syncAttrUI : function(attrs) {
+ var i, l = attrs.length, attr;
+ for (i = 0; i < l; i++) {
+ attr = attrs[i];
+ this[_UISET + _toInitialCap(attr)](this.get(attr));
+ }
+ },
+
+ /**
+ * @method _setAttrUI
+ * @private
+ * @param {EventFacade} e
+ */
+ _setAttrUI : function(e) {
+ if (e.target === this) {
+ this[_UISET + _toInitialCap(e.attrName)](e.newVal, e.src);
+ }
+ },
+
+ /**
+ * The default setter for the strings attribute. Merges partial sets
+ * into the full string set, to allow users to partial sets of strings
+ *
+ * @method _strSetter
+ * @protected
+ * @param {Object} strings
+ * @return {String} The full set of strings to set
+ */
+ _strSetter : function(strings) {
+ return Y.merge(this.get(STRINGS), strings);
+ },
+
+ /**
+ * Helper method to get a specific string value
+ *
+ * @deprecated Used by deprecated WidgetLocale implementations.
+ * @method getString
+ * @param {String} key
+ * @return {String} The string
+ */
+ getString : function(key) {
+ return this.get(STRINGS)[key];
+ },
+
+ /**
+ * Helper method to get the complete set of strings for the widget
+ *
+ * @deprecated Used by deprecated WidgetLocale implementations.
+ * @method getStrings
+ * @param {String} key
+ * @return {String} The strings
+ */
+ getStrings : function() {
+ return this.get(STRINGS);
+ },
+
+ /**
+ * The lists of UI attributes to bind and sync for widget's _bindUI and _syncUI implementations
+ *
+ * @property _UI_ATTRS
+ * @type Object
+ * @private
+ */
+ _UI_ATTRS : {
+ BIND: UI_ATTRS,
+ SYNC: UI_ATTRS
+ }
+});
+
+Y.Widget = Widget;
+
+
+}, '@VERSION@', {
+ "requires": [
+ "attribute",
+ "base-base",
+ "base-pluginhost",
+ "classnamemanager",
+ "event-focus",
+ "node-base",
+ "node-style"
+ ],
+ "skinnable": true
+});