~ahasenack/lazr-js/lazr-js-11.03-packaging

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/widget/widget-base-debug.js

  • Committer: Sidnei da Silva
  • Date: 2010-04-08 14:44:59 UTC
  • mfrom: (166.8.13 yui-3.1.0)
  • Revision ID: sidnei.da.silva@canonical.com-20100408144459-qozybvnrgr7iee7k
Merged yui-3.1.0 [r=therve,rockstar] [f=558457].

Updates lazr-js to use YUI 3.1.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.com/yui/license.html
 
5
version: 3.1.0
 
6
build: 2026
 
7
*/
 
8
YUI.add('widget-base', function(Y) {
 
9
 
 
10
/**
 
11
 * Provides the base Widget class, with HTML Parser support
 
12
 *
 
13
 * @module widget
 
14
 */
 
15
 
 
16
/**
 
17
 * Provides the base Widget class
 
18
 *
 
19
 * @module widget
 
20
 * @submodule widget-base
 
21
 */
 
22
var L = Y.Lang,
 
23
    Node = Y.Node,
 
24
 
 
25
    ClassNameManager = Y.ClassNameManager,
 
26
 
 
27
    _getClassName = ClassNameManager.getClassName,
 
28
    _getWidgetClassName,
 
29
 
 
30
    _toInitialCap = Y.cached(function(str) {
 
31
        return str.substring(0, 1).toUpperCase() + str.substring(1);
 
32
    }),
 
33
 
 
34
    // K-Weight, IE GC optimizations
 
35
    CONTENT = "content",
 
36
    VISIBLE = "visible",
 
37
    HIDDEN = "hidden",
 
38
    DISABLED = "disabled",
 
39
    FOCUSED = "focused",
 
40
    WIDTH = "width",
 
41
    HEIGHT = "height",
 
42
    BOUNDING_BOX = "boundingBox",
 
43
    CONTENT_BOX = "contentBox",
 
44
    PARENT_NODE = "parentNode",
 
45
    OWNER_DOCUMENT = "ownerDocument",
 
46
    OFFSET_HEIGHT = "offsetHeight",
 
47
    AUTO = "auto",
 
48
    SRC_NODE = "srcNode",
 
49
    BODY = "body",
 
50
        TAB_INDEX = "tabIndex",
 
51
    ID = "id",
 
52
    RENDER = "render",
 
53
    RENDERED = "rendered",
 
54
    DESTROYED = "destroyed",
 
55
    STRINGS = "strings",
 
56
    DIV = "<div></div>",
 
57
    CHANGE = "Change",
 
58
    LOADING = "loading",
 
59
    _UISET = "_uiSet",
 
60
 
 
61
    EMPTY_STR = "",
 
62
    EMPTY_FN = function() {},
 
63
 
 
64
    UI_EVENT_REGEX = /(\w+):(\w+)/,
 
65
    UI_EVENT_REGEX_REPLACE = "$2",
 
66
 
 
67
    TRUE = true,
 
68
    FALSE = false,
 
69
 
 
70
    UI,
 
71
    ATTRS = {},
 
72
    UI_ATTRS = [VISIBLE, DISABLED, HEIGHT, WIDTH, FOCUSED],
 
73
 
 
74
    WEBKIT = Y.UA.webkit,
 
75
    IE = Y.UA.ie,
 
76
 
 
77
    ContentUpdate = "contentUpdate",
 
78
 
 
79
    //  Map of Node instances serving as a delegation containers for a specific
 
80
    //  event type to Widget instances using that delegation container.
 
81
    _delegates = {},
 
82
 
 
83
    // Widget nodeguid-to-instance map.
 
84
    _instances = {};
 
85
 
 
86
/**
 
87
 * A base class for widgets, providing:
 
88
 * <ul>
 
89
 *    <li>The render lifecycle method, in addition to the init and destroy 
 
90
 *        lifecycle methods provide by Base</li>
 
91
 *    <li>Abstract methods to support consistent MVC structure across 
 
92
 *        widgets: renderer, renderUI, bindUI, syncUI</li>
 
93
 *    <li>Support for common widget attributes, such as boundingBox, contentBox, visible, 
 
94
 *        disabled, focused, strings</li>
 
95
 * </ul>
 
96
 *
 
97
 * @param config {Object} Object literal specifying widget configuration properties.
 
98
 *
 
99
 * @class Widget
 
100
 * @constructor
 
101
 * @extends Base
 
102
 */
 
103
function Widget(config) {
 
104
    Y.log('constructor called', 'life', 'widget');
 
105
 
 
106
    this._strs = {};
 
107
 
 
108
    this._cssPrefix = this.constructor.CSS_PREFIX || _getClassName(this.constructor.NAME.toLowerCase());
 
109
 
 
110
    Widget.superclass.constructor.apply(this, arguments);
 
111
 
 
112
    var render = this.get(RENDER), parentNode;
 
113
    if (render) {
 
114
        // Render could be a node or boolean
 
115
        if (render !== TRUE) {
 
116
            parentNode = render;
 
117
        }
 
118
        this.render(parentNode);
 
119
    }
 
120
}
 
121
 
 
122
/**
 
123
 * Static property provides a string to identify the class.
 
124
 * <p>
 
125
 * Currently used to apply class identifiers to the bounding box 
 
126
 * and to classify events fired by the widget.
 
127
 * </p>
 
128
 *
 
129
 * @property Widget.NAME
 
130
 * @type String
 
131
 * @static
 
132
 */
 
133
Widget.NAME = "widget";
 
134
 
 
135
/**
 
136
 * Constant used to identify state changes originating from
 
137
 * the DOM (as opposed to the JavaScript model).
 
138
 *
 
139
 * @property Widget.UI_SRC
 
140
 * @type String
 
141
 * @static
 
142
 * @final
 
143
 */
 
144
UI = Widget.UI_SRC = "ui";
 
145
 
 
146
/**
 
147
 * Static property used to define the default attribute 
 
148
 * configuration for the Widget.
 
149
 * 
 
150
 * @property Widget.ATTRS
 
151
 * @type Object
 
152
 * @static
 
153
 */
 
154
Widget.ATTRS = ATTRS;
 
155
 
 
156
// Trying to optimize kweight by setting up attrs this way saves about 0.4K min'd
 
157
 
 
158
/**
 
159
 * @attribute id
 
160
 * @writeOnce
 
161
 * @default Generated using guid()
 
162
 * @type String
 
163
 */
 
164
 
 
165
ATTRS[ID] = {
 
166
    valueFn: "_guid",
 
167
    writeOnce: TRUE
 
168
};
 
169
 
 
170
/**
 
171
 * Flag indicating whether or not this Widget
 
172
 * has been through the render lifecycle phase.
 
173
 *
 
174
 * @attribute rendered
 
175
 * @readOnly
 
176
 * @default false
 
177
 * @type boolean
 
178
 */
 
179
ATTRS[RENDERED] = {
 
180
    value:FALSE,
 
181
    readOnly: TRUE
 
182
};
 
183
 
 
184
/**
 
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 
 
188
 * for skinning.
 
189
 * @type String | Node
 
190
 * @writeOnce
 
191
 */
 
192
ATTRS[BOUNDING_BOX] = {
 
193
    value:null,
 
194
    setter: "_setBB",
 
195
    writeOnce: TRUE
 
196
};
 
197
 
 
198
/**
 
199
 * @attribute contentBox
 
200
 * @description A DOM node that is a direct descendent of a Widget's bounding box that 
 
201
 * houses its content.
 
202
 * @type String | Node
 
203
 * @writeOnce
 
204
 */
 
205
ATTRS[CONTENT_BOX] = {
 
206
    valueFn:"_defaultCB",
 
207
    setter: "_setCB",
 
208
    writeOnce: TRUE
 
209
};
 
210
 
 
211
/**
 
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.
 
219
 * @type Number
 
220
 * @default 0
 
221
 */
 
222
ATTRS[TAB_INDEX] = {
 
223
        value: null,
 
224
        validator: "_validTabIndex"
 
225
};
 
226
 
 
227
/**
 
228
 * @attribute focused
 
229
 * @description Boolean indicating if the Widget, or one of its descendants, 
 
230
 * has focus.
 
231
 * @readOnly
 
232
 * @default false
 
233
 * @type boolean
 
234
 */
 
235
ATTRS[FOCUSED] = {
 
236
    value: FALSE,
 
237
    readOnly:TRUE
 
238
};
 
239
 
 
240
/**
 
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.
 
244
 * @default false
 
245
 * @type boolean
 
246
 */
 
247
ATTRS[DISABLED] = {
 
248
    value: FALSE
 
249
};
 
250
 
 
251
/**
 
252
 * @attribute visible
 
253
 * @description Boolean indicating weather or not the Widget is visible.
 
254
 * @default TRUE
 
255
 * @type boolean
 
256
 */
 
257
ATTRS[VISIBLE] = {
 
258
    value: TRUE
 
259
};
 
260
 
 
261
/**
 
262
 * @attribute height
 
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.
 
265
 * @default EMPTY_STR
 
266
 * @type {String | Number}
 
267
 */
 
268
ATTRS[HEIGHT] = {
 
269
    value: EMPTY_STR
 
270
};
 
271
 
 
272
/**
 
273
 * @attribute width
 
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.
 
276
 * @default EMPTY_STR
 
277
 * @type {String | Number}
 
278
 */
 
279
ATTRS[WIDTH] = {
 
280
    value: EMPTY_STR
 
281
};
 
282
 
 
283
/**
 
284
 * @attribute strings
 
285
 * @description Collection of strings used to label elements of the Widget's UI.
 
286
 * @default null
 
287
 * @type Object
 
288
 */
 
289
ATTRS[STRINGS] = {
 
290
    value: {},
 
291
    setter: "_strSetter",
 
292
    getter: "_strGetter"
 
293
};
 
294
 
 
295
/**
 
296
 * Whether or not to render the widget automatically after init, and optionally, to which parent node.
 
297
 *
 
298
 * @attribute render
 
299
 * @type boolean | Node
 
300
 * @writeOnce
 
301
 */
 
302
ATTRS[RENDER] = {
 
303
    value:FALSE,
 
304
    writeOnce:TRUE
 
305
};
 
306
 
 
307
/**
 
308
 * The css prefix which the static Widget.getClassName method should use when constructing class names
 
309
 *
 
310
 * @property Widget.CSS_PREFIX
 
311
 * @type String
 
312
 * @default Widget.NAME.toLowerCase()
 
313
 * @private
 
314
 * @static
 
315
 */
 
316
Widget.CSS_PREFIX = _getClassName(Widget.NAME.toLowerCase());
 
317
 
 
318
/**
 
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).
 
323
 * <p>
 
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.
 
327
 * </p>
 
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
 
330
 */
 
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));
 
334
};
 
335
 
 
336
_getWidgetClassName = Widget.getClassName;
 
337
 
 
338
/**
 
339
 * Returns the widget instance whose bounding box contains, or is, the given node. 
 
340
 * <p>
 
341
 * In the case of nested widgets, the nearest bounding box ancestor is used to
 
342
 * return the widget instance.
 
343
 * </p>
 
344
 * @method Widget.getByNode
 
345
 * @static
 
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.
 
349
 */
 
350
Widget.getByNode = function(node) {
 
351
    var widget,
 
352
        widgetMarker = _getWidgetClassName();
 
353
 
 
354
    node = Node.one(node);
 
355
    if (node) {
 
356
        node = node.ancestor("." + widgetMarker, true);
 
357
        if (node) {
 
358
            widget = _instances[Y.stamp(node, TRUE)];
 
359
        }
 
360
    }
 
361
 
 
362
    return widget || null;
 
363
};
 
364
 
 
365
Y.extend(Widget, Y.Base, {
 
366
 
 
367
        /**
 
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.
 
371
         * e.g. 
 
372
         * <code>
 
373
         * <pre>
 
374
         *    // returns "yui-slider-foo-bar", for a slider instance
 
375
         *    var scn = slider.getClassName('foo','bar');
 
376
         *
 
377
         *    // returns "yui-overlay-foo-bar", for an overlay instance
 
378
         *    var ocn = overlay.getClassName('foo','bar');
 
379
         * </pre>
 
380
         * </code>
 
381
         *
 
382
         * @method getClassName
 
383
         * @param {String}+ One or more classname bits to be joined and prefixed
 
384
         */
 
385
        getClassName: function () {
 
386
        return _getClassName.apply(ClassNameManager, [this._cssPrefix].concat(Y.Array(arguments), true));
 
387
        },
 
388
 
 
389
    /**
 
390
     * Returns the name of the skin that's currently applied to the widget.
 
391
     * This is only really useful after the widget's DOM structure is in the
 
392
     * document, either by render or by progressive enhancement.  Searches up
 
393
     * the Widget's ancestor axis for a class yui3-skin-(name), and returns the
 
394
     * (name) portion.  Otherwise, returns null.
 
395
     *
 
396
     * @method getSkinName
 
397
     * @return {String} the name of the skin, or null (yui3-skin-sam => sam)
 
398
     */
 
399
    getSkinName: function () {
 
400
        var root = this.get( CONTENT_BOX ) || this.get( BOUNDING_BOX ),
 
401
            search = new RegExp( '\\b' + _getClassName( 'skin' ) + '-(\\S+)' ),
 
402
            match;
 
403
 
 
404
        if ( root ) {
 
405
            root.ancestor( function ( node ) {
 
406
                match = node.get( 'className' ).match( search );
 
407
                return match;
 
408
            } );
 
409
        }
 
410
 
 
411
        return ( match ) ? match[1] : null;
 
412
    },
 
413
 
 
414
    /**
 
415
     * Initializer lifecycle implementation for the Widget class. Registers the 
 
416
     * widget instance, and runs through the Widget's HTML_PARSER definition. 
 
417
     *
 
418
     * @method initializer
 
419
     * @protected
 
420
     * @param  config {Object} Configuration object literal for the widget
 
421
     */
 
422
    initializer: function(config) {
 
423
        Y.log('initializer called', 'life', 'widget');
 
424
 
 
425
        _instances[Y.stamp(this.get(BOUNDING_BOX))] = this;
 
426
 
 
427
        /**
 
428
         * Notification event, which widget implementations can fire, when
 
429
         * they change the content of the widget. This event has no default
 
430
         * behavior and cannot be prevented, so the "on" or "after"
 
431
         * moments are effectively equivalent (with on listeners being invoked before 
 
432
         * after listeners).
 
433
         *
 
434
         * @event widget:contentUpdate
 
435
         * @preventable false
 
436
         * @param {EventFacade} e The Event Facade
 
437
         */
 
438
        this.publish(ContentUpdate, { preventable:FALSE });
 
439
 
 
440
        if (this._applyParser) {
 
441
            this._applyParser(config);
 
442
        }
 
443
    },
 
444
 
 
445
    /**
 
446
     * Destructor lifecycle implementation for the Widget class. Purges events attached
 
447
     * to the bounding box (and all child nodes) and removes the Widget from the 
 
448
     * list of registered widgets.
 
449
     *
 
450
     * @method destructor
 
451
     * @protected
 
452
     */
 
453
    destructor: function() {
 
454
        Y.log('destructor called', 'life', 'widget');
 
455
 
 
456
        var boundingBox = this.get(BOUNDING_BOX),
 
457
            bbGuid = Y.stamp(boundingBox, TRUE),
 
458
            widgetGuid = Y.stamp(this, TRUE);
 
459
 
 
460
        if (bbGuid in _instances) {
 
461
            delete _instances[bbGuid];
 
462
        }
 
463
 
 
464
        Y.each(_delegates, function (info) {
 
465
            if (info.instances[widgetGuid]) {
 
466
                //  Unregister this Widget instance as needing this delegated
 
467
                //  event listener.
 
468
                delete info.instances[widgetGuid];
 
469
 
 
470
                //  There are no more Widget instances using this delegated 
 
471
                //  event listener, so detach it.
 
472
                if (Y.Object.size(info.instances) === 0) {
 
473
                    info.handle.detach();
 
474
                }
 
475
            }
 
476
        });
 
477
 
 
478
        this._unbindUI(boundingBox);
 
479
        boundingBox.remove(TRUE);
 
480
    },
 
481
 
 
482
    /**
 
483
     * Establishes the initial DOM for the widget. Invoking this
 
484
     * method will lead to the creating of all DOM elements for
 
485
     * the widget (or the manipulation of existing DOM elements 
 
486
     * for the progressive enhancement use case).
 
487
     * <p>
 
488
     * This method should only be invoked once for an initialized
 
489
     * widget.
 
490
     * </p>
 
491
     * <p>
 
492
     * It delegates to the widget specific renderer method to do
 
493
     * the actual work.
 
494
     * </p>
 
495
     *
 
496
     * @method render
 
497
     * @chainable
 
498
     * @final 
 
499
     * @param  parentNode {Object | String} Optional. The Node under which the 
 
500
     * Widget is to be rendered. This can be a Node instance or a CSS selector string. 
 
501
     * <p>
 
502
     * If the selector string returns more than one Node, the first node will be used 
 
503
     * as the parentNode. NOTE: This argument is required if both the boundingBox and contentBox
 
504
     * are not currently in the document. If it's not provided, the Widget will be rendered
 
505
     * to the body of the current document in this case.
 
506
     * </p>
 
507
     */
 
508
    render: function(parentNode) {
 
509
        if (this.get(DESTROYED)) { Y.log("Render failed; widget has been destroyed", "error", "widget"); }
 
510
 
 
511
        if (!this.get(DESTROYED) && !this.get(RENDERED)) {
 
512
             /**
 
513
              * Lifcyle event for the render phase, fired prior to rendering the UI 
 
514
              * for the widget (prior to invoking the widget's renderer method).
 
515
              * <p>
 
516
              * Subscribers to the "on" moment of this event, will be notified 
 
517
              * before the widget is rendered.
 
518
              * </p>
 
519
              * <p>
 
520
              * Subscribers to the "after" moment of this event, will be notified
 
521
              * after rendering is complete.
 
522
              * </p>
 
523
              *
 
524
              * @event widget:render
 
525
              * @preventable _defRenderFn
 
526
              * @param {EventFacade} e The Event Facade
 
527
              */
 
528
            this.publish(RENDER, {
 
529
                queuable:FALSE,
 
530
                fireOnce:TRUE,
 
531
                defaultTargetOnly:TRUE,
 
532
                defaultFn: this._defRenderFn
 
533
            });
 
534
 
 
535
            this.fire(RENDER, {parentNode: (parentNode) ? Node.one(parentNode) : null});
 
536
        }
 
537
        return this;
 
538
    },
 
539
 
 
540
    /**
 
541
     * Default render handler
 
542
     *
 
543
     * @method _defRenderFn
 
544
     * @protected
 
545
     * @param {EventFacade} e The Event object
 
546
     * @param {Node} parentNode The parent node to render to, if passed in to the <code>render</code> method
 
547
     */
 
548
    _defRenderFn : function(e) {
 
549
        this._parentNode = e.parentNode;
 
550
         
 
551
        this.renderer();
 
552
        this._set(RENDERED, TRUE);
 
553
 
 
554
        this._removeLoadingClassNames();
 
555
    },
 
556
 
 
557
    /**
 
558
     * Creates DOM (or manipulates DOM for progressive enhancement)
 
559
     * This method is invoked by render() and is not chained 
 
560
     * automatically for the class hierarchy (unlike initializer, destructor) 
 
561
     * so it should be chained manually for subclasses if required.
 
562
     *
 
563
     * @method renderer
 
564
     * @protected
 
565
     */
 
566
    renderer: function() {
 
567
        this._renderUI();
 
568
        this.renderUI();
 
569
 
 
570
        this._bindUI();
 
571
        this.bindUI();
 
572
 
 
573
        this._syncUI();
 
574
        this.syncUI();
 
575
    },
 
576
 
 
577
    /**
 
578
     * Configures/Sets up listeners to bind Widget State to UI/DOM
 
579
     * 
 
580
     * This method is not called by framework and is not chained 
 
581
     * automatically for the class hierarchy.
 
582
     * 
 
583
     * @method bindUI
 
584
     * @protected
 
585
     */
 
586
    bindUI: EMPTY_FN,
 
587
 
 
588
    /**
 
589
     * Adds nodes to the DOM 
 
590
     * 
 
591
     * This method is not called by framework and is not chained 
 
592
     * automatically for the class hierarchy.
 
593
     * 
 
594
     * @method renderUI
 
595
     * @protected
 
596
     */
 
597
    renderUI: EMPTY_FN,
 
598
 
 
599
    /**
 
600
     * Refreshes the rendered UI, based on Widget State
 
601
     * 
 
602
     * This method is not called by framework and is not chained
 
603
     * automatically for the class hierarchy.
 
604
     *
 
605
     * @method syncUI
 
606
     * @protected
 
607
     *
 
608
     */
 
609
    syncUI: EMPTY_FN,
 
610
 
 
611
    /**
 
612
     * @method hide
 
613
     * @description Hides the Widget by setting the "visible" attribute to "false".
 
614
     * @chainable
 
615
     */
 
616
    hide: function() {
 
617
        return this.set(VISIBLE, FALSE);
 
618
    },
 
619
 
 
620
    /**
 
621
     * @method show
 
622
     * @description Shows the Widget by setting the "visible" attribute to "true".
 
623
     * @chainable
 
624
     */
 
625
    show: function() {
 
626
        return this.set(VISIBLE, TRUE);
 
627
    },
 
628
 
 
629
    /**
 
630
     * @method focus
 
631
     * @description Causes the Widget to receive the focus by setting the "focused" 
 
632
     * attribute to "true".
 
633
     * @chainable
 
634
     */
 
635
    focus: function () {
 
636
        return this._set(FOCUSED, TRUE);
 
637
    },
 
638
 
 
639
    /**
 
640
     * @method blur
 
641
     * @description Causes the Widget to lose focus by setting the "focused" attribute 
 
642
     * to "false"
 
643
     * @chainable
 
644
     */
 
645
    blur: function () {
 
646
        return this._set(FOCUSED, FALSE);
 
647
    },
 
648
 
 
649
    /**
 
650
     * @method enable
 
651
     * @description Set the Widget's "disabled" attribute to "false".
 
652
     * @chainable
 
653
     */
 
654
    enable: function() {
 
655
        return this.set(DISABLED, FALSE);
 
656
    },
 
657
 
 
658
    /**
 
659
     * @method disable
 
660
     * @description Set the Widget's "disabled" attribute to "true".
 
661
     * @chainable
 
662
     */
 
663
    disable: function() {
 
664
        return this.set(DISABLED, TRUE);
 
665
    },
 
666
 
 
667
    /**
 
668
     * @method _uiSizeCB
 
669
     * @protected
 
670
     * @param {boolean} expand
 
671
     */
 
672
    _uiSizeCB : function(expand) {
 
673
 
 
674
        var bb = this.get(BOUNDING_BOX),
 
675
            cb = this.get(CONTENT_BOX),
 
676
 
 
677
            bbTempExpanding = _getWidgetClassName("tmp", "forcesize"),
 
678
 
 
679
            borderBoxSupported = this._bbs,
 
680
            heightReallyMinHeight = IE && IE < 7;
 
681
 
 
682
        if (borderBoxSupported) {
 
683
            cb.toggleClass(_getWidgetClassName(CONTENT, "expanded"), expand);
 
684
        } else {
 
685
            if (expand) {
 
686
                if (heightReallyMinHeight) {
 
687
                    bb.addClass(bbTempExpanding);
 
688
                }
 
689
 
 
690
                cb.set(OFFSET_HEIGHT, bb.get(OFFSET_HEIGHT));
 
691
 
 
692
                if (heightReallyMinHeight) {
 
693
                    bb.removeClass(bbTempExpanding);
 
694
                }
 
695
            } else {
 
696
                cb.setStyle(HEIGHT, EMPTY_STR);
 
697
            }
 
698
        }
 
699
    },
 
700
 
 
701
    /**
 
702
     * Helper method to collect the boundingBox and contentBox, set styles and append to the provided parentNode, if not
 
703
     * already a child. The owner document of the boundingBox, or the owner document of the contentBox will be used 
 
704
     * as the document into which the Widget is rendered if a parentNode is node is not provided. If both the boundingBox and
 
705
     * the contentBox are not currently in the document, and no parentNode is provided, the widget will be rendered 
 
706
     * to the current document's body.
 
707
     *
 
708
     * @method _renderBox
 
709
     * @private
 
710
     * @param {Node} parentNode The parentNode to render the widget to. If not provided, and both the boundingBox and
 
711
     * the contentBox are not currently in the document, the widget will be rendered to the current document's body.
 
712
     */
 
713
    _renderBox: function(parentNode) {
 
714
 
 
715
        // TODO: Performance Optimization [ More effective algo to reduce Node refs, compares, replaces? ]
 
716
 
 
717
        var contentBox = this.get(CONTENT_BOX),
 
718
            boundingBox = this.get(BOUNDING_BOX),
 
719
            srcNode = this.get(SRC_NODE),
 
720
            defParentNode = this.DEF_PARENT_NODE,
 
721
 
 
722
            doc = (srcNode && srcNode.get(OWNER_DOCUMENT)) || boundingBox.get(OWNER_DOCUMENT) || contentBox.get(OWNER_DOCUMENT);
 
723
 
 
724
        // If srcNode (assume it's always in doc), have contentBox take its place (widget render responsible for re-use of srcNode contents)
 
725
        if (srcNode && !srcNode.compareTo(contentBox) && !contentBox.inDoc(doc)) {
 
726
            srcNode.replace(contentBox);
 
727
        }
 
728
 
 
729
        if (!boundingBox.compareTo(contentBox.get(PARENT_NODE)) && !boundingBox.compareTo(contentBox)) {
 
730
            // If contentBox box is already in the document, have boundingBox box take it's place
 
731
            if (contentBox.inDoc(doc)) {
 
732
                contentBox.replace(boundingBox);
 
733
            }
 
734
            boundingBox.appendChild(contentBox);
 
735
        }
 
736
 
 
737
        parentNode = parentNode || (defParentNode && Node.one(defParentNode));
 
738
 
 
739
        if (parentNode) {
 
740
            parentNode.appendChild(boundingBox);
 
741
        } else if (!boundingBox.inDoc(doc)) {
 
742
            Node.one(BODY).insert(boundingBox, 0);
 
743
        }
 
744
 
 
745
        this._bbs = !(IE && IE < 8 && doc.compatMode != "BackCompat");
 
746
    },
 
747
 
 
748
    /**
 
749
     * Setter for the boundingBox attribute
 
750
     *
 
751
     * @method _setBB
 
752
     * @private
 
753
     * @param Node/String
 
754
     * @return Node
 
755
     */
 
756
    _setBB: function(node) {
 
757
        return this._setBox(this.get(ID), node, this.BOUNDING_TEMPLATE);
 
758
    },
 
759
 
 
760
    /**
 
761
     * Setter for the contentBox attribute
 
762
     *
 
763
     * @method _setCB
 
764
     * @private
 
765
     * @param {Node|String} node
 
766
     * @return Node
 
767
     */
 
768
    _setCB: function(node) {
 
769
        return (this.CONTENT_TEMPLATE === null) ? this.get(BOUNDING_BOX) : this._setBox(null, node, this.CONTENT_TEMPLATE);
 
770
    },
 
771
 
 
772
    /**
 
773
     * Returns the default value for the contentBox attribute. 
 
774
     *
 
775
     * For the Widget class, this will be the srcNode if provided, otherwise null (resulting in
 
776
     * a new contentBox node instance being created)
 
777
     *
 
778
     * @method _defaultCB
 
779
     * @protected
 
780
     */
 
781
    _defaultCB : function(node) {
 
782
        return this.get(SRC_NODE) || null;
 
783
    },
 
784
 
 
785
    /**
 
786
     * Helper method to set the bounding/content box, or create it from
 
787
     * the provided template if not found.
 
788
     *
 
789
     * @method _setBox
 
790
     * @private
 
791
     *
 
792
     * @param {String} id The node's id attribute
 
793
     * @param {Node|String} node The node reference
 
794
     * @param {String} template HTML string template for the node
 
795
     * @return {Node} The node
 
796
     */
 
797
    _setBox : function(id, node, template) {
 
798
        node = Node.one(node) || Node.create(template);
 
799
        if (!node.get(ID)) {
 
800
            node.set(ID, id || Y.guid());
 
801
        }
 
802
        return node;
 
803
    },
 
804
 
 
805
    /**
 
806
     * Initializes the UI state for the Widget's bounding/content boxes.
 
807
     *
 
808
     * @method _renderUI
 
809
     * @protected
 
810
     */
 
811
    _renderUI: function() {
 
812
        this._renderBoxClassNames();
 
813
        this._renderBox(this._parentNode);
 
814
    },
 
815
 
 
816
    /**
 
817
     * Applies standard class names to the boundingBox and contentBox
 
818
     *
 
819
     * @method _renderBoxClassNames
 
820
     * @protected
 
821
     */
 
822
    _renderBoxClassNames : function() {
 
823
        var classes = this._getClasses(),
 
824
            cl,
 
825
            boundingBox = this.get(BOUNDING_BOX),
 
826
            i;
 
827
 
 
828
        boundingBox.addClass(_getWidgetClassName());
 
829
 
 
830
        // Start from Widget Sub Class
 
831
        for (i = classes.length-3; i >= 0; i--) {
 
832
            cl = classes[i];
 
833
            boundingBox.addClass(cl.CSS_PREFIX || _getClassName(cl.NAME.toLowerCase()));
 
834
        }
 
835
 
 
836
        // Use instance based name for content box
 
837
        this.get(CONTENT_BOX).addClass(this.getClassName(CONTENT));
 
838
    },
 
839
 
 
840
 
 
841
    /**
 
842
     * Removes class names representative of the widget's loading state from 
 
843
     * the boundingBox.
 
844
     *
 
845
     * @method _removeLoadingClassNames
 
846
     * @protected
 
847
     */
 
848
    _removeLoadingClassNames: function () {
 
849
 
 
850
        var boundingBox = this.get(BOUNDING_BOX),
 
851
            contentBox = this.get(CONTENT_BOX);
 
852
 
 
853
        boundingBox.removeClass(_getWidgetClassName(LOADING));
 
854
        boundingBox.removeClass(this.getClassName(LOADING));
 
855
        
 
856
        contentBox.removeClass(_getWidgetClassName(LOADING));
 
857
        contentBox.removeClass(this.getClassName(LOADING));
 
858
        
 
859
    },
 
860
 
 
861
    /**
 
862
     * Sets up DOM and CustomEvent listeners for the widget.
 
863
     *
 
864
     * @method _bindUI
 
865
     * @protected
 
866
     */
 
867
    _bindUI: function() {
 
868
        this._bindAttrUI(this._BIND_UI_ATTRS);
 
869
        this._bindDOM();
 
870
    },
 
871
 
 
872
    /**
 
873
     * @method _unbindUI
 
874
     * @protected
 
875
     */
 
876
    _unbindUI : function(boundingBox) {
 
877
        this._unbindDOM(boundingBox);
 
878
    },
 
879
 
 
880
    /**
 
881
     * Sets up DOM listeners, on elements rendered by the widget.
 
882
     * 
 
883
     * @method _bindDOM
 
884
     * @protected
 
885
     */
 
886
    _bindDOM : function() {
 
887
                var oDocument = this.get(BOUNDING_BOX).get(OWNER_DOCUMENT);
 
888
 
 
889
        // TODO: Perf Optimization: Use Widget.getByNode delegation, to get by 
 
890
        // with just one _onDocFocus subscription per sandbox, instead of one per widget
 
891
                this._hDocFocus = oDocument.on("focus", this._onDocFocus, this);
 
892
 
 
893
                //      Fix for Webkit:
 
894
                //      Document doesn't receive focus in Webkit when the user mouses 
 
895
                //      down on it, so the "focused" attribute won't get set to the 
 
896
                //      correct value.
 
897
                if (WEBKIT) {
 
898
                        this._hDocMouseDown = oDocument.on("mousedown", this._onDocMouseDown, this);
 
899
                }
 
900
    },
 
901
 
 
902
    /**
 
903
     * @method _unbindDOM
 
904
     * @protected
 
905
     */   
 
906
    _unbindDOM : function(boundingBox) {
 
907
        if (this._hDocFocus) {
 
908
            this._hDocFocus.detach();
 
909
        }
 
910
 
 
911
        if (WEBKIT && this._hDocMouseDown) {
 
912
            this._hDocMouseDown.detach();
 
913
        }
 
914
    },
 
915
 
 
916
    /**
 
917
     * Updates the widget UI to reflect the attribute state.
 
918
     *
 
919
     * @method _syncUI
 
920
     * @protected
 
921
     */
 
922
    _syncUI: function() {
 
923
        this._syncAttrUI(this._SYNC_UI_ATTRS);
 
924
    },
 
925
 
 
926
    /**
 
927
     * Sets the height on the widget's bounding box element
 
928
     *
 
929
     * @method _uiSetHeight
 
930
     * @protected
 
931
     * @param {String | Number} val
 
932
     */
 
933
    _uiSetHeight: function(val) {
 
934
        this._uiSetDim(HEIGHT, val);
 
935
        this._uiSizeCB((val !== EMPTY_STR && val !== AUTO));
 
936
    },
 
937
 
 
938
    /**
 
939
     * Sets the width on the widget's bounding box element
 
940
     *
 
941
     * @method _uiSetWidth
 
942
     * @protected
 
943
     * @param {String | Number} val
 
944
     */
 
945
    _uiSetWidth: function(val) {
 
946
        this._uiSetDim(WIDTH, val);
 
947
    },
 
948
 
 
949
    /**
 
950
     * @method _uiSetDim
 
951
     * @private
 
952
     * @param {String} dim The dimension - "width" or "height"
 
953
     * @param {Number | String} val The value to set
 
954
     */
 
955
    _uiSetDim: function(dimension, val) {
 
956
        this.get(BOUNDING_BOX).setStyle(dimension, L.isNumber(val) ? val + this.DEF_UNIT : val);
 
957
    },
 
958
 
 
959
    /**
 
960
     * Sets the visible state for the UI
 
961
     * 
 
962
     * @method _uiSetVisible
 
963
     * @protected
 
964
     * @param {boolean} val
 
965
     */
 
966
    _uiSetVisible: function(val) {
 
967
        this.get(BOUNDING_BOX).toggleClass(this.getClassName(HIDDEN), !val);
 
968
    },
 
969
 
 
970
    /**
 
971
     * Sets the disabled state for the UI
 
972
     *
 
973
     * @protected
 
974
     * @param {boolean} val
 
975
     */
 
976
    _uiSetDisabled: function(val) {
 
977
        this.get(BOUNDING_BOX).toggleClass(this.getClassName(DISABLED), val);
 
978
    },
 
979
 
 
980
    /**
 
981
     * Sets the focused state for the UI
 
982
     *
 
983
     * @protected
 
984
     * @param {boolean} val
 
985
     * @param {string} src String representing the source that triggered an update to 
 
986
     * the UI.     
 
987
     */
 
988
    _uiSetFocused: function(val, src) {
 
989
         var boundingBox = this.get(BOUNDING_BOX);
 
990
 
 
991
         boundingBox.toggleClass(this.getClassName(FOCUSED), val);
 
992
         if (src !== UI) {
 
993
            if (val) {
 
994
                boundingBox.focus();  
 
995
            } else {
 
996
                boundingBox.blur();
 
997
            }
 
998
         }
 
999
    },
 
1000
 
 
1001
    /**
 
1002
     * Set the tabIndex on the widget's rendered UI
 
1003
     *
 
1004
     * @method _uiSetTabIndex
 
1005
     * @protected
 
1006
     * @param Number
 
1007
     */
 
1008
    _uiSetTabIndex: function(index) {
 
1009
                var boundingBox = this.get(BOUNDING_BOX);
 
1010
 
 
1011
                if (L.isNumber(index)) {
 
1012
                        boundingBox.set(TAB_INDEX, index);
 
1013
                } else {
 
1014
                        boundingBox.removeAttribute(TAB_INDEX);
 
1015
                }
 
1016
    },
 
1017
 
 
1018
        /**
 
1019
         * @method _onDocMouseDown
 
1020
         * @description "mousedown" event handler for the owner document of the 
 
1021
         * widget's bounding box.
 
1022
         * @protected
 
1023
     * @param {EventFacade} evt The event facade for the DOM focus event
 
1024
         */
 
1025
        _onDocMouseDown: function (evt) {
 
1026
                if (this._hasDOMFocus) {
 
1027
                        this._onDocFocus(evt);
 
1028
                }
 
1029
        },
 
1030
 
 
1031
    /**
 
1032
     * DOM focus event handler, used to sync the state of the Widget with the DOM
 
1033
     * 
 
1034
     * @method _onDocFocus
 
1035
     * @protected
 
1036
     * @param {EventFacade} evt The event facade for the DOM focus event
 
1037
     */
 
1038
    _onDocFocus: function (evt) {
 
1039
                var bFocused = this.get(BOUNDING_BOX).contains(evt.target); // contains() checks invoking node also
 
1040
 
 
1041
                this._hasDOMFocus = bFocused;
 
1042
        this._set(FOCUSED, bFocused, { src: UI });
 
1043
    },
 
1044
 
 
1045
    /**
 
1046
     * Generic toString implementation for all widgets.
 
1047
     *
 
1048
     * @method toString
 
1049
     * @return {String} The default string value for the widget [ displays the NAME of the instance, and the unique id ]
 
1050
     */
 
1051
    toString: function() {
 
1052
        return this.constructor.NAME + "[" + this.get(ID) + "]";
 
1053
    },
 
1054
 
 
1055
    /**
 
1056
     * Default unit to use for dimension values
 
1057
     * 
 
1058
     * @property DEF_UNIT
 
1059
     * @type String
 
1060
     */
 
1061
    DEF_UNIT : "px",
 
1062
 
 
1063
    /** 
 
1064
     * Default node to render the bounding box to. If not set,
 
1065
     * will default to the current document body.
 
1066
     * 
 
1067
     * @property DEF_PARENT_NODE
 
1068
     * @type String | Node
 
1069
     */ 
 
1070
    DEF_PARENT_NODE : null,
 
1071
 
 
1072
    /**
 
1073
     * Property defining the markup template for content box. If your Widget doesn't
 
1074
     * need the dual boundingBox/contentBox structure, set CONTENT_TEMPLATE to null,
 
1075
     * and contentBox and boundingBox will both point to the same Node. 
 
1076
     *
 
1077
     * @property CONTENT_TEMPLATE
 
1078
     * @type String
 
1079
     */
 
1080
    CONTENT_TEMPLATE : DIV,
 
1081
 
 
1082
    /**
 
1083
     * Property defining the markup template for bounding box.
 
1084
     *
 
1085
     * @property BOUNDING_TEMPLATE
 
1086
     * @type String
 
1087
     */
 
1088
    BOUNDING_TEMPLATE : DIV,
 
1089
 
 
1090
    /**
 
1091
     * @method _guid
 
1092
     * @protected
 
1093
     */
 
1094
    _guid : function() {
 
1095
        return Y.guid();
 
1096
    },
 
1097
 
 
1098
    /**
 
1099
     * @method _validTabIndex
 
1100
     * @protected
 
1101
     * @param {Number} tabIndex
 
1102
     */
 
1103
    _validTabIndex : function (tabIndex) {
 
1104
        return (L.isNumber(tabIndex) || L.isNull(tabIndex));
 
1105
    },
 
1106
 
 
1107
    /**
 
1108
     * Binds after listeners for the list of attributes provided
 
1109
     * 
 
1110
     * @method _bindAttrUI
 
1111
     * @private
 
1112
     * @param {Array} attrs
 
1113
     */
 
1114
    _bindAttrUI : function(attrs) {
 
1115
        var i, 
 
1116
            l = attrs.length; 
 
1117
 
 
1118
        for (i = 0; i < l; i++) {
 
1119
            this.after(attrs[i] + CHANGE, this._setAttrUI);
 
1120
        }
 
1121
    },
 
1122
 
 
1123
    /**
 
1124
     * Invokes the _uiSet&#61;ATTR NAME&#62; method for the list of attributes provided  
 
1125
     *
 
1126
     * @method _syncAttrUI
 
1127
     * @private
 
1128
     * @param {Array} attrs
 
1129
     */
 
1130
    _syncAttrUI : function(attrs) {
 
1131
        var i, l = attrs.length, attr;
 
1132
        for (i = 0; i < l; i++) {
 
1133
            attr = attrs[i];
 
1134
            this[_UISET + _toInitialCap(attr)](this.get(attr));
 
1135
        }
 
1136
    },
 
1137
 
 
1138
    /**
 
1139
     * @method _setAttrUI
 
1140
     * @private
 
1141
     * @param {EventFacade} e
 
1142
     */
 
1143
    _setAttrUI : function(e) {
 
1144
        this[_UISET + _toInitialCap(e.attrName)](e.newVal, e.src);
 
1145
    },
 
1146
 
 
1147
    /**
 
1148
     * The default setter for the strings attribute. Merges partial sets
 
1149
     * into the full string set, to allow users to partial sets of strings  
 
1150
     *
 
1151
     * @method _strSetter
 
1152
     * @protected
 
1153
     * @param {Object} strings
 
1154
     * @return {String} The full set of strings to set
 
1155
     */
 
1156
    _strSetter : function(strings) {
 
1157
        return Y.merge(this.get(STRINGS), strings);
 
1158
    },
 
1159
 
 
1160
    /**
 
1161
     * Helper method to get a specific string value
 
1162
     *
 
1163
     * @deprecated Used by deprecated WidgetLocale implementations. 
 
1164
     * @method getString
 
1165
     * @param {String} key
 
1166
     * @return {String} The string
 
1167
     */
 
1168
    getString : function(key) {
 
1169
        return this.get(STRINGS)[key];
 
1170
    },
 
1171
 
 
1172
    /**
 
1173
     * Helper method to get the complete set of strings for the widget
 
1174
     *
 
1175
     * @deprecated  Used by deprecated WidgetLocale implementations.
 
1176
     * @method getString
 
1177
     * @param {String} key
 
1178
     * @return {String} The string
 
1179
     */
 
1180
    getStrings : function() {
 
1181
        return this.get(STRINGS);
 
1182
    },
 
1183
 
 
1184
    /**
 
1185
     * The list of UI attributes to bind for Widget's _bindUI implementation
 
1186
     *
 
1187
     * @property _BIND_UI_ATTRS
 
1188
     * @type Array
 
1189
     * @private
 
1190
     */
 
1191
    _BIND_UI_ATTRS : UI_ATTRS,
 
1192
 
 
1193
    /**
 
1194
     * The list of UI attributes to sync for Widget's _syncUI implementation
 
1195
     *
 
1196
     * @property _SYNC_UI_ATTRS
 
1197
     * @type Array
 
1198
     * @private
 
1199
     */
 
1200
    _SYNC_UI_ATTRS : UI_ATTRS.concat(TAB_INDEX),
 
1201
 
 
1202
    /**
 
1203
     * Map of DOM events that should be fired as Custom Events by the  
 
1204
     * Widget instance.
 
1205
     *
 
1206
     * @property UI_EVENTS
 
1207
     * @type Object
 
1208
     */
 
1209
    UI_EVENTS: Y.Node.DOM_EVENTS,
 
1210
 
 
1211
    /**
 
1212
     * Returns the node on which to bind delegate listeners.
 
1213
     *
 
1214
     * @method _getUIEventNode
 
1215
     * @protected
 
1216
     */
 
1217
    _getUIEventNode: function () {
 
1218
        return this.get(BOUNDING_BOX);
 
1219
    },
 
1220
 
 
1221
    /**
 
1222
     * Binds a delegated DOM event listener of the specified type to the 
 
1223
     * Widget's outtermost DOM element to facilitate the firing of a Custom
 
1224
     * Event of the same type for the Widget instance.  
 
1225
     *
 
1226
     * @private
 
1227
     * @method _createUIEvent
 
1228
     * @param type {String} String representing the name of the event
 
1229
     */
 
1230
    _createUIEvent: function (type) {
 
1231
 
 
1232
        var uiEvtNode = this._getUIEventNode(),
 
1233
            parentNode = uiEvtNode.get(PARENT_NODE),
 
1234
            key = (Y.stamp(parentNode) + type),
 
1235
            info = _delegates[key],
 
1236
            handle;
 
1237
 
 
1238
        //  For each Node instance: Ensure that there is only one delegated 
 
1239
        //  event listener used to fire Widget UI events.
 
1240
 
 
1241
        if (!info) {
 
1242
 
 
1243
            Y.log("Creating delegate for the " + type + " event.", "info", "widget");
 
1244
 
 
1245
            handle = parentNode.delegate(type, function (evt) {
 
1246
 
 
1247
                var widget = Widget.getByNode(this);
 
1248
 
 
1249
                //  Make the DOM event a property of the custom event
 
1250
                //  so that developers still have access to it.
 
1251
                widget.fire(evt.type, { domEvent: evt });
 
1252
 
 
1253
            }, "." + _getWidgetClassName());
 
1254
 
 
1255
            _delegates[key] = info = { instances: {}, handle: handle };
 
1256
 
 
1257
        }
 
1258
 
 
1259
        //  Register this Widget as using this Node as a delegation container.
 
1260
        info.instances[Y.stamp(this)] = 1;
 
1261
 
 
1262
    },
 
1263
 
 
1264
    /**
 
1265
     * Determines if the specified event is a UI event.
 
1266
     *
 
1267
     * @private
 
1268
     * @method _isUIEvent
 
1269
     * @param type {String} String representing the name of the event
 
1270
     * @return {String} Event Returns the name of the UI Event, otherwise 
 
1271
     * undefined.
 
1272
     */
 
1273
    _getUIEvent: function (type) {
 
1274
        if (L.isString(type)) {
 
1275
            var sType = type.replace(UI_EVENT_REGEX, UI_EVENT_REGEX_REPLACE),
 
1276
                returnVal;
 
1277
 
 
1278
            if (this.UI_EVENTS[sType]) {
 
1279
                returnVal = sType;
 
1280
            }
 
1281
 
 
1282
            return returnVal;
 
1283
        }
 
1284
    },
 
1285
 
 
1286
    /**
 
1287
     * Sets up infastructure required to fire a UI event.
 
1288
     * 
 
1289
     * @private
 
1290
     * @method _initUIEvent
 
1291
     * @param type {String} String representing the name of the event
 
1292
     * @return {String}     
 
1293
     */
 
1294
    _initUIEvent: function (type) {
 
1295
        var sType = this._getUIEvent(type),
 
1296
            queue = this._uiEvtsInitQueue || {};
 
1297
 
 
1298
        if (sType && !queue[sType]) {
 
1299
 
 
1300
            Y.log("Deferring creation of " + type + " delegate until render.", "info", "widget");
 
1301
 
 
1302
            this.after(RENDER, function() { 
 
1303
                this._createUIEvent(sType);
 
1304
                delete this._uiEvtsInitQueue[sType];
 
1305
            });
 
1306
            
 
1307
            this._uiEvtsInitQueue = queue[sType] = 1;
 
1308
 
 
1309
        }
 
1310
    },
 
1311
 
 
1312
    //  Override of "on" from Base to facilitate the firing of Widget events
 
1313
    //  based on DOM events of the same name/type (e.g. "click", "mouseover").
 
1314
    //  Temporary solution until we have the ability to listen to when 
 
1315
    //  someone adds an event listener (bug 2528230)
 
1316
    on: function (type) {
 
1317
        this._initUIEvent(type);
 
1318
        return Widget.superclass.on.apply(this, arguments);
 
1319
    },
 
1320
 
 
1321
    //  Override of "after" from Base to facilitate the firing of Widget events
 
1322
    //  based on DOM events of the same name/type (e.g. "click", "mouseover").    
 
1323
    //  Temporary solution until we have the ability to listen to when 
 
1324
    //  someone adds an event listener (bug 2528230)    
 
1325
    after: function (type) {
 
1326
        this._initUIEvent(type);
 
1327
        return Widget.superclass.after.apply(this, arguments);
 
1328
    },
 
1329
 
 
1330
    //  Override of "publish" from Base to facilitate the firing of Widget events
 
1331
    //  based on DOM events of the same name/type (e.g. "click", "mouseover").    
 
1332
    //  Temporary solution until we have the ability to listen to when 
 
1333
    //  someone publishes an event (bug 2528230)     
 
1334
    publish: function (type, config) {
 
1335
        var sType = this._getUIEvent(type);
 
1336
        if (sType && config && config.defaultFn) {
 
1337
            this._initUIEvent(sType);
 
1338
        }        
 
1339
        return Widget.superclass.publish.apply(this, arguments);
 
1340
    }
 
1341
 
 
1342
});
 
1343
 
 
1344
Y.Widget = Widget;
 
1345
 
 
1346
 
 
1347
}, '3.1.0' ,{requires:['attribute', 'event-focus', 'base', 'node', 'classnamemanager', 'intl']});