slider-from-markup.mustache revision 7a6a57d5b030103b5b64157208acbecbfe4118b1
6bdda696b3ea703c47e87fea61017ec655f91d92nd<style scoped>
6bdda696b3ea703c47e87fea61017ec655f91d92nd background: #fff;
6bdda696b3ea703c47e87fea61017ec655f91d92nd border: 1px solid #999;
6bdda696b3ea703c47e87fea61017ec655f91d92nd color: #000;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .demo-content {
6bdda696b3ea703c47e87fea61017ec655f91d92nd padding: 1ex 1em;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_control {
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 25px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd line-height: 25px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd background: url("assets/images/sprite.png") repeat-x 0 0;
6bdda696b3ea703c47e87fea61017ec655f91d92nd position: relative;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_control label {
6bdda696b3ea703c47e87fea61017ec655f91d92nd font-weight: bold;
6bdda696b3ea703c47e87fea61017ec655f91d92nd margin: 0 1ex 0 1em;
6bdda696b3ea703c47e87fea61017ec655f91d92nd border: 1px inset #999;
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 16px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd margin-top: 3px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd padding: 0 3px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd text-align: right;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 2em;
6bdda696b3ea703c47e87fea61017ec655f91d92nd /* Support open/close action for the slider */
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .volume-hide #volume_slider {
6bdda696b3ea703c47e87fea61017ec655f91d92nd display: none;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_icon {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background: url("assets/images/sprite.png") no-repeat 0 -25px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd border: 0 none;
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 25px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd vertical-align: top;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 31px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd /* move the button text offscreen left */
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_icon p {
6bdda696b3ea703c47e87fea61017ec655f91d92nd text-indent: -9999px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd * adjust the speaker icon sprite in accordance with volume level and
6bdda696b3ea703c47e87fea61017ec655f91d92nd * active state
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .volume-hide .level_0 { background-position: 0 -25px; }
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .volume-hide .level_1 { background-position: 0 -50px; }
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .volume-hide .level_2 { background-position: 0 -75px; }
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .volume-hide .level_3 { background-position: 0 -100px; }
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg #demo .level_0,
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_0:hover {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background-position: 0 -125px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_1,
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_1:hover {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background-position: 0 -150px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_2,
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_2:hover {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background-position: 0 -175px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_3,
6bdda696b3ea703c47e87fea61017ec655f91d92nd #demo .level_3:hover {
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg background-position: 0 -200px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_slider {
6bdda696b3ea703c47e87fea61017ec655f91d92nd position: absolute;
6bdda696b3ea703c47e87fea61017ec655f91d92nd top: 25px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd /* rail image on the containing box rather than the rail element */
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_slider {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background: url("assets/images/sprite.png") no-repeat 0 -259px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 116px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 31px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd padding-top: 9px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd cursor: arrow;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_slider .yui3-slider-rail {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background-image: none;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 31px;
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg #volume_slider .yui3-slider-thumb {
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 17px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 31px;
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg overflow: hidden;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_slider .yui3-slider-thumb img {
6bdda696b3ea703c47e87fea61017ec655f91d92nd position: absolute;
6bdda696b3ea703c47e87fea61017ec655f91d92nd top: -225px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd #volume_slider .yui3-slider-disabled .yui3-slider-thumb img {
6bdda696b3ea703c47e87fea61017ec655f91d92nd top: -242px;
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg #demo_sprite {
6bdda696b3ea703c47e87fea61017ec655f91d92nd display: inline;
6bdda696b3ea703c47e87fea61017ec655f91d92nd float: left;
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg margin-right: 1em;
6bdda696b3ea703c47e87fea61017ec655f91d92nd<div class="intro">
6bdda696b3ea703c47e87fea61017ec655f91d92nd <p>This example illustrates a few points:</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd <li>How to create a Slider using existing markup</li>
6bdda696b3ea703c47e87fea61017ec655f91d92nd <li>How to disable a Slider</li>
6bdda696b3ea703c47e87fea61017ec655f91d92nd <li>How to use an image sprite to create a custom Slider skin</li>
6bdda696b3ea703c47e87fea61017ec655f91d92nd <p>The visualization of the Slider is based on the volume control in Mac OS X 10.5, with additional controls included for illustration. <strong>Click on the speaker icon to show the Slider</strong>.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<div class="example">
6bdda696b3ea703c47e87fea61017ec655f91d92nd {{>slider-from-markup-source}}
6bdda696b3ea703c47e87fea61017ec655f91d92nd<h3 id="prog_enh">Progressive Enhancement</h3>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>The <a href="http://en.wikipedia.org/wiki/Progressive_enhancement">Progressive Enhancement</a> strategy recommends that your page not contain markup that will only be useful in cases where JavaScript is available. For this reason, Slider does not include an `HTML_PARSER` to reuse existing markup. However, it is possible to override a couple methods to accomplish the task.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>The starting markup for the volume control area is as follows:</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<div id="volume_control" class="volume-hide">
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg <label for="volume">volume</label><input type="text" size="3" maxlength="3" name="volume" id="volume" value="50">
6bdda696b3ea703c47e87fea61017ec655f91d92nd <button type="button" id="volume_icon" class="level_2" title="Open volume slider"><p>Open</p></button>
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg <span id="volume_slider">
6bdda696b3ea703c47e87fea61017ec655f91d92nd <span class="yui3-slider-rail">
6bdda696b3ea703c47e87fea61017ec655f91d92nd <span class="yui3-slider-thumb"><img src="assets/images/sprite.png" height="384" width="31"></span>
6bdda696b3ea703c47e87fea61017ec655f91d92nd <label for="mute"><input type="checkbox" id="mute"> mute</label>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>To tell the Slider to use the existing rail and thumb elements, override the `renderRail` and `renderThumb` methods.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92ndvar volume = new Y.Slider({
6bdda696b3ea703c47e87fea61017ec655f91d92nd axis : 'y',
6bdda696b3ea703c47e87fea61017ec655f91d92nd min : 100, // reverse min and max to make the top
6bdda696b3ea703c47e87fea61017ec655f91d92nd max : 0, // equal 100 and the bottom 0
6bdda696b3ea703c47e87fea61017ec655f91d92nd value : 50,
6bdda696b3ea703c47e87fea61017ec655f91d92nd length: '105px'
6bdda696b3ea703c47e87fea61017ec655f91d92nd// Override renderRail to just return the existing rail node
6bdda696b3ea703c47e87fea61017ec655f91d92ndvolume.renderRail = function () {
6bdda696b3ea703c47e87fea61017ec655f91d92nd// Override renderThumb to just return the existing thumb node
6bdda696b3ea703c47e87fea61017ec655f91d92ndvolume.renderThumb = function () {
6bdda696b3ea703c47e87fea61017ec655f91d92ndvolume.render( "#volume_slider" );
6bdda696b3ea703c47e87fea61017ec655f91d92nd<h3 id="syncui">Hide and show the Slider</h3>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>By default, we want the Slider to be hidden until the user clicks on the speaker icon. However, we want to support muting or changing the value of the Slider while it is hidden.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92ndvar control = Y.one('#volume_control'),
6bdda696b3ea703c47e87fea61017ec655f91d92nd icon = Y.one('#volume_icon'),
6bdda696b3ea703c47e87fea61017ec655f91d92nd open = false;
6bdda696b3ea703c47e87fea61017ec655f91d92ndfunction showHideSlider(e) {
6bdda696b3ea703c47e87fea61017ec655f91d92nd control.toggleClass('volume-hide');
6bdda696b3ea703c47e87fea61017ec655f91d92nd open = !open;
6bdda696b3ea703c47e87fea61017ec655f91d92ndicon.on('click', showHideSlider);
6bdda696b3ea703c47e87fea61017ec655f91d92nd// Also support hiding the Slider when the user clicks outside the
6bdda696b3ea703c47e87fea61017ec655f91d92nd// Slider element.
6bdda696b3ea703c47e87fea61017ec655f91d92ndfunction handleDocumentClick(e) {
6bdda696b3ea703c47e87fea61017ec655f91d92nd showHideSlider();
6bdda696b3ea703c47e87fea61017ec655f91d92ndY.one( 'doc' ).on('click', handleDocumentClick );
6bdda696b3ea703c47e87fea61017ec655f91d92nd<h3 id="demo_mute">Mute and unmute</h3>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>We want to disable the Slider and input and set the value to 0 if a user checks the mute checkbox. The value should be returned to the last assigned value when unmuted. To disable the Slider, set its `disabled` attribute to `true`.</p>
ac7985784d08a3655291f24f711812b4d8b1cbcffuankgvar volInput = Y.one('#volume'),
6bdda696b3ea703c47e87fea61017ec655f91d92nd mute = Y.one('#mute'),
6bdda696b3ea703c47e87fea61017ec655f91d92nd beforeMute = 0;
6bdda696b3ea703c47e87fea61017ec655f91d92ndfunction muteVolume(e) {
6bdda696b3ea703c47e87fea61017ec655f91d92nd // Set disabled to false if currently true; true if currently false
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg var disabled = !volume.get('disabled');
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg volume.set('disabled', disabled);
6bdda696b3ea703c47e87fea61017ec655f91d92nd if (disabled) {
6bdda696b3ea703c47e87fea61017ec655f91d92nd beforeMute = volume.getValue();
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg volInput.set('disabled','disabled');
6bdda696b3ea703c47e87fea61017ec655f91d92nd volInput.set('disabled','');
6bdda696b3ea703c47e87fea61017ec655f91d92ndmute.on('click', muteVolume);
6bdda696b3ea703c47e87fea61017ec655f91d92nd<h3>Skinning and CSS</h3>
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg<img id="demo_sprite" src="assets/images/sprite.png" height="384" width="31" alt="Sprite of all custom image resources for this example">
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>We'll be using the image sprite to the left to create a custom skin. In this design, to keep things simple, the Slider's container and end caps are all rendered together at the bottom of the sprite.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd<p>Slider's thumb range is constrained by the rail element, so it wouldn't be appropriate to use this image as the rail's background—the thumb would slide off the ends. Instead, the rail image is assigned as the background to the Slider's containing element `#volume_slider`. Then the default skin background image is removed on the rail.</p>
6bdda696b3ea703c47e87fea61017ec655f91d92nd/* rail image on the containing box rather than the rail element */
6bdda696b3ea703c47e87fea61017ec655f91d92nd#volume_slider {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background: url("assets/images/sprite.png") no-repeat 0 -259px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd height: 116px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd width: 31px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd padding-top: 9px;
6bdda696b3ea703c47e87fea61017ec655f91d92nd#volume_slider .yui3-slider-rail {
6bdda696b3ea703c47e87fea61017ec655f91d92nd background-image: none;
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg width: 31px;
<p>You can see the full CSS and JavaScript for the other controls in the <a href="#full_code_listing">Full Code Listing</a> below.</p>
<p>Here is the full markup, CSS, and JavaScript for the entire example, including the volume input and mute controls, and CSS for placing the Slider and setting up the volume icon sprite positioning.</p>
<label for="volume">volume</label><input type="text" size="3" maxlength="3" name="volume" id="volume" value="50">
<button type="button" id="volume_icon" class="level_2" title="Open volume slider"><p>Open</p></button>
<span class="yui3-slider-thumb"><img src="assets/images/sprite.png" height="384" width="31"></span>
<p>Nulla facilisi. In vel sem. Morbi id urna in diam dignissim feugiat. Proin molestie tortor eu velit. Aliquam erat volutpat. Nullam ultrices, diam tempus vulputate egestas, eros pede varius leo, sed imperdiet lectus est ornare odio.</p>
<p>Phasellus wisi purus, interdum vitae, rutrum accumsan, viverra in, velit. Sed enim risus, congue non, tristique in, commodo eu, metus. Aenean tortor mi, imperdiet id, gravida eu, posuere eu, felis.</p>
var control = Y.one('#volume_control'),
volInput = Y.one('#volume'),
icon = Y.one('#volume_icon'),
mute = Y.one('#mute'),
// The style.top is known because of a fixed height control bar, but the
// style.left remains unknown until run time.
volume = new Y.Slider({
volume.renderRail = function () {
volume.renderThumb = function () {
volume.render( "#volume_slider" );
volume.after('valueChange', updateInput);
volume.after('valueChange', updateIcon);
mute.on('click', muteVolume);
icon.on('click', showHideSlider);
Y.one( 'doc' ).on('click', handleDocumentClick );
if (e.src !== 'KEY') {
icon.replaceClass('level_'+level, 'level_'+newLevel);
var disabled = !volume.get('disabled');
volume.set('disabled', disabled);
beforeMute = volume.getValue();
volume.setValue(0);
volInput.set('disabled','disabled');
volume.setValue(beforeMute);
volInput.set('disabled','');
if (e.keyCode > 57) {
e.halt();
wait.cancel();
wait = Y.later(400, null, function () {
var value = parseInt(volInput.get('value'),10) || 0;
volInput.set('value', 100);
volume.setValue( value );
control.toggleClass('volume-hide');
background: url("assets/images/sprite.png") repeat-x 0 0;
/* Support open/close action for the slider */
background: url("assets/images/sprite.png") no-repeat 0 -25px;
background: url("assets/images/sprite.png") no-repeat 0 -259px;