~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/slider/slider.js

  • Committer: Matt Nordhoff
  • Date: 2010-02-26 04:37:13 UTC
  • mfrom: (400 trunk)
  • mto: This revision was merged to the branch mainline in revision 401.
  • Revision ID: mnordhoff@mattnordhoff.com-20100226043713-7mw3r6dr9qowutmi
Merge trunk for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr2
 
6
*/
 
7
YUI.add('slider', function(Y) {
 
8
 
 
9
/**
 
10
 * Create a sliding value range input visualized as a draggable thumb on a
 
11
 * background element.
 
12
 * 
 
13
 * @module slider
 
14
 */
 
15
 
 
16
var SLIDER = 'slider',
 
17
    RAIL   = 'rail',
 
18
    THUMB  = 'thumb',
 
19
    VALUE  = 'value',
 
20
    MIN    = 'min',
 
21
    MAX    = 'max',
 
22
    THUMB_IMAGE = 'thumbImage',
 
23
    RAIL_SIZE   = 'railSize',
 
24
    CONTENT_BOX = 'contentBox',
 
25
 
 
26
    SLIDE_START = 'slideStart',
 
27
    SLIDE_END   = 'slideEnd',
 
28
 
 
29
    THUMB_DRAG  = 'thumbDrag',
 
30
    SYNC        = 'sync',
 
31
    VALUE_SET   = 'valueSet',
 
32
    RENDERED    = 'rendered',
 
33
    DISABLED    = 'disabled',
 
34
    DISABLED_CHANGE = 'disabledChange',
 
35
 
 
36
    DOT      = '.',
 
37
    PX       = 'px',
 
38
    WIDTH    = 'width',
 
39
    HEIGHT   = 'height',
 
40
    COMPLETE = 'complete',
 
41
 
 
42
    L = Y.Lang,
 
43
    isArray  = L.isArray,
 
44
    isBoolean= L.isBoolean,
 
45
    isString = L.isString,
 
46
    isNumber = L.isNumber,
 
47
    
 
48
    getCN    = Y.ClassNameManager.getClassName,
 
49
 
 
50
    IMAGE         = 'image',
 
51
    C_RAIL        = getCN(SLIDER,RAIL),
 
52
    C_THUMB       = getCN(SLIDER,THUMB),
 
53
    C_THUMB_IMAGE = getCN(SLIDER,THUMB,IMAGE),
 
54
    C_IMAGE_ERROR = getCN(SLIDER,IMAGE,'error'),
 
55
 
 
56
    M        = Math,
 
57
    max      = M.max,
 
58
    round    = M.round,
 
59
    floor    = M.floor,
 
60
    ceil     = M.ceil,
 
61
    abs      = M.abs;
 
62
 
 
63
/**
 
64
 * Create a slider to represent an integer value between a given minimum and
 
65
 * maximum.
 
66
 *
 
67
 * @class Slider
 
68
 * @extends Widget
 
69
 * @param config {Object} Configuration object
 
70
 * @constructor
 
71
 */
 
72
function Slider() {
 
73
    Slider.superclass.constructor.apply(this,arguments);
 
74
}
 
75
 
 
76
Y.mix(Slider, {
 
77
 
 
78
    /**
 
79
     * The identity of the widget.
 
80
     *
 
81
     * @property Slider.NAME
 
82
     * @type String
 
83
     * @static
 
84
     */
 
85
    NAME : SLIDER,
 
86
 
 
87
    /**
 
88
     * Object property names used for respective X and Y axis Sliders (e.g.
 
89
     * "left" vs. "top" for placing the thumb according to
 
90
     * its representative value).
 
91
     *
 
92
     * @property Slider.AXIS_KEYS
 
93
     * @type Object
 
94
     * @static
 
95
     */
 
96
    AXIS_KEYS : {
 
97
        x : {
 
98
            offsetEdge    : 'left',
 
99
            dim           : WIDTH,
 
100
            offAxisDim    : HEIGHT,
 
101
            eventPageAxis : 'pageX',
 
102
            ddStick       : 'stickX',
 
103
            xyIndex       : 0
 
104
        },
 
105
        y : {
 
106
            offsetEdge    : 'top',
 
107
            dim           : HEIGHT,
 
108
            offAxisDim    : WIDTH,
 
109
            eventPageAxis : 'pageY',
 
110
            ddStick       : 'stickY',
 
111
            xyIndex       : 1
 
112
        }
 
113
    },
 
114
 
 
115
    /**
 
116
     * Static Object hash used to capture existing markup for progressive
 
117
     * enhancement.  Keys correspond to config attribute names and values
 
118
     * are selectors used to inspect the contentBox for an existing node
 
119
     * structure.
 
120
     *
 
121
     * @property Slider.HTML_PARSER
 
122
     * @Type Object
 
123
     * @static
 
124
     */
 
125
    HTML_PARSER : {
 
126
        rail       : DOT + C_RAIL,
 
127
        thumb      : DOT + C_THUMB,
 
128
        thumbImage : DOT + C_THUMB_IMAGE
 
129
    },
 
130
 
 
131
    /**
 
132
     * Static property used to define the default attribute configuration of
 
133
     * the Widget.
 
134
     *
 
135
     * @property Slider.ATTRS
 
136
     * @Type Object
 
137
     * @static
 
138
     */
 
139
    ATTRS : {
 
140
 
 
141
        /**
 
142
         * Axis upon which the Slider's thumb moves.  "x" for
 
143
         * horizontal, "y" for vertical.
 
144
         *
 
145
         * @attribute axis
 
146
         * @type String
 
147
         * @default "x"
 
148
         * @writeOnce
 
149
         */
 
150
        axis : {
 
151
            value : 'x',
 
152
            writeOnce : true,
 
153
            validator : function (v) {
 
154
                return this._validateNewAxis(v);
 
155
            },
 
156
            set : function (v) {
 
157
                return this._setAxisFn(v);
 
158
            }
 
159
        },
 
160
 
 
161
        /**
 
162
         * Integer value associated with the left or top terminus of the
 
163
         * Slider's rail, depending on the configured axis.
 
164
         *
 
165
         * @attribute min
 
166
         * @type Number
 
167
         * @default 0
 
168
         */
 
169
        min : {
 
170
            value : 0,
 
171
            validator : function (v) {
 
172
                return this._validateNewMin(v);
 
173
            }
 
174
        },
 
175
 
 
176
        /**
 
177
         * Integer value associated with the right or bottom terminus of the
 
178
         * Slider's rail, depending on the configured axis.
 
179
         *
 
180
         * @attribute max
 
181
         * @type Number
 
182
         * @default 100
 
183
         */
 
184
        max : {
 
185
            value : 100,
 
186
            validator : function (v) {
 
187
                return this._validateNewMax(v);
 
188
            }
 
189
        },
 
190
 
 
191
        /**
 
192
         * The current value of the Slider.  This value is interpretted into a
 
193
         * position for the thumb along the Slider's rail.
 
194
         *
 
195
         * @attribute value
 
196
         * @type Number
 
197
         * @default 0
 
198
         */
 
199
        value : {
 
200
            value : 0,
 
201
            validator : function (v) {
 
202
                return this._validateNewValue(v);
 
203
            },
 
204
            set : function (v) {
 
205
                return this._setValueFn(v);
 
206
            }
 
207
        },
 
208
 
 
209
        /**
 
210
         * The Node representing the Slider's rail, usually visualized as a
 
211
         * bar of some sort using a background image, along which the thumb
 
212
         * moves.  This Node contains the thumb Node.
 
213
         *
 
214
         * @attribute rail
 
215
         * @type Node
 
216
         * @default null
 
217
         */
 
218
        rail : {
 
219
            value : null,
 
220
            validator : function (v) {
 
221
                return this._validateNewRail(v);
 
222
            },
 
223
            set : function (v) {
 
224
                return this._setRailFn(v);
 
225
            }
 
226
        },
 
227
 
 
228
        /**
 
229
         * The Node representing the Slider's thumb, usually visualized as a
 
230
         * pointer using a contained image Node (see thumbImage).  The current
 
231
         * value of the Slider is calculated from the centerpoint of this
 
232
         * Node in relation to the rail Node.  If provided, the thumbImage
 
233
         * Node is contained within this Node.
 
234
         *
 
235
         * If no thumbImage is provided and the Node passed as the thumb is an
 
236
         * <code>img</code> element, the assigned Node will be allocated to the
 
237
         * thumbImage and the thumb container defaulted.
 
238
         *
 
239
         * @attribute thumb
 
240
         * @type Node
 
241
         * @default null
 
242
         */
 
243
        thumb : {
 
244
            value : null,
 
245
            validator : function (v) {
 
246
                return this._validateNewThumb(v);
 
247
            },
 
248
            set : function (v) {
 
249
                return this._setThumbFn(v);
 
250
            }
 
251
        },
 
252
 
 
253
        /**
 
254
         * The Node representing the image element to use for the Slider's
 
255
         * thumb.
 
256
         *
 
257
         * Alternately, an image URL can be passed and an <code>img</code>
 
258
         * Node will be generated accordingly.
 
259
         *
 
260
         * If no thumbImage is provided and the Node passed as the thumb is an
 
261
         * <code>img</code> element, the assigned Node will be allocated to the
 
262
         * thumbImage and the thumb container defaulted.
 
263
         *
 
264
         * If thumbImage is provided but its URL resolves to a 404, a default
 
265
         * style will be applied to maintain basic functionality.
 
266
         *
 
267
         * @attribute thumbImage
 
268
         * @type Node|String
 
269
         * @default null
 
270
         */
 
271
        thumbImage : {
 
272
            value : null,
 
273
            validator : function (v) {
 
274
                return this._validateNewThumbImage(v);
 
275
            },
 
276
            set : function (v) {
 
277
                return this._setThumbImageFn(v);
 
278
            }
 
279
        },
 
280
 
 
281
        /**
 
282
         * The width or height of the rail element representing the physical
 
283
         * space along which the thumb can move.  CSS size values (e.g. '30em')
 
284
         * accepted but converted to pixels during render.
 
285
         *
 
286
         * Alternately, but not recommended, this attribute can be left
 
287
         * unassigned in favor of specifying height or width.
 
288
         *
 
289
         * @attribute railSize
 
290
         * @type String
 
291
         * @default '0'
 
292
         */
 
293
        railSize : {
 
294
            value : '0',
 
295
            validator : function (v) {
 
296
                return this._validateNewRailSize(v);
 
297
            }
 
298
        },
 
299
 
 
300
        /**
 
301
         * Boolean indicating whether clicking and dragging on the rail will
 
302
         * trigger thumb movement.
 
303
         *
 
304
         * @attribute railEnabled
 
305
         * @type @Boolean
 
306
         * @default true
 
307
         */
 
308
        railEnabled : {
 
309
            value : true,
 
310
            validator : isBoolean
 
311
        }
 
312
    }
 
313
});
 
314
 
 
315
Y.extend(Slider, Y.Widget, {
 
316
 
 
317
    /**
 
318
     * Collection of object property names from the appropriate hash set in
 
319
     * Slider.AXIS_KEYS.
 
320
     *
 
321
     * @property _key
 
322
     * @type Object
 
323
     * @protected
 
324
     */
 
325
    _key : null,
 
326
 
 
327
    /**
 
328
     * Factor used to translate positional coordinates (e.g. left or top) to
 
329
     * the Slider's value.
 
330
     *
 
331
     * @property _factor
 
332
     * @type Number
 
333
     * @protected
 
334
     */
 
335
    _factor : 1,
 
336
 
 
337
    /**
 
338
     * Pixel dimension of the rail Node's width for X axis Sliders or height
 
339
     * for Y axis Sliders.  Used with _factor to calculate positional
 
340
     * coordinates for the thumb.
 
341
     *
 
342
     * @property _railSize
 
343
     * @type Number
 
344
     * @protected
 
345
     */
 
346
    _railSize : null,
 
347
 
 
348
    /**
 
349
     * Pixel dimension of the thumb Node's width for X axis Sliders or height
 
350
     * for Y axis Sliders.  Used with _factor to calculate positional
 
351
     * coordinates for the thumb.
 
352
     *
 
353
     * @property _thumbSize
 
354
     * @type Number
 
355
     * @protected
 
356
     */
 
357
    _thumbSize : null,
 
358
 
 
359
    /**
 
360
     * Pixel offset of the point in the thumb element from its top/left edge
 
361
     * to where the value calculation should take place.  By default, this is
 
362
     * calculated to half the width of the thumb, causing the value to be
 
363
     * marked from the center of the thumb.
 
364
     *
 
365
     * @property _thumbOffset
 
366
     * @type Number
 
367
     * @protected
 
368
     */
 
369
    _thumbOffset : 0,
 
370
 
 
371
    /**
 
372
     * Object returned from temporary subscription to disabledChange event to
 
373
     * defer setting the disabled state while Slider is loading the thumb
 
374
     * image.
 
375
     *
 
376
     * @property _stall
 
377
     * @type Object
 
378
     * @protected
 
379
     */
 
380
    _stall : false,
 
381
 
 
382
    /**
 
383
     * Deferred value for the disabled attribute when stalled (see _stall
 
384
     * property).
 
385
     *
 
386
     * @property _disabled
 
387
     * @type Boolean
 
388
     * @protected
 
389
     */
 
390
    _disabled : false,
 
391
 
 
392
    /**
 
393
     * Construction logic executed durint Slider instantiation. Subscribe to
 
394
     * after events for min, max, and railSize.  Publish custom events
 
395
     * including slideStart and slideEnd.
 
396
     *
 
397
     * @method initializer
 
398
     * @protected
 
399
     */
 
400
    initializer : function () {
 
401
        this._key = Slider.AXIS_KEYS[this.get('axis')];
 
402
 
 
403
        this.after('minChange',    this._afterMinChange);
 
404
        this.after('maxChange',    this._afterMaxChange);
 
405
 
 
406
        this.after('railSizeChange', this._afterRailSizeChange);
 
407
 
 
408
        /**
 
409
         * Signals the beginning of a thumb drag operation.  Payload includes
 
410
         * the DD.Drag instance's drag:start event under key ddEvent.
 
411
         *
 
412
         * @event slideStart
 
413
         * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
 
414
         *  <dl>
 
415
         *      <dt>ddEvent</dt>
 
416
         *          <dd><code>drag:start</code> event from the managed DD.Drag instance</dd>
 
417
         *  </dl>
 
418
         */
 
419
        this.publish(SLIDE_START);
 
420
 
 
421
        /**
 
422
         * Signals the end of a thumb drag operation.  Payload includes
 
423
         * the DD.Drag instance's drag:end event under key ddEvent.
 
424
         *
 
425
         * @event slideEnd
 
426
         * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
 
427
         *  <dl>
 
428
         *      <dt>ddEvent</dt>
 
429
         *          <dd><code>drag:end</code> event from the managed DD.Drag instance</dd>
 
430
         *  </dl>
 
431
         */
 
432
        this.publish(SLIDE_END);
 
433
 
 
434
        /**
 
435
         * Communicates a request to synchronize the Slider UI with the
 
436
         * attribute state.  Links the sync request with the default sync
 
437
         * logic in the default function _defSyncUI.
 
438
         *
 
439
         * @event sync
 
440
         * @param event {Event.Facade} Event Facade object
 
441
         * @preventable _defSyncUI
 
442
         */
 
443
        this.publish(SYNC,       {defaultFn: this._defSyncUI});
 
444
 
 
445
        /**
 
446
         * Signals a value change via API, requiring the thumb position to be
 
447
         * updated.  Triggers the thumb placement logic in the default function
 
448
         * _defSetThumbPosition.
 
449
         *
 
450
         * @event valueSet
 
451
         * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
 
452
         *  <dl>
 
453
         *      <dt>changeEv</dt>
 
454
         *          <dd><code>valueChange</code> event fired in response to the change in the value attribute</dd>
 
455
         *  </dl>
 
456
         * @preventable _defSetThumbPosition
 
457
         */
 
458
        this.publish(VALUE_SET,  {defaultFn: this._defSetThumbPosition});
 
459
    },
 
460
 
 
461
    /**
 
462
     * Create the DOM structure for the Slider.  Calls _initRail and _initThumb.
 
463
     *
 
464
     * @method renderUI
 
465
     * @protected
 
466
     */
 
467
    renderUI : function () {
 
468
        this._initRail();
 
469
        this._initThumb();
 
470
    },
 
471
 
 
472
    /**
 
473
     * Creates the rail element if not provided or discovered via HTML_PARSER.
 
474
     *
 
475
     * @method _initRail
 
476
     * @protected
 
477
     */
 
478
    _initRail : function () {
 
479
        var cb   = this.get(CONTENT_BOX),
 
480
            rail = this.get(RAIL);
 
481
 
 
482
        // Create rail if necessary. Make sure it's in the contentBox
 
483
        if (!rail) {
 
484
            rail = cb.appendChild(
 
485
                Y.Node.create('<div class="'+C_RAIL+'"></div>'));
 
486
 
 
487
            this.set(RAIL,rail);
 
488
        } else if (!cb.contains(rail)) {
 
489
            cb.appendChild(rail);
 
490
        }
 
491
 
 
492
        rail.addClass(C_RAIL);
 
493
        rail.addClass(this.getClassName(RAIL,this.get('axis')));
 
494
    },
 
495
 
 
496
    /**
 
497
     * Creates the thumb element (not image) if not provided or discovered via
 
498
     * HTML_PARSER.  If thumb is present and an <code>img</code> element
 
499
     * <em>and</em> no thumbImage provided, reassigns the thumb element to the
 
500
     * thumbImage and defaults the thumb element as a div.
 
501
     *
 
502
     * Makes sure the thumb is a child of the rail element and calls
 
503
     * _initThumbImage if thumbImage is provided.
 
504
     *
 
505
     * @method _initThumb
 
506
     * @protected
 
507
     */
 
508
    _initThumb : function () {
 
509
        var rail    = this.get(RAIL),
 
510
            thumb   = this.get(THUMB);
 
511
 
 
512
        // Passed an img element as the thumb
 
513
        if (thumb && !this.get(THUMB_IMAGE) &&
 
514
            thumb.get('nodeName').toLowerCase() === 'img') {
 
515
            this.set(THUMB_IMAGE, thumb);
 
516
            this.set(THUMB,null);
 
517
            thumb = null;
 
518
        }
 
519
 
 
520
        if (!thumb) {
 
521
            thumb = Y.Node.create(
 
522
                '<div class="'+C_THUMB+'"></div>');
 
523
 
 
524
            this.set(THUMB,thumb);
 
525
        }
 
526
 
 
527
        thumb.addClass(C_THUMB);
 
528
 
 
529
        if (!rail.contains(thumb)) {
 
530
            rail.appendChild(thumb);
 
531
        }
 
532
 
 
533
        if (this.get(THUMB_IMAGE)) {
 
534
            this._initThumbImage();
 
535
        }
 
536
    },
 
537
 
 
538
    /**
 
539
     * Ensures the thumbImage is a child of the thumb element.
 
540
     *
 
541
     * @method _initThumbImage
 
542
     * @protected
 
543
     */
 
544
    _initThumbImage : function () {
 
545
        var thumb = this.get(THUMB),
 
546
            img   = this.get(THUMB_IMAGE);
 
547
 
 
548
        if (img) {
 
549
            img.replaceClass(C_THUMB,C_THUMB_IMAGE);
 
550
 
 
551
            if (!thumb.contains(img)) {
 
552
                thumb.appendChild(img);
 
553
            }
 
554
        }
 
555
    },
 
556
 
 
557
    /**
 
558
     * Calls _bindThumbDD to create the Y.DD instance used to handle the thumb
 
559
     * movement and binds Slider interaction to the configured value model.
 
560
     *
 
561
     * @method bindUI
 
562
     * @protected
 
563
     */
 
564
    bindUI : function () {
 
565
        /**
 
566
         * Communicates user interaction with the thumb.  Triggers the logic
 
567
         * to update the value via the default function _defUpdateValueFromDD.
 
568
         *
 
569
         * @event thumbDrag
 
570
         * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
 
571
         *  <dl>
 
572
         *      <dt>ddEvent</dt>
 
573
         *          <dd><code>drag:drag</code> event from the managed DD.Drag instance</dd>
 
574
         *  </dl>
 
575
         * @preventable _defUpdateValueFromDD
 
576
         */
 
577
        this.publish(THUMB_DRAG, {defaultFn: this._defUpdateValueFromDD});
 
578
 
 
579
        this._bindThumbDD();
 
580
 
 
581
        this.after('valueChange',      this._afterValueChange);
 
582
        this.after('thumbImageChange', this._afterThumbImageChange);
 
583
        this.after(DISABLED_CHANGE,    this._afterDisabledChange);
 
584
    },
 
585
 
 
586
    /**
 
587
     * Creates the Y.DD instance used to handle the thumb interaction.
 
588
     * 
 
589
     * @method _bindThumbDD
 
590
     * @protected
 
591
     */
 
592
    _bindThumbDD : function () {
 
593
        var ddConf = {
 
594
                node           : this.get(THUMB),
 
595
                constrain2node : this.get(RAIL)
 
596
            },
 
597
            dd;
 
598
 
 
599
        ddConf[this._key.ddStick] = true;
 
600
 
 
601
        this._dd = dd = new Y.DD.Drag(ddConf);
 
602
        dd.on('drag:start', Y.bind(this._onDDStartDrag, this));
 
603
        dd.on('drag:drag',  Y.bind(this._onDDDrag,      this));
 
604
        dd.on('drag:end',   Y.bind(this._onDDEndDrag,   this));
 
605
 
 
606
        this._initRailDD();
 
607
    },
 
608
 
 
609
    /**
 
610
     * Subscribes to the rail Node's mousedown event to actuate the thumb when
 
611
     * backgroundEnabled is true.
 
612
     *
 
613
     * @method _initRailDD
 
614
     * @protected
 
615
     */
 
616
    _initRailDD : function () {
 
617
        this.get(RAIL).on('mousedown',Y.bind(this._handleRailMouseDown,this));
 
618
    },
 
619
 
 
620
    /**
 
621
     * Moves the thumb to the mousedown position and hands control over to DD
 
622
     * if the Slider is not disabled and railEnabled is true.
 
623
     *
 
624
     * @method _handleRailMouseDown
 
625
     * @param e {Event} Mousedown event facade
 
626
     * @protected
 
627
     */
 
628
    _handleRailMouseDown : function (e) {
 
629
        if (this.get('railEnabled') && !this.get(DISABLED)) {
 
630
            var dd      = this._dd,
 
631
                xyIndex = this._key.xyIndex,
 
632
                xy;
 
633
 
 
634
            if (dd.get('primaryButtonOnly') && e.button > 1) {
 
635
                return false;
 
636
            }
 
637
 
 
638
            dd._dragThreshMet = true;
 
639
 
 
640
            dd._fixIEMouseDown();
 
641
            e.halt();
 
642
 
 
643
            Y.DD.DDM.activeDrag = dd;
 
644
 
 
645
            // Adjust registered starting position by half the thumb's x/y
 
646
            xy = dd.get('dragNode').getXY();
 
647
            xy[xyIndex] += this._thumbOffset;
 
648
 
 
649
            dd._setStartPosition(xy);
 
650
 
 
651
            dd.start();
 
652
            dd._moveNode([e.pageX,e.pageY]);
 
653
        }
 
654
    },
 
655
 
 
656
    /**
 
657
     * Synchronizes the DOM state with the attribute settings (most notably
 
658
     * railSize and value).  If thumbImage is provided and is still loading,
 
659
     * sync is delayed until it is complete, since the image's dimensions are
 
660
     * taken into consideration for calculations.
 
661
     *
 
662
     * @method syncUI
 
663
     */
 
664
    syncUI : function () {
 
665
        var img = this.get(THUMB_IMAGE);
 
666
 
 
667
        if (this._isImageLoading(img)) {
 
668
            // Schedule the sync for when the image loads/errors
 
669
            this._scheduleSync();
 
670
        } else {
 
671
            this._ready(img,!this._isImageLoaded(img));
 
672
        }
 
673
    },
 
674
 
 
675
    /**
 
676
     * Binds to the load and error event on the thumbImage to sync the DOM
 
677
     * state with the attribute settings when the image resource is resolved.
 
678
     * The Slider is disabled while it waits.
 
679
     *
 
680
     * @method _scheduleSync
 
681
     * @protected
 
682
     */
 
683
    _scheduleSync : function () {
 
684
        var img, handler;
 
685
 
 
686
        if (!this._stall) {
 
687
            // disable the control until the image is loaded
 
688
            this._disabled = this.get(DISABLED);
 
689
            this.set(DISABLED,true);
 
690
            this._stall    = this.on(DISABLED_CHANGE,this._stallDisabledChange);
 
691
 
 
692
            img     = this.get(THUMB_IMAGE);
 
693
            handler = Y.bind(this._imageLoaded,this,img);
 
694
            img.on('load', handler);
 
695
            img.on('error',handler);
 
696
        }
 
697
    },
 
698
 
 
699
    /**
 
700
     * Method subscribed to the disabledChange event when thumbImage is being
 
701
     * loaded.  Prevents manually enabling the Slider until the thumbImage
 
702
     * resource is resolved.  Intended value is stored during load and set upon
 
703
     * completion.
 
704
     *
 
705
     * @method _stallDisabledChange
 
706
     * @param e {Event} Change event for the disabled attribute
 
707
     * @protected
 
708
     */
 
709
    _stallDisabledChange : function (e) {
 
710
        this._disabled = e.newVal;
 
711
        e.preventDefault();
 
712
    },
 
713
 
 
714
    /**
 
715
     * Event handler assigned to the thumbImage's load and error event if it
 
716
     * was not loaded prior to instantiation.  Calls _ready method and restores
 
717
     * the Slider's disabled attribute.
 
718
     *
 
719
     * @method _imageLoaded
 
720
     * @param e {Event} load or error event fired by the thumbImage
 
721
     * @param img {Node} The thumbImage Node
 
722
     * @protected
 
723
     */
 
724
    _imageLoaded : function (e,img) {
 
725
        var error = (e.type.toLowerCase().indexOf('error') > -1);
 
726
 
 
727
        if (this._stall) {
 
728
            this._stall.detach();
 
729
        }
 
730
 
 
731
 
 
732
        this._stall = false;
 
733
 
 
734
        this._ready(img,error);
 
735
 
 
736
        this.set(DISABLED,this._disabled);
 
737
    },
 
738
 
 
739
    /**
 
740
     * Fires the internal sync event, which barring preventDefault should
 
741
     * execute _defSyncUI.
 
742
     *
 
743
     * @method _ready
 
744
     * @param img {Node} the thumbImage Node
 
745
     * @param error {Boolean} Indicates an error while loading the thumbImage
 
746
     * @protected
 
747
     */
 
748
    _ready : function (img,error) {
 
749
        var method = error ? 'addClass' : 'removeClass';
 
750
 
 
751
        // If the thumb image url results in 404, assign a class to provide
 
752
        // default thumb dimensions/UI
 
753
        this.get(CONTENT_BOX)[method](C_IMAGE_ERROR);
 
754
 
 
755
        this.fire(SYNC);
 
756
    },
 
757
 
 
758
    /**
 
759
     * The default synchronization behavior, updating the Slider's DOM state to
 
760
     * match the current attribute values.
 
761
     *
 
762
     * @method _defSyncUI
 
763
     * @param e {Event} Internal sync event
 
764
     * @protected
 
765
     */
 
766
    _defSyncUI : function (e) {
 
767
        this._uiSetThumbSize();
 
768
 
 
769
        this._setThumbOffset();
 
770
 
 
771
        this._uiSetRailSize();
 
772
 
 
773
        this._setRailOffsetXY();
 
774
 
 
775
        this._setDDGutter();
 
776
 
 
777
        this._setFactor();
 
778
 
 
779
 
 
780
        this.set(VALUE,this.get(VALUE));
 
781
    },
 
782
 
 
783
    /**
 
784
     * Captures the thumbs pixel height or width, depending on the Slider's
 
785
     * axis, for use in positioning calculations.
 
786
     *
 
787
     * @method _uiSetThumbSize
 
788
     * @protected
 
789
     */
 
790
    _uiSetThumbSize : function () {
 
791
        var thumb = this.get(THUMB),
 
792
            dim   = this._key.dim,
 
793
            img   = this.get(THUMB_IMAGE),
 
794
            size;
 
795
 
 
796
        // offsetWidth fails in hidden containers
 
797
        size = parseInt(thumb.getComputedStyle(dim),10);
 
798
 
 
799
 
 
800
        if (img && this._isImageLoaded(img)) {
 
801
 
 
802
            size = img.get(dim);
 
803
        }
 
804
 
 
805
        this._thumbSize = size;
 
806
    },
 
807
 
 
808
    /**
 
809
     * Sets the _thumbOffset property for use in establishing the point in the
 
810
     * thumb that should align to the rail position representing the calculated
 
811
     * value.
 
812
     *
 
813
     * @method _setThumbOffset
 
814
     * @protected
 
815
     */
 
816
    _setThumbOffset : function () {
 
817
        this._thumbOffset = floor(this._thumbSize / 2);
 
818
    },
 
819
 
 
820
    /**
 
821
     * Stores the rail Node's pixel height or width, depending on the Slider's
 
822
     * axis, for use in calculating thumb position from the value.
 
823
     *
 
824
     * @method _uiSetRailSize
 
825
     * @protected
 
826
     */
 
827
    _uiSetRailSize : function () {
 
828
        var rail  = this.get(RAIL),
 
829
            thumb = this.get(THUMB),
 
830
            img   = this.get(THUMB_IMAGE),
 
831
            dim   = this._key.dim,
 
832
            size  = this.get(RAIL_SIZE),
 
833
            setxy = false;
 
834
 
 
835
        if (parseInt(size,10)) {
 
836
 
 
837
            // Convert to pixels
 
838
            rail.setStyle(dim,size);
 
839
            size = parseInt(rail.getComputedStyle(dim),10);
 
840
 
 
841
        } else {
 
842
            // Default from height or width (axis respective), or dims assigned
 
843
            // via css to the rail or thumb, whichever is largest.
 
844
            // Dear implementers, please use railSize, not height/width to
 
845
            // set the rail dims
 
846
            size = this.get(dim);
 
847
            if (parseInt(size,10)) {
 
848
                setxy = true;
 
849
                rail.setStyle(dim,size);
 
850
                size = parseInt(rail.getComputedStyle(dim),10);
 
851
            }
 
852
            size = max(
 
853
                    size|0,
 
854
                    parseInt(thumb.getComputedStyle(dim),10),
 
855
                    parseInt(rail.getComputedStyle(dim),10));
 
856
 
 
857
 
 
858
            if (img && this._isImageLoaded(img)) {
 
859
 
 
860
                size = max(img.get(dim),size);
 
861
            }
 
862
        }
 
863
 
 
864
        rail.setStyle(dim, size + PX);
 
865
 
 
866
        this._railSize = size;
 
867
 
 
868
        // handle the (not recommended) fallback case of setting rail size via
 
869
        // widget height/width params.  This is the only case that sets the
 
870
        // off-axis rail dim in the code.
 
871
        if (setxy) {
 
872
            dim = this._key.offAxisDim;
 
873
            size = this.get(dim);
 
874
            if (size) {
 
875
                rail.set(dim,size);
 
876
            }
 
877
        }
 
878
    },
 
879
 
 
880
    /**
 
881
     * Store the current XY position of the rail Node on the page.  For use in calculating thumb position from value.
 
882
     *
 
883
     * @method _setRailOffsetXY
 
884
     * @protected
 
885
     */
 
886
    _setRailOffsetXY : function () {
 
887
        this._offsetXY = this.get(RAIL).getXY()[this._key.xyIndex] -
 
888
                         this._thumbOffset;
 
889
    },
 
890
 
 
891
    /**
 
892
     * Assigns the gutter attribute to the DD instance to allow the thumb to
 
893
     * overshoot the edges of the rail element up to the _thumbOffset.  By
 
894
     * default, this allows the thumb's center point to align with the far left
 
895
     * or top edge of the rail element to represent the min value and the far
 
896
     * right or bottom edge for the max.
 
897
    *
 
898
    * @method _setDDGutter
 
899
    * @protected
 
900
    */
 
901
    _setDDGutter : function () {
 
902
        var gutter = [0,0,0,0],
 
903
            i      = this._key.xyIndex,
 
904
            dim    = this._thumbOffset,
 
905
            start  = -dim,
 
906
            end    = -1 * (this._thumbSize - dim);
 
907
 
 
908
        if (i) { // y axis
 
909
            gutter[0] = start;
 
910
            gutter[2] = end;
 
911
        } else {
 
912
            gutter[3] = start;
 
913
            gutter[1] = end;
 
914
        }
 
915
            
 
916
 
 
917
        this._dd.set('gutter', gutter.join(' '));
 
918
    },
 
919
 
 
920
    /**
 
921
     * Calculates the multiplier used to translate the value into a thumb
 
922
     * position.
 
923
     *
 
924
     * @method _setFactor
 
925
     * @protected
 
926
     */
 
927
    _setFactor : function () {
 
928
        this._factor = this._railSize ?
 
929
            (this.get(MAX) - this.get(MIN)) / this._railSize :
 
930
            1;
 
931
    },
 
932
 
 
933
    /**
 
934
     * Convenience method for accessing the current value of the Slider.
 
935
     * Equivalent to <code>slider.get(&quot;value&quot;)</code>.
 
936
     *
 
937
     * @method getValue
 
938
     * @return {Number} the value
 
939
     */
 
940
    getValue : function () {
 
941
        return this.get(VALUE);
 
942
    },
 
943
 
 
944
    /**
 
945
     * Convenience method for updating the current value of the Slider.
 
946
     * Equivalent to <code>slider.set(&quot;value&quot;,val)</code>.
 
947
     *
 
948
     * @method setValue
 
949
     * @param val {Number} the new value
 
950
     */
 
951
    setValue : function (val) {
 
952
        this.set(VALUE,val);
 
953
    },
 
954
 
 
955
    /**
 
956
     * Validator applied to new values for the axis attribute. Only
 
957
     * &quot;x&quot; and &quot;y&quot; are permitted.
 
958
     *
 
959
     * @method _validateNewAxis
 
960
     * @param v {String} proposed value for the axis attribute
 
961
     * @return Boolean
 
962
     * @protected
 
963
     */
 
964
    _validateNewAxis : function (v) {
 
965
        return isString(v) &&
 
966
               v.length === 1 && 'xy'.indexOf(v.toLowerCase()) > -1;
 
967
    },
 
968
 
 
969
    /**
 
970
     * Validator applied to the min attribute. Only numbers are allowed.
 
971
     *
 
972
     * @method _validateNewMin
 
973
     * @param v {String} proposed value for the min attribute
 
974
     * @return Boolean
 
975
     * @protected
 
976
     */
 
977
    _validateNewMin : function (v) {
 
978
        return isNumber(v);
 
979
    },
 
980
 
 
981
    /**
 
982
     * Validator applied to the max attribute. Only numbers are allowed.
 
983
     *
 
984
     * @method _validateNewMax
 
985
     * @param v {String} proposed value for the max attribute
 
986
     * @return Boolean
 
987
     * @protected
 
988
     */
 
989
    _validateNewMax : function (v) {
 
990
        return isNumber(v);
 
991
    },
 
992
 
 
993
    /**
 
994
     * Validator applied to the value attribute. Only numbers between the min
 
995
     * and max are allowed.
 
996
     *
 
997
     * @method _validateNewValue
 
998
     * @param v {String} proposed value for the value attribute
 
999
     * @return Boolean
 
1000
     * @protected
 
1001
     */
 
1002
    _validateNewValue : function (v) {
 
1003
        var min    = this.get(MIN),
 
1004
            max    = this.get(MAX);
 
1005
 
 
1006
        return isNumber(v) &&
 
1007
                (min < max ? (v >= min && v <= max) : (v >= max && v <= min));
 
1008
    },
 
1009
 
 
1010
    /**
 
1011
     * Validator applied to the rail attribute. Only allows values through
 
1012
     * before the Slider is rendered.
 
1013
     *
 
1014
     * @method _validateNewRail
 
1015
     * @param v {String} proposed value for the rail attribute
 
1016
     * @return Boolean
 
1017
     * @protected
 
1018
     */
 
1019
    _validateNewRail : function (v) {
 
1020
        return !this.get(RENDERED) || v;
 
1021
    },
 
1022
 
 
1023
    /**
 
1024
     * Validator applied to the thumb attribute. Only allows values through
 
1025
     * before the Slider is rendered.
 
1026
     *
 
1027
     * @method _validateNewThumb
 
1028
     * @param v {String} proposed value for the thumb attribute
 
1029
     * @return Boolean
 
1030
     * @protected
 
1031
     */
 
1032
    _validateNewThumb : function (v) {
 
1033
        return !this.get(RENDERED) || v;
 
1034
    },
 
1035
 
 
1036
    /**
 
1037
     * Validator applied to the thumbImage attribute. Only allows values through
 
1038
     * before the Slider is rendered.
 
1039
     *
 
1040
     * @method _validateNewThumbImage
 
1041
     * @param v {String} proposed value for the thumbImage attribute
 
1042
     * @return Boolean
 
1043
     * @protected
 
1044
     */
 
1045
    _validateNewThumbImage : function (v) {
 
1046
        return !this.get(RENDERED) || v;
 
1047
    },
 
1048
 
 
1049
    /**
 
1050
     * Validator applied to the railSize attribute. Only css size values (e.g.
 
1051
     * '200px' are allowed.
 
1052
     *
 
1053
     * @method _validateNewRailSize
 
1054
     * @param v {String} proposed value for the railSize attribute
 
1055
     * @return Boolean
 
1056
     * @protected
 
1057
     */
 
1058
    _validateNewRailSize : function (v) {
 
1059
        return isString(v) &&
 
1060
            (v === '0' || /^\d+(?:p[xtc]|%|e[mx]|in|[mc]m)$/.test(v));
 
1061
    },
 
1062
 
 
1063
    /**
 
1064
     * Setter applied to the input when updating the railSize attribute.
 
1065
     *
 
1066
     * @method _setAxisFn
 
1067
     * @param v {String} proposed value for the axis attribute
 
1068
     * @return {String} lowercased first character of the input string
 
1069
     * @protected
 
1070
     */
 
1071
    _setAxisFn : function (v) {
 
1072
        return isString(v) ? v.toLowerCase().charAt(0) : null;
 
1073
    },
 
1074
 
 
1075
    /**
 
1076
     * Setter applied to the input when updating the value attribute.
 
1077
     *
 
1078
     * @method _setValueFn
 
1079
     * @param v {Number} proposed new value for the Slider
 
1080
     * @return {Number} rounded value or configured min if non-number input
 
1081
     * @protected
 
1082
     */
 
1083
    _setValueFn : function (v) {
 
1084
        if (!isNumber(v)) { 
 
1085
            v = this.get(MIN);
 
1086
        }
 
1087
 
 
1088
        return round(v);
 
1089
    },
 
1090
 
 
1091
    /**
 
1092
     * Setter applied to the input when updating the rail attribute.  Input can
 
1093
     * be a Node, raw HTMLElement, or a selector string to locate it.
 
1094
     *
 
1095
     * @method _setRailFn
 
1096
     * @param v {Node|String|HTMLElement} The rail element Node or selector
 
1097
     * @return {Node} The Node if found.  Otherwise null.
 
1098
     * @protected
 
1099
     */
 
1100
    _setRailFn : function (v) {
 
1101
        return v ? Y.get(v) : null;
 
1102
    },
 
1103
 
 
1104
    /**
 
1105
     * Setter applied to the input when updating the thumb attribute.  Input can
 
1106
     * be a Node, raw HTMLElement, or a selector string to locate it.
 
1107
     *
 
1108
     * @method _setThumbFn
 
1109
     * @param v {Node|String|HTMLElement} The thumb element Node or selector
 
1110
     * @return {Node} The Node if found.  Otherwise null.
 
1111
     * @protected
 
1112
     */
 
1113
    _setThumbFn : function (v) {
 
1114
        return v ? Y.get(v) : null;
 
1115
    },
 
1116
 
 
1117
    /**
 
1118
     * Setter applied to the input when updating the thumbImage attribute.
 
1119
     * Input can be a Node, raw HTMLElement, selector string to locate it, or
 
1120
     * the URL for an image resource.
 
1121
     *
 
1122
     * String input will be treated as a selector.  If no element is found using
 
1123
     * the selector, an <code>img</code> Node will be created with the string
 
1124
     * used as the <code>src</code> attribute.
 
1125
     *
 
1126
     * @method _setThumbImageFn
 
1127
     * @param v {Node|String|HTMLElement} The thumbImage element Node, selector,
 
1128
     *          or image URL
 
1129
     * @return {Node} The Node if found or created.  Otherwise null.
 
1130
     * @protected
 
1131
     */
 
1132
    _setThumbImageFn : function (v) {
 
1133
        return v ? Y.get(v) ||
 
1134
                Y.Node.create('<img src="'+v+'" alt="Slider thumb">') :
 
1135
                null;
 
1136
    },
 
1137
 
 
1138
 
 
1139
 
 
1140
 
 
1141
    /**
 
1142
     * Caches the current page position of the rail element and fires the
 
1143
     * slideStart event in response to the DD's drag:start.
 
1144
     *
 
1145
     * @method _onDDStartDrag
 
1146
     * @param e {Event} the DD instance's drag:start custom event
 
1147
     * @protected
 
1148
     */
 
1149
    _onDDStartDrag : function (e) {
 
1150
        this._setRailOffsetXY();
 
1151
        this.fire(SLIDE_START,{ ddEvent: e });
 
1152
    },
 
1153
 
 
1154
    /**
 
1155
     * Fires the thumbDrag event to queue Slider value update.
 
1156
     *
 
1157
     * @method _onDDDrag
 
1158
     * @param e {Event} the DD instance's drag:drag custom event
 
1159
     * @protected
 
1160
     */
 
1161
    _onDDDrag : function (e) {
 
1162
        this.fire(THUMB_DRAG, { ddEvent: e });
 
1163
    },
 
1164
 
 
1165
    /**
 
1166
     * The default value update behavior in response to Slider thumb
 
1167
     * interaction.  Calculates the value using stored offsets, the _factor
 
1168
     * multiplier and the min value.
 
1169
     *
 
1170
     * @method _defUpdateValueFromDD
 
1171
     * @param e {Event} the internal thumbDrag event
 
1172
     * @protected
 
1173
     */
 
1174
    _defUpdateValueFromDD : function (e) {
 
1175
        var before = this.get(VALUE),
 
1176
            val    = e.ddEvent[this._key.eventPageAxis] - this._offsetXY;
 
1177
 
 
1178
 
 
1179
        val = round(this.get(MIN) + (val * this._factor));
 
1180
 
 
1181
        if (before !== val) {
 
1182
            this.set(VALUE, val, { ddEvent: e.ddEvent });
 
1183
        }
 
1184
    },
 
1185
 
 
1186
    /**
 
1187
     * Fires the slideEnd event.
 
1188
     *
 
1189
     * @method _onDDEndDrag
 
1190
     * @param e {Event} the DD instance's drag:end custom event
 
1191
     * @protected
 
1192
     */
 
1193
    _onDDEndDrag : function (e) {
 
1194
        this.fire(SLIDE_END,{ ddEvent: e });
 
1195
    },
 
1196
 
 
1197
 
 
1198
 
 
1199
 
 
1200
    /**
 
1201
     * The default behavior for calculating the placement of the thumb in
 
1202
     * response to a value attribute update.  This is performed in response
 
1203
     * to firing the internal valueSet event.
 
1204
     *
 
1205
     * @method _defSetThumbPosition
 
1206
     * @param e {Event} the valueSet custom event
 
1207
     * @protected
 
1208
     */
 
1209
    _defSetThumbPosition : function (e) {
 
1210
        var min = this.get(MIN),
 
1211
            max = this.get(MAX),
 
1212
            v   = e.changeEv.newVal;
 
1213
 
 
1214
 
 
1215
        v = round(((v - min) / (max - min)) * this._railSize);
 
1216
 
 
1217
        this._uiPositionThumb(v);
 
1218
    },
 
1219
 
 
1220
    /**
 
1221
     * Places the thumb at a particular X or Y location based on the configured
 
1222
     * axis.
 
1223
     *
 
1224
     * @method _uiPositionThumb
 
1225
     * @param xy {Number} the desired left or top pixel position of the thumb
 
1226
     *           in relation to the rail Node.
 
1227
     * @protected
 
1228
     */
 
1229
    _uiPositionThumb : function (xy) {
 
1230
        var dd  = this._dd;
 
1231
 
 
1232
        xy += this._offsetXY;
 
1233
 
 
1234
        dd._setStartPosition(dd.get('dragNode').getXY());
 
1235
 
 
1236
        // stickX/stickY config on DD instance will negate off-axis move
 
1237
        dd._moveNode([xy,xy],true);
 
1238
    },
 
1239
 
 
1240
 
 
1241
 
 
1242
    /**
 
1243
     * Fires the internal valueSet event in response to a change in the value
 
1244
     * attribute.
 
1245
     *
 
1246
     * @method _afterValueChange
 
1247
     * @param e {Event} valueChange custom event
 
1248
     * @protected
 
1249
     */
 
1250
    _afterValueChange : function (e) {
 
1251
        if (!e.ddEvent) {
 
1252
 
 
1253
            this.fire(VALUE_SET,{ changeEv: e });
 
1254
        }
 
1255
    },
 
1256
 
 
1257
    /**
 
1258
     * Replaces the thumb Node in response to a change in the thumb attribute.
 
1259
     * This only has effect before the Slider is rendered.
 
1260
     *
 
1261
     * @method _afterThumbChange
 
1262
     * @param e {Event} thumbChange custom event
 
1263
     * @protected
 
1264
     */
 
1265
    _afterThumbChange : function (e) {
 
1266
        var thumb;
 
1267
 
 
1268
        if (this.get(RENDERED)) {
 
1269
            if (e.prevValue) {
 
1270
                e.prevValue.get('parentNode').removeChild(e.prevValue);
 
1271
            }
 
1272
 
 
1273
            this._initThumb();
 
1274
            
 
1275
            thumb = this.get(THUMB);
 
1276
            this._dd.set('node',thumb);
 
1277
            this._dd.set('dragNode',thumb);
 
1278
 
 
1279
            this.syncUI();
 
1280
        }
 
1281
    },
 
1282
 
 
1283
    /**
 
1284
     * Sets or replaces the thumb's contained <code>img</code> Node with the
 
1285
     * new Node in response to a change in the thumbImage attribute.  This only
 
1286
     * has effect before the Slider is rendered.
 
1287
     *
 
1288
     * @method _afterThumbImageChange
 
1289
     * @param e {Event} thumbImageChange custom event
 
1290
     * @protected
 
1291
     */
 
1292
    _afterThumbImageChange : function (e) {
 
1293
        if (this.get(RENDERED)) {
 
1294
            if (e.prevValue) {
 
1295
                e.prevValue.get('parentNode').removeChild(e.prevValue);
 
1296
            }
 
1297
 
 
1298
            this._initThumbImage();
 
1299
            
 
1300
            this.syncUI();
 
1301
        }
 
1302
    },
 
1303
 
 
1304
    /**
 
1305
     * Calls syncUI to update the Slider UI in response to change in the min
 
1306
     * attribute.
 
1307
     *
 
1308
     * @method _afterMinChange
 
1309
     * @param e {Event} minChange custom event
 
1310
     * @protected
 
1311
     */
 
1312
    _afterMinChange : function (e) {
 
1313
        this._refresh(e);
 
1314
    },
 
1315
 
 
1316
    /**
 
1317
     * Calls syncUI to update the Slider UI in response to change in the max
 
1318
     * attribute.
 
1319
     *
 
1320
     * @method _afterMaxChange
 
1321
     * @param e {Event} maxChange custom event
 
1322
     * @protected
 
1323
     */
 
1324
    _afterMaxChange : function (e) {
 
1325
        this._refresh(e);
 
1326
    },
 
1327
 
 
1328
    /**
 
1329
     * Calls syncUI to update the Slider UI in response to change in the
 
1330
     * railSize attribute.
 
1331
     *
 
1332
     * @method _afterRailSizeChange
 
1333
     * @param e {Event} railSizeChange custom event
 
1334
     * @protected
 
1335
     */
 
1336
    _afterRailSizeChange : function (e) {
 
1337
        this._refresh(e);
 
1338
    },
 
1339
 
 
1340
    /**
 
1341
     * Locks or unlocks the DD instance in response to a change in the disabled
 
1342
     * attribute.
 
1343
     *
 
1344
     * @method _afterDisabledChange
 
1345
     * @param e {Event} disabledChange custom event
 
1346
     * @protected
 
1347
     */
 
1348
    _afterDisabledChange : function (e) {
 
1349
        if (this._dd) {
 
1350
            this._dd.set('lock',e.newVal);
 
1351
        }
 
1352
    },
 
1353
 
 
1354
    /**
 
1355
     * Common handler to call syncUI in response to change events that occurred
 
1356
     * after the Slider is rendered.
 
1357
     *
 
1358
     * @method _refresh
 
1359
     * @param e {Event} An attribute change event
 
1360
     * @protected
 
1361
     */
 
1362
    _refresh : function (e) {
 
1363
        if (e.newVal !== e.prevVal && this.get(RENDERED)) {
 
1364
            this.syncUI();
 
1365
        }
 
1366
    },
 
1367
 
 
1368
    /**
 
1369
     * Used to determine if there is a current or pending request for the
 
1370
     * thumbImage resource.
 
1371
     *
 
1372
     * @method _isImageLoading
 
1373
     * @param img {Node} <code>img</code> Node
 
1374
     * @return Boolean
 
1375
     * @protected
 
1376
     */
 
1377
    _isImageLoading : function (img) {
 
1378
        return img && !img.get(COMPLETE);
 
1379
    },
 
1380
 
 
1381
    /**
 
1382
     * Used to determine if the image resource loaded successfully or there was
 
1383
     * an error.
 
1384
     *
 
1385
     * NOTES:
 
1386
     * <ul>
 
1387
     *    <li>img load error fired xbrowser for image resources not yet resolved</li>
 
1388
     *    <li>img.complete reports false in IE for images not yet loaded as well as images that failed to load</li>
 
1389
     *    <li>img.complete true && img.naturalWidth == 0 in FF and Safari indicate image failed to load</li>
 
1390
     *    <li>img.complete && img.width == 0 in Opera indicates image failed to load</li>
 
1391
     * </ul>
 
1392
     *
 
1393
     * @method _isImageLoaded
 
1394
     * @param img {Node} <code>img</code> Node
 
1395
     * @return Boolean
 
1396
     * @protected
 
1397
     */
 
1398
    _isImageLoaded : function (img) {
 
1399
        if (img) {
 
1400
            var w = img.get('naturalWidth');
 
1401
            return img.get(COMPLETE) && (!isNumber(w) ? img.get(WIDTH) : w);
 
1402
        }
 
1403
 
 
1404
        return true;
 
1405
    }
 
1406
 
 
1407
});
 
1408
 
 
1409
Y.Slider = Slider;
 
1410
 
 
1411
 
 
1412
}, '3.0.0pr2' ,{requires:['widget','dd-constrain']});