Forum Moderators: open

Message Too Old, No Replies

Slider input type?

To select percentages, or number range, etc

         

CgiBin

4:16 am on May 6, 2005 (gmt 0)

10+ Year Member



It seems like a fairly common input device in many applications, yet there isn't a correlating input type in HTML.

I've come up with a couple prototypes using styled divs and javascript, but I was curious if anyone has already done something similar? I don't want to waste my time re-inventing the wheel.

Bernard Marx

9:00 am on May 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Quite a few about in fact. I'm a WebFX fan:
[webfx.eae.net...]

CgiBin

1:48 pm on May 6, 2005 (gmt 0)

10+ Year Member



Hi,
Yeah, I ran accross that one while searching, but it seems buggy to me, the slider keeps dissapearing and seems very very difficult to use. I think part of the problem is it keeps trying to re-download the slider image every time I mouse over and the delay is breaking the whole thing.

Bernard Marx

2:42 pm on May 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



"it keeps trying to re-download the slider image every time I mouse over"

That sounds like the IE CSS-background bug. Do you perhaps have your cache settings set to "every visit". (This is the reason that this bug is largely only ever seen by developers).

If fiddling their one to fit won't do, then a search like
"Javascript slider"
"DHTML slider"

will reveal a good few more.
I'm reluctant to attempt wheel-reinvention on this one.

CgiBin

3:30 pm on May 6, 2005 (gmt 0)

10+ Year Member



That sounds like the IE CSS-background bug. Do you perhaps have your cache settings set to "every visit". (This is the reason that this bug is largely only ever seen by developers).

yep.

I've actually got 2 different ones I've written myself while tinkering with this. The first one is more specific to only allow choices for every 10%, but I like the way it looks better than the second one, which gives a lot more flexibility.

Luckily I have a slight benefit as I only need to support IE6, FireFox, and Safari, so I don't need a lot of backwards compatibility.

Unfortunately, the first one I could only get to lay-out properly in strict mode, and the pages I need to use it in are all still transitional (I know... get cracking and clean em up to use strict). However, the actual HTML portion of the slider is a bit bulky since it requires 2 nested divs for each data point on the slider (since this case I only needed every 10% it was only 10 sets, but expanding it to more granular would get a bit unwieldy).

Also the 2nd I have working in Transitional, but I just checked in Safari, and the damn offset values are wrong (using offsetLeft to get the position of the element on the page to subtract from the mouse position to get the relative position of the mouse in the object). Safari is adding the body's margin unlike FF and IE. Actually if I use strict the 2nd one IE does the same thing. It shouldn't be too hard to fix, I guess I can just sniff the browser and take care of it with a little extra math. It also has a weird "bug" that sometimes the onmouseout doesn't seem to fire in FF, and the slider can still move even if you aren't over the slider's div

Here are my 2 "working" examples if anyone is interested... (only tested in winIE6, FF-1.03, Safari-1.3)

First one is rather specific to only allow choices every 10%:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">
<html>
<head>
<style>
* {
color: #333333;
font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 12px;
font-weight: normal;
font-variant: normal;
letter-spacing: normal;
text-decoration: none;
margin: 0px;
padding: 0px;
}

body {
margin: 25px;
}

.outerSlide {
width: 200px;
height: 12px;
line-height: 1px;
font-size: 1px;
background-color: silver;
float: left;
}

.innerSlide {
width: 19px;
height: 12px;
line-height: 1px;
font-size: 1px;
border-right: 1px solid red;
float: left;
}

.slideLine {
width: 19px;
height: 4px;
line-height: 1px;
font-size: 1px;
margin: 4px 0px;
background-color: red;
}
</style>
<script>
var setPct = 100;
function pctOver(theID) {
var thePct = parseInt(theID.substring(3));

for (var x = 10; x <= thePct; x += 10 ) {
var node = document.getElementById("pct"+ x);
node.style.backgroundColor = "black";
}

var label = document.getElementById("pctLabel");
label.innerText = thePct + "%";
}

function pctOut(theID) {
var thePct = parseInt(theID.substring(3));

for (var x = 10; x <= 100; x += 10 ) {
var node = document.getElementById("pct"+ x);
node.style.backgroundColor = "transparent";
}

var label = document.getElementById("pctLabel");
label.innerText = setPct + "%";
}

function pctSet(theID) {
var thePct = parseInt(theID.substring(3));
setPct = thePct;

for (var x = 10; x <= 100; x += 10 ) {
var node = document.getElementById("set"+ x);
node.style.backgroundColor = (x <= thePct)? "green" : "red";
}

var label = document.getElementById("pctLabel");
label.innerText = setPct + "%";
}
</script>
</head>
<body>
<div class="outerSlide">
<div class="innerSlide" id="pct10" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set10">
</div>
</div>
<div class="innerSlide" id="pct20" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set20">
</div>
</div>
<div class="innerSlide" id="pct30" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set30">
</div>
</div>
<div class="innerSlide" id="pct40" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set40">
</div>
</div>
<div class="innerSlide" id="pct50" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set50">
</div>
</div>
<div class="innerSlide" id="pct60" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set60">
</div>
</div>
<div class="innerSlide" id="pct70" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set70">
</div>
</div>
<div class="innerSlide" id="pct80" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set80">
</div>
</div>
<div class="innerSlide" id="pct90" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set90">
</div>
</div>
<div class="innerSlide" id="pct100" onmouseover="pctOver(this.id)" onmouseout="pctOut(this.id)" onclick="pctSet(this.id)">
<div class="slideLine" id="set100">
</div>
</div>
</div>
<div id="pctLabel">
100%
</div>
</body></html>

The second one is a bit more generic and allows selection of any %:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style>
* {
color: #333333;
font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 12px;
font-weight: normal;
font-variant: normal;
letter-spacing: normal;
text-decoration: none;
margin: 0px;
padding: 0px;
}

body {
margin: 25px;
}

.outerSlide {
width: 200px;
_width: 202px;
height: 10px;
_height: 12px;
line-height: 10px;
font-size: 1px;
background-color: silver;
float: left;
border: 1px solid black;
}

.innerSlide {
width: 100%;
height: 100%;
font-size: 1px;
background-color: transparent;
position: relative;
left: 0px;
top: 0px;
}

.slideBar {
display: none;
width: 1px;
height: 10px;
line-height: 10px;
font-size: 1px;
background-color: red;
position: relative;
left: 0px;
top: 0px;
_margin-left: -2px;
}

#slideSet {
background-color: green;
margin-top: -10px;
}
</style>
<script>
var setPct = 100;
var curPct = null;
var activeSlide = null;
var slideLeft = null;

document.onmousemove = doMove;

function doMove(e) {
if (!activeSlide)
return;

var e = (e)? e : ((event)? event : null);

if (e.pageX) {
myX = e.pageX;
} else if (e.clientX) {
myX = e.clientX;
}

var myLeft = (myX - slideLeft);
curPct = parseInt(myLeft/2);
if (curPct > 100)
return hideStuff(activeSlide);

pctShow(curPct);

var slider = document.getElementById(activeSlide);
slider.style.left = myLeft + "px";
}

function showStuff(myID, theID) {
activeSlide = theID;

var myNode = document.getElementById(myID);
slideLeft = findX(myNode);

var slider = document.getElementById(theID);
slider.style.display = "block";
}

function hideStuff(theID) {
activeSlide = null;
slideLeft = null;
pctShow(setPct);

var slider = document.getElementById(theID);
slider.style.display = "none";
}

function pctShow(theNum) {
var label = document.getElementById("pctLabel");
label.innerHTML = theNum + "%";
}

function pctSet(myID, theID) {
var theNode = document.getElementById(myID);
var myWidth = theNode.offsetWidth;
var myLeft = parseInt(myWidth * (curPct/100));

var setNode = document.getElementById(theID);
setNode.style.display = "block";
setNode.style.left = myLeft +"px";
setPct = curPct;
}

function findX(obj) {
var curleft = 0;
while (obj.offsetParent) {
curleft += obj.offsetLeft
obj = obj.offsetParent;
}

return curleft;
}
</script>
</head>
<body>
<div id="slideWrap" class="outerSlide" onmouseout="hideStuff('slider')">
<div id="slideMain" class="innerSlide" onmouseover="showStuff(this.id, 'slider')" onmouseout="hideStuff('slider')" onclick="pctSet(this.id, 'slideSet')">
<div class="slideBar" id="slider"></div>
</div>
<div class="slideBar" id="slideSet"></div>
</div>
<div id="pctLabel">
100%
</div>
</body></html>