[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('slider-base', function (Y, NAME) { 9 10 /** 11 * Create a sliding value range input visualized as a draggable thumb on a 12 * background element. 13 * 14 * @module slider 15 * @submodule slider-base 16 */ 17 18 var INVALID_VALUE = Y.Attribute.INVALID_VALUE; 19 20 /** 21 * Create a slider to represent an input control capable of representing a 22 * series of intermediate states based on the position of the slider's thumb. 23 * These states are typically aligned to a value algorithm whereby the thumb 24 * position corresponds to a given value. Sliders may be oriented vertically or 25 * horizontally, based on the <code>axis</code> configuration. 26 * 27 * @class SliderBase 28 * @extends Widget 29 * @param config {Object} Configuration object 30 * @constructor 31 */ 32 function SliderBase() { 33 SliderBase.superclass.constructor.apply( this, arguments ); 34 } 35 36 Y.SliderBase = Y.extend( SliderBase, Y.Widget, { 37 38 // Y.Slider prototype 39 40 /** 41 * Construction logic executed during Slider instantiation. 42 * 43 * @method initializer 44 * @protected 45 */ 46 initializer : function () { 47 /** 48 * The configured axis, stored for fast lookup since it's a writeOnce 49 * attribute. This is for use by extension classes. For 50 * implementation code, use <code>get( "axis" )</code> for 51 * authoritative source. Never write to this property. 52 * 53 * @property axis 54 * @type {String} 55 * @protected 56 */ 57 this.axis = this.get( 'axis' ); 58 59 /** 60 * Cached fast access map for DOM properties and attributes that 61 * pertain to accessing dimensional or positioning information 62 * according to the Slider's axis (e.g. "height" vs. 63 * "width"). Extension classes should add to this collection 64 * for axis related strings if necessary. 65 * 66 * @property _key 67 * @type {Object} 68 * @protected 69 */ 70 this._key = { 71 dim : ( this.axis === 'y' ) ? 'height' : 'width', 72 minEdge: ( this.axis === 'y' ) ? 'top' : 'left', 73 maxEdge: ( this.axis === 'y' ) ? 'bottom' : 'right', 74 xyIndex: ( this.axis === 'y' ) ? 1 : 0 75 }; 76 77 /** 78 * Signals that the thumb has moved. Payload includes the thumb's 79 * pixel offset from the top/left edge of the rail, and if triggered by 80 * dragging the thumb, the <code>drag:drag</code> event. 81 * 82 * @event thumbMove 83 * @param event {Event} The event object for the thumbMove with the 84 * following extra properties: 85 * <dl> 86 * <dt>offset</dt> 87 * <dd>Pixel offset from top/left of the slider to the new 88 * thumb position</dd> 89 * <dt>ddEvent (deprecated)</dt> 90 * <dd><code>drag:drag</code> event from the thumb</dd> 91 * <dt>originEvent</dt> 92 * <dd><code>drag:drag</code> event from the thumb</dd> 93 * </dl> 94 */ 95 this.publish( 'thumbMove', { 96 defaultFn: this._defThumbMoveFn, 97 queuable : true 98 } ); 99 }, 100 101 /** 102 * Create the DOM structure for the Slider. 103 * 104 * @method renderUI 105 * @protected 106 */ 107 renderUI : function () { 108 var contentBox = this.get( 'contentBox' ); 109 110 /** 111 * The Node instance of the Slider's rail element. Do not write to 112 * this property. 113 * 114 * @property rail 115 * @type {Node} 116 */ 117 this.rail = this.renderRail(); 118 119 this._uiSetRailLength( this.get( 'length' ) ); 120 121 /** 122 * The Node instance of the Slider's thumb element. Do not write to 123 * this property. 124 * 125 * @property thumb 126 * @type {Node} 127 */ 128 this.thumb = this.renderThumb(); 129 130 this.rail.appendChild( this.thumb ); 131 // @TODO: insert( contentBox, 'replace' ) or setHTML? 132 contentBox.appendChild( this.rail ); 133 134 // <span class="yui3-slider-x"> 135 contentBox.addClass( this.getClassName( this.axis ) ); 136 }, 137 138 /** 139 * Creates the Slider rail DOM subtree for insertion into the Slider's 140 * <code>contentBox</code>. Override this method if you want to provide 141 * the rail element (presumably from existing markup). 142 * 143 * @method renderRail 144 * @return {Node} the rail node subtree 145 */ 146 renderRail: function () { 147 var minCapClass = this.getClassName( 'rail', 'cap', this._key.minEdge ), 148 maxCapClass = this.getClassName( 'rail', 'cap', this._key.maxEdge ); 149 150 return Y.Node.create( 151 Y.Lang.sub( this.RAIL_TEMPLATE, { 152 railClass : this.getClassName( 'rail' ), 153 railMinCapClass: minCapClass, 154 railMaxCapClass: maxCapClass 155 } ) ); 156 }, 157 158 /** 159 * Sets the rail length according to the <code>length</code> attribute. 160 * 161 * @method _uiSetRailLength 162 * @param length {String} the length to apply to the rail style 163 * @protected 164 */ 165 _uiSetRailLength: function ( length ) { 166 this.rail.setStyle( this._key.dim, length ); 167 }, 168 169 /** 170 * Creates the Slider thumb DOM subtree for insertion into the Slider's 171 * rail. Override this method if you want to provide the thumb element 172 * (presumably from existing markup). 173 * 174 * @method renderThumb 175 * @return {Node} the thumb node subtree 176 */ 177 renderThumb: function () { 178 this._initThumbUrl(); 179 180 var imageUrl = this.get( 'thumbUrl' ); 181 182 return Y.Node.create( 183 Y.Lang.sub( this.THUMB_TEMPLATE, { 184 thumbClass : this.getClassName( 'thumb' ), 185 thumbShadowClass: this.getClassName( 'thumb', 'shadow' ), 186 thumbImageClass : this.getClassName( 'thumb', 'image' ), 187 thumbShadowUrl : imageUrl, 188 thumbImageUrl : imageUrl, 189 thumbAriaLabelId: this.getClassName( 'label', Y.guid()) // get unique id for specifying a label for ARIA 190 } ) ); 191 }, 192 193 /** 194 * Gives focus to the thumb enabling keyboard access after clicking thumb 195 * 196 * @method _onThumbClick 197 * @protected 198 */ 199 _onThumbClick : function(e){ 200 this.thumb.focus(); 201 }, 202 203 204 /** 205 * Creates the Y.DD.Drag instance used to handle the thumb movement and 206 * binds Slider interaction to the configured value model. 207 * 208 * @method bindUI 209 * @protected 210 */ 211 bindUI : function () { 212 213 // Begin keyboard listeners /////////////////////////////// 214 var boundingBox = this.get("boundingBox"), //Y.one('body'), 215 // Looking for a key event which will fire continously across browsers while the key is held down. 216 keyEvent = (!Y.UA.opera) ? "down:" : "press:", 217 // 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home 218 keyEventSpec = keyEvent + "38,40,33,34,35,36", 219 // 37 , 39 = arrow left/right 220 keyLeftRightSpec = keyEvent + "37,39", 221 // 37 , 39 = arrow left/right + meta (command/apple key) for mac 222 keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta"; 223 224 boundingBox.on("key", this._onDirectionKey, keyEventSpec, this); 225 boundingBox.on("key", this._onLeftRightKey, keyLeftRightSpec, this); 226 boundingBox.on("key", this._onLeftRightKeyMeta, keyLeftRightSpecMeta, this); 227 // End keyboard listeners ////////////////////////////////// 228 229 this.thumb.on('click', this._onThumbClick, this); 230 231 this._bindThumbDD(); 232 233 this._bindValueLogic(); 234 235 this.after( 'disabledChange', this._afterDisabledChange ); 236 this.after( 'lengthChange', this._afterLengthChange ); 237 238 }, 239 240 /** 241 * increments Slider value by a minor increment 242 * 243 * @method _incrMinor 244 * @protected 245 */ 246 _incrMinor : function(){ 247 this.set('value', (this.get('value') + this.get('minorStep'))); 248 }, 249 250 /** 251 * decrements Slider value by a minor increment 252 * 253 * @method _decrMinor 254 * @protected 255 */ 256 _decrMinor : function(){ 257 this.set('value', (this.get('value') - this.get('minorStep'))); 258 }, 259 260 /** 261 * increments Slider value by a major increment 262 * 263 * @method _incrMajor 264 * @protected 265 */ 266 _incrMajor : function(){ 267 this.set('value', (this.get('value') + this.get('majorStep'))); 268 }, 269 270 /** 271 * decrements Slider value by a major increment 272 * 273 * @method _decrMajor 274 * @protected 275 */ 276 _decrMajor : function(){ 277 this.set('value', (this.get('value') - this.get('majorStep'))); 278 }, 279 280 /** 281 * sets the Slider value to the min value. 282 * 283 * @method _setToMin 284 * @protected 285 */ 286 _setToMin : function(e){ 287 this.set('value', this.get('min')); 288 }, 289 290 /** 291 * sets the Slider value to the max value. 292 * 293 * @method _setToMax 294 * @protected 295 */ 296 _setToMax : function(e){ 297 this.set('value', this.get('max')); 298 }, 299 300 /** 301 * sets the Slider's value in response to key events. 302 * Left and right keys are in a separate method 303 * in case an implementation wants to increment values 304 * but needs left and right arrow keys for other purposes. 305 * 306 * @method _onDirectionKey 307 * @param e {Event} the key event 308 * @protected 309 */ 310 _onDirectionKey : function(e) { 311 e.preventDefault(); 312 if(this.get('disabled') === false){ 313 switch (e.charCode) { 314 case 38: // up 315 this._incrMinor(); 316 break; 317 case 40: // down 318 this._decrMinor(); 319 break; 320 case 36: // home 321 this._setToMin(); 322 break; 323 case 35: // end 324 this._setToMax(); 325 break; 326 case 33: // page up 327 this._incrMajor(); 328 break; 329 case 34: // page down 330 this._decrMajor(); 331 break; 332 } 333 } 334 }, 335 336 /** 337 * sets the Slider's value in response to left or right key events 338 * 339 * @method _onLeftRightKey 340 * @param e {Event} the key event 341 * @protected 342 */ 343 _onLeftRightKey : function(e) { 344 e.preventDefault(); 345 if(this.get('disabled') === false){ 346 switch (e.charCode) { 347 case 37: // left 348 this._decrMinor(); 349 break; 350 case 39: // right 351 this._incrMinor(); 352 break; 353 } 354 } 355 }, 356 357 /** 358 * sets the Slider's value in response to left or right key events when a meta (mac command/apple) key is also pressed 359 * 360 * @method _onLeftRightKeyMeta 361 * @param e {Event} the key event 362 * @protected 363 */ 364 _onLeftRightKeyMeta : function(e) { 365 e.preventDefault(); 366 if(this.get('disabled') === false){ 367 switch (e.charCode) { 368 case 37: // left + meta 369 this._setToMin(); 370 break; 371 case 39: // right + meta 372 this._setToMax(); 373 break; 374 } 375 } 376 }, 377 378 379 380 381 382 /** 383 * Makes the thumb draggable and constrains it to the rail. 384 * 385 * @method _bindThumbDD 386 * @protected 387 */ 388 _bindThumbDD: function () { 389 var config = { constrain: this.rail }; 390 391 // { constrain: rail, stickX: true } 392 config[ 'stick' + this.axis.toUpperCase() ] = true; 393 394 /** 395 * The DD.Drag instance linked to the thumb node. 396 * 397 * @property _dd 398 * @type {DD.Drag} 399 * @protected 400 */ 401 this._dd = new Y.DD.Drag( { 402 node : this.thumb, 403 bubble : false, 404 on : { 405 'drag:start': Y.bind( this._onDragStart, this ) 406 }, 407 after : { 408 'drag:drag': Y.bind( this._afterDrag, this ), 409 'drag:end' : Y.bind( this._afterDragEnd, this ) 410 } 411 } ); 412 413 // Constrain the thumb to the rail 414 this._dd.plug( Y.Plugin.DDConstrained, config ); 415 }, 416 417 /** 418 * Stub implementation. Override this (presumably in a class extension) to 419 * initialize any value logic that depends on the presence of the Drag 420 * instance. 421 * 422 * @method _bindValueLogic 423 * @protected 424 */ 425 _bindValueLogic: function () {}, 426 427 /** 428 * Moves the thumb to pixel offset position along the rail. 429 * 430 * @method _uiMoveThumb 431 * @param offset {Number} the pixel offset to set as left or top style 432 * @param [options] {Object} Details to send with the `thumbMove` event 433 * @protected 434 */ 435 _uiMoveThumb: function ( offset, options ) { 436 if ( this.thumb ) { 437 this.thumb.setStyle( this._key.minEdge, offset + 'px' ); 438 439 440 options || (options = {}); 441 options.offset = offset; 442 443 this.fire( 'thumbMove', options ); 444 } 445 }, 446 447 /** 448 * Dispatches the <code>slideStart</code> event. 449 * 450 * @method _onDragStart 451 * @param e {Event} the <code>drag:start</code> event from the thumb 452 * @protected 453 */ 454 _onDragStart: function ( e ) { 455 /** 456 * Signals the beginning of a thumb drag operation. Payload includes 457 * the thumb's drag:start event. 458 * 459 * @event slideStart 460 * @param event {Event} The event object for the slideStart with the 461 * following extra properties: 462 * <dl> 463 * <dt>ddEvent (deprecated)</dt> 464 * <dd><code>drag:start</code> event from the thumb</dd> 465 * <dt>originEvent</dt> 466 * <dd><code>drag:start</code> event from the thumb</dd> 467 * </dl> 468 */ 469 this.fire('slideStart', { 470 ddEvent: e, // for backward compatibility 471 originEvent: e 472 }); 473 }, 474 475 /** 476 * Dispatches the <code>thumbMove</code> event. 477 * 478 * @method _afterDrag 479 * @param e {Event} the <code>drag:drag</code> event from the thumb 480 * @protected 481 */ 482 _afterDrag: function ( e ) { 483 var thumbXY = e.info.xy[ this._key.xyIndex ], 484 railXY = e.target.con._regionCache[ this._key.minEdge ]; 485 486 this.fire( 'thumbMove', { 487 offset : (thumbXY - railXY), 488 ddEvent: e, // for backward compatibility 489 originEvent: e 490 } ); 491 }, 492 493 /** 494 * Dispatches the <code>slideEnd</code> event. 495 * 496 * @method _afterDragEnd 497 * @param e {Event} the <code>drag:end</code> event from the thumb 498 * @protected 499 */ 500 _afterDragEnd: function ( e ) { 501 /** 502 * Signals the end of a thumb drag operation. Payload includes 503 * the thumb's drag:end event. 504 * 505 * @event slideEnd 506 * @param event {Event} The event object for the slideEnd with the 507 * following extra properties: 508 * <dl> 509 * <dt>ddEvent (deprecated)</dt> 510 * <dd><code>drag:end</code> event from the thumb</dd> 511 * <dt>originEvent</dt> 512 * <dd><code>drag:end</code> event from the thumb</dd> 513 * </dl> 514 */ 515 this.fire('slideEnd', { 516 ddEvent: e, 517 originEvent: e 518 }); 519 }, 520 521 /** 522 * Locks or unlocks the thumb. 523 * 524 * @method _afterDisabledChange 525 * @param e {Event} The disabledChange event object 526 * @protected 527 */ 528 _afterDisabledChange: function ( e ) { 529 this._dd.set( 'lock', e.newVal ); 530 }, 531 532 /** 533 * Handles changes to the <code>length</code> attribute. By default, it 534 * triggers an update to the UI. 535 * 536 * @method _afterLengthChange 537 * @param e {Event} The lengthChange event object 538 * @protected 539 */ 540 _afterLengthChange: function ( e ) { 541 if ( this.get( 'rendered' ) ) { 542 this._uiSetRailLength( e.newVal ); 543 544 this.syncUI(); 545 } 546 }, 547 548 /** 549 * Synchronizes the DOM state with the attribute settings. 550 * 551 * @method syncUI 552 */ 553 syncUI : function () { 554 this._dd.con.resetCache(); 555 556 this._syncThumbPosition(); 557 558 // Forces a reflow of the bounding box to address IE8 inline-block 559 // container not expanding correctly. bug 2527905 560 //this.get('boundingBox').toggleClass(''); 561 this.thumb.set('aria-valuemin', this.get('min')); 562 this.thumb.set('aria-valuemax', this.get('max')); 563 564 this._dd.set('lock', this.get('disabled')); 565 }, 566 567 /** 568 * Stub implementation. Override this (presumably in a class extension) to 569 * ensure the thumb is in the correct position according to the value 570 * alogorithm. 571 * instance. 572 * 573 * @method _syncThumbPosition 574 * @protected 575 */ 576 _syncThumbPosition: function () {}, 577 578 /** 579 * Validates the axis is "x" or "y" (case insensitive). 580 * Converts to lower case for storage. 581 * 582 * @method _setAxis 583 * @param v {String} proposed value for the axis attribute 584 * @return {String} lowercased first character of the input string 585 * @protected 586 */ 587 _setAxis : function (v) { 588 v = ( v + '' ).toLowerCase(); 589 590 return ( v === 'x' || v === 'y' ) ? v : INVALID_VALUE; 591 }, 592 593 /** 594 * <p>Ensures the stored length value is a string with a quantity and unit. 595 * Unit will be defaulted to "px" if not included. Rejects 596 * values less than or equal to 0 and those that don't at least start with 597 * a number.</p> 598 * 599 * <p>Currently only pixel lengths are supported.</p> 600 * 601 * @method _setLength 602 * @param v {String} proposed value for the length attribute 603 * @return {String} the sanitized value 604 * @protected 605 */ 606 _setLength: function ( v ) { 607 v = ( v + '' ).toLowerCase(); 608 609 var length = parseFloat( v, 10 ), 610 units = v.replace( /[\d\.\-]/g, '' ) || this.DEF_UNIT; 611 612 return length > 0 ? ( length + units ) : INVALID_VALUE; 613 }, 614 615 /** 616 * <p>Defaults the thumbURL attribute according to the current skin, or 617 * "sam" if none can be determined. Horizontal Sliders will have 618 * their <code>thumbUrl</code> attribute set to</p> 619 * <p><code>"/<em>configured</em>/<em>yu</em>i/<em>builddi</em>r/slider-base/assets/skins/sam/thumb-x.png"</code></p> 620 * <p>And vertical thumbs will get</p> 621 * <p><code>"/<em>configured</em>/<em>yui</em>/<em>builddir</em>/slider-base/assets/skins/sam/thumb-y.png"</code></p> 622 * 623 * @method _initThumbUrl 624 * @protected 625 */ 626 _initThumbUrl: function () { 627 if (!this.get('thumbUrl')) { 628 var skin = this.getSkinName() || 'sam', 629 base = Y.config.base; 630 631 // Unfortunate hack to avoid requesting image resources from the 632 // combo service. The combo service does not serve images. 633 if (base.indexOf('http://yui.yahooapis.com/combo') === 0) { 634 base = 'http://yui.yahooapis.com/' + Y.version + '/build/'; 635 } 636 637 // <img src="/path/to/build/slider-base/assets/skins/sam/thumb-x.png"> 638 this.set('thumbUrl', base + 'slider-base/assets/skins/' + 639 skin + '/thumb-' + this.axis + '.png'); 640 641 } 642 }, 643 644 /** 645 * Bounding box template that will contain the Slider's DOM subtree. <span>s are used to support inline-block styling. 646 * 647 * @property BOUNDING_TEMPLATE 648 * @type {String} 649 * @default <span></span> 650 */ 651 BOUNDING_TEMPLATE : '<span></span>', 652 653 /** 654 * Content box template that will contain the Slider's rail and thumb. 655 * 656 * @property CONTENT_TEMPLATE 657 * @type {String} 658 * @default <span></span> 659 */ 660 CONTENT_TEMPLATE : '<span></span>', 661 662 /** 663 * Rail template that will contain the end caps and the thumb. 664 * {placeholder}s are used for template substitution at render time. 665 * 666 * @property RAIL_TEMPLATE 667 * @type {String} 668 * @default <span class="{railClass}"><span class="{railMinCapClass}"></span><span class="{railMaxCapClass}"></span></span> 669 */ 670 RAIL_TEMPLATE : '<span class="{railClass}">' + 671 '<span class="{railMinCapClass}"></span>' + 672 '<span class="{railMaxCapClass}"></span>' + 673 '</span>', 674 675 /** 676 * Thumb template that will contain the thumb image and shadow. <img> 677 * tags are used instead of background images to avoid a flicker bug in IE. 678 * {placeholder}s are used for template substitution at render time. 679 * 680 * @property THUMB_TEMPLATE 681 * @type {String} 682 * @default <span class="{thumbClass}" tabindex="-1"><img src="{thumbShadowUrl}" alt="Slider thumb shadow" class="{thumbShadowClass}"><img src="{thumbImageUrl}" alt="Slider thumb" class="{thumbImageClass}"></span> 683 */ 684 THUMB_TEMPLATE : '<span class="{thumbClass}" aria-labelledby="{thumbAriaLabelId}" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0">' + // keyboard access jeff tabindex="-1" 685 '<img src="{thumbShadowUrl}" ' + 686 'alt="Slider thumb shadow" ' + 687 'class="{thumbShadowClass}">' + 688 '<img src="{thumbImageUrl}" ' + 689 'alt="Slider thumb" ' + 690 'class="{thumbImageClass}">' + 691 '</span>' 692 693 }, { 694 695 // Y.SliderBase static properties 696 697 /** 698 * The identity of the widget. 699 * 700 * @property NAME 701 * @type String 702 * @default 'sliderBase' 703 * @readOnly 704 * @protected 705 * @static 706 */ 707 NAME : 'sliderBase', 708 709 /** 710 * Static property used to define the default attribute configuration of 711 * the Widget. 712 * 713 * @property ATTRS 714 * @type {Object} 715 * @protected 716 * @static 717 */ 718 ATTRS : { 719 720 /** 721 * Axis upon which the Slider's thumb moves. "x" for 722 * horizontal, "y" for vertical. 723 * 724 * @attribute axis 725 * @type {String} 726 * @default "x" 727 * @writeOnce 728 */ 729 axis : { 730 value : 'x', 731 writeOnce : true, 732 setter : '_setAxis', 733 lazyAdd : false 734 }, 735 736 /** 737 * The length of the rail (exclusive of the end caps if positioned by 738 * CSS). This corresponds to the movable range of the thumb. 739 * 740 * @attribute length 741 * @type {String | Number} e.g. "200px" or 200 742 * @default 150px 743 */ 744 length: { 745 value: '150px', 746 setter: '_setLength' 747 }, 748 749 /** 750 * Path to the thumb image. This will be used as both the thumb and 751 * shadow as a sprite. Defaults at render() to thumb-x.png or 752 * thumb-y.png in the skin directory of the current skin. 753 * 754 * @attribute thumbUrl 755 * @type {String} 756 * @default thumb-x.png or thumb-y.png in the sam skin directory of the 757 * current build path for Slider 758 */ 759 thumbUrl: { 760 value: null, 761 validator: Y.Lang.isString 762 } 763 } 764 }); 765 766 767 }, '3.17.2', {"requires": ["widget", "dd-constrain", "event-key"], "skinnable": true});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |