2 YUI 3.12.0 (build 8655935)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('widget-base', function (Y, NAME) {
11 * Provides the base Widget class, with HTML Parser support
18 * Provides the base Widget class
21 * @submodule widget-base
26 ClassNameManager = Y.ClassNameManager,
28 _getClassName = ClassNameManager.getClassName,
31 _toInitialCap = Y.cached(function(str) {
32 return str.substring(0, 1).toUpperCase() + str.substring(1);
35 // K-Weight, IE GC optimizations
39 DISABLED = "disabled",
43 BOUNDING_BOX = "boundingBox",
44 CONTENT_BOX = "contentBox",
45 PARENT_NODE = "parentNode",
46 OWNER_DOCUMENT = "ownerDocument",
50 TAB_INDEX = "tabIndex",
53 RENDERED = "rendered",
54 DESTROYED = "destroyed",
63 EMPTY_FN = function() {},
70 UI_ATTRS = [VISIBLE, DISABLED, HEIGHT, WIDTH, FOCUSED, TAB_INDEX],
74 // Widget nodeid-to-instance map.
78 * A base class for widgets, providing:
80 * <li>The render lifecycle method, in addition to the init and destroy
81 * lifecycle methods provide by Base</li>
82 * <li>Abstract methods to support consistent MVC structure across
83 * widgets: renderer, renderUI, bindUI, syncUI</li>
84 * <li>Support for common widget attributes, such as boundingBox, contentBox, visible,
85 * disabled, focused, strings</li>
88 * @param config {Object} Object literal specifying widget configuration properties.
94 function Widget(config) {
95 Y.log('constructor called', 'life', 'widget');
101 constructor = widget.constructor;
104 widget._cssPrefix = constructor.CSS_PREFIX || _getClassName(constructor.NAME.toLowerCase());
106 // We need a config for HTML_PARSER to work.
107 config = config || {};
109 Widget.superclass.constructor.call(widget, config);
111 render = widget.get(RENDER);
114 // Render could be a node or boolean
115 if (render !== TRUE) {
118 widget.render(parentNode);
123 * Static property provides a string to identify the class.
125 * Currently used to apply class identifiers to the bounding box
126 * and to classify events fired by the widget.
133 Widget.NAME = "widget";
136 * Constant used to identify state changes originating from
137 * the DOM (as opposed to the JavaScript model).
144 UI = Widget.UI_SRC = "ui";
147 * Static property used to define the default attribute
148 * configuration for the Widget.
154 Widget.ATTRS = ATTRS;
156 // Trying to optimize kweight by setting up attrs this way saves about 0.4K min'd
161 * @default Generated using guid()
171 * Flag indicating whether or not this Widget
172 * has been through the render lifecycle phase.
174 * @attribute rendered
185 * @attribute boundingBox
186 * @description The outermost DOM node for the Widget, used for sizing and positioning
187 * of a Widget as well as a containing element for any decorator elements used
189 * @type String | Node
192 ATTRS[BOUNDING_BOX] = {
199 * @attribute contentBox
200 * @description A DOM node that is a direct descendant of a Widget's bounding box that
201 * houses its content.
202 * @type String | Node
205 ATTRS[CONTENT_BOX] = {
206 valueFn:"_defaultCB",
212 * @attribute tabIndex
213 * @description Number (between -32767 to 32767) indicating the widget's
214 * position in the default tab flow. The value is used to set the
215 * "tabIndex" attribute on the widget's bounding box. Negative values allow
216 * the widget to receive DOM focus programmatically (by calling the focus
217 * method), while being removed from the default tab flow. A value of
218 * null removes the "tabIndex" attribute from the widget's bounding box.
224 validator: "_validTabIndex"
229 * @description Boolean indicating if the Widget, or one of its descendants,
241 * @attribute disabled
242 * @description Boolean indicating if the Widget should be disabled. The disabled implementation
243 * is left to the specific classes extending widget.
253 * @description Boolean indicating whether or not the Widget is visible.
263 * @description String with units, or number, representing the height of the Widget. If a number is provided,
264 * the default unit, defined by the Widgets DEF_UNIT, property is used.
266 * @type {String | Number}
274 * @description String with units, or number, representing the width of the Widget. If a number is provided,
275 * the default unit, defined by the Widgets DEF_UNIT, property is used.
277 * @type {String | Number}
285 * @description Collection of strings used to label elements of the Widget's UI.
291 setter: "_strSetter",
296 * Whether or not to render the widget automatically after init, and optionally, to which parent node.
299 * @type boolean | Node
308 * The css prefix which the static Widget.getClassName method should use when constructing class names
310 * @property CSS_PREFIX
312 * @default Widget.NAME.toLowerCase()
316 Widget.CSS_PREFIX = _getClassName(Widget.NAME.toLowerCase());
319 * Generate a standard prefixed classname for the Widget, prefixed by the default prefix defined
320 * by the <code>Y.config.classNamePrefix</code> attribute used by <code>ClassNameManager</code> and
321 * <code>Widget.NAME.toLowerCase()</code> (e.g. "yui-widget-xxxxx-yyyyy", based on default values for
322 * the prefix and widget class name).
324 * The instance based version of this method can be used to generate standard prefixed classnames,
325 * based on the instances NAME, as opposed to Widget.NAME. This method should be used when you
326 * need to use a constant class name across different types instances.
328 * @method getClassName
329 * @param {String*} args* 0..n strings which should be concatenated, using the default separator defined by ClassNameManager, to create the class name
331 Widget.getClassName = function() {
332 // arguments needs to be array'fied to concat
333 return _getClassName.apply(ClassNameManager, [Widget.CSS_PREFIX].concat(Y.Array(arguments), true));
336 _getWidgetClassName = Widget.getClassName;
339 * Returns the widget instance whose bounding box contains, or is, the given node.
341 * In the case of nested widgets, the nearest bounding box ancestor is used to
342 * return the widget instance.
346 * @param node {Node | String} The node for which to return a Widget instance. If a selector
347 * string is passed in, which selects more than one node, the first node found is used.
348 * @return {Widget} Widget instance, or null if not found.
350 Widget.getByNode = function(node) {
352 widgetMarker = _getWidgetClassName();
354 node = Node.one(node);
356 node = node.ancestor("." + widgetMarker, true);
358 widget = _instances[Y.stamp(node, true)];
362 return widget || null;
365 Y.extend(Widget, Y.Base, {
368 * Returns a class name prefixed with the the value of the
369 * <code>YUI.config.classNamePrefix</code> attribute + the instances <code>NAME</code> property.
370 * Uses <code>YUI.config.classNameDelimiter</code> attribute to delimit the provided strings.
374 * // returns "yui-slider-foo-bar", for a slider instance
375 * var scn = slider.getClassName('foo','bar');
377 * // returns "yui-overlay-foo-bar", for an overlay instance
378 * var ocn = overlay.getClassName('foo','bar');
382 * @method getClassName
383 * @param {String}+ One or more classname bits to be joined and prefixed
385 getClassName: function () {
386 return _getClassName.apply(ClassNameManager, [this._cssPrefix].concat(Y.Array(arguments), true));
390 * Initializer lifecycle implementation for the Widget class. Registers the
391 * widget instance, and runs through the Widget's HTML_PARSER definition.
393 * @method initializer
395 * @param config {Object} Configuration object literal for the widget
397 initializer: function(config) {
398 Y.log('initializer called', 'life', 'widget');
400 var bb = this.get(BOUNDING_BOX);
402 if (bb instanceof Node) {
403 this._mapInstance(Y.stamp(bb));
407 * Notification event, which widget implementations can fire, when
408 * they change the content of the widget. This event has no default
409 * behavior and cannot be prevented, so the "on" or "after"
410 * moments are effectively equivalent (with on listeners being invoked before
413 * @event widget:contentUpdate
415 * @param {EventFacade} e The Event Facade
420 * Utility method used to add an entry to the boundingBox id to instance map.
422 * This method can be used to populate the instance with lazily created boundingBox Node references.
424 * @method _mapInstance
425 * @param {String} The boundingBox id
428 _mapInstance : function(id) {
429 _instances[id] = this;
433 * Destructor lifecycle implementation for the Widget class. Purges events attached
434 * to the bounding box and content box, removes them from the DOM and removes
435 * the Widget from the list of registered widgets.
440 destructor: function() {
441 Y.log('destructor called', 'life', 'widget');
443 var boundingBox = this.get(BOUNDING_BOX),
446 if (boundingBox instanceof Node) {
447 bbGuid = Y.stamp(boundingBox,true);
449 if (bbGuid in _instances) {
450 delete _instances[bbGuid];
459 * Destroy lifecycle method. Fires the destroy
460 * event, prior to invoking destructors for the
463 * Overrides Base's implementation, to support arguments to destroy
466 * Subscribers to the destroy
467 * event can invoke preventDefault on the event object, to prevent destruction
471 * @param destroyAllNodes {Boolean} If true, all nodes contained within the Widget are
472 * removed and destroyed. Defaults to false due to potentially high run-time cost.
473 * @return {Widget} A reference to this object
476 destroy: function(destroyAllNodes) {
477 this._destroyAllNodes = destroyAllNodes;
478 return Widget.superclass.destroy.apply(this);
482 * Removes and destroys the widgets rendered boundingBox, contentBox,
483 * and detaches bound UI events.
485 * @method _destroyBox
488 _destroyBox : function() {
490 var boundingBox = this.get(BOUNDING_BOX),
491 contentBox = this.get(CONTENT_BOX),
492 deep = this._destroyAllNodes,
495 same = boundingBox && boundingBox.compareTo(contentBox);
497 if (this.UI_EVENTS) {
498 this._destroyUIEvents();
501 this._unbindUI(boundingBox);
507 contentBox.remove(TRUE);
514 boundingBox.remove(TRUE);
519 * Establishes the initial DOM for the widget. Invoking this
520 * method will lead to the creating of all DOM elements for
521 * the widget (or the manipulation of existing DOM elements
522 * for the progressive enhancement use case).
524 * This method should only be invoked once for an initialized
528 * It delegates to the widget specific renderer method to do
535 * @param parentNode {Object | String} Optional. The Node under which the
536 * Widget is to be rendered. This can be a Node instance or a CSS selector string.
538 * If the selector string returns more than one Node, the first node will be used
539 * as the parentNode. NOTE: This argument is required if both the boundingBox and contentBox
540 * are not currently in the document. If it's not provided, the Widget will be rendered
541 * to the body of the current document in this case.
544 render: function(parentNode) {
545 if (this.get(DESTROYED)) { Y.log("Render failed; widget has been destroyed", "error", "widget"); }
547 if (!this.get(DESTROYED) && !this.get(RENDERED)) {
549 * Lifecycle event for the render phase, fired prior to rendering the UI
550 * for the widget (prior to invoking the widget's renderer method).
552 * Subscribers to the "on" moment of this event, will be notified
553 * before the widget is rendered.
556 * Subscribers to the "after" moment of this event, will be notified
557 * after rendering is complete.
561 * @preventable _defRenderFn
562 * @param {EventFacade} e The Event Facade
564 this.publish(RENDER, {
567 defaultTargetOnly:TRUE,
568 defaultFn: this._defRenderFn
571 this.fire(RENDER, {parentNode: (parentNode) ? Node.one(parentNode) : null});
577 * Default render handler
579 * @method _defRenderFn
581 * @param {EventFacade} e The Event object
582 * @param {Node} parentNode The parent node to render to, if passed in to the <code>render</code> method
584 _defRenderFn : function(e) {
585 this._parentNode = e.parentNode;
588 this._set(RENDERED, TRUE);
590 this._removeLoadingClassNames();
594 * Creates DOM (or manipulates DOM for progressive enhancement)
595 * This method is invoked by render() and is not chained
596 * automatically for the class hierarchy (unlike initializer, destructor)
597 * so it should be chained manually for subclasses if required.
602 renderer: function() {
617 * Configures/Sets up listeners to bind Widget State to UI/DOM
619 * This method is not called by framework and is not chained
620 * automatically for the class hierarchy.
628 * Adds nodes to the DOM
630 * This method is not called by framework and is not chained
631 * automatically for the class hierarchy.
639 * Refreshes the rendered UI, based on Widget State
641 * This method is not called by framework and is not chained
642 * automatically for the class hierarchy.
652 * @description Hides the Widget by setting the "visible" attribute to "false".
656 return this.set(VISIBLE, FALSE);
661 * @description Shows the Widget by setting the "visible" attribute to "true".
665 return this.set(VISIBLE, TRUE);
670 * @description Causes the Widget to receive the focus by setting the "focused"
671 * attribute to "true".
675 return this._set(FOCUSED, TRUE);
680 * @description Causes the Widget to lose focus by setting the "focused" attribute
685 return this._set(FOCUSED, FALSE);
690 * @description Set the Widget's "disabled" attribute to "false".
694 return this.set(DISABLED, FALSE);
699 * @description Set the Widget's "disabled" attribute to "true".
702 disable: function() {
703 return this.set(DISABLED, TRUE);
709 * @param {boolean} expand
711 _uiSizeCB : function(expand) {
712 this.get(CONTENT_BOX).toggleClass(_getWidgetClassName(CONTENT, "expanded"), expand);
716 * Helper method to collect the boundingBox and contentBox and append to the provided parentNode, if not
717 * already a child. The owner document of the boundingBox, or the owner document of the contentBox will be used
718 * as the document into which the Widget is rendered if a parentNode is node is not provided. If both the boundingBox and
719 * the contentBox are not currently in the document, and no parentNode is provided, the widget will be rendered
720 * to the current document's body.
724 * @param {Node} parentNode The parentNode to render the widget to. If not provided, and both the boundingBox and
725 * the contentBox are not currently in the document, the widget will be rendered to the current document's body.
727 _renderBox: function(parentNode) {
729 // TODO: Performance Optimization [ More effective algo to reduce Node refs, compares, replaces? ]
731 var widget = this, // kweight
732 contentBox = widget.get(CONTENT_BOX),
733 boundingBox = widget.get(BOUNDING_BOX),
734 srcNode = widget.get(SRC_NODE),
735 defParentNode = widget.DEF_PARENT_NODE,
737 doc = (srcNode && srcNode.get(OWNER_DOCUMENT)) || boundingBox.get(OWNER_DOCUMENT) || contentBox.get(OWNER_DOCUMENT);
739 // If srcNode (assume it's always in doc), have contentBox take its place (widget render responsible for re-use of srcNode contents)
740 if (srcNode && !srcNode.compareTo(contentBox) && !contentBox.inDoc(doc)) {
741 srcNode.replace(contentBox);
744 if (!boundingBox.compareTo(contentBox.get(PARENT_NODE)) && !boundingBox.compareTo(contentBox)) {
745 // If contentBox box is already in the document, have boundingBox box take it's place
746 if (contentBox.inDoc(doc)) {
747 contentBox.replace(boundingBox);
749 boundingBox.appendChild(contentBox);
752 parentNode = parentNode || (defParentNode && Node.one(defParentNode));
755 parentNode.appendChild(boundingBox);
756 } else if (!boundingBox.inDoc(doc)) {
757 Node.one(BODY).insert(boundingBox, 0);
762 * Setter for the boundingBox attribute
769 _setBB: function(node) {
770 return this._setBox(this.get(ID), node, this.BOUNDING_TEMPLATE, true);
774 * Setter for the contentBox attribute
778 * @param {Node|String} node
781 _setCB: function(node) {
782 return (this.CONTENT_TEMPLATE === null) ? this.get(BOUNDING_BOX) : this._setBox(null, node, this.CONTENT_TEMPLATE, false);
786 * Returns the default value for the contentBox attribute.
788 * For the Widget class, this will be the srcNode if provided, otherwise null (resulting in
789 * a new contentBox node instance being created)
794 _defaultCB : function(node) {
795 return this.get(SRC_NODE) || null;
799 * Helper method to set the bounding/content box, or create it from
800 * the provided template if not found.
805 * @param {String} id The node's id attribute
806 * @param {Node|String} node The node reference
807 * @param {String} template HTML string template for the node
808 * @param {boolean} true if this is the boundingBox, false if it's the contentBox
809 * @return {Node} The node
811 _setBox : function(id, node, template, isBounding) {
813 node = Node.one(node);
816 node = Node.create(template);
819 this._bbFromTemplate = true;
821 this._cbFromTemplate = true;
826 node.set(ID, id || Y.guid());
833 * Initializes the UI state for the Widget's bounding/content boxes.
838 _renderUI: function() {
839 this._renderBoxClassNames();
840 this._renderBox(this._parentNode);
844 * Applies standard class names to the boundingBox and contentBox
846 * @method _renderBoxClassNames
849 _renderBoxClassNames : function() {
850 var classes = this._getClasses(),
852 boundingBox = this.get(BOUNDING_BOX),
855 boundingBox.addClass(_getWidgetClassName());
857 // Start from Widget Sub Class
858 for (i = classes.length-3; i >= 0; i--) {
860 boundingBox.addClass(cl.CSS_PREFIX || _getClassName(cl.NAME.toLowerCase()));
863 // Use instance based name for content box
864 this.get(CONTENT_BOX).addClass(this.getClassName(CONTENT));
868 * Removes class names representative of the widget's loading state from
871 * @method _removeLoadingClassNames
874 _removeLoadingClassNames: function () {
876 var boundingBox = this.get(BOUNDING_BOX),
877 contentBox = this.get(CONTENT_BOX),
878 instClass = this.getClassName(LOADING),
879 widgetClass = _getWidgetClassName(LOADING);
881 boundingBox.removeClass(widgetClass)
882 .removeClass(instClass);
884 contentBox.removeClass(widgetClass)
885 .removeClass(instClass);
889 * Sets up DOM and CustomEvent listeners for the widget.
894 _bindUI: function() {
895 this._bindAttrUI(this._UI_ATTRS.BIND);
903 _unbindUI : function(boundingBox) {
904 this._unbindDOM(boundingBox);
908 * Sets up DOM listeners, on elements rendered by the widget.
913 _bindDOM : function() {
914 var oDocument = this.get(BOUNDING_BOX).get(OWNER_DOCUMENT),
915 focusHandle = Widget._hDocFocus;
917 // Shared listener across all Widgets.
919 focusHandle = Widget._hDocFocus = oDocument.on("focus", this._onDocFocus, this);
920 focusHandle.listeners = {
925 focusHandle.listeners[Y.stamp(this, true)] = true;
926 focusHandle.listeners.count++;
929 // Document doesn't receive focus in Webkit when the user mouses
930 // down on it, so the "focused" attribute won't get set to the
931 // correct value. Keeping this instance based for now, potential better performance.
932 // Otherwise we'll end up looking up widgets from the DOM on every mousedown.
934 this._hDocMouseDown = oDocument.on("mousedown", this._onDocMouseDown, this);
942 _unbindDOM : function(boundingBox) {
944 var focusHandle = Widget._hDocFocus,
945 yuid = Y.stamp(this, true),
947 mouseHandle = this._hDocMouseDown;
951 focusListeners = focusHandle.listeners;
953 if (focusListeners[yuid]) {
954 delete focusListeners[yuid];
955 focusListeners.count--;
958 if (focusListeners.count === 0) {
959 focusHandle.detach();
960 Widget._hDocFocus = null;
964 if (WEBKIT && mouseHandle) {
965 mouseHandle.detach();
970 * Updates the widget UI to reflect the attribute state.
975 _syncUI: function() {
976 this._syncAttrUI(this._UI_ATTRS.SYNC);
980 * Sets the height on the widget's bounding box element
982 * @method _uiSetHeight
984 * @param {String | Number} val
986 _uiSetHeight: function(val) {
987 this._uiSetDim(HEIGHT, val);
988 this._uiSizeCB((val !== EMPTY_STR && val !== AUTO));
992 * Sets the width on the widget's bounding box element
994 * @method _uiSetWidth
996 * @param {String | Number} val
998 _uiSetWidth: function(val) {
999 this._uiSetDim(WIDTH, val);
1005 * @param {String} dim The dimension - "width" or "height"
1006 * @param {Number | String} val The value to set
1008 _uiSetDim: function(dimension, val) {
1009 this.get(BOUNDING_BOX).setStyle(dimension, L.isNumber(val) ? val + this.DEF_UNIT : val);
1013 * Sets the visible state for the UI
1015 * @method _uiSetVisible
1017 * @param {boolean} val
1019 _uiSetVisible: function(val) {
1020 this.get(BOUNDING_BOX).toggleClass(this.getClassName(HIDDEN), !val);
1024 * Sets the disabled state for the UI
1026 * @method _uiSetDisabled
1028 * @param {boolean} val
1030 _uiSetDisabled: function(val) {
1031 this.get(BOUNDING_BOX).toggleClass(this.getClassName(DISABLED), val);
1035 * Sets the focused state for the UI
1037 * @method _uiSetFocused
1039 * @param {boolean} val
1040 * @param {string} src String representing the source that triggered an update to
1043 _uiSetFocused: function(val, src) {
1044 var boundingBox = this.get(BOUNDING_BOX);
1045 boundingBox.toggleClass(this.getClassName(FOCUSED), val);
1049 boundingBox.focus();
1057 * Set the tabIndex on the widget's rendered UI
1059 * @method _uiSetTabIndex
1063 _uiSetTabIndex: function(index) {
1064 var boundingBox = this.get(BOUNDING_BOX);
1066 if (L.isNumber(index)) {
1067 boundingBox.set(TAB_INDEX, index);
1069 boundingBox.removeAttribute(TAB_INDEX);
1074 * @method _onDocMouseDown
1075 * @description "mousedown" event handler for the owner document of the
1076 * widget's bounding box.
1078 * @param {EventFacade} evt The event facade for the DOM focus event
1080 _onDocMouseDown: function (evt) {
1081 if (this._domFocus) {
1082 this._onDocFocus(evt);
1087 * DOM focus event handler, used to sync the state of the Widget with the DOM
1089 * @method _onDocFocus
1091 * @param {EventFacade} evt The event facade for the DOM focus event
1093 _onDocFocus: function (evt) {
1094 var widget = Widget.getByNode(evt.target),
1095 activeWidget = Widget._active;
1097 if (activeWidget && (activeWidget !== widget)) {
1098 activeWidget._domFocus = false;
1099 activeWidget._set(FOCUSED, false, {src:UI});
1101 Widget._active = null;
1105 widget._domFocus = true;
1106 widget._set(FOCUSED, true, {src:UI});
1108 Widget._active = widget;
1113 * Generic toString implementation for all widgets.
1116 * @return {String} The default string value for the widget [ displays the NAME of the instance, and the unique id ]
1118 toString: function() {
1119 // Using deprecated name prop for kweight squeeze.
1120 return this.name + "[" + this.get(ID) + "]";
1124 * Default unit to use for dimension values
1126 * @property DEF_UNIT
1132 * Default node to render the bounding box to. If not set,
1133 * will default to the current document body.
1135 * @property DEF_PARENT_NODE
1136 * @type String | Node
1138 DEF_PARENT_NODE : null,
1141 * Property defining the markup template for content box. If your Widget doesn't
1142 * need the dual boundingBox/contentBox structure, set CONTENT_TEMPLATE to null,
1143 * and contentBox and boundingBox will both point to the same Node.
1145 * @property CONTENT_TEMPLATE
1148 CONTENT_TEMPLATE : DIV,
1151 * Property defining the markup template for bounding box.
1153 * @property BOUNDING_TEMPLATE
1156 BOUNDING_TEMPLATE : DIV,
1162 _guid : function() {
1167 * @method _validTabIndex
1169 * @param {Number} tabIndex
1171 _validTabIndex : function (tabIndex) {
1172 return (L.isNumber(tabIndex) || L.isNull(tabIndex));
1176 * Binds after listeners for the list of attributes provided
1178 * @method _bindAttrUI
1180 * @param {Array} attrs
1182 _bindAttrUI : function(attrs) {
1186 for (i = 0; i < l; i++) {
1187 this.after(attrs[i] + CHANGE, this._setAttrUI);
1192 * Invokes the _uiSet=ATTR NAME> method for the list of attributes provided
1194 * @method _syncAttrUI
1196 * @param {Array} attrs
1198 _syncAttrUI : function(attrs) {
1199 var i, l = attrs.length, attr;
1200 for (i = 0; i < l; i++) {
1202 this[_UISET + _toInitialCap(attr)](this.get(attr));
1207 * @method _setAttrUI
1209 * @param {EventFacade} e
1211 _setAttrUI : function(e) {
1212 if (e.target === this) {
1213 this[_UISET + _toInitialCap(e.attrName)](e.newVal, e.src);
1218 * The default setter for the strings attribute. Merges partial sets
1219 * into the full string set, to allow users to partial sets of strings
1221 * @method _strSetter
1223 * @param {Object} strings
1224 * @return {String} The full set of strings to set
1226 _strSetter : function(strings) {
1227 return Y.merge(this.get(STRINGS), strings);
1231 * Helper method to get a specific string value
1233 * @deprecated Used by deprecated WidgetLocale implementations.
1235 * @param {String} key
1236 * @return {String} The string
1238 getString : function(key) {
1239 return this.get(STRINGS)[key];
1243 * Helper method to get the complete set of strings for the widget
1245 * @deprecated Used by deprecated WidgetLocale implementations.
1246 * @method getStrings
1247 * @param {String} key
1248 * @return {String} The strings
1250 getStrings : function() {
1251 return this.get(STRINGS);
1255 * The lists of UI attributes to bind and sync for widget's _bindUI and _syncUI implementations
1257 * @property _UI_ATTRS