limit the value of a slider dynamically - javascript

I want a slider with range 0 to 2400, which is limited by another slider's value. Together they only may add up to 2400. I have tried to implement it in the change method like this:
var cal_sl = $("#sl_4");
cal_sl.attr('max', 2400);
cal_sl.change(function()
{
var sumv = ($("#sl_3").val()*1)+($(this).val()*1);
if(sumv>2400)
{
$(this).val(2400-$("#sl_3").val());
}
var slider_value = $(this).val();
});
But then the slider won't move (only the text box of the slider would be correct). If I also add a refresh, the change function would enter an infinite loop of refreshing/changing/refreshing/...
Also, I do not want to change the 'max' value, since the thumb should be in the middle of the slider with a value 1200, but it should not be able to move to a higher value if the other slider has a value of 1200 as well.
How could this be implemented?

I just had to set the refresh within the if, this way the infinite loop does not happen:
$(this).slider('refresh');

Related

How to set dependent slider so that the 2nd anchor moves automatically?

I'm using the following code in the JS editor in Qualtrics with constant sum and 2 sliders. I'd like to set it up so that when participants are asked to allocate $10,000 between two choices, the slider that isn't being moved by the participant will move automatically to reflect the allocation on the first slider. The code below works so that the amount for each choice automatically updates as the slider moves, but the actual slider stays put. Any thoughts or suggestions on how to make the 2nd slider move as the participant moves the first slider?
I'm very new to coding so anything that might point me in the right direction is extremely appreciated!
{
var that=this.questionId;
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~1~holder']").addClass("activated");
jQuery("[id='"+that+"~1~result']").bind('input propertychange',function(){
var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
console.log(A);
if((A+parseInt(jQuery("[id='"+that+"~2~result']").val()))==10000) {
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_1', A );
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_2',parseInt(jQuery("[id='"+that+"~2~result']").val()));
console.log("rturn");
return;
}
jQuery("[id='"+that+"~2~result']").val(10000-A);
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~2~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~2~bar']").css({"width":p*t+"px"});
var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
var B=parseFloat(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);

Change background on hover of a draggable div

I have a small draggable division (black) and many nodes with different IDs beside it
I need a hovering effect when I drag the black element on the nodes. What I am doing in allowDrop function is:
var dragObj;
function drag(ev){
dragObj = ev;
}
function allowDrop(ev){
ev.preventDefault();
var Dragged = dragObj;
var Hovered = ev;
var leftIndent = Dragged.layerX;
var hoveredID = Hovered.target.id.toString().split('_');
var nodesOnLeft = Math.floor(leftIndent/12);
var startingNode = hoveredID[0]-nodesOnLeft;
for (i=1;i<=Math.floor(draggableElementLength/12);i++){
var toApplyCssID = startingNode.toString() + '_1';
var toApplyCss = document.getElementById(toApplyCssID);
$('#'+toApplyCssID).css('background-color','lightgreen');
}
}
basically I am using the layerX property to find out the distance between my mouse pointer and draggable division's border and adjusting that to calculate number of nodes where I have to apply new CSS and applying that by finding the ID of node.
This is working but its making the process very slow as it involves many calculations and its not the hover effect as its not going away when I am removing the draggable division.
Is there any other way to achieve this or do I need to make code changes in existing code.
thanks
Without the HTML and the rest of the script, I can only point you in the direction you should be taking in this kind of scenario:
Don't constantly repeat calculations (that do not change) in a loop, store them outside the function:
Use document.getElementById(toApplyCssID) for each node and store the
elements in an array
Get the distance from the mouse position to the required edge or
edges of the div (leftIndent) on initial drag/mousedown and store
that in a variable
Store Math.floor(draggableElementLength/12) in another variable (you
haven't shown where this originates, but it doesn't seem to change in
the function...)
Apply the CSS to the relavent elements (from the array of elements)
using the other stored values to select them
Remove the CSS on those that had it applied earlier
This may not be the ultimate solution, but these are some of the things you can look at to speed up what you (may) have currently.

Check Position During Each Click and Add Class

I want the class .disabled to be added to the left and/or right controls (.tab-left, .tab-right) if the first or last tab is showing so a user can see that they have reached the end and cannot click any further.
Right now I something like this to prevent the user from going past the end.
if (tabs are at the end) {
return;
}
This works for users not being able to click past the end, but if I add the class before returning, the problem is the .disabled class won't be added until the tabs have reached the end and the user clicks again.
if (tabs are at the end) {
$('.tab-right').addClass('disabled');
return;
}
I need the disabled class to be added when the last tab is showing, not when the user trys to click past the end.
Here's a link to the js fiddle: http://jsfiddle.net/uue6pgcx/
One option you could try is to enable/disable the right and left buttons once the animation is complete.
$ul.filter(':not(:animated)').animate({
"left": dir + liWidth
}, {
complete: function () {
// Calculate the number of items in the container (without left and right navigation buttons).
var lisContainer = Math.round(($container.width() - $left.outerWidth() - $right.outerWidth()) / liWidth);
// Disable right button when list is moved to the left a number of items
// such as the remaining number of them is less or equal than the number
// of items that fit in the container.
$right.toggleClass('disabled', $li.length + $ul.position().left / liWidth <= lisContainer);
// Disable left button when list is in the origin.
$left.toggleClass('disabled', $ul.position().left === 0);
}
});
Disclaimer: According to jQuery outerWidth additional notes, The number returned by dimensions-related APIs, including .outerWidth(), may be fractional in some cases. Code should not assume it is an integer.. So lets hope Math.round will suffice to get the proper number.
Maybe there is a better way to calculate if the right button must be disabled/enabled instead of relying on the number of items that fit in the container.
Here it is your code with the above modification:
http://jsfiddle.net/0Lsepxeu/

how to adjust the width of all the right or left elements at the same time?

I have some divs(sibblings) and on drag and resize of one of them, according to wether its being resized to west or east i would like to either increase or decrease all the other sibblings widths accordingly.
$(function () {
var west;
var east;
var clientX;
$("#resizable1").resizable({
start: function (event, ui) {
west = $(event.srcElement).hasClass('ui-resizable-w');
east = $(event.srcElement).hasClass('ui-resizable-e');
clientX = event.clientX;
},
resize: function (event, ui) {
if (east) {
//decrease one by one --?
$(this).nextAll().css('width', --? );
}
}
});
});
Set width to:
if (east) {
//decrease one by one
var newWidth = ($('#resizable1').width() - $(this).outerWidth(true)) / $(this).nextAll().length
...
}
EDIT:
How do the 3rd and 4rd sibling react when you resize the second one?
When calculating the remaining space, I only took the first one into account... if they fill the remaining space, yout must add up all outerWidths from the previous sibling instead of just taking $(this).outerWidth(true).
btw, the above code is not tested, just a suggestion to get remaining space to fill.
Make them all share the same width variable, decrease or increase the variable to affect all the div's at the same time.
Either by manually setting every divs size by calling a function and using the same variable as parameter for all of the calls.
Or make the divs share a css class and call the resize function on all the html elements sharing that css class.
EDIT:
Ah i completely miss understood you...
Make all the divs sizes relative and floating, then they should fill their parent.

How can I create an HTML text field that has scrolling background images before it is clicked?

I'm looking to add a textbox on my website that captures a single email address. Behind it, I would like scrolling (or sliding) images to be a "hint" for what the field should be.
Example: http://steamboat.com/ - the "Newsletter sign up" toward the top of the page.
I can find plenty of jQuery plugins that provide a plain text "hint". Where should I start looking to add this additional affect?
Note: I do not want to add any flash elements on the page.
you can do this with plain javascript.
initialization: get a reference to your input element. set the background image using the style property
emailInput.style.backgroundImage = "url('emailbackground.png')";
emailInput.style.backgroundPosition = '0px 0px';
also declare variables to track running y offset, the height of the image in pixels, and if you want a staggered roll like on steamboat, how many steps you've moved and a timerID.
you'll have two functions- one will start an interval timer where the position of the image will change, the other will call the first function to restart the interval whenever you pause the background.
first the 'start' method:
function startScrolling() {
// start the process of moving the image
stepCounter = 0;
timerID = setInterval(updateScrolling, 10);
}
the 'update' method :
function updateScrolling() {
// update the y offset
stepCounter++;
y = (stepCounter * 1) % imageHeight;
emailInput.style.backgroundPosition = '0px ' + (-y).toString() + 'px';
// check for changes to timing
if (stepCounter >= steps) {
clearInterval(timerID);
timerID = setTimeout(startScrolling, 1000);
}
}
this example is set up to move 1 pixel for every step taken. you can provide a fixed value or derive it based on image height or whatever. if we've completed all the steps for this cycle, the interval is stopped and a longer timeout is set for the restart function.
Well, this is just a vague idea, but it might get you started.
You could:
Give the text box a class at startup that has a grey font color and displays the message
When the user clicks on the item, it checks to see if the grey class is being used in the control
If it is, it clears the control and assigns it a black font-color
This way subsequent click events won't find the grey class and the text box won't clear the user's stuff.
These are the steps I would take...
Create the text input field and give it a class with a background-image attribute that points to an image that has the text you want to display in the order you want listed vertically.. So your image would look like
Newsletter Sign Up
Enter your Email Address
Then you can use a CSS Sprite approach to shift the image up at the rate you want using a library like jQuery to animate it, getting the same effect....
Then you need an event binder on the input box that would clear out the background image when the user clicks in the box OR if the box contains text
Try this :
<body onload="changingBG()">
<input type="text" id="thisBox">
</body>
here is the script: you need to have an array of images that you want to keep in background, change the timer as u want:
function changingBG(){
var inboxEle = document.getElementById("thisBox");
inboxEle.style.backgroundImage = varArray[x] //this array contains various images
t=setTimeout("changingBG()",1000);
}

Categories