[ 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 Y.log("Setting thumb " + this._key.minEdge + " to " + offset + "px","info","slider"); 440 441 options || (options = {}); 442 options.offset = offset; 443 444 this.fire( 'thumbMove', options ); 445 } 446 }, 447 448 /** 449 * Dispatches the <code>slideStart</code> event. 450 * 451 * @method _onDragStart 452 * @param e {Event} the <code>drag:start</code> event from the thumb 453 * @protected 454 */ 455 _onDragStart: function ( e ) { 456 /** 457 * Signals the beginning of a thumb drag operation. Payload includes 458 * the thumb's drag:start event. 459 * 460 * @event slideStart 461 * @param event {Event} The event object for the slideStart with the 462 * following extra properties: 463 * <dl> 464 * <dt>ddEvent (deprecated)</dt> 465 * <dd><code>drag:start</code> event from the thumb</dd> 466 * <dt>originEvent</dt> 467 * <dd><code>drag:start</code> event from the thumb</dd> 468 * </dl> 469 */ 470 this.fire('slideStart', { 471 ddEvent: e, // for backward compatibility 472 originEvent: e 473 }); 474 }, 475 476 /** 477 * Dispatches the <code>thumbMove</code> event. 478 * 479 * @method _afterDrag 480 * @param e {Event} the <code>drag:drag</code> event from the thumb 481 * @protected 482 */ 483 _afterDrag: function ( e ) { 484 var thumbXY = e.info.xy[ this._key.xyIndex ], 485 railXY = e.target.con._regionCache[ this._key.minEdge ]; 486 487 Y.log("Thumb position: " + thumbXY + ", Rail position: " + railXY, "info", "slider"); 488 this.fire( 'thumbMove', { 489 offset : (thumbXY - railXY), 490 ddEvent: e, // for backward compatibility 491 originEvent: e 492 } ); 493 }, 494 495 /** 496 * Dispatches the <code>slideEnd</code> event. 497 * 498 * @method _afterDragEnd 499 * @param e {Event} the <code>drag:end</code> event from the thumb 500 * @protected 501 */ 502 _afterDragEnd: function ( e ) { 503 /** 504 * Signals the end of a thumb drag operation. Payload includes 505 * the thumb's drag:end event. 506 * 507 * @event slideEnd 508 * @param event {Event} The event object for the slideEnd with the 509 * following extra properties: 510 * <dl> 511 * <dt>ddEvent (deprecated)</dt> 512 * <dd><code>drag:end</code> event from the thumb</dd> 513 * <dt>originEvent</dt> 514 * <dd><code>drag:end</code> event from the thumb</dd> 515 * </dl> 516 */ 517 this.fire('slideEnd', { 518 ddEvent: e, 519 originEvent: e 520 }); 521 }, 522 523 /** 524 * Locks or unlocks the thumb. 525 * 526 * @method _afterDisabledChange 527 * @param e {Event} The disabledChange event object 528 * @protected 529 */ 530 _afterDisabledChange: function ( e ) { 531 this._dd.set( 'lock', e.newVal ); 532 }, 533 534 /** 535 * Handles changes to the <code>length</code> attribute. By default, it 536 * triggers an update to the UI. 537 * 538 * @method _afterLengthChange 539 * @param e {Event} The lengthChange event object 540 * @protected 541 */ 542 _afterLengthChange: function ( e ) { 543 if ( this.get( 'rendered' ) ) { 544 this._uiSetRailLength( e.newVal ); 545 546 this.syncUI(); 547 } 548 }, 549 550 /** 551 * Synchronizes the DOM state with the attribute settings. 552 * 553 * @method syncUI 554 */ 555 syncUI : function () { 556 this._dd.con.resetCache(); 557 558 this._syncThumbPosition(); 559 560 // Forces a reflow of the bounding box to address IE8 inline-block 561 // container not expanding correctly. bug 2527905 562 //this.get('boundingBox').toggleClass(''); 563 this.thumb.set('aria-valuemin', this.get('min')); 564 this.thumb.set('aria-valuemax', this.get('max')); 565 566 this._dd.set('lock', this.get('disabled')); 567 }, 568 569 /** 570 * Stub implementation. Override this (presumably in a class extension) to 571 * ensure the thumb is in the correct position according to the value 572 * alogorithm. 573 * instance. 574 * 575 * @method _syncThumbPosition 576 * @protected 577 */ 578 _syncThumbPosition: function () {}, 579 580 /** 581 * Validates the axis is "x" or "y" (case insensitive). 582 * Converts to lower case for storage. 583 * 584 * @method _setAxis 585 * @param v {String} proposed value for the axis attribute 586 * @return {String} lowercased first character of the input string 587 * @protected 588 */ 589 _setAxis : function (v) { 590 v = ( v + '' ).toLowerCase(); 591 592 return ( v === 'x' || v === 'y' ) ? v : INVALID_VALUE; 593 }, 594 595 /** 596 * <p>Ensures the stored length value is a string with a quantity and unit. 597 * Unit will be defaulted to "px" if not included. Rejects 598 * values less than or equal to 0 and those that don't at least start with 599 * a number.</p> 600 * 601 * <p>Currently only pixel lengths are supported.</p> 602 * 603 * @method _setLength 604 * @param v {String} proposed value for the length attribute 605 * @return {String} the sanitized value 606 * @protected 607 */ 608 _setLength: function ( v ) { 609 v = ( v + '' ).toLowerCase(); 610 611 var length = parseFloat( v, 10 ), 612 units = v.replace( /[\d\.\-]/g, '' ) || this.DEF_UNIT; 613 614 return length > 0 ? ( length + units ) : INVALID_VALUE; 615 }, 616 617 /** 618 * <p>Defaults the thumbURL attribute according to the current skin, or 619 * "sam" if none can be determined. Horizontal Sliders will have 620 * their <code>thumbUrl</code> attribute set to</p> 621 * <p><code>"/<em>configured</em>/<em>yu</em>i/<em>builddi</em>r/slider-base/assets/skins/sam/thumb-x.png"</code></p> 622 * <p>And vertical thumbs will get</p> 623 * <p><code>"/<em>configured</em>/<em>yui</em>/<em>builddir</em>/slider-base/assets/skins/sam/thumb-y.png"</code></p> 624 * 625 * @method _initThumbUrl 626 * @protected 627 */ 628 _initThumbUrl: function () { 629 if (!this.get('thumbUrl')) { 630 var skin = this.getSkinName() || 'sam', 631 base = Y.config.base; 632 633 // Unfortunate hack to avoid requesting image resources from the 634 // combo service. The combo service does not serve images. 635 if (base.indexOf('http://yui.yahooapis.com/combo') === 0) { 636 base = 'http://yui.yahooapis.com/' + Y.version + '/build/'; 637 } 638 639 // <img src="/path/to/build/slider-base/assets/skins/sam/thumb-x.png"> 640 this.set('thumbUrl', base + 'slider-base/assets/skins/' + 641 skin + '/thumb-' + this.axis + '.png'); 642 643 } 644 }, 645 646 /** 647 * Bounding box template that will contain the Slider's DOM subtree. <span>s are used to support inline-block styling. 648 * 649 * @property BOUNDING_TEMPLATE 650 * @type {String} 651 * @default <span></span> 652 */ 653 BOUNDING_TEMPLATE : '<span></span>', 654 655 /** 656 * Content box template that will contain the Slider's rail and thumb. 657 * 658 * @property CONTENT_TEMPLATE 659 * @type {String} 660 * @default <span></span> 661 */ 662 CONTENT_TEMPLATE : '<span></span>', 663 664 /** 665 * Rail template that will contain the end caps and the thumb. 666 * {placeholder}s are used for template substitution at render time. 667 * 668 * @property RAIL_TEMPLATE 669 * @type {String} 670 * @default <span class="{railClass}"><span class="{railMinCapClass}"></span><span class="{railMaxCapClass}"></span></span> 671 */ 672 RAIL_TEMPLATE : '<span class="{railClass}">' + 673 '<span class="{railMinCapClass}"></span>' + 674 '<span class="{railMaxCapClass}"></span>' + 675 '</span>', 676 677 /** 678 * Thumb template that will contain the thumb image and shadow. <img> 679 * tags are used instead of background images to avoid a flicker bug in IE. 680 * {placeholder}s are used for template substitution at render time. 681 * 682 * @property THUMB_TEMPLATE 683 * @type {String} 684 * @default <span class="{thumbClass}" tabindex="-1"><img src="{thumbShadowUrl}" alt="Slider thumb shadow" class="{thumbShadowClass}"><img src="{thumbImageUrl}" alt="Slider thumb" class="{thumbImageClass}"></span> 685 */ 686 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" 687 '<img src="{thumbShadowUrl}" ' + 688 'alt="Slider thumb shadow" ' + 689 'class="{thumbShadowClass}">' + 690 '<img src="{thumbImageUrl}" ' + 691 'alt="Slider thumb" ' + 692 'class="{thumbImageClass}">' + 693 '</span>' 694 695 }, { 696 697 // Y.SliderBase static properties 698 699 /** 700 * The identity of the widget. 701 * 702 * @property NAME 703 * @type String 704 * @default 'sliderBase' 705 * @readOnly 706 * @protected 707 * @static 708 */ 709 NAME : 'sliderBase', 710 711 /** 712 * Static property used to define the default attribute configuration of 713 * the Widget. 714 * 715 * @property ATTRS 716 * @type {Object} 717 * @protected 718 * @static 719 */ 720 ATTRS : { 721 722 /** 723 * Axis upon which the Slider's thumb moves. "x" for 724 * horizontal, "y" for vertical. 725 * 726 * @attribute axis 727 * @type {String} 728 * @default "x" 729 * @writeOnce 730 */ 731 axis : { 732 value : 'x', 733 writeOnce : true, 734 setter : '_setAxis', 735 lazyAdd : false 736 }, 737 738 /** 739 * The length of the rail (exclusive of the end caps if positioned by 740 * CSS). This corresponds to the movable range of the thumb. 741 * 742 * @attribute length 743 * @type {String | Number} e.g. "200px" or 200 744 * @default 150px 745 */ 746 length: { 747 value: '150px', 748 setter: '_setLength' 749 }, 750 751 /** 752 * Path to the thumb image. This will be used as both the thumb and 753 * shadow as a sprite. Defaults at render() to thumb-x.png or 754 * thumb-y.png in the skin directory of the current skin. 755 * 756 * @attribute thumbUrl 757 * @type {String} 758 * @default thumb-x.png or thumb-y.png in the sam skin directory of the 759 * current build path for Slider 760 */ 761 thumbUrl: { 762 value: null, 763 validator: Y.Lang.isString 764 } 765 } 766 }); 767 768 769 }, '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 |