Logic, but in a different way

Daft Logic

Javascript Slider Control

Last Updated 18th June 2008

Description

One of the limitations of standard HTML form controls is that they do not provide the ability for the user to input an analogue value in the sense that they can either type in something using the keyboard or switch on or off check boxes or radio buttons. From time to time it would be beneficial to allow a variable value to be input. In this example it is shown how to implement such an input control using javascript.

Demonstration

How To Use

  1. Using your mouse drag the handle left and right along the slider
  2. Once you have it a position that suits, let go of your mouse
  3. Click the submit button to confirm your choice

Requirements

javascript enabled

How it Works

 

<input name="sliderValue" id="sliderValue4h" type="Text" size="3" onChange="A_SLIDERS[3].f_setValue(this.value)">
<input name="Submit" type="button" value="Submit" onClick="javascript:alert('You have selected '+document.getElementById('sliderValue4h').value);">

 

<script>
function slider (a_init, a_tpl)
{
this.f_setValue = f_sliderSetValue;
this.f_getPos = f_sliderGetPos;

// register in the global collection
if (!window.A_SLIDERS)
{
window.A_SLIDERS = [];
}
this.n_id = window.A_SLIDERS.length;
window.A_SLIDERS[this.n_id] = this;

// save config parameters in the slider object
var s_key;
if (a_tpl)
{
for (s_key in a_tpl)
{
this[s_key] = a_tpl[s_key];
}
}
for (s_key in a_init)
{
this[s_key] = a_init[s_key];
}

this.n_pix2value = this.n_pathLength / (this.n_maxValue - this.n_minValue);
if (this.n_value == null)
{
this.n_value = this.n_minValue;
}
// generate the control's HTML
document.write(
'<div style="width:' + this.n_controlWidth + 'px;height:' + this.n_controlHeight + 'px;border:0; background-image:url(' + this.s_imgControl + ')" id="sl' + this.n_id + 'base">' +
'<img src="' + this.s_imgSlider + '" width="' + this.n_sliderWidth + '" height="' + this.n_sliderHeight + '" border="0" style="position:relative;left:' + this.n_pathLeft + 'px;top:' + this.n_pathTop + 'px;z-index:' + this.n_zIndex + ';cursor:pointer;visibility:hidden;" name="sl' + this.n_id + 'slider" id="sl' + this.n_id + 'slider" onmousedown="return f_sliderMouseDown(' + this.n_id + ')"/></div>'
);
this.e_base = get_element('sl' + this.n_id + 'base');
this.e_slider = get_element('sl' + this.n_id + 'slider');

// safely hook document/window events
if (document.onmousemove != f_sliderMouseMove) {
window.f_savedMouseMove = document.onmousemove;
document.onmousemove = f_sliderMouseMove;
}
if (document.onmouseup != f_sliderMouseUp) {
window.f_savedMouseUp = document.onmouseup;
document.onmouseup = f_sliderMouseUp;
}
// preset to the value in the input box if available
var e_input = this.s_form == null
? get_element(this.s_name)
: document.forms[this.s_form]
? document.forms[this.s_form].elements[this.s_name]
: null;
this.f_setValue(e_input && e_input.value != '' ? e_input.value : null, 1);
this.e_slider.style.visibility = 'visible';
}

function f_sliderSetValue (n_value, b_noInputCheck) {
if (n_value == null)
n_value = this.n_value == null ? this.n_minValue : this.n_value;
if (isNaN(n_value))
return false;
// round to closest multiple if step is specified
if (this.n_step)
n_value = Math.round((n_value - this.n_minValue) / this.n_step) * this.n_step + this.n_minValue;
// smooth out the result
if (n_value % 1)
n_value = Math.round(n_value * 1e5) / 1e5;

if (n_value < this.n_minValue)
n_value = this.n_minValue;
if (n_value > this.n_maxValue)
n_value = this.n_maxValue;

this.n_value = n_value;

// move the slider
if (this.b_vertical)
this.e_slider.style.top = (this.n_pathTop + this.n_pathLength - Math.round((n_value - this.n_minValue) * this.n_pix2value)) + 'px';
else
this.e_slider.style.left = (this.n_pathLeft + Math.round((n_value - this.n_minValue) * this.n_pix2value)) + 'px';

// save new value
var e_input;
if (this.s_form == null) {
e_input = get_element(this.s_name);
if (!e_input)
return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the input with ID='" + this.s_name + "'.");
}
else {
var e_form = document.forms[this.s_form];
if (!e_form)
return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the form with NAME='" + this.s_form + "'.");
e_input = e_form.elements[this.s_name];
if (!e_input)
return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the input with NAME='" + this.s_name + "'.");
}
e_input.value = n_value;
}

// get absolute position of the element in the document
function f_sliderGetPos (b_vertical, b_base) {
var n_pos = 0,
s_coord = (b_vertical ? 'Top' : 'Left');
var o_elem = o_elem2 = b_base ? this.e_base : this.e_slider;

while (o_elem) {
n_pos += o_elem["offset" + s_coord];
o_elem = o_elem.offsetParent;
}
o_elem = o_elem2;

var n_offset;
while (o_elem.tagName != "BODY") {
n_offset = o_elem["scroll" + s_coord];
if (n_offset)
n_pos -= o_elem["scroll" + s_coord];
o_elem = o_elem.parentNode;
}
return n_pos;
}

function f_sliderMouseDown (n_id) {
window.n_activeSliderId = n_id;
return false;
}

function f_sliderMouseUp (e_event, b_watching) {
if (window.n_activeSliderId != null) {
var o_slider = window.A_SLIDERS[window.n_activeSliderId];
o_slider.f_setValue(o_slider.n_minValue + (o_slider.b_vertical
? (o_slider.n_pathLength - parseInt(o_slider.e_slider.style.top) + o_slider.n_pathTop)
: (parseInt(o_slider.e_slider.style.left) - o_slider.n_pathLeft)) / o_slider.n_pix2value);
if (b_watching) return;
window.n_activeSliderId = null;
}
if (window.f_savedMouseUp)
return window.f_savedMouseUp(e_event);
}

function f_sliderMouseMove (e_event) {

if (!e_event && window.event) e_event = window.event;

// save mouse coordinates
if (e_event) {
window.n_mouseX = e_event.clientX + f_scrollLeft();
window.n_mouseY = e_event.clientY + f_scrollTop();
}

// check if in drag mode
if (window.n_activeSliderId != null) {
var o_slider = window.A_SLIDERS[window.n_activeSliderId];

var n_pxOffset;
if (o_slider.b_vertical) {
var n_sliderTop = window.n_mouseY - o_slider.n_sliderHeight / 2 - o_slider.f_getPos(1, 1) - 3;
// limit the slider movement
if (n_sliderTop < o_slider.n_pathTop)
n_sliderTop = o_slider.n_pathTop;
var n_pxMax = o_slider.n_pathTop + o_slider.n_pathLength;
if (n_sliderTop > n_pxMax)
n_sliderTop = n_pxMax;
o_slider.e_slider.style.top = n_sliderTop + 'px';
n_pxOffset = o_slider.n_pathLength - n_sliderTop + o_slider.n_pathTop;
}
else {
var n_sliderLeft = window.n_mouseX - o_slider.n_sliderWidth / 2 - o_slider.f_getPos(0, 1) - 3;
// limit the slider movement
if (n_sliderLeft < o_slider.n_pathLeft)
n_sliderLeft = o_slider.n_pathLeft;
var n_pxMax = o_slider.n_pathLeft + o_slider.n_pathLength;
if (n_sliderLeft > n_pxMax)
n_sliderLeft = n_pxMax;
o_slider.e_slider.style.left = n_sliderLeft + 'px';
n_pxOffset = n_sliderLeft - o_slider.n_pathLeft;
}
if (o_slider.b_watch)
f_sliderMouseUp(e_event, 1);

return false;
}

if (window.f_savedMouseMove)
return window.f_savedMouseMove(e_event);
}

// get the scroller positions of the page
function f_scrollLeft() {
return f_filterResults (
window.pageXOffset ? window.pageXOffset : 0,
document.documentElement ? document.documentElement.scrollLeft : 0,
document.body ? document.body.scrollLeft : 0
);
}
function f_scrollTop() {
return f_filterResults (
window.pageYOffset ? window.pageYOffset : 0,
document.documentElement ? document.documentElement.scrollTop : 0,
document.body ? document.body.scrollTop : 0
);
}
function f_filterResults(n_win, n_docel, n_body) {
var n_result = n_win ? n_win : 0;
if (n_docel && (!n_result || (n_result > n_docel)))
n_result = n_docel;
return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

function f_sliderError (n_id, s_message) {
alert("Slider #" + n_id + " Error:\n" + s_message);
window.n_activeSliderId = null;
}

get_element = document.all ?
function (s_id) { return document.all[s_id] } :
function (s_id) { return document.getElementById(s_id) };
</script>

<script language="JavaScript">
var A_TPL4h = {
'b_vertical' : false,
'b_watch': true,
'n_controlWidth': 100,
'n_controlHeight': 16,
'n_sliderWidth': 17,
'n_sliderHeight': 16,
'n_pathLeft' : 0,
'n_pathTop' : 0,
'n_pathLength' : 83,
's_imgControl': 'images/slider/background.gif',
's_imgSlider': 'images/slider/handle.gif',
'n_zIndex': 1
}
var A_INIT4h = {
's_form' : 0,
's_name': 'sliderValue4h',
'n_minValue' : 0,
'n_maxValue' : 100,
'n_value' : 85,
'n_step' : 1
}

new slider(A_INIT4h, A_TPL4h);
</script>

Further Uses and Ideas

Version History

Previous Comments For This Page

Hi Rob, to do this, change the value for n_step from 1 to 10.
By Daft Logic on 03/01/2012
solve a problem is " Can not find the Input width Name='sliderValue4h' ". Just change "'s_form' : 0," to order of form that text box (sliderValue4h) is stay as 's_form' : 1, in
var A_INIT4h = {
's_form' : 0,
's_name': 'sliderValue4h',
'n_minValue' : 0,
'n_maxValue' : 100,
'n_value' : 85,
'n_step' : 1 }
By Nop on 27/12/2011
it can not work when it has a form before the form which have a text box name is "sliderValue4h". How i solve about that.
By Nop on 27/12/2011
What would I have to do to change the increments to be in 10's rather 1's?
By Rob on 22/12/2011
hey i've just managed to create a really cool jquery plugin slider which is the same as the google news slider control. interested to hear people's thoughts. http://jsfiddle.net/LucP/BPdKR/2/
By Luc on 05/12/2011
Nice! works really nice. Just want to add more functionality by adding extra buttons such as minus and plus buttions to increase and decrease value. Can anyone suggest modifications?
On 08/09/2011
Hey thanks for such an important tutorial to implement slider.I copied all but i get the error: Slider #0 error: Can not find the Input width Name='sliderValue4h' can you please help me on this? I need it very urgently. Thanks in advance
On 18/07/2011
like wonga I want a total box that adds the number to another number using this slider. Can anyone help? I don't want to use ajax or jquery. I want something simple.
By Tim on 14/07/2011
How do I add a calculator to it like on wonga?
By Tim on 13/07/2011
Nice script...
By Gaurav Sharma (gaurav.motivati on 25/06/2011
can we add multiple control on slider
By shashi on 27/04/2011
Very nice example, but is there a way to have the slider move to a value that a user input into the textbox?
By DB on 28/03/2011
great example
On 24/02/2011
Thanks a lot.
By Ross on 25/11/2010
pity i can't usse it using an ipad still i think it can be useful with an idea i call subjective enumeration where i ask peeps for a subjective value from 1 to 10 this might be a useful means of inputing it... interested?
By happyseaurchin on 11/11/2010
oops... working link: http://www.updatemywebsite.com/revision30-developers-blog/curved-rounded-or-circular-sliders-javascript-jquery-ui
By dRock on 16/10/2010
Check out this rounded slider... they are using jQuery UI: http://www.updatemywebsite.com/revision30-dev-blog/curved-rounded-or-circular-sliders-javascript-jquery-ui
By dRock on 14/10/2010
Please help... I am getting the error Slider #0 error: Can not find the Input width Name='sliderValue4h'
On 10/10/2010
hey, can you help me another time? The First Slider works yet, but i tried to integrate a second one, but i get the same error again. Maybe you could help me another time? Domain is http://sack.bplaced.net/boni24/
On 21/07/2010
Try this code (adds a form around the INPUT and renames the id value)

By Daft Logic on 20/07/2010
Yes, it is: http://sack.bplaced.net/boni24/ I hope you can help me.
On 20/07/2010
On 19/07/2010, do you have a URL to show this error?
By Daft Loigic on 20/07/2010
First of all: thanks. I copied all and only changed the images, but i get the error: Slider #0 error: Can not find the Input width Name='sliderValue4h' Do you know why?
On 19/07/2010
Anyone added a click event so that it will work with a touch display?
On 03/06/2010
Hi, You could use a div tag. See http://www.yourhtmlsource.com/stylesheets/csslayout.html
By Daft Logic on 18/04/2010
I got it working but how do I give it an absolute position in my window? (I'm very new to website building.) Great code, thanks!
On 17/04/2010
In Firefox, Image was not showing, but after changing code, now Scroll Cursor image is showing, but I am unable to drag the Slide, can you solve it, I am thankful to you.
By Anoop on 29/10/2009
How to make the slider handle bounce back to the left end on mouse out please?
On 14/07/2009
nice work, can it work with multiple forms on the page?
On 04/07/2009
Very usefull code, I need to make a variation of this and make it a fillup bar to manually indicate progress of an activity. I needed to do some stuff to make the code work at first like adding type="text/javascript" in the script tags, also you need to enclose the input tags into a form tag, or it will throw up errors.
By Ruakuu on 03/06/2009

30 out of 37 comments shown. See all comments.

Add your own comment below and let others know what you think:

Comments :

Your Name (optional) :