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

Dear, people at Data Logic Thank you very much, excellent code. We will continue visiting your site. Of all the examples out there this is is best simple solution.
By GR on 30/12/2008
Thanks. Very helpful, and much simpler than some other examples I've found.
On 04/12/2008
None, copy it until the cows come home!
By Daft Logic on 03/12/2008
Does this code have any particular license? Open source, public domain, restrictive copyright?
On 02/12/2008

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

Comments :

Your Name (optional) :