Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 11 commits
  • 28 files changed
  • 0 comments
  • 2 contributors

Showing 28 changed files with 1,314 additions and 1,265 deletions. Show diff stats Hide diff stats

  1. +457 451 build/dial/dial-coverage.js
  2. +206 199 build/dial/dial-debug.js
  3. +1 1  build/dial/dial-min.js
  4. +206 199 build/dial/dial.js
  5. +14 11 build/simpleyui/simpleyui-debug.js
  6. +1 1  build/simpleyui/simpleyui-min.js
  7. +14 11 build/simpleyui/simpleyui.js
  8. +36 35 build/yui-base/yui-base-coverage.js
  9. +5 4 build/yui-base/yui-base-debug.js
  10. +1 1  build/yui-base/yui-base-min.js
  11. +5 4 build/yui-base/yui-base.js
  12. +36 35 build/yui-core/yui-core-coverage.js
  13. +5 4 build/yui-core/yui-core-debug.js
  14. +1 1  build/yui-core/yui-core-min.js
  15. +5 4 build/yui-core/yui-core.js
  16. +36 35 build/yui-nodejs/yui-nodejs-coverage.js
  17. +5 4 build/yui-nodejs/yui-nodejs-debug.js
  18. +1 1  build/yui-nodejs/yui-nodejs-min.js
  19. +5 4 build/yui-nodejs/yui-nodejs.js
  20. +36 35 build/yui/yui-coverage.js
  21. +5 4 build/yui/yui-debug.js
  22. +1 1  build/yui/yui-min.js
  23. +5 4 build/yui/yui.js
  24. +206 199 src/dial/js/Dial.js
  25. +1 1  src/scrollview/tests/unit/scrollview-base-unit-test.html
  26. +14 11 src/simpleyui/js/concat.js
  27. +5 4 src/yui/js/yui-ua.js
  28. +1 1  src/yui/tests/unit/assets/ua-tests.js
908 build/dial/dial-coverage.js
457 additions, 451 deletions not shown
405 build/dial/dial-debug.js
@@ -3,7 +3,7 @@ YUI.add('dial', function (Y, NAME) {
3 3 /**
4 4 * Create a circular dial value range input visualized as a draggable handle on a
5 5 * background element.
6   - *
  6 + *
7 7 * @module dial
8 8 */
9 9 var supportsVML = false;
@@ -148,7 +148,7 @@ YUI.add('dial', function (Y, NAME) {
148 148 return this._validateValue(val);
149 149 }
150 150 },
151   -
  151 +
152 152 /**
153 153 * amount to increment/decrement the dial value
154 154 * when the arrow up/down/left/right keys are pressed
@@ -174,7 +174,7 @@ YUI.add('dial', function (Y, NAME) {
174 174 },
175 175
176 176 /**
177   - * number of value increments in one 360 degree revolution
  177 + * number of value increments in one 360 degree revolution
178 178 * of the handle around the dial
179 179 *
180 180 * @attribute stepsPerRevolution
@@ -186,7 +186,7 @@ YUI.add('dial', function (Y, NAME) {
186 186 },
187 187
188 188 /**
189   - * number of decimal places of accuracy in the value
  189 + * number of decimal places of accuracy in the value
190 190 *
191 191 * @attribute decimalPlaces
192 192 * @type {Number}
@@ -197,7 +197,7 @@ YUI.add('dial', function (Y, NAME) {
197 197 },
198 198
199 199 /**
200   - * visible strings for the dial UI. This attribute is
  200 + * visible strings for the dial UI. This attribute is
201 201 * defined by the base Widget class but has an empty value. The
202 202 * Dial is simply providing a default value for the attribute.
203 203 * Gets localized strings in the current language
@@ -213,8 +213,8 @@ YUI.add('dial', function (Y, NAME) {
213 213 },
214 214
215 215 /**
216   - * distance from the center of the dial to the
217   - * center of the marker and handle, when at rest.
  216 + * distance from the center of the dial to the
  217 + * center of the marker and handle, when at rest.
218 218 * The value is a percent of the radius of the dial.
219 219 *
220 220 * @attribute handleDistance
@@ -224,7 +224,7 @@ YUI.add('dial', function (Y, NAME) {
224 224 handleDistance:{
225 225 value:0.75
226 226 }
227   -
  227 +
228 228 };
229 229
230 230 /**
@@ -238,8 +238,8 @@ YUI.add('dial', function (Y, NAME) {
238 238 function makeClassName(str) {
239 239 return Y.ClassNameManager.getClassName(Dial.NAME, str);
240 240 }
241   -
242   - /** array of static constants used to identify the classname applied to the Dial DOM objects
  241 +
  242 + /** array of static constants used to identify the classname applied to the Dial DOM objects
243 243 *
244 244 * @property CSS_CLASSES
245 245 * @type {Array}
@@ -264,9 +264,9 @@ YUI.add('dial', function (Y, NAME) {
264 264 hidden : makeClassName("hidden"),
265 265 dragging : Y.ClassNameManager.getClassName("dd-dragging")
266 266 };
267   -
  267 +
268 268 /* Static constants used to define the markup templates used to create Dial DOM elements */
269   -
  269 +
270 270
271 271 /**
272 272 * template that will contain the Dial's label.
@@ -319,7 +319,7 @@ YUI.add('dial', function (Y, NAME) {
319 319 * @protected
320 320 */
321 321 Dial.HANDLE_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.handle + '" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">';
322   -
  322 +
323 323 }else{ // VML case
324 324 Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + ' ' + Dial.CSS_CLASSES.ringVml + '">'+
325 325 '<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
@@ -363,7 +363,7 @@ YUI.add('dial', function (Y, NAME) {
363 363 this._renderMarker();
364 364 this._renderCenterButton();
365 365 this._renderHandle();
366   -
  366 +
367 367 // object handles
368 368 this.contentBox = this.get("contentBox");
369 369
@@ -379,7 +379,7 @@ YUI.add('dial', function (Y, NAME) {
379 379 this._timesWrapped = 0;
380 380 this._angle = this._getAngleFromValue(this.get('value'));
381 381 this._prevAng = this._angle;
382   -
  382 +
383 383 // init
384 384 this._setTimesWrappedFromValue(this._originalValue);
385 385 this._handleNode.set('aria-valuemin', this._minValue);
@@ -411,27 +411,27 @@ YUI.add('dial', function (Y, NAME) {
411 411 'borderRadius':this._centerButtonNodeRadius + 'px'
412 412 });
413 413 },
414   -
  414 +
415 415 /**
416 416 * Handles the mouseenter on the centerButton
417   - *
  417 + *
418 418 * @method _handleCenterButtonEnter
419 419 * @protected
420 420 */
421 421 _handleCenterButtonEnter : function(){
422   - this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
423   - },
424   -
  422 + this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
  423 + },
  424 +
425 425 /**
426 426 * Handles the mouseleave on the centerButton
427   - *
  427 + *
428 428 * @method _handleCenterButtonLeave
429 429 * @protected
430 430 */
431 431 _handleCenterButtonLeave : function(){
432   - this._resetString.addClass(Dial.CSS_CLASSES.hidden);
433   - },
434   -
  432 + this._resetString.addClass(Dial.CSS_CLASSES.hidden);
  433 + },
  434 +
435 435 /**
436 436 * Creates the Y.DD.Drag instance used for the handle movement and
437 437 * binds Dial interaction to the configured value model.
@@ -440,17 +440,19 @@ YUI.add('dial', function (Y, NAME) {
440 440 * @protected
441 441 */
442 442 bindUI : function() {
  443 +
443 444 this.after("valueChange", this._afterValueChange);
444 445
445 446 var boundingBox = this.get("boundingBox"),
446 447 // Looking for a key event which will fire continously across browsers while the key is held down.
447   - keyEvent = (!Y.UA.opera) ? "down:" : "press:",
  448 + keyEvent = (!Y.UA.opera) ? "down:" : "press:",
448 449 // 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
449 450 keyEventSpec = keyEvent + "38,40,33,34,35,36",
450 451 // 37 , 39 = arrow left/right
451 452 keyLeftRightSpec = keyEvent + "37,39",
452 453 // 37 , 39 = arrow left/right + meta (command/apple key) for mac
453   - keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta";
  454 + keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta",
  455 + Drag = Y.DD.Drag;
454 456
455 457 Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
456 458 Y.on("key", Y.bind(this._onLeftRightKey, this), boundingBox, keyLeftRightSpec);
@@ -459,14 +461,17 @@ YUI.add('dial', function (Y, NAME) {
459 461 Y.on('mouseenter', Y.bind(this._handleCenterButtonEnter, this), this._centerButtonNode);
460 462 Y.on('mouseleave', Y.bind(this._handleCenterButtonLeave, this), this._centerButtonNode);
461 463 // Needed to replace mousedown/up with gesturemovestart/end to make behavior on touch devices work the same.
462   - Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
463   - Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
464   - Y.on('gesturemovestart', Y.bind(this._handleHandleMousedown, this), this._handleNode);
  464 + Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
  465 + Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
  466 +
  467 +
  468 + Y.on(Drag.START_EVENT, Y.bind(this._handleHandleMousedown, this), this._handleNode);
  469 + Y.on(Drag.START_EVENT, Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
465 470
466   - Y.on('gesturemovestart', Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
  471 + //TODO: Can this be merged this into the drag:end event listener to avoid another registration?
467 472 Y.on('gesturemoveend', Y.bind(this._handleRingMouseup, this), this._ringNode);
468 473
469   - this._dd1 = new Y.DD.Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
  474 + this._dd1 = new Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
470 475 node: this._handleNode,
471 476 on : {
472 477 'drag:drag' : Y.bind(this._handleDrag, this),
@@ -492,68 +497,68 @@ YUI.add('dial', function (Y, NAME) {
492 497 this._timesWrapped = Math.floor(val / this._stepsPerRevolution);
493 498 }
494 499 },
495   -
  500 +
496 501 /**
497   - * gets the angle of the line from the center of the Dial to the center of the handle
  502 + * gets the angle of the line from the center of the Dial to the center of the handle
498 503 *
499 504 * @method _getAngleFromHandleCenter
500   - * @param handleCenterX {number}
  505 + * @param handleCenterX {number}
501 506 * @param handleCenterY {number}
502 507 * @return ang {number} the angle
503 508 * @protected
504 509 */
505 510 _getAngleFromHandleCenter : function(handleCenterX, handleCenterY){
506   - var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
  511 + var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
507 512 ang = ((this._dialCenterX - handleCenterX) < 0) ? ang + 90 : ang + 90 + 180; // Compensate for neg angles from Math.atan
508 513 return ang;
509 514 },
510   -
  515 +
511 516 /**
512   - * calculates the XY of the center of the dial relative to the ring node.
  517 + * calculates the XY of the center of the dial relative to the ring node.
513 518 * This is needed for calculating the angle of the handle
514 519 *
515 520 * @method _calculateDialCenter
516 521 * @protected
517 522 */
518 523 _calculateDialCenter : function(){ // #2531111 value, and marker don't track handle when dial position changes on page (resize when inline)
519   - this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
  524 + this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
520 525 this._dialCenterY = this._ringNode.get('offsetHeight') / 2;
521 526 },
522   -
  527 +
523 528 /**
524 529 * Handles the mouseup on the ring
525   - *
  530 + *
526 531 * @method _handleRingMouseup
527 532 * @protected
528 533 */
529 534 _handleRingMouseup : function(){
530   - this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
531   - },
532   -
  535 + this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
  536 + },
  537 +
533 538 /**
534 539 * Handles the mouseup on the centerButton
535   - *
  540 + *
536 541 * @method _handleCenterButtonMouseup
537 542 * @protected
538 543 */
539 544 _handleCenterButtonMouseup : function(){
540   - this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
541   - },
542   -
  545 + this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
  546 + },
  547 +
543 548 /**
544 549 * Handles the mousedown on the handle
545   - *
  550 + *
546 551 * @method _handleHandleMousedown
547 552 * @protected
548 553 */
549 554 _handleHandleMousedown : function(){
550 555 this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
551   - // this is better done here instead of on _handleDragEnd
552   - // because we should make the keyboard accessible after a click of the handle
553   - },
554   -
  556 + // this is better done here instead of on _handleDragEnd
  557 + // because we should make the keyboard accessible after a click of the handle
  558 + },
  559 +
555 560 /**
556   - * handles the user dragging the handle around the Dial, gets the angle,
  561 + * handles the user dragging the handle around the Dial, gets the angle,
557 562 * checks for wrapping around top center.
558 563 * Sets the new value of the Dial
559 564 *
@@ -567,7 +572,7 @@ YUI.add('dial', function (Y, NAME) {
567 572 ang,
568 573 newValue;
569 574
570   - // The event was emitted from drag:drag of handle.
  575 + // The event was emitted from drag:drag of handle.
571 576 // The center of the handle is top left position of the handle node + radius of handle.
572 577 // This is different than a mousedown on the ring.
573 578 handleCenterX = (parseInt(this._handleNode.getStyle('left'),10) + this._handleNodeRadius);
@@ -585,7 +590,7 @@ YUI.add('dial', function (Y, NAME) {
585 590 }
586 591 }
587 592 newValue = this._getValueFromAngle(ang); // This function needs the current _timesWrapped value. That's why it comes after the _timesWrapped code above
588   -
  593 +
589 594 // If you've gone past max more than one full revolution, we decrement the _timesWrapped value
590 595 // This gives the effect of a ratchet mechanism.
591 596 // It feels like you are never more than one revolution past max
@@ -597,7 +602,7 @@ YUI.add('dial', function (Y, NAME) {
597 602 }else if(newValue < (this._minValue - this._stepsPerRevolution) ){
598 603 this._timesWrapped ++;
599 604 }
600   - this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
  605 + this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
601 606
602 607 this._handleValuesBeyondMinMax(e, newValue);
603 608 },
@@ -610,119 +615,125 @@ YUI.add('dial', function (Y, NAME) {
610 615 * @private
611 616 */
612 617 _handleMousedown : function(e){ // #2530306
613   - var minAng = this._getAngleFromValue(this._minValue),
614   - maxAng = this._getAngleFromValue(this._maxValue),
615   - newValue, oppositeMidRangeAngle,
616   - handleCenterX, handleCenterY,
617   - ang;
618   -
619   - // The event was emitted from mousedown on the ring node,
620   - // so the center of the handle should be the XY of mousedown.
621   - if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
622   - handleCenterX = (e.clientX - this._ringNode.getX());
623   - handleCenterY = (e.clientY - this._ringNode.getY());
624   - }else{
625   - handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
626   - handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
627   - }
628   - ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
629   -
630   - /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
631   - * The next sections of logic
632   - * set this._timesWrapped in the different cases of value range
633   - * and value range position,
634   - * then the Dial value is set at the end of this method
635   - */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
636   -
637   -
638   - ////////////////////////////////////////////////////////////////////////////////////////////////////////////
639   - if(this._maxValue - this._minValue > this._stepsPerRevolution){
640   - // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
641   -
642   - // This checks the shortest way around the dial between the prevAng and this ang.
643   - if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
644   -
645   - // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
646   - if((this._timesWrapped > this._minTimesWrapped) &&
647   - (this._timesWrapped < this._maxTimesWrapped)
648   - ){
649   - // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
650   - this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
651   - }
652   - // special case of getting un-stuck from a min value case
653   - // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
654   - // because prevAng is set to 0 or > 0
655   - }else if(
656   - (this._timesWrapped === this._minTimesWrapped) &&
657   - (ang - this._prevAng < 180)
658   - ){
659   - this._timesWrapped ++;
660   - } //it didn't cross a wrapping boundary
661   -
662   - } /////////////////////////////////////////////////////////////////////////////////////////////////////////
663   - else if(this._maxValue - this._minValue === this._stepsPerRevolution){
664   - // Case: range min-to-max === stepsPerRevolution (one revolution)
665   - // This means min and max will be at same angle
666   - // This does not mean they are at "north"
667   -
668   - if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
669   - // The only way it can be, is if min and max are not at north
670   - this._timesWrapped = 1;
  618 +
  619 + if (this._ringNode.compareTo(e.target)) {
  620 + var minAng = this._getAngleFromValue(this._minValue),
  621 + maxAng = this._getAngleFromValue(this._maxValue),
  622 + newValue, oppositeMidRangeAngle,
  623 + handleCenterX, handleCenterY,
  624 + ang;
  625 +
  626 +
  627 +
  628 + // The event was emitted from mousedown on the ring node,
  629 + // so the center of the handle should be the XY of mousedown.
  630 + if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
  631 + handleCenterX = (e.clientX - this._ringNode.getX());
  632 + handleCenterY = (e.clientY - this._ringNode.getY());
671 633 }else{
672   - this._timesWrapped = 0;
673   - }
674   -
675   - } //////////////////////////////////////////////////////////////////////////////////////////////////////////
676   - else if(minAng > maxAng){
677   - // Case: range includes the wrap point (north)
678   - // Because of "else if"...
679   - // range is < stepsPerRevolution
680   -
681   - if(
682   - (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
683   - (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
684   - // the angle opposite the mid-range angle, then...
685   - ){
686   - this._timesWrapped ++;
687   - }else if(
688   - (this._prevAng <= maxAng) &&
689   - // if prev angle is < max angle and...
690   -
691   - (ang > (minAng + maxAng) / 2)
692   - // the angle of this click is greater than,
693   - // the angle opposite the mid-range angle and...
694   -
695   - ){
696   - this._timesWrapped --;
  634 + handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
  635 + handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
697 636 }
698   -
699   - } ////////////////////////////////////////////////////////////////////////////////////////////////////
700   - else{
701   - // "else" Case: min-to-max range doesn't include the wrap point
702   - // Because of "else if"...
703   - // range is still < stepsPerRevolution
704   -
705   - if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
706   - oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
707   - // This is the bisection of the min-to-max range + 180. (opposite the bisection)
708   -
709   - if(oppositeMidRangeAngle > 180){
710   - newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
711   - }else{ //oppositeMidRangeAngle <= 180
712   - newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
  637 + ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
  638 +
  639 + /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
  640 + * The next sections of logic
  641 + * set this._timesWrapped in the different cases of value range
  642 + * and value range position,
  643 + * then the Dial value is set at the end of this method
  644 + */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
  645 +
  646 +
  647 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  648 + if(this._maxValue - this._minValue > this._stepsPerRevolution){
  649 +
  650 + // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
  651 +
  652 + // This checks the shortest way around the dial between the prevAng and this ang.
  653 + if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
  654 +
  655 + // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
  656 + if((this._timesWrapped > this._minTimesWrapped) &&
  657 + (this._timesWrapped < this._maxTimesWrapped)
  658 + ){
  659 + // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
  660 + this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
  661 + }
  662 + // special case of getting un-stuck from a min value case
  663 + // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
  664 + // because prevAng is set to 0 or > 0
  665 + }else if(
  666 + (this._timesWrapped === this._minTimesWrapped) &&
  667 + (ang - this._prevAng < 180)
  668 + ){
  669 + this._timesWrapped ++;
  670 + } //it didn't cross a wrapping boundary
  671 +
  672 + } /////////////////////////////////////////////////////////////////////////////////////////////////////////
  673 + else if(this._maxValue - this._minValue === this._stepsPerRevolution){
  674 + // Case: range min-to-max === stepsPerRevolution (one revolution)
  675 + // This means min and max will be at same angle
  676 + // This does not mean they are at "north"
  677 +
  678 + if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
  679 + // The only way it can be, is if min and max are not at north
  680 + this._timesWrapped = 1;
  681 + }else{
  682 + this._timesWrapped = 0;
  683 + }
  684 +
  685 + } //////////////////////////////////////////////////////////////////////////////////////////////////////////
  686 + else if(minAng > maxAng){
  687 + // Case: range includes the wrap point (north)
  688 + // Because of "else if"...
  689 + // range is < stepsPerRevolution
  690 +
  691 + if(
  692 + (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
  693 + (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
  694 + // the angle opposite the mid-range angle, then...
  695 + ){
  696 + this._timesWrapped ++;
  697 + }else if(
  698 + (this._prevAng <= maxAng) &&
  699 + // if prev angle is < max angle and...
  700 +
  701 + (ang > (minAng + maxAng) / 2)
  702 + // the angle of this click is greater than,
  703 + // the angle opposite the mid-range angle and...
  704 +
  705 + ){
  706 + this._timesWrapped --;
  707 + }
  708 +
  709 + } ////////////////////////////////////////////////////////////////////////////////////////////////////
  710 + else{
  711 + // "else" Case: min-to-max range doesn't include the wrap point
  712 + // Because of "else if"...
  713 + // range is still < stepsPerRevolution
  714 +
  715 + if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
  716 + oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
  717 + // This is the bisection of the min-to-max range + 180. (opposite the bisection)
  718 +
  719 + if(oppositeMidRangeAngle > 180){
  720 + newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
  721 + }else{ //oppositeMidRangeAngle <= 180
  722 + newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
  723 + }
  724 + this._prevAng = this._getAngleFromValue(newValue);
  725 + this.set('value', newValue);
  726 + this._setTimesWrappedFromValue(newValue);
  727 + return;
713 728 }
714   - this._prevAng = this._getAngleFromValue(newValue);
715   - this.set('value', newValue);
716   - this._setTimesWrappedFromValue(newValue);
717   - return;
718 729 }
719   - }
720   -
721   - // Now that _timesWrapped is set value .......................................................................
722   - newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
723   - this._prevAng = ang;
724 730
725   - this._handleValuesBeyondMinMax(e, newValue);
  731 + // Now that _timesWrapped is set value .......................................................................
  732 + newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
  733 + this._prevAng = ang;
  734 +
  735 + this._handleValuesBeyondMinMax(e, newValue);
  736 + }
726 737 },
727 738
728 739 /**
@@ -735,24 +746,20 @@ YUI.add('dial', function (Y, NAME) {
735 746 */
736 747 _handleValuesBeyondMinMax : function(e, newValue){ // #2530306
737 748 // If _getValueFromAngle() is passed 0, it increments the _timesWrapped value.
738   - // handle hitting max and min and going beyond, stops at max or min
  749 + // handle hitting max and min and going beyond, stops at max or min
739 750 if((newValue >= this._minValue) && (newValue <= this._maxValue)) {
740 751 this.set('value', newValue);
741 752 // [#2530206] transfer the mousedown event from the _ringNode to the _handleNode drag, so we can mousedown, then continue dragging
742 753 if(e.currentTarget === this._ringNode){
743 754 // Delegate to DD's natural behavior
744 755 this._dd1._handleMouseDownEvent(e);
745   - }
746   - }else if(newValue > this._maxValue){
  756 + }
  757 + } else if(newValue > this._maxValue){
747 758 this.set('value', this._maxValue);
748   - if(e.type === 'gesturemovestart'){
749   - this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
750   - }
751   - }else if(newValue < this._minValue){
  759 + this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
  760 + } else if(newValue < this._minValue){
752 761 this.set('value', this._minValue);
753   - if(e.type === 'gesturemovestart'){
754   - this._prevAng = this._getAngleFromValue(this._minValue);
755   - }
  762 + this._prevAng = this._getAngleFromValue(this._minValue);
756 763 }
757 764 },
758 765
@@ -769,7 +776,7 @@ YUI.add('dial', function (Y, NAME) {
769 776
770 777 /*
771 778 * When handle is handleDragEnd, this animates the return to the fixed dial
772   - */
  779 + */
773 780
774 781 /**
775 782 * handles the end of a user dragging the handle, animates the handle returning to
@@ -779,7 +786,7 @@ YUI.add('dial', function (Y, NAME) {
779 786 * @protected
780 787 */
781 788 _handleDragEnd : function(){
782   - var node = this._handleNode;
  789 + var node = this._handleNode;
783 790 node.transition({
784 791 duration: 0.08, // seconds
785 792 easing: 'ease-in',
@@ -817,7 +824,7 @@ YUI.add('dial', function (Y, NAME) {
817 824 newY = Math.round(Math.sin(thisAngle * rad) * this._handleDistance),
818 825 newX = Math.round(Math.cos(thisAngle * rad) * this._handleDistance),
819 826 dia = obj.get('offsetWidth'); //Ticket #2529852
820   -
  827 +
821 828 newY = newY - (dia * 0.5);
822 829 newX = newX - (dia * 0.5);
823 830 if(typeArray){ // just need the style for css transform left and top to animate the handle drag:end
@@ -835,7 +842,7 @@ YUI.add('dial', function (Y, NAME) {
835 842 */
836 843 syncUI : function() {
837 844 // Make the marker and the resetString display so their placement and borderRadius can be calculated, then hide them again.
838   - // We would have used visibility:hidden in the css of this class,
  845 + // We would have used visibility:hidden in the css of this class,
839 846 // but IE8 VML never returns to visible after applying visibility:hidden then removing it.
840 847 this._setSizes();
841 848 this._calculateDialCenter(); // #2531111 initialize center of dial
@@ -847,7 +854,7 @@ YUI.add('dial', function (Y, NAME) {
847 854
848 855 /**
849 856 * sets the sizes of ring, center-button, marker, handle, and VML ovals in pixels.
850   - * Needed only because some IE versions
  857 + * Needed only because some IE versions
851 858 * ignore CSS percent sizes/offsets.
852 859 * so these must be set in pixels.
853 860 * Normally these are set in % of the ring.
@@ -869,8 +876,8 @@ YUI.add('dial', function (Y, NAME) {
869 876 setSize(this._handleNode, dia, this.get('handleDiameter'));
870 877 setSize(this._markerNode, dia, this.get('markerDiameter'));
871 878 setSize(this._centerButtonNode, dia, this.get('centerButtonDiameter'));
872   -
873   - // Set these (used for trig) this way instead of relative to dia,
  879 +
  880 + // Set these (used for trig) this way instead of relative to dia,
874 881 // in case they have borders, have images etc.
875 882 this._ringNodeRadius = this._ringNode.get('offsetWidth') * 0.5;
876 883 this._handleNodeRadius = this._handleNode.get('offsetWidth') * 0.5;
@@ -881,7 +888,7 @@ YUI.add('dial', function (Y, NAME) {
881 888 offset = (this._ringNodeRadius - this._centerButtonNodeRadius);
882 889 this._centerButtonNode.setStyle('left', offset + 'px');
883 890 this._centerButtonNode.setStyle('top', offset + 'px');
884   - /*
  891 + /*
885 892 Place the resetString
886 893 This seems like it should be able to be done with CSS,
887 894 But since there is also a VML oval in IE that is absolute positioned,
@@ -927,7 +934,7 @@ YUI.add('dial', function (Y, NAME) {
927 934 },
928 935
929 936 /**
930   - * renders the DOM object for the Dial's background marker which
  937 + * renders the DOM object for the Dial's background marker which
931 938 * tracks the angle of the user dragging the handle
932 939 *
933 940 * @method _renderMarker
@@ -941,7 +948,7 @@ YUI.add('dial', function (Y, NAME) {
941 948 }
942 949 this._markerNode = marker;
943 950 },
944   -
  951 +
945 952 /**
946 953 * renders the DOM object for the Dial's center
947 954 *
@@ -965,7 +972,7 @@ YUI.add('dial', function (Y, NAME) {
965 972 * @method _renderHandle
966 973 * @protected
967 974 */
968   - _renderHandle : function() {
  975 + _renderHandle : function() {
969 976 var labelId = Dial.CSS_CLASSES.label + Y.guid(), //get this unique id once then use for handle and label for ARIA
970 977 contentBox = this.get("contentBox"),
971 978 handle = contentBox.one("." + Dial.CSS_CLASSES.handle);
@@ -1019,7 +1026,7 @@ YUI.add('dial', function (Y, NAME) {
1019 1026
1020 1027 /**
1021 1028 * sets the Dial's value in response to key events.
1022   - * Left and right keys are in a separate method
  1029 + * Left and right keys are in a separate method
1023 1030 * in case an implementation wants to increment values
1024 1031 * but needs left and right arrow keys for other purposes.
1025 1032 *
@@ -1088,7 +1095,7 @@ YUI.add('dial', function (Y, NAME) {
1088 1095 break;
1089 1096 }
1090 1097 },
1091   -
  1098 +
1092 1099 /**
1093 1100 * increments Dial value by a minor increment
1094 1101 *
@@ -1104,7 +1111,7 @@ YUI.add('dial', function (Y, NAME) {
1104 1111 // Removing the toFixed here, loses the feature of "snap-to" when for example, stepsPerRevolution is 10 and decimalPlaces is 0.
1105 1112 this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
1106 1113 },
1107   -
  1114 +
1108 1115 /**
1109 1116 * decrements Dial value by a minor increment
1110 1117 *
@@ -1116,7 +1123,7 @@ YUI.add('dial', function (Y, NAME) {
1116 1123 newVal = Math.max(newVal, this.get("min"));
1117 1124 this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
1118 1125 },
1119   -
  1126 +
1120 1127 /**
1121 1128 * increments Dial value by a major increment
1122 1129 *
@@ -1128,7 +1135,7 @@ YUI.add('dial', function (Y, NAME) {
1128 1135 newVal = Math.min(newVal, this.get("max"));
1129 1136 this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
1130 1137 },
1131   -
  1138 +
1132 1139 /**
1133 1140 * decrements Dial value by a major increment
1134 1141 *
@@ -1149,8 +1156,8 @@ YUI.add('dial', function (Y, NAME) {
1149 1156 */
1150 1157 _setToMax : function(){
1151 1158 this.set('value', this.get("max"));
1152   - },
1153   -
  1159 + },
  1160 +
1154 1161 /**
1155 1162 * sets Dial value to dial's min attr
1156 1163 *
@@ -1159,10 +1166,10 @@ YUI.add('dial', function (Y, NAME) {
1159 1166 */
1160 1167 _setToMin : function(){
1161 1168 this.set('value', this.get("min"));
1162   - },
1163   -
  1169 + },
  1170 +
1164 1171 /**
1165   - * resets Dial value to the orignal initial value.
  1172 + * resets Dial value to the orignal initial value.
1166 1173 *
1167 1174 * @method _resetDial
1168 1175 * @protected
@@ -1175,9 +1182,9 @@ YUI.add('dial', function (Y, NAME) {
1175 1182 this._resetString.addClass(Dial.CSS_CLASSES.hidden); //[#2530441]
1176 1183 this._handleNode.focus();
1177 1184 },
1178   -
  1185 +
1179 1186 /**
1180   - * returns the handle angle associated with the current value of the Dial.
  1187 + * returns the handle angle associated with the current value of the Dial.
1181 1188 * Returns a number between 0 and 360.
1182 1189 *
1183 1190 * @method _getAngleFromValue
@@ -1231,11 +1238,11 @@ YUI.add('dial', function (Y, NAME) {
1231 1238 * @protected
1232 1239 */
1233 1240 _valueToDecimalPlaces : function(val) { // [#2530206] cleaned up and better user feedback of when it's max or min.
1234   -
  1241 +
1235 1242 },
1236 1243
1237 1244 /**
1238   - * Updates the UI display value of the Dial to reflect
  1245 + * Updates the UI display value of the Dial to reflect
1239 1246 * the value passed in.
1240 1247 * Makes all other needed UI display changes
1241 1248 *
2  build/dial/dial-min.js
... ... @@ -1 +1 @@
1   -YUI.add("dial",function(e,t){function o(e){o.superclass.constructor.apply(this,arguments)}function u(t){return e.ClassNameManager.getClassName(o.NAME,t)}var n=!1;e.UA.ie&&e.UA.ie<9&&(n=!0);var r=e.Lang,i=e.Widget,s=e.Node;o.NAME="dial",o.ATTRS={min:{value:-220},max:{value:220},diameter:{value:100},handleDiameter:{value:.2},markerDiameter:{value:.1},centerButtonDiameter:{value:.5},value:{value:0,validator:function(e){return this._validateValue(e)}},minorStep:{value:1},majorStep:{value:10},stepsPerRevolution:{value:100},decimalPlaces:{value:0},strings:{valueFn:function(){return e.Intl.get("dial")}},handleDistance:{value:.75}},o.CSS_CLASSES={label:u("label"),labelString:u("label-string"),valueString:u("value-string"),northMark:u("north-mark"),ring:u("ring"),ringVml:u("ring-vml"),marker:u("marker"),markerVml:u("marker-vml"),markerMaxMin:u("marker-max-min"),centerButton:u("center-button"),centerButtonVml:u("center-button-vml"),resetString:u("reset-string"),handle:u("handle"),handleVml:u("handle-vml"),hidden:u("hidden"),dragging:e.ClassNameManager.getClassName("dd-dragging")},o.LABEL_TEMPLATE='<div class="'+o.CSS_CLASSES.label+'"><span id="" class="'+o.CSS_CLASSES.labelString+'">{label}</span><span class="'+o.CSS_CLASSES.valueString+'"></span></div>',n===!1?(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+'"><div class="'+o.CSS_CLASSES.northMark+'"></div></div>',o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.marker+" "+o.CSS_CLASSES.hidden+'"></div>',o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+'"><div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div></div>',o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handle+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'):(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+" "+o.CSS_CLASSES.ringVml+'">'+'<div class="'+o.CSS_CLASSES.northMark+'"></div>'+'<v:oval strokecolor="#ceccc0" strokeweight="1px"><v:fill type=gradient color="#8B8A7F" color2="#EDEDEB" angle="45"/></v:oval>'+"</div>"+"",o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.markerVml+" "+o.CSS_CLASSES.hidden+'">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#000"/>'+"</v:oval>"+"</div>"+"",o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+" "+o.CSS_CLASSES.centerButtonVml+'">'+'<v:oval strokecolor="#ceccc0" strokeweight="1px">'+'<v:fill type=gradient color="#C7C5B9" color2="#fefcf6" colors="35% #d9d7cb, 65% #fefcf6" angle="45"/>'+'<v:shadow on="True" color="#000" opacity="10%" offset="2px, 2px"/>'+"</v:oval>"+'<div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div>'+"</div>"+"",o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handleVml+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#6C3A3A"/>'+"</v:oval>"+"</div>"+""),e.extend(o,i,{renderUI:function(){this._renderLabel(),this._renderRing(),this._renderMarker(),this._renderCenterButton(),this._renderHandle(),this.contentBox=this.get("contentBox"),this._originalValue=this.get("value"),this._minValue=this.get("min"),this._maxValue=this.get("max"),this._stepsPerRevolution=this.get("stepsPerRevolution"),this._minTimesWrapped=Math.floor(this._minValue/this._stepsPerRevolution-1),this._maxTimesWrapped=Math.floor(this._maxValue/this._stepsPerRevolution+1),this._timesWrapped=0,this._angle=this._getAngleFromValue(this.get("value")),this._prevAng=this._angle,this._setTimesWrappedFromValue(this._originalValue),this._handleNode.set("aria-valuemin",this._minValue),this._handleNode.set("aria-valuemax",this._maxValue)},_setBorderRadius:function(){this._ringNode.setStyles({WebkitBorderRadius:this._ringNodeRadius+"px",MozBorderRadius:this._ringNodeRadius+"px",borderRadius:this._ringNodeRadius+"px"}),this._handleNode.setStyles({WebkitBorderRadius:this._handleNodeRadius+"px",MozBorderRadius:this._handleNodeRadius+"px",borderRadius:this._handleNodeRadius+"px"}),this._markerNode.setStyles({WebkitBorderRadius:this._markerNodeRadius+"px",MozBorderRadius:this._markerNodeRadius+"px",borderRadius:this._markerNodeRadius+"px"}),this._centerButtonNode.setStyles({WebkitBorderRadius:this._centerButtonNodeRadius+"px",MozBorderRadius:this._centerButtonNodeRadius+"px",borderRadius:this._centerButtonNodeRadius+"px"})},_handleCenterButtonEnter:function(){this._resetString.removeClass(o.CSS_CLASSES.hidden)},_handleCenterButtonLeave:function(){this._resetString.addClass(o.CSS_CLASSES.hidden)},bindUI:function(){this.after("valueChange",this._afterValueChange);var t=this.get("boundingBox"),n=e.UA.opera?"press:":"down:",r=n+"38,40,33,34,35,36",i=n+"37,39",s=n+"37+meta,39+meta";e.on("key",e.bind(this._onDirectionKey,this),t,r),e.on("key",e.bind(this._onLeftRightKey,this),t,i),t.on("key",this._onLeftRightKeyMeta,s,this),e.on("mouseenter",e.bind(this._handleCenterButtonEnter,this),this._centerButtonNode),e.on("mouseleave",e.bind(this._handleCenterButtonLeave,this),this._centerButtonNode),e.on("gesturemovestart",e.bind(this._resetDial,this),this._centerButtonNode),e.on("gesturemoveend",e.bind(this._handleCenterButtonMouseup,this),this._centerButtonNode),e.on("gesturemovestart",e.bind(this._handleHandleMousedown,this),this._handleNode),e.on("gesturemovestart",e.bind(this._handleMousedown,this),this._ringNode),e.on("gesturemoveend",e.bind(this._handleRingMouseup,this),this._ringNode),this._dd1=new e.DD.Drag({node:this._handleNode,on:{"drag:drag":e.bind(this._handleDrag,this),"drag:start":e.bind(this._handleDragStart,this),"drag:end":e.bind(this._handleDragEnd,this)}}),e.bind(this._dd1.addHandle(this._ringNode),this)},_setTimesWrappedFromValue:function(e){e%this._stepsPerRevolution===0?this._timesWrapped=e/this._stepsPerRevolution:this._timesWrapped=Math.floor(e/this._stepsPerRevolution)},_getAngleFromHandleCenter:function(e,t){var n=Math.atan((this._dialCenterY-t)/(this._dialCenterX-e))*(180/Math.PI);return n=this._dialCenterX-e<0?n+90:n+90+180,n},_calculateDialCenter:function(){this._dialCenterX=this._ringNode.get("offsetWidth")/2,this._dialCenterY=this._ringNode.get("offsetHeight")/2},_handleRingMouseup:function(){this._handleNode.focus()},_handleCenterButtonMouseup:function(){this._handleNode.focus()},_handleHandleMousedown:function(){this._handleNode.focus()},_handleDrag:function(e){var t,n,r,i;t=parseInt(this._handleNode.getStyle("left"),10)+this._handleNodeRadius,n=parseInt(this._handleNode.getStyle("top"),10)+this._handleNodeRadius,r=this._getAngleFromHandleCenter(t,n),this._prevAng>270&&r<90?this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._timesWrapped+1):this._prevAng<90&&r>270&&this._timesWrapped>this._minTimesWrapped&&(this._timesWrapped=this._timesWrapped-1),i=this._getValueFromAngle(r),i>this._maxValue+this._stepsPerRevolution?this._timesWrapped--:i<this._minValue-this._stepsPerRevolution&&this._timesWrapped++,this._prevAng=r,this._handleValuesBeyondMinMax(e,i)},_handleMousedown:function(t){var n=this._getAngleFromValue(this._minValue),r=this._getAngleFromValue(this._maxValue),i,s,o,u,a;e.UA.ios?(o=t.clientX-this._ringNode.getX(),u=t.clientY-this._ringNode.getY()):(o=t.clientX+e.one("document").get("scrollLeft")-this._ringNode.getX(),u=t.clientY+e.one("document").get("scrollTop")-this._ringNode.getY()),a=this._getAngleFromHandleCenter(o,u);if(this._maxValue-this._minValue>this._stepsPerRevolution)Math.abs(this._prevAng-a)>180?this._timesWrapped>this._minTimesWrapped&&this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._prevAng-a>0?this._timesWrapped+1:this._timesWrapped-1):this._timesWrapped===this._minTimesWrapped&&a-this._prevAng<180&&this._timesWrapped++;else if(this._maxValue-this._minValue===this._stepsPerRevolution)a<n?this._timesWrapped=1:this._timesWrapped=0;else if(n>r)this._prevAng>=n&&a<=(n+r)/2?this._timesWrapped++:this._prevAng<=r&&a>(n+r)/2&&this._timesWrapped--;else if(a<n||a>r){s=((n+r)/2+180)%360,s>180?i=r<a&&a<s?this.get("max"):this.get("min"):i=n>a&&a>s?this.get("min"):this.get("max"),this._prevAng=this._getAngleFromValue(i),this.set("value",i),this._setTimesWrappedFromValue(i);return}i=this._getValueFromAngle(a),this._prevAng=a,this._handleValuesBeyondMinMax(t,i)},_handleValuesBeyondMinMax:function(e,t){t>=this._minValue&&t<=this._maxValue?(this.set("value",t),e.currentTarget===this._ringNode&&this._dd1._handleMouseDownEvent(e)):t>this._maxValue?(this.set("value",this._maxValue),e.type==="gesturemovestart"&&(this._prevAng=this._getAngleFromValue(this._maxValue))):t<this._minValue&&(this.set("value",this._minValue),e.type==="gesturemovestart"&&(this._prevAng=this._getAngleFromValue(this._minValue)))},_handleDragStart:function(e){this._markerNode.removeClass(o.CSS_CLASSES.hidden)},_handleDragEnd:function(){var t=this._handleNode;t.transition({duration:.08,easing:"ease-in",left:this._setNodeToFixedRadius(this._handleNode,!0)[0]+"px",top:this._setNodeToFixedRadius(this._handleNode,!0)[1]+"px"},e.bind(function(){var e=this.get("value");e>this._minValue&&e<this._maxValue?this._markerNode.addClass(o.CSS_CLASSES.hidden):(this._setTimesWrappedFromValue(e),this._prevAng=this._getAngleFromValue(e))},this))},_setNodeToFixedRadius:function(e,t){var n=this._angle-90,r=Math.PI/180,i=Math.round(Math.sin(n*r)*this._handleDistance),s=Math.round(Math.cos(n*r)*this._handleDistance),o=e.get("offsetWidth");i-=o*.5,s-=o*.5;if(t)return[this._ringNodeRadius+s,this._ringNodeRadius+i];e.setStyle("left",this._ringNodeRadius+s+"px"),e.setStyle("top",this._ringNodeRadius+i+"px")},syncUI:function(){this._setSizes(),this._calculateDialCenter(),this._setBorderRadius(),this._uiSetValue(this.get("value")),this._markerNode.addClass(o.CSS_CLASSES.hidden),this._resetString.addClass(o.CSS_CLASSES.hidden)},_setSizes:function(){var e=this.get("diameter"),t,n,r,i=function(e,t,n){var r="px";e.getElementsByTagName("oval").setStyle("width",t*n+r),e.getElementsByTagName("oval").setStyle("height",t*n+r),e.setStyle("width",t*n+r),e.setStyle("height",t*n+r)};i(this._ringNode,e,1),i(this._handleNode,e,this.get("handleDiameter")),i(this._markerNode,e,this.get("markerDiameter")),i(this._centerButtonNode,e,this.get("centerButtonDiameter")),this._ringNodeRadius=this._ringNode.get("offsetWidth")*.5,this._handleNodeRadius=this._handleNode.get("offsetWidth")*.5,this._markerNodeRadius=this._markerNode.get("offsetWidth")*.5,this._centerButtonNodeRadius=this._centerButtonNode.get("offsetWidth")*.5,this._handleDistance=this._ringNodeRadius*this.get("handleDistance"),t=this._ringNodeRadius-this._centerButtonNodeRadius,this._centerButtonNode.setStyle("left",t+"px"),this._centerButtonNode.setStyle("top",t+"px"),n=this._centerButtonNodeRadius-this._resetString.get("offsetWidth")*.5,r=this._centerButtonNodeRadius-this._resetString.get("offsetHeight")*.5,this._resetString.setStyles({left:n+"px",top:r+"px"})},_renderLabel:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.label);n||(n=s.create(e.Lang.sub(o.LABEL_TEMPLATE,this.get("strings"))),t.append(n)),this._labelNode=n,this._valueStringNode=this._labelNode.one("."+o.CSS_CLASSES.valueString)},_renderRing:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.ring);t||(t=e.appendChild(o.RING_TEMPLATE),t.setStyles({width:this.get("diameter")+"px",height:this.get("diameter")+"px"})),this._ringNode=t},_renderMarker:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.marker);t||(t=e.one("."+o.CSS_CLASSES.ring).appendChild(o.MARKER_TEMPLATE)),this._markerNode=t},_renderCenterButton:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.centerButton);n||(n=s.create(e.Lang.sub(o.CENTER_BUTTON_TEMPLATE,this.get("strings"))),t.one("."+o.CSS_CLASSES.ring).append(n)),this._centerButtonNode=n,this._resetString=this._centerButtonNode.one("."+o.CSS_CLASSES.resetString)},_renderHandle:function(){var t=o.CSS_CLASSES.label+e.guid(),n=this.get("contentBox"),r=n.one("."+o.CSS_CLASSES.handle);r||(r=s.create(e.Lang.sub(o.HANDLE_TEMPLATE,this.get("strings"))),r.setAttribute("aria-labelledby",t),this._labelNode.one("."+o.CSS_CLASSES.labelString).setAttribute("id",t),n.one("."+o.CSS_CLASSES.ring).append(r)),this._handleNode=r},_setLabelString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.labelString).setHTML(e)},_setResetString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.resetString).setHTML(e)},_setTooltipString:function(e){this._handleNode.set("title",e)},_onDirectionKey:function(e){e.preventDefault();switch(e.charCode){case 38:this._incrMinor();break;case 40:this._decrMinor();break;case 36:this._setToMin();break;case 35:this._setToMax();break;case 33:this._incrMajor();break;case 34:this._decrMajor()}},_onLeftRightKey:function(e){e.preventDefault();switch(e.charCode){case 37:this._decrMinor();break;case 39:this._incrMinor()}},_onLeftRightKeyMeta:function(e){e.preventDefault();switch(e.charCode){case 37:this._setToMin();break;case 39:this._setToMax()}},_incrMinor:function(){var e=this.get("value")+this.get("minorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMinor:function(){var e=this.get("value")-this.get("minorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_incrMajor:function(){var e=this.get("value")+this.get("majorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMajor:function(){var e=this.get("value")-this.get("majorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_setToMax:function(){this.set("value",this.get("max"))},_setToMin:function(){this.set("value",this.get("min"))},_resetDial:function(e){e&&e.stopPropagation(),this.set("value",this._originalValue),this._resetString.addClass(o.CSS_CLASSES.hidden),this._handleNode.focus()},_getAngleFromValue:function(e){var t=e%this._stepsPerRevolution,n=t/this._stepsPerRevolution*360;return n<0?n+360:n},_getValueFromAngle:function(e){e<0?e=360+e:e===0&&(e=360);var t=e/360*this._stepsPerRevolution;return t+=this._timesWrapped*this._stepsPerRevolution,t.toFixed(this.get("decimalPlaces"))-0},_afterValueChange:function(e){this._uiSetValue(e.newVal)},_valueToDecimalPlaces:function(e){},_uiSetValue:function(e){this._angle=this._getAngleFromValue(e),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&(this._setTimesWrappedFromValue(e),this._setNodeToFixedRadius(this._handleNode,!1),this._prevAng=this._getAngleFromValue(this.get("value"))),this._valueStringNode.setHTML(e.toFixed(this.get("decimalPlaces"))),this._handleNode.set("aria-valuenow",e),this._handleNode.set("aria-valuetext",e),this._setNodeToFixedRadius(this._markerNode,!1),e===this._maxValue||e===this._minValue?(this._markerNode.addClass(o.CSS_CLASSES.markerMaxMin),n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#AB3232"),this._markerNode.removeClass(o.CSS_CLASSES.hidden)):(n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#000"),this._markerNode.removeClass(o.CSS_CLASSES.markerMaxMin),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&this._markerNode.addClass(o.CSS_CLASSES.hidden))},_validateValue:function(e){var t=this.get("min"),n=this.get("max");return r.isNumber(e)&&e>=t&&e<=n}}),e.Dial=o},"@VERSION@",{requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],lang:["en","es"],skinnable:!0});
  1 +YUI.add("dial",function(e,t){function o(e){o.superclass.constructor.apply(this,arguments)}function u(t){return e.ClassNameManager.getClassName(o.NAME,t)}var n=!1;e.UA.ie&&e.UA.ie<9&&(n=!0);var r=e.Lang,i=e.Widget,s=e.Node;o.NAME="dial",o.ATTRS={min:{value:-220},max:{value:220},diameter:{value:100},handleDiameter:{value:.2},markerDiameter:{value:.1},centerButtonDiameter:{value:.5},value:{value:0,validator:function(e){return this._validateValue(e)}},minorStep:{value:1},majorStep:{value:10},stepsPerRevolution:{value:100},decimalPlaces:{value:0},strings:{valueFn:function(){return e.Intl.get("dial")}},handleDistance:{value:.75}},o.CSS_CLASSES={label:u("label"),labelString:u("label-string"),valueString:u("value-string"),northMark:u("north-mark"),ring:u("ring"),ringVml:u("ring-vml"),marker:u("marker"),markerVml:u("marker-vml"),markerMaxMin:u("marker-max-min"),centerButton:u("center-button"),centerButtonVml:u("center-button-vml"),resetString:u("reset-string"),handle:u("handle"),handleVml:u("handle-vml"),hidden:u("hidden"),dragging:e.ClassNameManager.getClassName("dd-dragging")},o.LABEL_TEMPLATE='<div class="'+o.CSS_CLASSES.label+'"><span id="" class="'+o.CSS_CLASSES.labelString+'">{label}</span><span class="'+o.CSS_CLASSES.valueString+'"></span></div>',n===!1?(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+'"><div class="'+o.CSS_CLASSES.northMark+'"></div></div>',o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.marker+" "+o.CSS_CLASSES.hidden+'"></div>',o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+'"><div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div></div>',o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handle+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'):(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+" "+o.CSS_CLASSES.ringVml+'">'+'<div class="'+o.CSS_CLASSES.northMark+'"></div>'+'<v:oval strokecolor="#ceccc0" strokeweight="1px"><v:fill type=gradient color="#8B8A7F" color2="#EDEDEB" angle="45"/></v:oval>'+"</div>"+"",o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.markerVml+" "+o.CSS_CLASSES.hidden+'">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#000"/>'+"</v:oval>"+"</div>"+"",o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+" "+o.CSS_CLASSES.centerButtonVml+'">'+'<v:oval strokecolor="#ceccc0" strokeweight="1px">'+'<v:fill type=gradient color="#C7C5B9" color2="#fefcf6" colors="35% #d9d7cb, 65% #fefcf6" angle="45"/>'+'<v:shadow on="True" color="#000" opacity="10%" offset="2px, 2px"/>'+"</v:oval>"+'<div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div>'+"</div>"+"",o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handleVml+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#6C3A3A"/>'+"</v:oval>"+"</div>"+""),e.extend(o,i,{renderUI:function(){this._renderLabel(),this._renderRing(),this._renderMarker(),this._renderCenterButton(),this._renderHandle(),this.contentBox=this.get("contentBox"),this._originalValue=this.get("value"),this._minValue=this.get("min"),this._maxValue=this.get("max"),this._stepsPerRevolution=this.get("stepsPerRevolution"),this._minTimesWrapped=Math.floor(this._minValue/this._stepsPerRevolution-1),this._maxTimesWrapped=Math.floor(this._maxValue/this._stepsPerRevolution+1),this._timesWrapped=0,this._angle=this._getAngleFromValue(this.get("value")),this._prevAng=this._angle,this._setTimesWrappedFromValue(this._originalValue),this._handleNode.set("aria-valuemin",this._minValue),this._handleNode.set("aria-valuemax",this._maxValue)},_setBorderRadius:function(){this._ringNode.setStyles({WebkitBorderRadius:this._ringNodeRadius+"px",MozBorderRadius:this._ringNodeRadius+"px",borderRadius:this._ringNodeRadius+"px"}),this._handleNode.setStyles({WebkitBorderRadius:this._handleNodeRadius+"px",MozBorderRadius:this._handleNodeRadius+"px",borderRadius:this._handleNodeRadius+"px"}),this._markerNode.setStyles({WebkitBorderRadius:this._markerNodeRadius+"px",MozBorderRadius:this._markerNodeRadius+"px",borderRadius:this._markerNodeRadius+"px"}),this._centerButtonNode.setStyles({WebkitBorderRadius:this._centerButtonNodeRadius+"px",MozBorderRadius:this._centerButtonNodeRadius+"px",borderRadius:this._centerButtonNodeRadius+"px"})},_handleCenterButtonEnter:function(){this._resetString.removeClass(o.CSS_CLASSES.hidden)},_handleCenterButtonLeave:function(){this._resetString.addClass(o.CSS_CLASSES.hidden)},bindUI:function(){this.after("valueChange",this._afterValueChange);var t=this.get("boundingBox"),n=e.UA.opera?"press:":"down:",r=n+"38,40,33,34,35,36",i=n+"37,39",s=n+"37+meta,39+meta",o=e.DD.Drag;e.on("key",e.bind(this._onDirectionKey,this),t,r),e.on("key",e.bind(this._onLeftRightKey,this),t,i),t.on("key",this._onLeftRightKeyMeta,s,this),e.on("mouseenter",e.bind(this._handleCenterButtonEnter,this),this._centerButtonNode),e.on("mouseleave",e.bind(this._handleCenterButtonLeave,this),this._centerButtonNode),e.on("gesturemovestart",e.bind(this._resetDial,this),this._centerButtonNode),e.on("gesturemoveend",e.bind(this._handleCenterButtonMouseup,this),this._centerButtonNode),e.on(o.START_EVENT,e.bind(this._handleHandleMousedown,this),this._handleNode),e.on(o.START_EVENT,e.bind(this._handleMousedown,this),this._ringNode),e.on("gesturemoveend",e.bind(this._handleRingMouseup,this),this._ringNode),this._dd1=new o({node:this._handleNode,on:{"drag:drag":e.bind(this._handleDrag,this),"drag:start":e.bind(this._handleDragStart,this),"drag:end":e.bind(this._handleDragEnd,this)}}),e.bind(this._dd1.addHandle(this._ringNode),this)},_setTimesWrappedFromValue:function(e){e%this._stepsPerRevolution===0?this._timesWrapped=e/this._stepsPerRevolution:this._timesWrapped=Math.floor(e/this._stepsPerRevolution)},_getAngleFromHandleCenter:function(e,t){var n=Math.atan((this._dialCenterY-t)/(this._dialCenterX-e))*(180/Math.PI);return n=this._dialCenterX-e<0?n+90:n+90+180,n},_calculateDialCenter:function(){this._dialCenterX=this._ringNode.get("offsetWidth")/2,this._dialCenterY=this._ringNode.get("offsetHeight")/2},_handleRingMouseup:function(){this._handleNode.focus()},_handleCenterButtonMouseup:function(){this._handleNode.focus()},_handleHandleMousedown:function(){this._handleNode.focus()},_handleDrag:function(e){var t,n,r,i;t=parseInt(this._handleNode.getStyle("left"),10)+this._handleNodeRadius,n=parseInt(this._handleNode.getStyle("top"),10)+this._handleNodeRadius,r=this._getAngleFromHandleCenter(t,n),this._prevAng>270&&r<90?this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._timesWrapped+1):this._prevAng<90&&r>270&&this._timesWrapped>this._minTimesWrapped&&(this._timesWrapped=this._timesWrapped-1),i=this._getValueFromAngle(r),i>this._maxValue+this._stepsPerRevolution?this._timesWrapped--:i<this._minValue-this._stepsPerRevolution&&this._timesWrapped++,this._prevAng=r,this._handleValuesBeyondMinMax(e,i)},_handleMousedown:function(t){if(this._ringNode.compareTo(t.target)){var n=this._getAngleFromValue(this._minValue),r=this._getAngleFromValue(this._maxValue),i,s,o,u,a;e.UA.ios?(o=t.clientX-this._ringNode.getX(),u=t.clientY-this._ringNode.getY()):(o=t.clientX+e.one("document").get("scrollLeft")-this._ringNode.getX(),u=t.clientY+e.one("document").get("scrollTop")-this._ringNode.getY()),a=this._getAngleFromHandleCenter(o,u);if(this._maxValue-this._minValue>this._stepsPerRevolution)Math.abs(this._prevAng-a)>180?this._timesWrapped>this._minTimesWrapped&&this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._prevAng-a>0?this._timesWrapped+1:this._timesWrapped-1):this._timesWrapped===this._minTimesWrapped&&a-this._prevAng<180&&this._timesWrapped++;else if(this._maxValue-this._minValue===this._stepsPerRevolution)a<n?this._timesWrapped=1:this._timesWrapped=0;else if(n>r)this._prevAng>=n&&a<=(n+r)/2?this._timesWrapped++:this._prevAng<=r&&a>(n+r)/2&&this._timesWrapped--;else if(a<n||a>r){s=((n+r)/2+180)%360,s>180?i=r<a&&a<s?this.get("max"):this.get("min"):i=n>a&&a>s?this.get("min"):this.get("max"),this._prevAng=this._getAngleFromValue(i),this.set("value",i),this._setTimesWrappedFromValue(i);return}i=this._getValueFromAngle(a),this._prevAng=a,this._handleValuesBeyondMinMax(t,i)}},_handleValuesBeyondMinMax:function(e,t){t>=this._minValue&&t<=this._maxValue?(this.set("value",t),e.currentTarget===this._ringNode&&this._dd1._handleMouseDownEvent(e)):t>this._maxValue?(this.set("value",this._maxValue),this._prevAng=this._getAngleFromValue(this._maxValue)):t<this._minValue&&(this.set("value",this._minValue),this._prevAng=this._getAngleFromValue(this._minValue))},_handleDragStart:function(e){this._markerNode.removeClass(o.CSS_CLASSES.hidden)},_handleDragEnd:function(){var t=this._handleNode;t.transition({duration:.08,easing:"ease-in",left:this._setNodeToFixedRadius(this._handleNode,!0)[0]+"px",top:this._setNodeToFixedRadius(this._handleNode,!0)[1]+"px"},e.bind(function(){var e=this.get("value");e>this._minValue&&e<this._maxValue?this._markerNode.addClass(o.CSS_CLASSES.hidden):(this._setTimesWrappedFromValue(e),this._prevAng=this._getAngleFromValue(e))},this))},_setNodeToFixedRadius:function(e,t){var n=this._angle-90,r=Math.PI/180,i=Math.round(Math.sin(n*r)*this._handleDistance),s=Math.round(Math.cos(n*r)*this._handleDistance),o=e.get("offsetWidth");i-=o*.5,s-=o*.5;if(t)return[this._ringNodeRadius+s,this._ringNodeRadius+i];e.setStyle("left",this._ringNodeRadius+s+"px"),e.setStyle("top",this._ringNodeRadius+i+"px")},syncUI:function(){this._setSizes(),this._calculateDialCenter(),this._setBorderRadius(),this._uiSetValue(this.get("value")),this._markerNode.addClass(o.CSS_CLASSES.hidden),this._resetString.addClass(o.CSS_CLASSES.hidden)},_setSizes:function(){var e=this.get("diameter"),t,n,r,i=function(e,t,n){var r="px";e.getElementsByTagName("oval").setStyle("width",t*n+r),e.getElementsByTagName("oval").setStyle("height",t*n+r),e.setStyle("width",t*n+r),e.setStyle("height",t*n+r)};i(this._ringNode,e,1),i(this._handleNode,e,this.get("handleDiameter")),i(this._markerNode,e,this.get("markerDiameter")),i(this._centerButtonNode,e,this.get("centerButtonDiameter")),this._ringNodeRadius=this._ringNode.get("offsetWidth")*.5,this._handleNodeRadius=this._handleNode.get("offsetWidth")*.5,this._markerNodeRadius=this._markerNode.get("offsetWidth")*.5,this._centerButtonNodeRadius=this._centerButtonNode.get("offsetWidth")*.5,this._handleDistance=this._ringNodeRadius*this.get("handleDistance"),t=this._ringNodeRadius-this._centerButtonNodeRadius,this._centerButtonNode.setStyle("left",t+"px"),this._centerButtonNode.setStyle("top",t+"px"),n=this._centerButtonNodeRadius-this._resetString.get("offsetWidth")*.5,r=this._centerButtonNodeRadius-this._resetString.get("offsetHeight")*.5,this._resetString.setStyles({left:n+"px",top:r+"px"})},_renderLabel:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.label);n||(n=s.create(e.Lang.sub(o.LABEL_TEMPLATE,this.get("strings"))),t.append(n)),this._labelNode=n,this._valueStringNode=this._labelNode.one("."+o.CSS_CLASSES.valueString)},_renderRing:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.ring);t||(t=e.appendChild(o.RING_TEMPLATE),t.setStyles({width:this.get("diameter")+"px",height:this.get("diameter")+"px"})),this._ringNode=t},_renderMarker:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.marker);t||(t=e.one("."+o.CSS_CLASSES.ring).appendChild(o.MARKER_TEMPLATE)),this._markerNode=t},_renderCenterButton:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.centerButton);n||(n=s.create(e.Lang.sub(o.CENTER_BUTTON_TEMPLATE,this.get("strings"))),t.one("."+o.CSS_CLASSES.ring).append(n)),this._centerButtonNode=n,this._resetString=this._centerButtonNode.one("."+o.CSS_CLASSES.resetString)},_renderHandle:function(){var t=o.CSS_CLASSES.label+e.guid(),n=this.get("contentBox"),r=n.one("."+o.CSS_CLASSES.handle);r||(r=s.create(e.Lang.sub(o.HANDLE_TEMPLATE,this.get("strings"))),r.setAttribute("aria-labelledby",t),this._labelNode.one("."+o.CSS_CLASSES.labelString).setAttribute("id",t),n.one("."+o.CSS_CLASSES.ring).append(r)),this._handleNode=r},_setLabelString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.labelString).setHTML(e)},_setResetString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.resetString).setHTML(e)},_setTooltipString:function(e){this._handleNode.set("title",e)},_onDirectionKey:function(e){e.preventDefault();switch(e.charCode){case 38:this._incrMinor();break;case 40:this._decrMinor();break;case 36:this._setToMin();break;case 35:this._setToMax();break;case 33:this._incrMajor();break;case 34:this._decrMajor()}},_onLeftRightKey:function(e){e.preventDefault();switch(e.charCode){case 37:this._decrMinor();break;case 39:this._incrMinor()}},_onLeftRightKeyMeta:function(e){e.preventDefault();switch(e.charCode){case 37:this._setToMin();break;case 39:this._setToMax()}},_incrMinor:function(){var e=this.get("value")+this.get("minorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMinor:function(){var e=this.get("value")-this.get("minorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_incrMajor:function(){var e=this.get("value")+this.get("majorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMajor:function(){var e=this.get("value")-this.get("majorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_setToMax:function(){this.set("value",this.get("max"))},_setToMin:function(){this.set("value",this.get("min"))},_resetDial:function(e){e&&e.stopPropagation(),this.set("value",this._originalValue),this._resetString.addClass(o.CSS_CLASSES.hidden),this._handleNode.focus()},_getAngleFromValue:function(e){var t=e%this._stepsPerRevolution,n=t/this._stepsPerRevolution*360;return n<0?n+360:n},_getValueFromAngle:function(e){e<0?e=360+e:e===0&&(e=360);var t=e/360*this._stepsPerRevolution;return t+=this._timesWrapped*this._stepsPerRevolution,t.toFixed(this.get("decimalPlaces"))-0},_afterValueChange:function(e){this._uiSetValue(e.newVal)},_valueToDecimalPlaces:function(e){},_uiSetValue:function(e){this._angle=this._getAngleFromValue(e),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&(this._setTimesWrappedFromValue(e),this._setNodeToFixedRadius(this._handleNode,!1),this._prevAng=this._getAngleFromValue(this.get("value"))),this._valueStringNode.setHTML(e.toFixed(this.get("decimalPlaces"))),this._handleNode.set("aria-valuenow",e),this._handleNode.set("aria-valuetext",e),this._setNodeToFixedRadius(this._markerNode,!1),e===this._maxValue||e===this._minValue?(this._markerNode.addClass(o.CSS_CLASSES.markerMaxMin),n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#AB3232"),this._markerNode.removeClass(o.CSS_CLASSES.hidden)):(n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#000"),this._markerNode.removeClass(o.CSS_CLASSES.markerMaxMin),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&this._markerNode.addClass(o.CSS_CLASSES.hidden))},_validateValue:function(e){var t=this.get("min"),n=this.get("max");return r.isNumber(e)&&e>=t&&e<=n}}),e.Dial=o},"@VERSION@",{requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],lang:["en","es"],skinnable:!0});
405 build/dial/dial.js
@@ -3,7 +3,7 @@ YUI.add('dial', function (Y, NAME) {
3 3 /**
4 4 * Create a circular dial value range input visualized as a draggable handle on a
5 5 * background element.
6   - *
  6 + *
7 7 * @module dial
8 8 */
9 9 var supportsVML = false;
@@ -148,7 +148,7 @@ YUI.add('dial', function (Y, NAME) {
148 148 return this._validateValue(val);
149 149 }
150 150 },
151   -
  151 +
152 152 /**
153 153 * amount to increment/decrement the dial value
154 154 * when the arrow up/down/left/right keys are pressed
@@ -174,7 +174,7 @@ YUI.add('dial', function (Y, NAME) {
174 174 },
175 175
176 176 /**
177   - * number of value increments in one 360 degree revolution
  177 + * number of value increments in one 360 degree revolution
178 178 * of the handle around the dial
179 179 *
180 180 * @attribute stepsPerRevolution
@@ -186,7 +186,7 @@ YUI.add('dial', function (Y, NAME) {
186 186 },
187 187
188 188 /**
189   - * number of decimal places of accuracy in the value
  189 + * number of decimal places of accuracy in the value
190 190 *
191 191 * @attribute decimalPlaces
192 192 * @type {Number}
@@ -197,7 +197,7 @@ YUI.add('dial', function (Y, NAME) {
197 197 },
198 198
199 199 /**
200   - * visible strings for the dial UI. This attribute is
  200 + * visible strings for the dial UI. This attribute is
201 201 * defined by the base Widget class but has an empty value. The
202 202 * Dial is simply providing a default value for the attribute.
203 203 * Gets localized strings in the current language
@@ -213,8 +213,8 @@ YUI.add('dial', function (Y, NAME) {
213 213 },
214 214
215 215 /**
216   - * distance from the center of the dial to the
217   - * center of the marker and handle, when at rest.
  216 + * distance from the center of the dial to the
  217 + * center of the marker and handle, when at rest.
218 218 * The value is a percent of the radius of the dial.
219 219 *
220 220 * @attribute handleDistance
@@ -224,7 +224,7 @@ YUI.add('dial', function (Y, NAME) {
224 224 handleDistance:{
225 225 value:0.75
226 226 }
227   -
  227 +
228 228 };
229 229
230 230 /**
@@ -238,8 +238,8 @@ YUI.add('dial', function (Y, NAME) {
238 238 function makeClassName(str) {
239 239 return Y.ClassNameManager.getClassName(Dial.NAME, str);
240 240 }
241   -
242   - /** array of static constants used to identify the classname applied to the Dial DOM objects
  241 +
  242 + /** array of static constants used to identify the classname applied to the Dial DOM objects
243 243 *
244 244 * @property CSS_CLASSES
245 245 * @type {Array}
@@ -264,9 +264,9 @@ YUI.add('dial', function (Y, NAME) {
264 264 hidden : makeClassName("hidden"),
265 265 dragging : Y.ClassNameManager.getClassName("dd-dragging")
266 266 };
267   -
  267 +
268 268 /* Static constants used to define the markup templates used to create Dial DOM elements */
269   -
  269 +
270 270
271 271 /**
272 272 * template that will contain the Dial's label.
@@ -319,7 +319,7 @@ YUI.add('dial', function (Y, NAME) {
319 319 * @protected
320 320 */
321 321 Dial.HANDLE_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.handle + '" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">';
322   -
  322 +
323 323 }else{ // VML case
324 324 Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + ' ' + Dial.CSS_CLASSES.ringVml + '">'+
325 325 '<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
@@ -363,7 +363,7 @@ YUI.add('dial', function (Y, NAME) {
363 363 this._renderMarker();
364 364 this._renderCenterButton();
365 365 this._renderHandle();
366   -
  366 +
367 367 // object handles
368 368 this.contentBox = this.get("contentBox");
369 369
@@ -379,7 +379,7 @@ YUI.add('dial', function (Y, NAME) {
379 379 this._timesWrapped = 0;
380 380 this._angle = this._getAngleFromValue(this.get('value'));
381 381 this._prevAng = this._angle;
382   -
  382 +
383 383 // init
384 384 this._setTimesWrappedFromValue(this._originalValue);
385 385 this._handleNode.set('aria-valuemin', this._minValue);
@@ -411,27 +411,27 @@ YUI.add('dial', function (Y, NAME) {
411 411 'borderRadius':this._centerButtonNodeRadius + 'px'
412 412 });
413 413 },
414   -
  414 +
415 415 /**
416 416 * Handles the mouseenter on the centerButton
417   - *
  417 + *
418 418 * @method _handleCenterButtonEnter
419 419 * @protected
420 420 */
421 421 _handleCenterButtonEnter : function(){
422   - this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
423   - },
424   -
  422 + this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
  423 + },
  424 +
425 425 /**
426 426 * Handles the mouseleave on the centerButton
427   - *
  427 + *
428 428 * @method _handleCenterButtonLeave
429 429 * @protected
430 430 */
431 431 _handleCenterButtonLeave : function(){
432   - this._resetString.addClass(Dial.CSS_CLASSES.hidden);
433   - },
434   -
  432 + this._resetString.addClass(Dial.CSS_CLASSES.hidden);
  433 + },
  434 +
435 435 /**
436 436 * Creates the Y.DD.Drag instance used for the handle movement and
437 437 * binds Dial interaction to the configured value model.
@@ -440,17 +440,19 @@ YUI.add('dial', function (Y, NAME) {
440 440 * @protected
441 441 */
442 442 bindUI : function() {
  443 +
443 444 this.after("valueChange", this._afterValueChange);
444 445
445 446 var boundingBox = this.get("boundingBox"),
446 447 // Looking for a key event which will fire continously across browsers while the key is held down.
447   - keyEvent = (!Y.UA.opera) ? "down:" : "press:",
  448 + keyEvent = (!Y.UA.opera) ? "down:" : "press:",
448 449 // 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
449 450 keyEventSpec = keyEvent + "38,40,33,34,35,36",
450 451 // 37 , 39 = arrow left/right
451 452 keyLeftRightSpec = keyEvent + "37,39",
452 453 // 37 , 39 = arrow left/right + meta (command/apple key) for mac
453   - keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta";
  454 + keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta",
  455 + Drag = Y.DD.Drag;
454 456
455 457 Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
456 458 Y.on("key", Y.bind(this._onLeftRightKey, this), boundingBox, keyLeftRightSpec);
@@ -459,14 +461,17 @@ YUI.add('dial', function (Y, NAME) {
459 461 Y.on('mouseenter', Y.bind(this._handleCenterButtonEnter, this), this._centerButtonNode);
460 462 Y.on('mouseleave', Y.bind(this._handleCenterButtonLeave, this), this._centerButtonNode);
461 463 // Needed to replace mousedown/up with gesturemovestart/end to make behavior on touch devices work the same.
462   - Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
463   - Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
464   - Y.on('gesturemovestart', Y.bind(this._handleHandleMousedown, this), this._handleNode);
  464 + Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
  465 + Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
  466 +
  467 +
  468 + Y.on(Drag.START_EVENT, Y.bind(this._handleHandleMousedown, this), this._handleNode);
  469 + Y.on(Drag.START_EVENT, Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
465 470
466   - Y.on('gesturemovestart', Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
  471 + //TODO: Can this be merged this into the drag:end event listener to avoid another registration?
467 472 Y.on('gesturemoveend', Y.bind(this._handleRingMouseup, this), this._ringNode);
468 473
469   - this._dd1 = new Y.DD.Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
  474 + this._dd1 = new Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
470 475 node: this._handleNode,
471 476 on : {
472 477 'drag:drag' : Y.bind(this._handleDrag, this),
@@ -492,68 +497,68 @@ YUI.add('dial', function (Y, NAME) {
492 497 this._timesWrapped = Math.floor(val / this._stepsPerRevolution);
493 498 }
494 499 },
495   -
  500 +
496 501 /**
497   - * gets the angle of the line from the center of the Dial to the center of the handle
  502 + * gets the angle of the line from the center of the Dial to the center of the handle
498 503 *
499 504 * @method _getAngleFromHandleCenter
500   - * @param handleCenterX {number}
  505 + * @param handleCenterX {number}
501 506 * @param handleCenterY {number}
502 507 * @return ang {number} the angle
503 508 * @protected
504 509 */
505 510 _getAngleFromHandleCenter : function(handleCenterX, handleCenterY){
506   - var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
  511 + var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
507 512 ang = ((this._dialCenterX - handleCenterX) < 0) ? ang + 90 : ang + 90 + 180; // Compensate for neg angles from Math.atan
508 513 return ang;
509 514 },
510   -
  515 +
511 516 /**
512   - * calculates the XY of the center of the dial relative to the ring node.
  517 + * calculates the XY of the center of the dial relative to the ring node.
513 518 * This is needed for calculating the angle of the handle
514 519 *
515 520 * @method _calculateDialCenter
516 521 * @protected
517 522 */
518 523 _calculateDialCenter : function(){ // #2531111 value, and marker don't track handle when dial position changes on page (resize when inline)
519   - this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
  524 + this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
520 525 this._dialCenterY = this._ringNode.get('offsetHeight') / 2;
521 526 },
522   -
  527 +
523 528 /**
524 529 * Handles the mouseup on the ring
525   - *
  530 + *
526 531 * @method _handleRingMouseup
527 532 * @protected
528 533 */
529 534 _handleRingMouseup : function(){
530   - this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
531   - },
532   -
  535 + this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
  536 + },
  537 +
533 538 /**
534 539 * Handles the mouseup on the centerButton
535   - *
  540 + *
536 541 * @method _handleCenterButtonMouseup
537 542 * @protected
538 543 */
539 544 _handleCenterButtonMouseup : function(){
540   - this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
541   - },
542   -
  545 + this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
  546 + },
  547 +
543 548 /**
544 549 * Handles the mousedown on the handle
545   - *
  550 + *
546 551 * @method _handleHandleMousedown
547 552 * @protected
548 553 */
549 554 _handleHandleMousedown : function(){
550 555 this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
551   - // this is better done here instead of on _handleDragEnd
552   - // because we should make the keyboard accessible after a click of the handle
553   - },
554   -
  556 + // this is better done here instead of on _handleDragEnd
  557 + // because we should make the keyboard accessible after a click of the handle
  558 + },
  559 +
555 560 /**
556   - * handles the user dragging the handle around the Dial, gets the angle,
  561 + * handles the user dragging the handle around the Dial, gets the angle,
557 562 * checks for wrapping around top center.
558 563 * Sets the new value of the Dial
559 564 *
@@ -567,7 +572,7 @@ YUI.add('dial', function (Y, NAME) {
567 572 ang,
568 573 newValue;
569 574
570   - // The event was emitted from drag:drag of handle.
  575 + // The event was emitted from drag:drag of handle.
571 576 // The center of the handle is top left position of the handle node + radius of handle.
572 577 // This is different than a mousedown on the ring.
573 578 handleCenterX = (parseInt(this._handleNode.getStyle('left'),10) + this._handleNodeRadius);
@@ -585,7 +590,7 @@ YUI.add('dial', function (Y, NAME) {
585 590 }
586 591 }
587 592 newValue = this._getValueFromAngle(ang); // This function needs the current _timesWrapped value. That's why it comes after the _timesWrapped code above
588   -
  593 +
589 594 // If you've gone past max more than one full revolution, we decrement the _timesWrapped value
590 595 // This gives the effect of a ratchet mechanism.
591 596 // It feels like you are never more than one revolution past max
@@ -597,7 +602,7 @@ YUI.add('dial', function (Y, NAME) {
597 602 }else if(newValue < (this._minValue - this._stepsPerRevolution) ){
598 603 this._timesWrapped ++;
599 604 }
600   - this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
  605 + this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
601 606
602 607 this._handleValuesBeyondMinMax(e, newValue);
603 608 },
@@ -610,119 +615,125 @@ YUI.add('dial', function (Y, NAME) {
610 615 * @private
611 616 */
612 617 _handleMousedown : function(e){ // #2530306
613   - var minAng = this._getAngleFromValue(this._minValue),
614   - maxAng = this._getAngleFromValue(this._maxValue),
615   - newValue, oppositeMidRangeAngle,
616   - handleCenterX, handleCenterY,
617   - ang;
618   -
619   - // The event was emitted from mousedown on the ring node,
620   - // so the center of the handle should be the XY of mousedown.
621   - if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
622   - handleCenterX = (e.clientX - this._ringNode.getX());
623   - handleCenterY = (e.clientY - this._ringNode.getY());
624   - }else{
625   - handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
626   - handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
627   - }
628   - ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
629   -
630   - /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
631   - * The next sections of logic
632   - * set this._timesWrapped in the different cases of value range
633   - * and value range position,
634   - * then the Dial value is set at the end of this method
635   - */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
636   -
637   -
638   - ////////////////////////////////////////////////////////////////////////////////////////////////////////////
639   - if(this._maxValue - this._minValue > this._stepsPerRevolution){
640   - // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
641   -
642   - // This checks the shortest way around the dial between the prevAng and this ang.
643   - if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
644   -
645   - // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
646   - if((this._timesWrapped > this._minTimesWrapped) &&
647   - (this._timesWrapped < this._maxTimesWrapped)
648   - ){
649   - // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
650   - this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
651   - }
652   - // special case of getting un-stuck from a min value case
653   - // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
654   - // because prevAng is set to 0 or > 0
655   - }else if(
656   - (this._timesWrapped === this._minTimesWrapped) &&
657   - (ang - this._prevAng < 180)
658   - ){
659   - this._timesWrapped ++;
660   - } //it didn't cross a wrapping boundary
661   -
662   - } /////////////////////////////////////////////////////////////////////////////////////////////////////////
663   - else if(this._maxValue - this._minValue === this._stepsPerRevolution){
664   - // Case: range min-to-max === stepsPerRevolution (one revolution)
665   - // This means min and max will be at same angle
666