Dial: Dial With Interactive UI
Dial widget example shows the following:
- A demonstration of a large value range combined with fine increment control.
- Setting UI strings before rendering
- Setting configuration attributes
- Construction-time event subscription allowing Dial to control an interactive UI
- Calling one of Dial's value change methods from the click of a link.
<a>Hubble</a>
Notice the Dial can traverse the entire 6,000+ pixels of the scene height, but by pulling the handle farther away from the Dial's center while rotating, the user can get 1 pixel movements, without strain. After the dial has focus, the following keys also opperate the Dial, arrow up/down/left/right, page up/down, home, end.
Making a Dial Drive an Interactive UI
The valueChange event of a Dial can be the means of controling other UI displayed on a page.
The Markup
The only markup requirement for the Dial itself is a div to contain the Dial.
The rest of the markup and CSS in this example is just for the scene of the earth to the Hubble.
<div id="demo"></div>
<div id="demo"></div>
The JavaScript
Dial extends the Widget class, following the same pattern
as any widget constructor, accepting a configuration object to
set the initial configuration for the widget.
After creating and configuring the new Dial,
call the render method on your Dial object passing it
the selector of a container object.
This renders it in the container and makes it usable.
This example also shows how to modify the visible UI strings before the dial renders.
During instatiation of a Dial, several configuration attributes can be set. See below.
Note the construction-time event subscription
YUI({ filter: 'raw' }).use("dial", function(Y) { var dial = new Y.Dial({ // The units in this example are Altitude in Kilometers... min:-35, // min altitude -35 Kilometers (below earth's surface) max:559, // max altitude = Hubble's orbit stepsPerRev:30, // One revolution of the Dial's handle will change the altitude this many units value: 0, // starting altitude of sea level diameter: 100, // diameter of the ring of the dial control in pixels minorStep: 1, // keyboard (arrow key) changes this many units majorStep: 10, // keyboard pg up/down changes this many units decimalPlaces: 2, // display this many digits to the right of the decimal point // an object literal containing key-value pairs of the visible strings in the Dial UI strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'}, // construction-time event subscription. // Whenever the value of this dial object changes, the event handler function (setSceneY) fires after : { valueChange: Y.bind( setSceneY, dial ) } }); dial.render("#demo"); });
YUI({ filter: 'raw' }).use("dial", function(Y) { var dial = new Y.Dial({ // The units in this example are Altitude in Kilometers... min:-35, // min altitude -35 Kilometers (below earth's surface) max:559, // max altitude = Hubble's orbit stepsPerRev:30, // One revolution of the Dial's handle will change the altitude this many units value: 0, // starting altitude of sea level diameter: 100, // diameter of the ring of the dial control in pixels minorStep: 1, // keyboard (arrow key) changes this many units majorStep: 10, // keyboard pg up/down changes this many units decimalPlaces: 2, // display this many digits to the right of the decimal point // an object literal containing key-value pairs of the visible strings in the Dial UI strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'}, // construction-time event subscription. // Whenever the value of this dial object changes, the event handler function (setSceneY) fires after : { valueChange: Y.bind( setSceneY, dial ) } }); dial.render("#demo"); });
The Event Handler
Preceeding the code that instatiates the Dial widget, declare the event handler.
Of course we can use the value of the Dial to do whatever we want, but
in this example, the event handler updates the CSS top of the pictoral scene <div id="scene"> of the earth to the Hubble.
This scene is moved up or down inside a viewframe <div class="viewframe"> that has CSS overflow:hidden;.
The reason e.newVal is multiplied by 10 is so that the scene moves 10px for every 1 kilometer of the Dial's value.
/** * The Dial's valueChange event is passed to this. * sets the CSS top value of the pictoral scene of the earth to the hubble. * This scene is an absolute positioned div inside another div with * overflow set to hidden. */ setSceneY = function(e) { Y.one('#scene').setStyle('top', (originY + (e.newVal * 10)) + 'px'); }
/** * The Dial's valueChange event is passed to this. * sets the CSS top value of the pictoral scene of the earth to the hubble. * This scene is an absolute positioned div inside another div with * overflow set to hidden. */ setSceneY = function(e) { Y.one('#scene').setStyle('top', (originY + (e.newVal * 10)) + 'px'); }
Full Code Listing
The Markup
<div id="example_container"> <div id="view_frame"> <div id="scene"> <div id="stars"></div> <img id="hubble" src="assets/images/hubble.png"/> <img id="earth" src="assets/images/mountain_earth.png"/> <div class="label hubble">hubble</div> <div class="label thermosphere">thermosphere</div> <div class="label mesosphere">mesosphere</div> <div class="label stratosphere">stratosphere</div> <div class="label troposphere">troposphere</div> <div class="label ozone">ozone</div> <div class="label crust">crust</div> <div class="label mantle">mantle</div> </div> </div> <div class="controls"> <div class="intro-sentence">From Earth to <a id="a-hubble">Hubble</a></div> <div id="altitude_mark"></div> <div id="demo"></div> </div> </div>
<div id="example_container"> <div id="view_frame"> <div id="scene"> <div id="stars"></div> <img id="hubble" src="assets/images/hubble.png"/> <img id="earth" src="assets/images/mountain_earth.png"/> <div class="label hubble">hubble</div> <div class="label thermosphere">thermosphere</div> <div class="label mesosphere">mesosphere</div> <div class="label stratosphere">stratosphere</div> <div class="label troposphere">troposphere</div> <div class="label ozone">ozone</div> <div class="label crust">crust</div> <div class="label mantle">mantle</div> </div> </div> <div class="controls"> <div class="intro-sentence">From Earth to <a id="a-hubble">Hubble</a></div> <div id="altitude_mark"></div> <div id="demo"></div> </div> </div>
The JavaScript
YUI({ filter: 'raw' }).use("dial", function(Y) { // get and set some variable used to calculate the orininal Y position of the scene var sceneH = Y.one('#scene').get('region').height, subSea = 350, viewFrameH = Y.one('#view_frame').get('region').height - 2, // minus 2 for border zeroPt = 100, // original Y position of the scene originY = -sceneH + subSea + viewFrameH - zeroPt; // initialize the Y of the scene so earth surface aligns with altitude marker Y.one('#scene').setStyle('top', originY + 'px'); /** * The Dial's valueChange event is passed to this. * sets the CSS top value of the pictoral scene of the earth to the hubble. * This scene is an absolute positioned div inside another div with * overflow set to hidden. */ setSceneY = function(e) { Y.one('#scene').setStyle('top', (originY + (e.newVal * 10)) + 'px'); } var dial = new Y.Dial({ min:-35, max:559, stepsPerRev:30, value: 0, diameter: 100, minorStep: 1, majorStep: 10, decimalPlaces: 2, // an object literal containing key-value pairs of the visible strings in the Dial UI strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'}, // construction-time event subscription. // Whenever the value of this dial object changes, the event handler (setSceneY) function fires after : { valueChange: Y.bind( setSceneY, dial ) } }); dial.render('#demo'); Y.one('#altitude_mark').setXY([Y.one('#view_frame').get('region').right, Y.one('#view_frame').get('region').bottom - 100] ); });
YUI({ filter: 'raw' }).use("dial", function(Y) { // get and set some variable used to calculate the orininal Y position of the scene var sceneH = Y.one('#scene').get('region').height, subSea = 350, viewFrameH = Y.one('#view_frame').get('region').height - 2, // minus 2 for border zeroPt = 100, // original Y position of the scene originY = -sceneH + subSea + viewFrameH - zeroPt; // initialize the Y of the scene so earth surface aligns with altitude marker Y.one('#scene').setStyle('top', originY + 'px'); /** * The Dial's valueChange event is passed to this. * sets the CSS top value of the pictoral scene of the earth to the hubble. * This scene is an absolute positioned div inside another div with * overflow set to hidden. */ setSceneY = function(e) { Y.one('#scene').setStyle('top', (originY + (e.newVal * 10)) + 'px'); } var dial = new Y.Dial({ min:-35, max:559, stepsPerRev:30, value: 0, diameter: 100, minorStep: 1, majorStep: 10, decimalPlaces: 2, // an object literal containing key-value pairs of the visible strings in the Dial UI strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'}, // construction-time event subscription. // Whenever the value of this dial object changes, the event handler (setSceneY) function fires after : { valueChange: Y.bind( setSceneY, dial ) } }); dial.render('#demo'); Y.one('#altitude_mark').setXY([Y.one('#view_frame').get('region').right, Y.one('#view_frame').get('region').bottom - 100] ); });
The CSS
#example_container { position:relative; } #demo{ margin:0; position:absolute; top:321px; left:0; } .controls { position:absolute; top:0; left:328px; margin:0 0 0 0; color:#808080; width:300px; } .controls a { color:#4B78D9 !important; cursor:pointer; } .intro-sentence{ font-size: 183%; left: 0; line-height: 0.9em; position: absolute; top: 273px; width: 6em; } #view_frame{ position:relative; height:500px; width:300px; border:solid 1px #cccccc; overflow:hidden; } #scene{position:absolute; left:0; top:-6440px; height:6440px; width:100%; background:url(assets/images/earth_to_hubble_bkg.png) repeat; } #altitude_mark { border-top:solid 1px #CCCCCC; left:-33px; position:absolute; top:403px; width:30px; } #earth{ position:absolute; left:0; top:5834px; height:214px; width:300px; } #hubble{ position:absolute; left:5px; top:7px; height:393px; width:300px; } #stars{ position:absolute; left:0; top:0; background:url(assets/images/stars.png) repeat; height:5000px; width:300px; } .label{ text-transform:uppercase; width:100%; letter-spacing:5px; font-family:Verdana; font-size:85%; position:absolute; left:0; text-align:center; } .hubble{ bottom:6023px; color:#612C88; } .thermosphere{ bottom:1290px; color:#5A009D; } .mesosphere{ bottom:840px; color:#570BFF; } .stratosphere{ bottom:540px; color:#006999; } .troposphere{ bottom:477px; color:#036585; } .ozone{ bottom:692px; color:#005AAE; } .crust{ bottom:270px; color:#4F2D00; } .mantle{ bottom:42px; color:#897701; }
#example_container { position:relative; } #demo{ margin:0; position:absolute; top:321px; left:0; } .controls { position:absolute; top:0; left:328px; margin:0 0 0 0; color:#808080; width:300px; } .controls a { color:#4B78D9 !important; cursor:pointer; } .intro-sentence{ font-size: 183%; left: 0; line-height: 0.9em; position: absolute; top: 273px; width: 6em; } #view_frame{ position:relative; height:500px; width:300px; border:solid 1px #cccccc; overflow:hidden; } #scene{position:absolute; left:0; top:-6440px; height:6440px; width:100%; background:url(assets/images/earth_to_hubble_bkg.png) repeat; } #altitude_mark { border-top:solid 1px #CCCCCC; left:-33px; position:absolute; top:403px; width:30px; } #earth{ position:absolute; left:0; top:5834px; height:214px; width:300px; } #hubble{ position:absolute; left:5px; top:7px; height:393px; width:300px; } #stars{ position:absolute; left:0; top:0; background:url(assets/images/stars.png) repeat; height:5000px; width:300px; } .label{ text-transform:uppercase; width:100%; letter-spacing:5px; font-family:Verdana; font-size:85%; position:absolute; left:0; text-align:center; } .hubble{ bottom:6023px; color:#612C88; } .thermosphere{ bottom:1290px; color:#5A009D; } .mesosphere{ bottom:840px; color:#570BFF; } .stratosphere{ bottom:540px; color:#006999; } .troposphere{ bottom:477px; color:#036585; } .ozone{ bottom:692px; color:#005AAE; } .crust{ bottom:270px; color:#4F2D00; } .mantle{ bottom:42px; color:#897701; }

