Multiple sliders with a maximum total value.
Hello all,
My page has three slider controls. They represent three values:gpa,comm, and e6. These values are percentages, and I don't want them to go over 100% in total. Here is what the html layout is like :
- <p>
<label>GPA : </label><input type = "text" disabled = "disabled" id = "gpa_value" name = "gpa_value" class = "value_text" value = "33" />
</p>
<div id = "gpa" class = "slider"></div>
<p>
<label>Comm : </label><input type = "text" disabled = "disabled" id = "comm_value" name = "comm_value" class = "value_text" value = "33" />
</p>
<div id = "comm" class = "slider"></div>
<p>
<label>e6: </label><input type = "text" disabled = "disabled" id = "e6_value" name = "e6_value" class = "value_text" value = "34" />
</p>
<div id = "e6" class = "slider"></div>
<p>
<label>Total: </label> <input type = "text" id = "total" class = "value_text" disabled = "disabled" />
</p>
What I want to do is when the user moves the slider, have it's siblings move up or down based on how much the slider has moved. For example, if I moved the gpa slider up one then either the comm or e6 slider would move down one to keep the total at 100%. Right now I have this sort of working but I really don't like how it is coded. It seems like it will be too bulky when it is done. Here is the code I used to turn the elements into a slider and assign a function to them when they are moved:
- $(".slider").each(function(){
//Textbox associated with the slider
var text = "#" + $(this).attr("id") + "_value";
//value in that textbox
var value = parseInt($(text).val());
//make this element a slider
$(this).slider({
range:'min',
value:value,
slide: function(event,ui){
var oldValue = parseInt($(this).slider("value")); // value before the slide event
var newValue = parseInt(ui.value); // value after the slide event completes
//The amout of steps the slider has moved
var difference = newValue - oldValue;
// If moveSiblings returns false cancel the slide action
if(!moveSiblings(difference,$(this)))
{
return false;
}
//Set the value of this slider to it's cooresponding textbox
$(text).val(ui.value);
//Set the value of the total textbox
setTotal();
}
});
}); //end slider each
As you can see when the slider is moved it calls a function called moveSiblings that returns a bool. It passes in the amount the slider has moved(difference) and the slider itself. Here is the moveSiblings function:
- /*This will be used to move the siblings of the slider being moved. The intent is to have the total always at
100%. For example if you moved the gpa slider up, the comm and e6 sliders would move down. */
- function moveSiblings(difference,slider)
{
//Get the id of the slider being moved
var id = slider.attr("id");
if(id == "gpa")
{
//if sibling is set to 0 make #comm the moved sibling
if(slider.data("sibling") == 0)
{
var sib = $("#comm");
slider.data("sibling",1);
}
//else make e6 the moved sibling
else
{
var sib = $("#e6");
slider.data("sibling",0);
}
//get the id of the corresponding value text box
var text = "#" + sib.attr("id") + "_value";
var newValue = parseInt($(text).val()) - parseInt(difference);
- //If this makes the value of the sibling over 100 or under 0 then cancel the move event
if(newValue > 100 || newValue < 0)
{
return false;
}
else
{
$("#cont").text(newValue);
sib.slider("option", "value", newValue)
$(text).val(newValue);
return true;
}
} // end gpa
} // End moveSiblings
As you can see I give the slider a data item called "sibling" which changes from 0 to 1 every time the function is called. This is how I alternate between which of the siblings to move. If the value of the moved sibling goes under 0 or over 100 then this returns false, canceling the move event of the slider the user is moving. This works for the gpa slider(a few smaller issues to work out), and I would just have to include code for the other two. However, there are a number of things I don't like about this method. First of all I have to hard code allot of it having to do if(id == "gpa),else if(id == "comm") etc. When I write out code for the next two sliders this function is going to be close to 100 lines, that seems like far too much for one function. Another problem is this is not extensible. If in the future I wanted to add another slider I would have to add ALLOT more code, first for another if condition for the id. Then I would have to change the other three and include the new slider as one of the siblings to be moved. Could anyone suggest a better, more extensible way to do this? I try to use a certain level of finesse when I code but I am still pretty new to jQuery so my code is kinda clunky. Any advice or suggestions anyone could give me to improve how this works would be very much appreciated, thanks!
Jstall