--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/widget-base/widget-base.js Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,1281 @@
+/*
+YUI 3.10.3 (build 2fb5187)
+Copyright 2013 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+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 = "<div></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:
+ * <ul>
+ * <li>The render lifecycle method, in addition to the init and destroy
+ * lifecycle methods provide by Base</li>
+ * <li>Abstract methods to support consistent MVC structure across
+ * widgets: renderer, renderUI, bindUI, syncUI</li>
+ * <li>Support for common widget attributes, such as boundingBox, contentBox, visible,
+ * disabled, focused, strings</li>
+ * </ul>
+ *
+ * @param config {Object} Object literal specifying widget configuration properties.
+ *
+ * @class Widget
+ * @constructor
+ * @extends Base
+ */
+function Widget(config) {
+
+ // kweight
+ var widget = this,
+ parentNode,
+ render,
+ constructor = widget.constructor;
+
+ widget._strs = {};
+ widget._cssPrefix = constructor.CSS_PREFIX || _getClassName(constructor.NAME.toLowerCase());
+
+ // We need a config for HTML_PARSER to work.
+ config = config || {};
+
+ Widget.superclass.constructor.call(widget, config);
+
+ render = widget.get(RENDER);
+
+ if (render) {
+ // Render could be a node or boolean
+ if (render !== TRUE) {
+ parentNode = render;
+ }
+ widget.render(parentNode);
+ }
+}
+
+/**
+ * Static property provides a string to identify the class.
+ * <p>
+ * Currently used to apply class identifiers to the bounding box
+ * and to classify events fired by the widget.
+ * </p>
+ *
+ * @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] = {
+ value:null,
+ 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 the <code>Y.config.classNamePrefix</code> attribute used by <code>ClassNameManager</code> and
+ * <code>Widget.NAME.toLowerCase()</code> (e.g. "yui-widget-xxxxx-yyyyy", based on default values for
+ * the prefix and widget class name).
+ * <p>
+ * 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.
+ * </p>
+ * @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.
+ * <p>
+ * In the case of nested widgets, the nearest bounding box ancestor is used to
+ * return the widget instance.
+ * </p>
+ * @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
+ * <code>YUI.config.classNamePrefix</code> attribute + the instances <code>NAME</code> property.
+ * Uses <code>YUI.config.classNameDelimiter</code> attribute to delimit the provided strings.
+ * e.g.
+ * <code>
+ * <pre>
+ * // 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');
+ * </pre>
+ * </code>
+ *
+ * @method getClassName
+ * @param {String}+ 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) {
+
+ 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
+ */
+
+ if (this._applyParser) {
+ this._applyParser(config);
+ }
+ },
+
+ /**
+ * 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() {
+
+ 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();
+ }
+ },
+
+ /**
+ * <p>
+ * Destroy lifecycle method. Fires the destroy
+ * event, prior to invoking destructors for the
+ * class hierarchy.
+ *
+ * Overrides Base's implementation, to support arguments to destroy
+ * </p>
+ * <p>
+ * Subscribers to the destroy
+ * event can invoke preventDefault on the event object, to prevent destruction
+ * from proceeding.
+ * </p>
+ * @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).
+ * <p>
+ * This method should only be invoked once for an initialized
+ * widget.
+ * </p>
+ * <p>
+ * It delegates to the widget specific renderer method to do
+ * the actual work.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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.
+ * </p>
+ */
+ render: function(parentNode) {
+
+ 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).
+ * <p>
+ * Subscribers to the "on" moment of this event, will be notified
+ * before the widget is rendered.
+ * </p>
+ * <p>
+ * Subscribers to the "after" moment of this event, will be notified
+ * after rendering is complete.
+ * </p>
+ *
+ * @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 the <code>render</code> 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
+ * @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 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} 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;
+
+
+}, '3.10.3', {
+ "requires": [
+ "attribute",
+ "base-base",
+ "base-pluginhost",
+ "classnamemanager",
+ "event-focus",
+ "node-base",
+ "node-style"
+ ],
+ "skinnable": true
+});