dial-debug.js revision 736745cee753d967cf5fb1063c21578ecca61b4a
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Create a circular dial value range input visualized as a draggable handle on a
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * background element.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * @module dial
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync if(Y.config.doc.namespaces && Y.config.doc.namespaces.add){
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync 'urn:schemas-microsoft-com:vml',
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync if(Y.config.doc.createElement('v:oval').strokeColor){
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Create a dial to represent an input control capable of representing a
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * series of intermediate states based on the position of the Dial's handle.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * These states are typically aligned to a value algorithm whereby the angle of the handle's
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * position corresponds to a given value.
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * @class Dial
4dfd6183e24104912e45b4b7d052cee00993ff1avboxsync * @extends Widget
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * @param config {Object} Configuration object
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * @constructor
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync Dial.superclass.constructor.apply(this, arguments);
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync // static properties
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * The identity of the widget.
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * @property Dial.NAME
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * @type String
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * @default 'dial'
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @readOnly
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @protected
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Static property used to define the default attribute configuration of
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * the Widget.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @property Dial.ATTRS
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Object}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @protected
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * minimum value allowed
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute min
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default -220
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * maximum value allowed
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute max
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default 220
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * diameter of the circular background object
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * other objects scale accordingly
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute diameter
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number} the number of px in diameter
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default 100
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * initial value of the Dial
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute value
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default 0
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * amount to increment/decrement the dial value
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * when the arrow up/down/left/right keys are pressed
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * @attribute minorStep
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @type {Number}
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * @default 1
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * amount to increment/decrement the dial value
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * when the page up/down keys are pressed
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute majorStep
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number}
660fd430a3a8cfa16505d04c7c577acf89d45a40vboxsync * @default 10
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * number of value increments in one 360 degree revolution
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * of the handle around the dial
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * @attribute stepsPerRev
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Number}
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @default 100
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * visible strings for the dial UI. This attribute is
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * defined by the base Widget class but has an empty value. The
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Dial is simply providing a default value for the attribute.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @attribute strings
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Object}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default {label: 'My label', resetStr: 'Reset', tooltipHandle: 'Press the ... for reset.'}
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync tooltipHandle: 'Press the arrow up/down/left/right keys for minor increments, page up/down for major increments, home for reset.'
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * distance from the center of the dial to the
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * resting place of the center of the handle and marker.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * The value is a percent of the radius of the dial.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @attribute handleDist
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @type {number}
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @default 0.75
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * returns a properly formed yui class name
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @function
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param {String} string to be appended at the end of class name
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync return Y.ClassNameManager.getClassName(Dial.NAME, str);
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * array of static constants used to identify the classname applied to the Dial DOM objects
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @property Dial.CSS_CLASSES
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {Array}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync labelString : Dial.LABEL_CLASS = makeClassName("label-string"),
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync valueString : Dial.LABEL_CLASS = makeClassName("value-string"),
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync northMark : Dial.NORTH_MARK_CLASS = makeClassName("north-mark"),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync ringVml : Dial.RING_CLASS = makeClassName('ring-vml'),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync marker : Dial.MARKER_CLASS = makeClassName("marker"),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync markerUser : Dial.MARKER_USER_CLASS = makeClassName("marker-user"),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync centerButton : Dial.CENTER_BUTTON_CLASS = makeClassName("center-button"),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync centerButtonVml : Dial.RING_CLASS = makeClassName('center-button-vml'),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync resetString : Dial.RESET_STRING_CLASS = makeClassName("reset-str"),
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync handle : Dial.HANDLE_CLASS = makeClassName("handle"),
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync handleUser : Dial.HANDLE_USER_CLASS = makeClassName("handle-user")
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* Static constants used to define the markup templates used to create Dial DOM elements */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync //var strs = this.get('strings');
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync var strs = Dial.ATTRS.strings.value, //('strings');
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * template that will contain the Dial's label.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @property Dial.LABEL_TEMPLATE
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {String}
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @default <div>...</div>
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync Dial.LABEL_TEMPLATE = '<div id="' + labelId + '" class="' + Dial.CSS_CLASSES.label + '"><span class="' + Dial.CSS_CLASSES.labelString + '">{label}</span><span class="' + Dial.CSS_CLASSES.valueString + '"></span></div>';
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * template that will contain the Dial's text input field.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @property Dial.INPUT_TEMPLATE
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @type {String}
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @default <input type="text" class="..."/>
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync Dial.INPUT_TEMPLATE = '<input type="text" class="' + Dial.CSS_CLASSES.input + '">';
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync if(supportsVML === false){
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * template that will contain the Dial's background ring.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @property Dial.RING_TEMPLATE
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @type {String}
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @default <div class="[...-ring]"><div class="[...-northMark]"></div></div>
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + '"><div class="' + Dial.CSS_CLASSES.northMark + '"></div></div>';
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * template that will contain the Dial's current angle marker.
e190faad3061288ae099cd3ea8a858bd224c00a7vboxsync * @property Dial.MARKER_TEMPLATE
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * @type {String}
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * @default <div class="[...-marker] marker-hidden"><div class="[...-markerUser]"></div></div>
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync Dial.MARKER_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.marker + ' marker-hidden"><div class="' + Dial.CSS_CLASSES.markerUser + '"></div></div>';
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * template that will contain the Dial's center button.
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * @property Dial.CENTER_BUTTON_TEMPLATE
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * @type {String}
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * @default <div class="[...-centerButton]"><div class="[...-resetString]">' + Y.substitute('{resetStr}', Dial.ATTRS.strings.value) + '</div></div>
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync Dial.CENTER_BUTTON_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.centerButton + '"><div class="' + Dial.CSS_CLASSES.resetString + '">{resetStr}</div></div>';
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync * template that will contain the Dial's handle.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @property Dial.HANDLE_TEMPLATE
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @type {String}
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * @default <div class="[...-handle]"><div class="[...-handleUser]" aria-labelledby="' + labelId + '" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0"></div></div>';// title="{tooltipHandle}"
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Dial.HANDLE_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.handle + '"><div class="' + Dial.CSS_CLASSES.handleUser + '" aria-labelledby="' + labelId + '" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}"></div></div>';// title="{tooltipHandle}"
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync }else{ // VML case
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Dial.RING_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.ring + '">'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '<div class="' + Dial.CSS_CLASSES.northMark + '"></div>'+
f9e38e609bea9e849b27173024dc82d93bcbf5fcvboxsync '<v:oval strokecolor="#ceccc0" strokeweight="1px" class="' + Dial.CSS_CLASSES.ringVml + '"><v:fill type=gradient color="#8B8A7F" color2="#EDEDEB" angle="45"/></v:oval>'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '<v:oval></v:oval>'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Dial.MARKER_TEMPLATE = '<div class="' + Dial.CSS_CLASSES.marker + ' marker-hidden">'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '<v:oval stroked="false" class="' + Dial.CSS_CLASSES.markerUser + '">'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '<v:fill opacity="20%" color="#000"/>'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '</v:oval>'+
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync '<v:oval></v:oval>'+
'<v:oval strokecolor="#ceccc0" strokeweight="1px" class="' + Dial.CSS_CLASSES.centerButtonVml + '">'+
'<v:fill type=gradient color="#C7C5B9" color2="#fefcf6" colors="35% #d9d7cb, 65% #fefcf6" angle="45"/>'+
' aria-labelledby="' + labelId + '" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'+ //title="{tooltipHandle}"
renderUI : function() {
this._renderLabel();
this._renderInput();
this._renderRing();
this._renderMarker();
this._renderCenterButton();
this._renderHandle();
bindUI : function() {
on : {
_dialCenterOver : function(e){
_dialCenterOut : function(e){
_resetDial : function(){
_handleDrag : function(e){
var ang = Math.atan( (this._centerYOnPage - e.pageY) / (this._centerXOnPage - e.pageX) ) * (180 / Math.PI),
if((this._prevX <= this._centerXOnPage) && (e.pageX > this._centerXOnPage)){ // If wrapping, clockwise
}else if((this._prevX > this._centerXOnPage) && (e.pageX <= this._centerXOnPage)){ // if un-wrapping, counter-clockwise
// Y.log('this._centerYOnPage: ' + this._centerXOnPage + '.....e.pageX: '+ e.pageX + '.......wrap: ' + this._timesWrapped + '......ang: ' + ang);
_handleDragStart : function(e){
if(!this._prevX){
_handleDragEnd : function(){
}, Y.bind(function(){
if(obj){
obj.setXY([(this._ringNode.getX() + this._centerX + newX), (this._ringNode.getY() + this._centerY + newY)]);
syncUI : function() {
_renderInput : function() {
if (!input) {
_renderLabel : function() {
if (!label) {
_renderRing : function() {
if (!ring) {
_renderMarker : function() {
if (!marker) {
_setXYResetString : function(){
this._resetString.setStyle('top', (this._centerButtonNode.get('region').height / 2) - (this._resetString.get('region').height / 2) + 'px');
this._resetString.setStyle('left', (this._centerButtonNode.get('region').width / 2) - (this._resetString.get('region').width / 2) + 'px');
_renderCenterButton : function() {
if (!centerButton) {
_renderHandle : function() {
if (!handle) {
_defaultCB : function() {
_onDirectionKey : function(e) {
e.preventDefault();
switch (e.charCode) { //37 , 39 = arrow left/right, 38, 40 = arrow up/down, 33, 34 = page up/down, 35 , 36 = end/home
return angleFromValue;
_numberKey : function(e){
_afterValueChange : function(e) {
if(supportsVML === true){
if(supportsVML === true){