Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'dial-ie10-fixes'

  • Loading branch information...
commit e014093eaead42b4ac276a62016737f363cd39b6 2 parents 1d5e727 + 3b9bf9b
@tilomitra tilomitra authored
View
908 build/dial/dial-coverage.js
457 additions, 451 deletions not shown
View
405 build/dial/dial-debug.js
@@ -3,7 +3,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* Create a circular dial value range input visualized as a draggable handle on a
* background element.
- *
+ *
* @module dial
*/
var supportsVML = false;
@@ -148,7 +148,7 @@ YUI.add('dial', function (Y, NAME) {
return this._validateValue(val);
}
},
-
+
/**
* amount to increment/decrement the dial value
* when the arrow up/down/left/right keys are pressed
@@ -174,7 +174,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * number of value increments in one 360 degree revolution
+ * number of value increments in one 360 degree revolution
* of the handle around the dial
*
* @attribute stepsPerRevolution
@@ -186,7 +186,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * number of decimal places of accuracy in the value
+ * number of decimal places of accuracy in the value
*
* @attribute decimalPlaces
* @type {Number}
@@ -197,7 +197,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * visible strings for the dial UI. This attribute is
+ * visible strings for the dial UI. This attribute is
* defined by the base Widget class but has an empty value. The
* Dial is simply providing a default value for the attribute.
* Gets localized strings in the current language
@@ -213,8 +213,8 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * distance from the center of the dial to the
- * center of the marker and handle, when at rest.
+ * distance from the center of the dial to the
+ * center of the marker and handle, when at rest.
* The value is a percent of the radius of the dial.
*
* @attribute handleDistance
@@ -224,7 +224,7 @@ YUI.add('dial', function (Y, NAME) {
handleDistance:{
value:0.75
}
-
+
};
/**
@@ -238,8 +238,8 @@ YUI.add('dial', function (Y, NAME) {
function makeClassName(str) {
return Y.ClassNameManager.getClassName(Dial.NAME, str);
}
-
- /** array of static constants used to identify the classname applied to the Dial DOM objects
+
+ /** array of static constants used to identify the classname applied to the Dial DOM objects
*
* @property CSS_CLASSES
* @type {Array}
@@ -264,9 +264,9 @@ YUI.add('dial', function (Y, NAME) {
hidden : makeClassName("hidden"),
dragging : Y.ClassNameManager.getClassName("dd-dragging")
};
-
+
/* Static constants used to define the markup templates used to create Dial DOM elements */
-
+
/**
* template that will contain the Dial's label.
@@ -319,7 +319,7 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
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}">';
-
+
}else{ // VML case
Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + ' ' + Dial.CSS_CLASSES.ringVml + '">'+
'<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
@@ -363,7 +363,7 @@ YUI.add('dial', function (Y, NAME) {
this._renderMarker();
this._renderCenterButton();
this._renderHandle();
-
+
// object handles
this.contentBox = this.get("contentBox");
@@ -379,7 +379,7 @@ YUI.add('dial', function (Y, NAME) {
this._timesWrapped = 0;
this._angle = this._getAngleFromValue(this.get('value'));
this._prevAng = this._angle;
-
+
// init
this._setTimesWrappedFromValue(this._originalValue);
this._handleNode.set('aria-valuemin', this._minValue);
@@ -411,27 +411,27 @@ YUI.add('dial', function (Y, NAME) {
'borderRadius':this._centerButtonNodeRadius + 'px'
});
},
-
+
/**
* Handles the mouseenter on the centerButton
- *
+ *
* @method _handleCenterButtonEnter
* @protected
*/
_handleCenterButtonEnter : function(){
- this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Handles the mouseleave on the centerButton
- *
+ *
* @method _handleCenterButtonLeave
* @protected
*/
_handleCenterButtonLeave : function(){
- this._resetString.addClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.addClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Creates the Y.DD.Drag instance used for the handle movement and
* binds Dial interaction to the configured value model.
@@ -440,17 +440,19 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
bindUI : function() {
+
this.after("valueChange", this._afterValueChange);
var boundingBox = this.get("boundingBox"),
// Looking for a key event which will fire continously across browsers while the key is held down.
- keyEvent = (!Y.UA.opera) ? "down:" : "press:",
+ keyEvent = (!Y.UA.opera) ? "down:" : "press:",
// 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
keyEventSpec = keyEvent + "38,40,33,34,35,36",
// 37 , 39 = arrow left/right
keyLeftRightSpec = keyEvent + "37,39",
// 37 , 39 = arrow left/right + meta (command/apple key) for mac
- keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta";
+ keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta",
+ Drag = Y.DD.Drag;
Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
Y.on("key", Y.bind(this._onLeftRightKey, this), boundingBox, keyLeftRightSpec);
@@ -459,14 +461,17 @@ YUI.add('dial', function (Y, NAME) {
Y.on('mouseenter', Y.bind(this._handleCenterButtonEnter, this), this._centerButtonNode);
Y.on('mouseleave', Y.bind(this._handleCenterButtonLeave, this), this._centerButtonNode);
// Needed to replace mousedown/up with gesturemovestart/end to make behavior on touch devices work the same.
- Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
- Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
- Y.on('gesturemovestart', Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
+ Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
+
+
+ Y.on(Drag.START_EVENT, Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on(Drag.START_EVENT, Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
- Y.on('gesturemovestart', Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
+ //TODO: Can this be merged this into the drag:end event listener to avoid another registration?
Y.on('gesturemoveend', Y.bind(this._handleRingMouseup, this), this._ringNode);
- this._dd1 = new Y.DD.Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
+ this._dd1 = new Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
node: this._handleNode,
on : {
'drag:drag' : Y.bind(this._handleDrag, this),
@@ -492,68 +497,68 @@ YUI.add('dial', function (Y, NAME) {
this._timesWrapped = Math.floor(val / this._stepsPerRevolution);
}
},
-
+
/**
- * gets the angle of the line from the center of the Dial to the center of the handle
+ * gets the angle of the line from the center of the Dial to the center of the handle
*
* @method _getAngleFromHandleCenter
- * @param handleCenterX {number}
+ * @param handleCenterX {number}
* @param handleCenterY {number}
* @return ang {number} the angle
* @protected
*/
_getAngleFromHandleCenter : function(handleCenterX, handleCenterY){
- var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
+ var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
ang = ((this._dialCenterX - handleCenterX) < 0) ? ang + 90 : ang + 90 + 180; // Compensate for neg angles from Math.atan
return ang;
},
-
+
/**
- * calculates the XY of the center of the dial relative to the ring node.
+ * calculates the XY of the center of the dial relative to the ring node.
* This is needed for calculating the angle of the handle
*
* @method _calculateDialCenter
* @protected
*/
_calculateDialCenter : function(){ // #2531111 value, and marker don't track handle when dial position changes on page (resize when inline)
- this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
+ this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
this._dialCenterY = this._ringNode.get('offsetHeight') / 2;
},
-
+
/**
* Handles the mouseup on the ring
- *
+ *
* @method _handleRingMouseup
* @protected
*/
_handleRingMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mouseup on the centerButton
- *
+ *
* @method _handleCenterButtonMouseup
* @protected
*/
_handleCenterButtonMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mousedown on the handle
- *
+ *
* @method _handleHandleMousedown
* @protected
*/
_handleHandleMousedown : function(){
this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- // this is better done here instead of on _handleDragEnd
- // because we should make the keyboard accessible after a click of the handle
- },
-
+ // this is better done here instead of on _handleDragEnd
+ // because we should make the keyboard accessible after a click of the handle
+ },
+
/**
- * handles the user dragging the handle around the Dial, gets the angle,
+ * handles the user dragging the handle around the Dial, gets the angle,
* checks for wrapping around top center.
* Sets the new value of the Dial
*
@@ -567,7 +572,7 @@ YUI.add('dial', function (Y, NAME) {
ang,
newValue;
- // The event was emitted from drag:drag of handle.
+ // The event was emitted from drag:drag of handle.
// The center of the handle is top left position of the handle node + radius of handle.
// This is different than a mousedown on the ring.
handleCenterX = (parseInt(this._handleNode.getStyle('left'),10) + this._handleNodeRadius);
@@ -585,7 +590,7 @@ YUI.add('dial', function (Y, NAME) {
}
}
newValue = this._getValueFromAngle(ang); // This function needs the current _timesWrapped value. That's why it comes after the _timesWrapped code above
-
+
// If you've gone past max more than one full revolution, we decrement the _timesWrapped value
// This gives the effect of a ratchet mechanism.
// It feels like you are never more than one revolution past max
@@ -597,7 +602,7 @@ YUI.add('dial', function (Y, NAME) {
}else if(newValue < (this._minValue - this._stepsPerRevolution) ){
this._timesWrapped ++;
}
- this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
+ this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
this._handleValuesBeyondMinMax(e, newValue);
},
@@ -610,119 +615,125 @@ YUI.add('dial', function (Y, NAME) {
* @private
*/
_handleMousedown : function(e){ // #2530306
- var minAng = this._getAngleFromValue(this._minValue),
- maxAng = this._getAngleFromValue(this._maxValue),
- newValue, oppositeMidRangeAngle,
- handleCenterX, handleCenterY,
- ang;
-
- // The event was emitted from mousedown on the ring node,
- // so the center of the handle should be the XY of mousedown.
- if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
- handleCenterX = (e.clientX - this._ringNode.getX());
- handleCenterY = (e.clientY - this._ringNode.getY());
- }else{
- handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
- handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
- }
- ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
-
- /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
- * The next sections of logic
- * set this._timesWrapped in the different cases of value range
- * and value range position,
- * then the Dial value is set at the end of this method
- */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- if(this._maxValue - this._minValue > this._stepsPerRevolution){
- // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
-
- // This checks the shortest way around the dial between the prevAng and this ang.
- if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
-
- // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
- if((this._timesWrapped > this._minTimesWrapped) &&
- (this._timesWrapped < this._maxTimesWrapped)
- ){
- // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
- this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
- }
- // special case of getting un-stuck from a min value case
- // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
- // because prevAng is set to 0 or > 0
- }else if(
- (this._timesWrapped === this._minTimesWrapped) &&
- (ang - this._prevAng < 180)
- ){
- this._timesWrapped ++;
- } //it didn't cross a wrapping boundary
-
- } /////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(this._maxValue - this._minValue === this._stepsPerRevolution){
- // Case: range min-to-max === stepsPerRevolution (one revolution)
- // This means min and max will be at same angle
- // This does not mean they are at "north"
-
- if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
- // The only way it can be, is if min and max are not at north
- this._timesWrapped = 1;
+
+ if (this._ringNode.compareTo(e.target)) {
+ var minAng = this._getAngleFromValue(this._minValue),
+ maxAng = this._getAngleFromValue(this._maxValue),
+ newValue, oppositeMidRangeAngle,
+ handleCenterX, handleCenterY,
+ ang;
+
+
+
+ // The event was emitted from mousedown on the ring node,
+ // so the center of the handle should be the XY of mousedown.
+ if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
+ handleCenterX = (e.clientX - this._ringNode.getX());
+ handleCenterY = (e.clientY - this._ringNode.getY());
}else{
- this._timesWrapped = 0;
- }
-
- } //////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(minAng > maxAng){
- // Case: range includes the wrap point (north)
- // Because of "else if"...
- // range is < stepsPerRevolution
-
- if(
- (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
- (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
- // the angle opposite the mid-range angle, then...
- ){
- this._timesWrapped ++;
- }else if(
- (this._prevAng <= maxAng) &&
- // if prev angle is < max angle and...
-
- (ang > (minAng + maxAng) / 2)
- // the angle of this click is greater than,
- // the angle opposite the mid-range angle and...
-
- ){
- this._timesWrapped --;
+ handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
+ handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
}
-
- } ////////////////////////////////////////////////////////////////////////////////////////////////////
- else{
- // "else" Case: min-to-max range doesn't include the wrap point
- // Because of "else if"...
- // range is still < stepsPerRevolution
-
- if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
- oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
- // This is the bisection of the min-to-max range + 180. (opposite the bisection)
-
- if(oppositeMidRangeAngle > 180){
- newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
- }else{ //oppositeMidRangeAngle <= 180
- newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
+ ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
+
+ /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ * The next sections of logic
+ * set this._timesWrapped in the different cases of value range
+ * and value range position,
+ * then the Dial value is set at the end of this method
+ */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ if(this._maxValue - this._minValue > this._stepsPerRevolution){
+
+ // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
+
+ // This checks the shortest way around the dial between the prevAng and this ang.
+ if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
+
+ // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
+ if((this._timesWrapped > this._minTimesWrapped) &&
+ (this._timesWrapped < this._maxTimesWrapped)
+ ){
+ // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
+ this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
+ }
+ // special case of getting un-stuck from a min value case
+ // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
+ // because prevAng is set to 0 or > 0
+ }else if(
+ (this._timesWrapped === this._minTimesWrapped) &&
+ (ang - this._prevAng < 180)
+ ){
+ this._timesWrapped ++;
+ } //it didn't cross a wrapping boundary
+
+ } /////////////////////////////////////////////////////////////////////////////////////////////////////////
+ else if(this._maxValue - this._minValue === this._stepsPerRevolution){
+ // Case: range min-to-max === stepsPerRevolution (one revolution)
+ // This means min and max will be at same angle
+ // This does not mean they are at "north"
+
+ if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
+ // The only way it can be, is if min and max are not at north
+ this._timesWrapped = 1;
+ }else{
+ this._timesWrapped = 0;
+ }
+
+ } //////////////////////////////////////////////////////////////////////////////////////////////////////////
+ else if(minAng > maxAng){
+ // Case: range includes the wrap point (north)
+ // Because of "else if"...
+ // range is < stepsPerRevolution
+
+ if(
+ (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
+ (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
+ // the angle opposite the mid-range angle, then...
+ ){
+ this._timesWrapped ++;
+ }else if(
+ (this._prevAng <= maxAng) &&
+ // if prev angle is < max angle and...
+
+ (ang > (minAng + maxAng) / 2)
+ // the angle of this click is greater than,
+ // the angle opposite the mid-range angle and...
+
+ ){
+ this._timesWrapped --;
+ }
+
+ } ////////////////////////////////////////////////////////////////////////////////////////////////////
+ else{
+ // "else" Case: min-to-max range doesn't include the wrap point
+ // Because of "else if"...
+ // range is still < stepsPerRevolution
+
+ if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
+ oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
+ // This is the bisection of the min-to-max range + 180. (opposite the bisection)
+
+ if(oppositeMidRangeAngle > 180){
+ newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
+ }else{ //oppositeMidRangeAngle <= 180
+ newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
+ }
+ this._prevAng = this._getAngleFromValue(newValue);
+ this.set('value', newValue);
+ this._setTimesWrappedFromValue(newValue);
+ return;
}
- this._prevAng = this._getAngleFromValue(newValue);
- this.set('value', newValue);
- this._setTimesWrappedFromValue(newValue);
- return;
}
- }
-
- // Now that _timesWrapped is set value .......................................................................
- newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
- this._prevAng = ang;
- this._handleValuesBeyondMinMax(e, newValue);
+ // Now that _timesWrapped is set value .......................................................................
+ newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
+ this._prevAng = ang;
+
+ this._handleValuesBeyondMinMax(e, newValue);
+ }
},
/**
@@ -735,24 +746,20 @@ YUI.add('dial', function (Y, NAME) {
*/
_handleValuesBeyondMinMax : function(e, newValue){ // #2530306
// If _getValueFromAngle() is passed 0, it increments the _timesWrapped value.
- // handle hitting max and min and going beyond, stops at max or min
+ // handle hitting max and min and going beyond, stops at max or min
if((newValue >= this._minValue) && (newValue <= this._maxValue)) {
this.set('value', newValue);
// [#2530206] transfer the mousedown event from the _ringNode to the _handleNode drag, so we can mousedown, then continue dragging
if(e.currentTarget === this._ringNode){
// Delegate to DD's natural behavior
this._dd1._handleMouseDownEvent(e);
- }
- }else if(newValue > this._maxValue){
+ }
+ } else if(newValue > this._maxValue){
this.set('value', this._maxValue);
- if(e.type === 'gesturemovestart'){
- this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
- }
- }else if(newValue < this._minValue){
+ this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
+ } else if(newValue < this._minValue){
this.set('value', this._minValue);
- if(e.type === 'gesturemovestart'){
- this._prevAng = this._getAngleFromValue(this._minValue);
- }
+ this._prevAng = this._getAngleFromValue(this._minValue);
}
},
@@ -769,7 +776,7 @@ YUI.add('dial', function (Y, NAME) {
/*
* When handle is handleDragEnd, this animates the return to the fixed dial
- */
+ */
/**
* handles the end of a user dragging the handle, animates the handle returning to
@@ -779,7 +786,7 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
_handleDragEnd : function(){
- var node = this._handleNode;
+ var node = this._handleNode;
node.transition({
duration: 0.08, // seconds
easing: 'ease-in',
@@ -817,7 +824,7 @@ YUI.add('dial', function (Y, NAME) {
newY = Math.round(Math.sin(thisAngle * rad) * this._handleDistance),
newX = Math.round(Math.cos(thisAngle * rad) * this._handleDistance),
dia = obj.get('offsetWidth'); //Ticket #2529852
-
+
newY = newY - (dia * 0.5);
newX = newX - (dia * 0.5);
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) {
*/
syncUI : function() {
// Make the marker and the resetString display so their placement and borderRadius can be calculated, then hide them again.
- // We would have used visibility:hidden in the css of this class,
+ // We would have used visibility:hidden in the css of this class,
// but IE8 VML never returns to visible after applying visibility:hidden then removing it.
this._setSizes();
this._calculateDialCenter(); // #2531111 initialize center of dial
@@ -847,7 +854,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* sets the sizes of ring, center-button, marker, handle, and VML ovals in pixels.
- * Needed only because some IE versions
+ * Needed only because some IE versions
* ignore CSS percent sizes/offsets.
* so these must be set in pixels.
* Normally these are set in % of the ring.
@@ -869,8 +876,8 @@ YUI.add('dial', function (Y, NAME) {
setSize(this._handleNode, dia, this.get('handleDiameter'));
setSize(this._markerNode, dia, this.get('markerDiameter'));
setSize(this._centerButtonNode, dia, this.get('centerButtonDiameter'));
-
- // Set these (used for trig) this way instead of relative to dia,
+
+ // Set these (used for trig) this way instead of relative to dia,
// in case they have borders, have images etc.
this._ringNodeRadius = this._ringNode.get('offsetWidth') * 0.5;
this._handleNodeRadius = this._handleNode.get('offsetWidth') * 0.5;
@@ -881,7 +888,7 @@ YUI.add('dial', function (Y, NAME) {
offset = (this._ringNodeRadius - this._centerButtonNodeRadius);
this._centerButtonNode.setStyle('left', offset + 'px');
this._centerButtonNode.setStyle('top', offset + 'px');
- /*
+ /*
Place the resetString
This seems like it should be able to be done with CSS,
But since there is also a VML oval in IE that is absolute positioned,
@@ -927,7 +934,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * renders the DOM object for the Dial's background marker which
+ * renders the DOM object for the Dial's background marker which
* tracks the angle of the user dragging the handle
*
* @method _renderMarker
@@ -941,7 +948,7 @@ YUI.add('dial', function (Y, NAME) {
}
this._markerNode = marker;
},
-
+
/**
* renders the DOM object for the Dial's center
*
@@ -965,7 +972,7 @@ YUI.add('dial', function (Y, NAME) {
* @method _renderHandle
* @protected
*/
- _renderHandle : function() {
+ _renderHandle : function() {
var labelId = Dial.CSS_CLASSES.label + Y.guid(), //get this unique id once then use for handle and label for ARIA
contentBox = this.get("contentBox"),
handle = contentBox.one("." + Dial.CSS_CLASSES.handle);
@@ -1019,7 +1026,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* sets the Dial's value in response to key events.
- * Left and right keys are in a separate method
+ * Left and right keys are in a separate method
* in case an implementation wants to increment values
* but needs left and right arrow keys for other purposes.
*
@@ -1088,7 +1095,7 @@ YUI.add('dial', function (Y, NAME) {
break;
}
},
-
+
/**
* increments Dial value by a minor increment
*
@@ -1104,7 +1111,7 @@ YUI.add('dial', function (Y, NAME) {
// Removing the toFixed here, loses the feature of "snap-to" when for example, stepsPerRevolution is 10 and decimalPlaces is 0.
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* decrements Dial value by a minor increment
*
@@ -1116,7 +1123,7 @@ YUI.add('dial', function (Y, NAME) {
newVal = Math.max(newVal, this.get("min"));
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* increments Dial value by a major increment
*
@@ -1128,7 +1135,7 @@ YUI.add('dial', function (Y, NAME) {
newVal = Math.min(newVal, this.get("max"));
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* decrements Dial value by a major increment
*
@@ -1149,8 +1156,8 @@ YUI.add('dial', function (Y, NAME) {
*/
_setToMax : function(){
this.set('value', this.get("max"));
- },
-
+ },
+
/**
* sets Dial value to dial's min attr
*
@@ -1159,10 +1166,10 @@ YUI.add('dial', function (Y, NAME) {
*/
_setToMin : function(){
this.set('value', this.get("min"));
- },
-
+ },
+
/**
- * resets Dial value to the orignal initial value.
+ * resets Dial value to the orignal initial value.
*
* @method _resetDial
* @protected
@@ -1175,9 +1182,9 @@ YUI.add('dial', function (Y, NAME) {
this._resetString.addClass(Dial.CSS_CLASSES.hidden); //[#2530441]
this._handleNode.focus();
},
-
+
/**
- * returns the handle angle associated with the current value of the Dial.
+ * returns the handle angle associated with the current value of the Dial.
* Returns a number between 0 and 360.
*
* @method _getAngleFromValue
@@ -1231,11 +1238,11 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
_valueToDecimalPlaces : function(val) { // [#2530206] cleaned up and better user feedback of when it's max or min.
-
+
},
/**
- * Updates the UI display value of the Dial to reflect
+ * Updates the UI display value of the Dial to reflect
* the value passed in.
* Makes all other needed UI display changes
*
View
2  build/dial/dial-min.js
@@ -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});
+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});
View
405 build/dial/dial.js
@@ -3,7 +3,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* Create a circular dial value range input visualized as a draggable handle on a
* background element.
- *
+ *
* @module dial
*/
var supportsVML = false;
@@ -148,7 +148,7 @@ YUI.add('dial', function (Y, NAME) {
return this._validateValue(val);
}
},
-
+
/**
* amount to increment/decrement the dial value
* when the arrow up/down/left/right keys are pressed
@@ -174,7 +174,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * number of value increments in one 360 degree revolution
+ * number of value increments in one 360 degree revolution
* of the handle around the dial
*
* @attribute stepsPerRevolution
@@ -186,7 +186,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * number of decimal places of accuracy in the value
+ * number of decimal places of accuracy in the value
*
* @attribute decimalPlaces
* @type {Number}
@@ -197,7 +197,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * visible strings for the dial UI. This attribute is
+ * visible strings for the dial UI. This attribute is
* defined by the base Widget class but has an empty value. The
* Dial is simply providing a default value for the attribute.
* Gets localized strings in the current language
@@ -213,8 +213,8 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * distance from the center of the dial to the
- * center of the marker and handle, when at rest.
+ * distance from the center of the dial to the
+ * center of the marker and handle, when at rest.
* The value is a percent of the radius of the dial.
*
* @attribute handleDistance
@@ -224,7 +224,7 @@ YUI.add('dial', function (Y, NAME) {
handleDistance:{
value:0.75
}
-
+
};
/**
@@ -238,8 +238,8 @@ YUI.add('dial', function (Y, NAME) {
function makeClassName(str) {
return Y.ClassNameManager.getClassName(Dial.NAME, str);
}
-
- /** array of static constants used to identify the classname applied to the Dial DOM objects
+
+ /** array of static constants used to identify the classname applied to the Dial DOM objects
*
* @property CSS_CLASSES
* @type {Array}
@@ -264,9 +264,9 @@ YUI.add('dial', function (Y, NAME) {
hidden : makeClassName("hidden"),
dragging : Y.ClassNameManager.getClassName("dd-dragging")
};
-
+
/* Static constants used to define the markup templates used to create Dial DOM elements */
-
+
/**
* template that will contain the Dial's label.
@@ -319,7 +319,7 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
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}">';
-
+
}else{ // VML case
Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + ' ' + Dial.CSS_CLASSES.ringVml + '">'+
'<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
@@ -363,7 +363,7 @@ YUI.add('dial', function (Y, NAME) {
this._renderMarker();
this._renderCenterButton();
this._renderHandle();
-
+
// object handles
this.contentBox = this.get("contentBox");
@@ -379,7 +379,7 @@ YUI.add('dial', function (Y, NAME) {
this._timesWrapped = 0;
this._angle = this._getAngleFromValue(this.get('value'));
this._prevAng = this._angle;
-
+
// init
this._setTimesWrappedFromValue(this._originalValue);
this._handleNode.set('aria-valuemin', this._minValue);
@@ -411,27 +411,27 @@ YUI.add('dial', function (Y, NAME) {
'borderRadius':this._centerButtonNodeRadius + 'px'
});
},
-
+
/**
* Handles the mouseenter on the centerButton
- *
+ *
* @method _handleCenterButtonEnter
* @protected
*/
_handleCenterButtonEnter : function(){
- this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Handles the mouseleave on the centerButton
- *
+ *
* @method _handleCenterButtonLeave
* @protected
*/
_handleCenterButtonLeave : function(){
- this._resetString.addClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.addClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Creates the Y.DD.Drag instance used for the handle movement and
* binds Dial interaction to the configured value model.
@@ -440,17 +440,19 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
bindUI : function() {
+
this.after("valueChange", this._afterValueChange);
var boundingBox = this.get("boundingBox"),
// Looking for a key event which will fire continously across browsers while the key is held down.
- keyEvent = (!Y.UA.opera) ? "down:" : "press:",
+ keyEvent = (!Y.UA.opera) ? "down:" : "press:",
// 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
keyEventSpec = keyEvent + "38,40,33,34,35,36",
// 37 , 39 = arrow left/right
keyLeftRightSpec = keyEvent + "37,39",
// 37 , 39 = arrow left/right + meta (command/apple key) for mac
- keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta";
+ keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta",
+ Drag = Y.DD.Drag;
Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
Y.on("key", Y.bind(this._onLeftRightKey, this), boundingBox, keyLeftRightSpec);
@@ -459,14 +461,17 @@ YUI.add('dial', function (Y, NAME) {
Y.on('mouseenter', Y.bind(this._handleCenterButtonEnter, this), this._centerButtonNode);
Y.on('mouseleave', Y.bind(this._handleCenterButtonLeave, this), this._centerButtonNode);
// Needed to replace mousedown/up with gesturemovestart/end to make behavior on touch devices work the same.
- Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
- Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
- Y.on('gesturemovestart', Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
+ Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
+
+
+ Y.on(Drag.START_EVENT, Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on(Drag.START_EVENT, Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
- Y.on('gesturemovestart', Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
+ //TODO: Can this be merged this into the drag:end event listener to avoid another registration?
Y.on('gesturemoveend', Y.bind(this._handleRingMouseup, this), this._ringNode);
- this._dd1 = new Y.DD.Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
+ this._dd1 = new Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
node: this._handleNode,
on : {
'drag:drag' : Y.bind(this._handleDrag, this),
@@ -492,68 +497,68 @@ YUI.add('dial', function (Y, NAME) {
this._timesWrapped = Math.floor(val / this._stepsPerRevolution);
}
},
-
+
/**
- * gets the angle of the line from the center of the Dial to the center of the handle
+ * gets the angle of the line from the center of the Dial to the center of the handle
*
* @method _getAngleFromHandleCenter
- * @param handleCenterX {number}
+ * @param handleCenterX {number}
* @param handleCenterY {number}
* @return ang {number} the angle
* @protected
*/
_getAngleFromHandleCenter : function(handleCenterX, handleCenterY){
- var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
+ var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
ang = ((this._dialCenterX - handleCenterX) < 0) ? ang + 90 : ang + 90 + 180; // Compensate for neg angles from Math.atan
return ang;
},
-
+
/**
- * calculates the XY of the center of the dial relative to the ring node.
+ * calculates the XY of the center of the dial relative to the ring node.
* This is needed for calculating the angle of the handle
*
* @method _calculateDialCenter
* @protected
*/
_calculateDialCenter : function(){ // #2531111 value, and marker don't track handle when dial position changes on page (resize when inline)
- this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
+ this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
this._dialCenterY = this._ringNode.get('offsetHeight') / 2;
},
-
+
/**
* Handles the mouseup on the ring
- *
+ *
* @method _handleRingMouseup
* @protected
*/
_handleRingMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mouseup on the centerButton
- *
+ *
* @method _handleCenterButtonMouseup
* @protected
*/
_handleCenterButtonMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mousedown on the handle
- *
+ *
* @method _handleHandleMousedown
* @protected
*/
_handleHandleMousedown : function(){
this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- // this is better done here instead of on _handleDragEnd
- // because we should make the keyboard accessible after a click of the handle
- },
-
+ // this is better done here instead of on _handleDragEnd
+ // because we should make the keyboard accessible after a click of the handle
+ },
+
/**
- * handles the user dragging the handle around the Dial, gets the angle,
+ * handles the user dragging the handle around the Dial, gets the angle,
* checks for wrapping around top center.
* Sets the new value of the Dial
*
@@ -567,7 +572,7 @@ YUI.add('dial', function (Y, NAME) {
ang,
newValue;
- // The event was emitted from drag:drag of handle.
+ // The event was emitted from drag:drag of handle.
// The center of the handle is top left position of the handle node + radius of handle.
// This is different than a mousedown on the ring.
handleCenterX = (parseInt(this._handleNode.getStyle('left'),10) + this._handleNodeRadius);
@@ -585,7 +590,7 @@ YUI.add('dial', function (Y, NAME) {
}
}
newValue = this._getValueFromAngle(ang); // This function needs the current _timesWrapped value. That's why it comes after the _timesWrapped code above
-
+
// If you've gone past max more than one full revolution, we decrement the _timesWrapped value
// This gives the effect of a ratchet mechanism.
// It feels like you are never more than one revolution past max
@@ -597,7 +602,7 @@ YUI.add('dial', function (Y, NAME) {
}else if(newValue < (this._minValue - this._stepsPerRevolution) ){
this._timesWrapped ++;
}
- this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
+ this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
this._handleValuesBeyondMinMax(e, newValue);
},
@@ -610,119 +615,125 @@ YUI.add('dial', function (Y, NAME) {
* @private
*/
_handleMousedown : function(e){ // #2530306
- var minAng = this._getAngleFromValue(this._minValue),
- maxAng = this._getAngleFromValue(this._maxValue),
- newValue, oppositeMidRangeAngle,
- handleCenterX, handleCenterY,
- ang;
-
- // The event was emitted from mousedown on the ring node,
- // so the center of the handle should be the XY of mousedown.
- if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
- handleCenterX = (e.clientX - this._ringNode.getX());
- handleCenterY = (e.clientY - this._ringNode.getY());
- }else{
- handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
- handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
- }
- ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
-
- /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
- * The next sections of logic
- * set this._timesWrapped in the different cases of value range
- * and value range position,
- * then the Dial value is set at the end of this method
- */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- if(this._maxValue - this._minValue > this._stepsPerRevolution){
- // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
-
- // This checks the shortest way around the dial between the prevAng and this ang.
- if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
-
- // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
- if((this._timesWrapped > this._minTimesWrapped) &&
- (this._timesWrapped < this._maxTimesWrapped)
- ){
- // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
- this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
- }
- // special case of getting un-stuck from a min value case
- // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
- // because prevAng is set to 0 or > 0
- }else if(
- (this._timesWrapped === this._minTimesWrapped) &&
- (ang - this._prevAng < 180)
- ){
- this._timesWrapped ++;
- } //it didn't cross a wrapping boundary
-
- } /////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(this._maxValue - this._minValue === this._stepsPerRevolution){
- // Case: range min-to-max === stepsPerRevolution (one revolution)
- // This means min and max will be at same angle
- // This does not mean they are at "north"
-
- if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
- // The only way it can be, is if min and max are not at north
- this._timesWrapped = 1;
+
+ if (this._ringNode.compareTo(e.target)) {
+ var minAng = this._getAngleFromValue(this._minValue),
+ maxAng = this._getAngleFromValue(this._maxValue),
+ newValue, oppositeMidRangeAngle,
+ handleCenterX, handleCenterY,
+ ang;
+
+
+
+ // The event was emitted from mousedown on the ring node,
+ // so the center of the handle should be the XY of mousedown.
+ if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
+ handleCenterX = (e.clientX - this._ringNode.getX());
+ handleCenterY = (e.clientY - this._ringNode.getY());
}else{
- this._timesWrapped = 0;
- }
-
- } //////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(minAng > maxAng){
- // Case: range includes the wrap point (north)
- // Because of "else if"...
- // range is < stepsPerRevolution
-
- if(
- (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
- (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
- // the angle opposite the mid-range angle, then...
- ){
- this._timesWrapped ++;
- }else if(
- (this._prevAng <= maxAng) &&
- // if prev angle is < max angle and...
-
- (ang > (minAng + maxAng) / 2)
- // the angle of this click is greater than,
- // the angle opposite the mid-range angle and...
-
- ){
- this._timesWrapped --;
+ handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
+ handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
}
-
- } ////////////////////////////////////////////////////////////////////////////////////////////////////
- else{
- // "else" Case: min-to-max range doesn't include the wrap point
- // Because of "else if"...
- // range is still < stepsPerRevolution
-
- if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
- oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
- // This is the bisection of the min-to-max range + 180. (opposite the bisection)
-
- if(oppositeMidRangeAngle > 180){
- newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
- }else{ //oppositeMidRangeAngle <= 180
- newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
+ ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
+
+ /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ * The next sections of logic
+ * set this._timesWrapped in the different cases of value range
+ * and value range position,
+ * then the Dial value is set at the end of this method
+ */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ if(this._maxValue - this._minValue > this._stepsPerRevolution){
+
+ // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
+
+ // This checks the shortest way around the dial between the prevAng and this ang.
+ if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
+
+ // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
+ if((this._timesWrapped > this._minTimesWrapped) &&
+ (this._timesWrapped < this._maxTimesWrapped)
+ ){
+ // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
+ this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
+ }
+ // special case of getting un-stuck from a min value case
+ // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
+ // because prevAng is set to 0 or > 0
+ }else if(
+ (this._timesWrapped === this._minTimesWrapped) &&
+ (ang - this._prevAng < 180)
+ ){
+ this._timesWrapped ++;
+ } //it didn't cross a wrapping boundary
+
+ } /////////////////////////////////////////////////////////////////////////////////////////////////////////
+ else if(this._maxValue - this._minValue === this._stepsPerRevolution){
+ // Case: range min-to-max === stepsPerRevolution (one revolution)
+ // This means min and max will be at same angle
+ // This does not mean they are at "north"
+
+ if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
+ // The only way it can be, is if min and max are not at north
+ this._timesWrapped = 1;
+ }else{
+ this._timesWrapped = 0;
+ }
+
+ } //////////////////////////////////////////////////////////////////////////////////////////////////////////
+ else if(minAng > maxAng){
+ // Case: range includes the wrap point (north)
+ // Because of "else if"...
+ // range is < stepsPerRevolution
+
+ if(
+ (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
+ (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
+ // the angle opposite the mid-range angle, then...
+ ){
+ this._timesWrapped ++;
+ }else if(
+ (this._prevAng <= maxAng) &&
+ // if prev angle is < max angle and...
+
+ (ang > (minAng + maxAng) / 2)
+ // the angle of this click is greater than,
+ // the angle opposite the mid-range angle and...
+
+ ){
+ this._timesWrapped --;
+ }
+
+ } ////////////////////////////////////////////////////////////////////////////////////////////////////
+ else{
+ // "else" Case: min-to-max range doesn't include the wrap point
+ // Because of "else if"...
+ // range is still < stepsPerRevolution
+
+ if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
+ oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
+ // This is the bisection of the min-to-max range + 180. (opposite the bisection)
+
+ if(oppositeMidRangeAngle > 180){
+ newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
+ }else{ //oppositeMidRangeAngle <= 180
+ newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
+ }
+ this._prevAng = this._getAngleFromValue(newValue);
+ this.set('value', newValue);
+ this._setTimesWrappedFromValue(newValue);
+ return;
}
- this._prevAng = this._getAngleFromValue(newValue);
- this.set('value', newValue);
- this._setTimesWrappedFromValue(newValue);
- return;
}
- }
-
- // Now that _timesWrapped is set value .......................................................................
- newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
- this._prevAng = ang;
- this._handleValuesBeyondMinMax(e, newValue);
+ // Now that _timesWrapped is set value .......................................................................
+ newValue = this._getValueFromAngle(ang); // This function needs the correct, current _timesWrapped value.
+ this._prevAng = ang;
+
+ this._handleValuesBeyondMinMax(e, newValue);
+ }
},
/**
@@ -735,24 +746,20 @@ YUI.add('dial', function (Y, NAME) {
*/
_handleValuesBeyondMinMax : function(e, newValue){ // #2530306
// If _getValueFromAngle() is passed 0, it increments the _timesWrapped value.
- // handle hitting max and min and going beyond, stops at max or min
+ // handle hitting max and min and going beyond, stops at max or min
if((newValue >= this._minValue) && (newValue <= this._maxValue)) {
this.set('value', newValue);
// [#2530206] transfer the mousedown event from the _ringNode to the _handleNode drag, so we can mousedown, then continue dragging
if(e.currentTarget === this._ringNode){
// Delegate to DD's natural behavior
this._dd1._handleMouseDownEvent(e);
- }
- }else if(newValue > this._maxValue){
+ }
+ } else if(newValue > this._maxValue){
this.set('value', this._maxValue);
- if(e.type === 'gesturemovestart'){
- this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
- }
- }else if(newValue < this._minValue){
+ this._prevAng = this._getAngleFromValue(this._maxValue); // #2530766 need for mousedown on the ring; causes prob for drag
+ } else if(newValue < this._minValue){
this.set('value', this._minValue);
- if(e.type === 'gesturemovestart'){
- this._prevAng = this._getAngleFromValue(this._minValue);
- }
+ this._prevAng = this._getAngleFromValue(this._minValue);
}
},
@@ -769,7 +776,7 @@ YUI.add('dial', function (Y, NAME) {
/*
* When handle is handleDragEnd, this animates the return to the fixed dial
- */
+ */
/**
* handles the end of a user dragging the handle, animates the handle returning to
@@ -779,7 +786,7 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
_handleDragEnd : function(){
- var node = this._handleNode;
+ var node = this._handleNode;
node.transition({
duration: 0.08, // seconds
easing: 'ease-in',
@@ -817,7 +824,7 @@ YUI.add('dial', function (Y, NAME) {
newY = Math.round(Math.sin(thisAngle * rad) * this._handleDistance),
newX = Math.round(Math.cos(thisAngle * rad) * this._handleDistance),
dia = obj.get('offsetWidth'); //Ticket #2529852
-
+
newY = newY - (dia * 0.5);
newX = newX - (dia * 0.5);
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) {
*/
syncUI : function() {
// Make the marker and the resetString display so their placement and borderRadius can be calculated, then hide them again.
- // We would have used visibility:hidden in the css of this class,
+ // We would have used visibility:hidden in the css of this class,
// but IE8 VML never returns to visible after applying visibility:hidden then removing it.
this._setSizes();
this._calculateDialCenter(); // #2531111 initialize center of dial
@@ -847,7 +854,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* sets the sizes of ring, center-button, marker, handle, and VML ovals in pixels.
- * Needed only because some IE versions
+ * Needed only because some IE versions
* ignore CSS percent sizes/offsets.
* so these must be set in pixels.
* Normally these are set in % of the ring.
@@ -869,8 +876,8 @@ YUI.add('dial', function (Y, NAME) {
setSize(this._handleNode, dia, this.get('handleDiameter'));
setSize(this._markerNode, dia, this.get('markerDiameter'));
setSize(this._centerButtonNode, dia, this.get('centerButtonDiameter'));
-
- // Set these (used for trig) this way instead of relative to dia,
+
+ // Set these (used for trig) this way instead of relative to dia,
// in case they have borders, have images etc.
this._ringNodeRadius = this._ringNode.get('offsetWidth') * 0.5;
this._handleNodeRadius = this._handleNode.get('offsetWidth') * 0.5;
@@ -881,7 +888,7 @@ YUI.add('dial', function (Y, NAME) {
offset = (this._ringNodeRadius - this._centerButtonNodeRadius);
this._centerButtonNode.setStyle('left', offset + 'px');
this._centerButtonNode.setStyle('top', offset + 'px');
- /*
+ /*
Place the resetString
This seems like it should be able to be done with CSS,
But since there is also a VML oval in IE that is absolute positioned,
@@ -927,7 +934,7 @@ YUI.add('dial', function (Y, NAME) {
},
/**
- * renders the DOM object for the Dial's background marker which
+ * renders the DOM object for the Dial's background marker which
* tracks the angle of the user dragging the handle
*
* @method _renderMarker
@@ -941,7 +948,7 @@ YUI.add('dial', function (Y, NAME) {
}
this._markerNode = marker;
},
-
+
/**
* renders the DOM object for the Dial's center
*
@@ -965,7 +972,7 @@ YUI.add('dial', function (Y, NAME) {
* @method _renderHandle
* @protected
*/
- _renderHandle : function() {
+ _renderHandle : function() {
var labelId = Dial.CSS_CLASSES.label + Y.guid(), //get this unique id once then use for handle and label for ARIA
contentBox = this.get("contentBox"),
handle = contentBox.one("." + Dial.CSS_CLASSES.handle);
@@ -1019,7 +1026,7 @@ YUI.add('dial', function (Y, NAME) {
/**
* sets the Dial's value in response to key events.
- * Left and right keys are in a separate method
+ * Left and right keys are in a separate method
* in case an implementation wants to increment values
* but needs left and right arrow keys for other purposes.
*
@@ -1088,7 +1095,7 @@ YUI.add('dial', function (Y, NAME) {
break;
}
},
-
+
/**
* increments Dial value by a minor increment
*
@@ -1104,7 +1111,7 @@ YUI.add('dial', function (Y, NAME) {
// Removing the toFixed here, loses the feature of "snap-to" when for example, stepsPerRevolution is 10 and decimalPlaces is 0.
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* decrements Dial value by a minor increment
*
@@ -1116,7 +1123,7 @@ YUI.add('dial', function (Y, NAME) {
newVal = Math.max(newVal, this.get("min"));
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* increments Dial value by a major increment
*
@@ -1128,7 +1135,7 @@ YUI.add('dial', function (Y, NAME) {
newVal = Math.min(newVal, this.get("max"));
this.set('value', newVal.toFixed(this.get('decimalPlaces')) - 0);
},
-
+
/**
* decrements Dial value by a major increment
*
@@ -1149,8 +1156,8 @@ YUI.add('dial', function (Y, NAME) {
*/
_setToMax : function(){
this.set('value', this.get("max"));
- },
-
+ },
+
/**
* sets Dial value to dial's min attr
*
@@ -1159,10 +1166,10 @@ YUI.add('dial', function (Y, NAME) {
*/
_setToMin : function(){
this.set('value', this.get("min"));
- },
-
+ },
+
/**
- * resets Dial value to the orignal initial value.
+ * resets Dial value to the orignal initial value.
*
* @method _resetDial
* @protected
@@ -1175,9 +1182,9 @@ YUI.add('dial', function (Y, NAME) {
this._resetString.addClass(Dial.CSS_CLASSES.hidden); //[#2530441]
this._handleNode.focus();
},
-
+
/**
- * returns the handle angle associated with the current value of the Dial.
+ * returns the handle angle associated with the current value of the Dial.
* Returns a number between 0 and 360.
*
* @method _getAngleFromValue
@@ -1231,11 +1238,11 @@ YUI.add('dial', function (Y, NAME) {
* @protected
*/
_valueToDecimalPlaces : function(val) { // [#2530206] cleaned up and better user feedback of when it's max or min.
-
+
},
/**
- * Updates the UI display value of the Dial to reflect
+ * Updates the UI display value of the Dial to reflect
* the value passed in.
* Makes all other needed UI display changes
*
View
405 src/dial/js/Dial.js
@@ -1,7 +1,7 @@
/**
* Create a circular dial value range input visualized as a draggable handle on a
* background element.
- *
+ *
* @module dial
*/
var supportsVML = false;
@@ -146,7 +146,7 @@
return this._validateValue(val);
}
},
-
+
/**
* amount to increment/decrement the dial value
* when the arrow up/down/left/right keys are pressed
@@ -172,7 +172,7 @@
},
/**
- * number of value increments in one 360 degree revolution
+ * number of value increments in one 360 degree revolution
* of the handle around the dial
*
* @attribute stepsPerRevolution
@@ -184,7 +184,7 @@
},
/**
- * number of decimal places of accuracy in the value
+ * number of decimal places of accuracy in the value
*
* @attribute decimalPlaces
* @type {Number}
@@ -195,7 +195,7 @@
},
/**
- * visible strings for the dial UI. This attribute is
+ * visible strings for the dial UI. This attribute is
* defined by the base Widget class but has an empty value. The
* Dial is simply providing a default value for the attribute.
* Gets localized strings in the current language
@@ -211,8 +211,8 @@
},
/**
- * distance from the center of the dial to the
- * center of the marker and handle, when at rest.
+ * distance from the center of the dial to the
+ * center of the marker and handle, when at rest.
* The value is a percent of the radius of the dial.
*
* @attribute handleDistance
@@ -222,7 +222,7 @@
handleDistance:{
value:0.75
}
-
+
};
/**
@@ -236,8 +236,8 @@
function makeClassName(str) {
return Y.ClassNameManager.getClassName(Dial.NAME, str);
}
-
- /** array of static constants used to identify the classname applied to the Dial DOM objects
+
+ /** array of static constants used to identify the classname applied to the Dial DOM objects
*
* @property CSS_CLASSES
* @type {Array}
@@ -262,9 +262,9 @@
hidden : makeClassName("hidden"),
dragging : Y.ClassNameManager.getClassName("dd-dragging")
};
-
+
/* Static constants used to define the markup templates used to create Dial DOM elements */
-
+
/**
* template that will contain the Dial's label.
@@ -317,7 +317,7 @@
* @protected
*/
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}">';
-
+
}else{ // VML case
Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + ' ' + Dial.CSS_CLASSES.ringVml + '">'+
'<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
@@ -361,7 +361,7 @@
this._renderMarker();
this._renderCenterButton();
this._renderHandle();
-
+
// object handles
this.contentBox = this.get("contentBox");
@@ -377,7 +377,7 @@
this._timesWrapped = 0;
this._angle = this._getAngleFromValue(this.get('value'));
this._prevAng = this._angle;
-
+
// init
this._setTimesWrappedFromValue(this._originalValue);
this._handleNode.set('aria-valuemin', this._minValue);
@@ -409,27 +409,27 @@
'borderRadius':this._centerButtonNodeRadius + 'px'
});
},
-
+
/**
* Handles the mouseenter on the centerButton
- *
+ *
* @method _handleCenterButtonEnter
* @protected
*/
_handleCenterButtonEnter : function(){
- this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.removeClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Handles the mouseleave on the centerButton
- *
+ *
* @method _handleCenterButtonLeave
* @protected
*/
_handleCenterButtonLeave : function(){
- this._resetString.addClass(Dial.CSS_CLASSES.hidden);
- },
-
+ this._resetString.addClass(Dial.CSS_CLASSES.hidden);
+ },
+
/**
* Creates the Y.DD.Drag instance used for the handle movement and
* binds Dial interaction to the configured value model.
@@ -438,17 +438,19 @@
* @protected
*/
bindUI : function() {
+
this.after("valueChange", this._afterValueChange);
var boundingBox = this.get("boundingBox"),
// Looking for a key event which will fire continously across browsers while the key is held down.
- keyEvent = (!Y.UA.opera) ? "down:" : "press:",
+ keyEvent = (!Y.UA.opera) ? "down:" : "press:",
// 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
keyEventSpec = keyEvent + "38,40,33,34,35,36",
// 37 , 39 = arrow left/right
keyLeftRightSpec = keyEvent + "37,39",
// 37 , 39 = arrow left/right + meta (command/apple key) for mac
- keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta";
+ keyLeftRightSpecMeta = keyEvent + "37+meta,39+meta",
+ Drag = Y.DD.Drag;
Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
Y.on("key", Y.bind(this._onLeftRightKey, this), boundingBox, keyLeftRightSpec);
@@ -457,14 +459,17 @@
Y.on('mouseenter', Y.bind(this._handleCenterButtonEnter, this), this._centerButtonNode);
Y.on('mouseleave', Y.bind(this._handleCenterButtonLeave, this), this._centerButtonNode);
// Needed to replace mousedown/up with gesturemovestart/end to make behavior on touch devices work the same.
- Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
- Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
- Y.on('gesturemovestart', Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on('gesturemovestart', Y.bind(this._resetDial, this), this._centerButtonNode); //[#2530441]
+ Y.on('gesturemoveend', Y.bind(this._handleCenterButtonMouseup, this), this._centerButtonNode);
+
+
+ Y.on(Drag.START_EVENT, Y.bind(this._handleHandleMousedown, this), this._handleNode);
+ Y.on(Drag.START_EVENT, Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
- Y.on('gesturemovestart', Y.bind(this._handleMousedown, this), this._ringNode); // [#2530766]
+ //TODO: Can this be merged this into the drag:end event listener to avoid another registration?
Y.on('gesturemoveend', Y.bind(this._handleRingMouseup, this), this._ringNode);
- this._dd1 = new Y.DD.Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
+ this._dd1 = new Drag({ //// [#2530206] changed global this._dd1 from just var dd1 = new Y.DD.drag so
node: this._handleNode,
on : {
'drag:drag' : Y.bind(this._handleDrag, this),
@@ -490,68 +495,68 @@
this._timesWrapped = Math.floor(val / this._stepsPerRevolution);
}
},
-
+
/**
- * gets the angle of the line from the center of the Dial to the center of the handle
+ * gets the angle of the line from the center of the Dial to the center of the handle
*
* @method _getAngleFromHandleCenter
- * @param handleCenterX {number}
+ * @param handleCenterX {number}
* @param handleCenterY {number}
* @return ang {number} the angle
* @protected
*/
_getAngleFromHandleCenter : function(handleCenterX, handleCenterY){
- var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
+ var ang = Math.atan( (this._dialCenterY - handleCenterY) / (this._dialCenterX - handleCenterX) ) * (180 / Math.PI);
ang = ((this._dialCenterX - handleCenterX) < 0) ? ang + 90 : ang + 90 + 180; // Compensate for neg angles from Math.atan
return ang;
},
-
+
/**
- * calculates the XY of the center of the dial relative to the ring node.
+ * calculates the XY of the center of the dial relative to the ring node.
* This is needed for calculating the angle of the handle
*
* @method _calculateDialCenter
* @protected
*/
_calculateDialCenter : function(){ // #2531111 value, and marker don't track handle when dial position changes on page (resize when inline)
- this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
+ this._dialCenterX = this._ringNode.get('offsetWidth') / 2;
this._dialCenterY = this._ringNode.get('offsetHeight') / 2;
},
-
+
/**
* Handles the mouseup on the ring
- *
+ *
* @method _handleRingMouseup
* @protected
*/
_handleRingMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mouseup on the centerButton
- *
+ *
* @method _handleCenterButtonMouseup
* @protected
*/
_handleCenterButtonMouseup : function(){
- this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- },
-
+ this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
+ },
+
/**
* Handles the mousedown on the handle
- *
+ *
* @method _handleHandleMousedown
* @protected
*/
_handleHandleMousedown : function(){
this._handleNode.focus(); // need to re-focus on the handle so keyboard is accessible [#2530206]
- // this is better done here instead of on _handleDragEnd
- // because we should make the keyboard accessible after a click of the handle
- },
-
+ // this is better done here instead of on _handleDragEnd
+ // because we should make the keyboard accessible after a click of the handle
+ },
+
/**
- * handles the user dragging the handle around the Dial, gets the angle,
+ * handles the user dragging the handle around the Dial, gets the angle,
* checks for wrapping around top center.
* Sets the new value of the Dial
*
@@ -565,7 +570,7 @@
ang,
newValue;
- // The event was emitted from drag:drag of handle.
+ // The event was emitted from drag:drag of handle.
// The center of the handle is top left position of the handle node + radius of handle.
// This is different than a mousedown on the ring.
handleCenterX = (parseInt(this._handleNode.getStyle('left'),10) + this._handleNodeRadius);
@@ -583,7 +588,7 @@
}
}
newValue = this._getValueFromAngle(ang); // This function needs the current _timesWrapped value. That's why it comes after the _timesWrapped code above
-
+
// If you've gone past max more than one full revolution, we decrement the _timesWrapped value
// This gives the effect of a ratchet mechanism.
// It feels like you are never more than one revolution past max
@@ -595,7 +600,7 @@
}else if(newValue < (this._minValue - this._stepsPerRevolution) ){
this._timesWrapped ++;
}
- this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
+ this._prevAng = ang; // need to keep the previous angle in order to check for wrapping on the next drag, click, or keypress
this._handleValuesBeyondMinMax(e, newValue);
},
@@ -608,119 +613,125 @@
* @private
*/
_handleMousedown : function(e){ // #2530306
- var minAng = this._getAngleFromValue(this._minValue),
- maxAng = this._getAngleFromValue(this._maxValue),
- newValue, oppositeMidRangeAngle,
- handleCenterX, handleCenterY,
- ang;
-
- // The event was emitted from mousedown on the ring node,
- // so the center of the handle should be the XY of mousedown.
- if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
- handleCenterX = (e.clientX - this._ringNode.getX());
- handleCenterY = (e.clientY - this._ringNode.getY());
- }else{
- handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
- handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
- }
- ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
-
- /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
- * The next sections of logic
- * set this._timesWrapped in the different cases of value range
- * and value range position,
- * then the Dial value is set at the end of this method
- */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- if(this._maxValue - this._minValue > this._stepsPerRevolution){
- // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
-
- // This checks the shortest way around the dial between the prevAng and this ang.
- if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
-
- // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
- if((this._timesWrapped > this._minTimesWrapped) &&
- (this._timesWrapped < this._maxTimesWrapped)
- ){
- // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
- this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
- }
- // special case of getting un-stuck from a min value case
- // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
- // because prevAng is set to 0 or > 0
- }else if(
- (this._timesWrapped === this._minTimesWrapped) &&
- (ang - this._prevAng < 180)
- ){
- this._timesWrapped ++;
- } //it didn't cross a wrapping boundary
-
- } /////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(this._maxValue - this._minValue === this._stepsPerRevolution){
- // Case: range min-to-max === stepsPerRevolution (one revolution)
- // This means min and max will be at same angle
- // This does not mean they are at "north"
-
- if(ang < minAng){ // if mousedown angle is < minAng (and maxAng, because they're the same)
- // The only way it can be, is if min and max are not at north
- this._timesWrapped = 1;
+
+ if (this._ringNode.compareTo(e.target)) {
+ var minAng = this._getAngleFromValue(this._minValue),
+ maxAng = this._getAngleFromValue(this._maxValue),
+ newValue, oppositeMidRangeAngle,
+ handleCenterX, handleCenterY,
+ ang;
+
+
+
+ // The event was emitted from mousedown on the ring node,
+ // so the center of the handle should be the XY of mousedown.
+ if(Y.UA.ios){ // ios adds the scrollLeft and top onto clientX and Y in a native click
+ handleCenterX = (e.clientX - this._ringNode.getX());
+ handleCenterY = (e.clientY - this._ringNode.getY());
}else{
- this._timesWrapped = 0;
- }
-
- } //////////////////////////////////////////////////////////////////////////////////////////////////////////
- else if(minAng > maxAng){
- // Case: range includes the wrap point (north)
- // Because of "else if"...
- // range is < stepsPerRevolution
-
- if(
- (this._prevAng >= minAng) && // if prev angle was greater than angle of min and...
- (ang <= (minAng + maxAng) / 2) // the angle of this click is less than
- // the angle opposite the mid-range angle, then...
- ){
- this._timesWrapped ++;
- }else if(
- (this._prevAng <= maxAng) &&
- // if prev angle is < max angle and...
-
- (ang > (minAng + maxAng) / 2)
- // the angle of this click is greater than,
- // the angle opposite the mid-range angle and...
-
- ){
- this._timesWrapped --;
+ handleCenterX = (e.clientX + Y.one('document').get('scrollLeft') - this._ringNode.getX());
+ handleCenterY = (e.clientY + Y.one('document').get('scrollTop') - this._ringNode.getY());
}
-
- } ////////////////////////////////////////////////////////////////////////////////////////////////////
- else{
- // "else" Case: min-to-max range doesn't include the wrap point
- // Because of "else if"...
- // range is still < stepsPerRevolution
-
- if ((ang < minAng) || (ang > maxAng)){ // angle is out of range
- oppositeMidRangeAngle = (((minAng + maxAng) / 2) + 180) % 360;
- // This is the bisection of the min-to-max range + 180. (opposite the bisection)
-
- if(oppositeMidRangeAngle > 180){
- newValue = ((maxAng < ang) && (ang < oppositeMidRangeAngle)) ? this.get('max') : this.get('min');
- }else{ //oppositeMidRangeAngle <= 180
- newValue = ((minAng > ang) && (ang > oppositeMidRangeAngle)) ? this.get('min') : this.get('max');
+ ang = this._getAngleFromHandleCenter(handleCenterX, handleCenterY);
+
+ /* ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ * The next sections of logic
+ * set this._timesWrapped in the different cases of value range
+ * and value range position,
+ * then the Dial value is set at the end of this method
+ */ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ if(this._maxValue - this._minValue > this._stepsPerRevolution){
+
+ // Case: range min-to-max is greater than stepsPerRevolution (one revolution)
+
+ // This checks the shortest way around the dial between the prevAng and this ang.
+ if(Math.abs(this._prevAng - ang) > 180){ // this crossed a wrapping
+
+ // Only change the _timesWrapped if it's between minTimesWrapped and maxTimesWrapped
+ if((this._timesWrapped > this._minTimesWrapped) &&
+ (this._timesWrapped < this._maxTimesWrapped)
+ ){
+ // this checks which direction, clock wise or CCW and incr or decr _timesWrapped
+ this._timesWrapped = ((this._prevAng - ang) > 0) ? (this._timesWrapped + 1) : (this._timesWrapped - 1);
+ }
+ // special case of getting un-stuck from a min value case
+ // where timesWrapped is minTimesWrapped but new ang won't trigger a cross wrap boundry
+ // because prevAng is set to 0 or > 0
+ }else if(
+ (this._timesWrapped === this._minTimesWrapped) &&
+ (ang - this._prevAng < 180)
+ ){
+ this._timesWrapped ++;
+ } //it didn't cross a wrapping boundary