Jump to Table of Contents

Example: Dial With Interactive UI

This Dial widget example shows the following:

  1. A demonstration of a large value range combined with fine increment control.
  2. Setting UI strings before rendering
  3. Setting configuration attributes
  4. Construction-time event subscription allowing Dial to control an interactive UI
  5. 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. The action of these keys can be controlled via Dial's configuration attributes.

hubble
thermosphere
mesosphere
stratosphere
troposphere
ozone
crust
mantle
From Earth to Hubble

Making a Dial Drive an Interactive UI

The valueChange event of a Dial can be the means of controlling other UI displayed on a page.

The Markup

Note: be sure to add the yui3-skin-sam classname to the page's <body> element or to a parent element of the widget in order to apply the default CSS skin. See Understanding Skinning.

<body class="yui3-skin-sam"> <!-- You need this skin class -->

The only markup requirement for the Dial itself is an element to contain the Dial. The rest of the markup and CSS in this example is just for the Hubble telescope visualization.

<div id="demo"></div>

The JavaScript

This example builds on previous examples by showing how to modify the visible UI strings before the dial renders.

During instatiation of a Dial, several configuration attributes can be set (see the code-block below); note the construction-time event subscription:

YUI().use('dial', function(Y) {

    var sceneH = Y.one('#scene').get('region').height,
    subSea = 450,
    viewFrameH = Y.one('#view_frame').get('region').height -2,
    zeroPt = 100,
    originY = -sceneH + subSea + viewFrameH - zeroPt;

    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,
        stepsPerRevolution:30,
        value: 0,
        diameter: 100,
        minorStep: 1,
        majorStep: 10,
        decimalPlaces: 2, 
        strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'},
        // construction-time event subscription
        after : {
            valueChange: Y.bind( setSceneY, dial )
        }
    });
    dial.render('#demo');
    
    // Function that calls a method in Dial that sets its value to the value of the max config attribute 
    // Other methods available include,
    // _setToMin(), _resetDial(), _incrMinor(), _decrMinor(), _incrMajor(), _decrMajor(),  
    var setDialToMax = function(e){
        e.preventDefault();
        this._setToMax();
    }
    
    // Subscribe to the click of the "Hubble" anchor, passing the dial as the 'this'
    Y.on('click', setDialToMax, '#a-hubble', dial);

});
The Event Handler

Preceding the code that instantiates the Dial widget, declare the event handler. We can use the value of the Dial to do whatever we want, but in this example the event handler updates the CSS top property of the pictorial scene <div id="scene"> of Hubble's relationship to Earth. This scene is moved up or down inside a framing element <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');
}

Complete Example Source

<!DOCTYPE HTML>
<html>
<script src="http://yui.yahooapis.com/3.8.0/build/yui/yui-min.js"></script>

<style>
    #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/dial/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/dial/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;
    }
</style>

<body class="yui3-skin-sam"> <!-- You need this skin class -->
<div id="example_container">
    <div id="view_frame">
        <div id="scene">
            <div id="stars"></div>
            <img id="hubble" src="http://yuilibrary.com/yui/docs/assets/dial/images/hubble.png"/>
            <img id="earth" src="http://yuilibrary.com/yui/docs/assets/dial/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>
</body>

<script>
YUI().use('dial', function(Y) {

    var sceneH = Y.one('#scene').get('region').height,
    subSea = 450,
    viewFrameH = Y.one('#view_frame').get('region').height -2,
    zeroPt = 100,
    originY = -sceneH + subSea + viewFrameH - zeroPt;

    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,
        stepsPerRevolution:30,
        value: 0,
        diameter: 100,
        minorStep: 1,
        majorStep: 10,
        decimalPlaces: 2, 
        strings:{label:'Altitude in Kilometers:', resetStr: 'Reset', tooltipHandle: 'Drag to set'},
        // construction-time event subscription
        after : {
            valueChange: Y.bind( setSceneY, dial )
        }
    });
    dial.render('#demo');
    
    // Function that calls a method in Dial that sets its value to the value of the max config attribute 
    // Other methods available include,
    // _setToMin(), _resetDial(), _incrMinor(), _decrMinor(), _incrMajor(), _decrMajor(),  
    var setDialToMax = function(e){
        e.preventDefault();
        this._setToMax();
    }
    
    // Subscribe to the click of the "Hubble" anchor, passing the dial as the 'this'
    Y.on('click', setDialToMax, '#a-hubble', dial);

});
</script>
</html>