jquery using multiple setTimeouts - javascript

I am currently creating a site with some dynamic content, so that whenever a user hovers over a label, the label expands to show more information, then after a specific time the label will collapse again, unless the user hovers over the label again in which case the Timeout will reset. I have developed the code to do this for 1 label, but I would to develop it now to do it for multiple labels.
The problem I'm having though is that I am defining the variable for the timer globally so it can be used for both events, this won't work when I have multiple labels though.
I can't think how I can achieve this for multiple labels, does anyone have any idea how I can do this?
Here is my code so far...
var timer;
$('.label').mouseenter(function(){
clearTimeout(timer);
$('#' + this.id + ' div').slideDown('slow');
});
$('.label').mouseleave(function(){
var temp = $('#' + this.id + ' div');
timer = setTimeout(function() {
temp.stop().slideUp('slow');
}, 2000);
});
Thanks in advance for any help.

You can maintain an array of timers like
var timer = [];
$('.label').mouseenter(function(){
clearTimeout(timer[$(this).index()]);
$('#' + this.id + ' div').slideDown('slow');
});
$('.label').mouseleave(function(){
var temp = $('#' + this.id + ' div');
timer[$(this).index()] = setTimeout(function() {
temp.stop().slideUp('slow');
}, 2000);
});
You can also achieve this with a more clear syntax using .hover like
var timer = [];
$('.label').hover(function(){
clearTimeout(timer[$(this).index()]);
$('#' + this.id + ' div').slideDown('slow');
},function(){
var temp = $('#' + this.id + ' div');
timer[$(this).index()] = setTimeout(function() {
temp.stop().slideUp('slow');
}, 2000);
});

Why dont you use hover :
$('.label').hover(function(){
$('#' + this.id + ' div').slideDown('slow');
},
function(){
$('#' + this.id + ' div').slideUp('slow');
})
This way, when labels are hovered upon, more info will show and when mouse leaves them, they will hide back again.
The first param to hover is for mouse enter while second for mouse leave.
More Info:
http://api.jquery.com/hover/

Instead of using global variable timer you can use jQuery's .data() method like this:
$('.label').hover(function(){
clearTimeout($(this).data('hover_timeout'));
$('#' + this.id + ' div').slideDown('slow');
},function(){
var temp = $('#' + this.id + ' div');
$(this).data('hover_timeout', setTimeout(function() {
temp.stop().slideUp('slow');
}, 2000));
});
jQuery.data() documentation

Related

Suggestions to make this jQuery function more DRY / more efficient

Following previous post the this code works and does the job but I am conscious this is about as DRY as the Pacific on a wet day.
I's be grateful for any suggestions that will make it more efficient.
$( "#cvl_mb_services .content-switch" ).each(function(index, el) {
var parent = $(el).parent().parent().attr("id");
var inputValue = $('#' + parent + ' input[type=radio]:checked').val();
var targetBox = '#' + parent + ' .cvl-' + inputValue + '-fields';
$(targetBox).removeClass('cvl-hide');
});
$('#cvl_mb_services .content-switch').on('click', 'input[type="radio"]', function(){
var parent = $(this).parent().parent().parent().parent().parent().parent().attr("id");
var inputValue = $(this).closest('input[type="radio"]').attr("value");
var targetBox = '#' + parent + ' .cvl-' + inputValue + '-fields';
if (inputValue == 'content') {
$('#' + parent + ' .cvl-content-fields').removeClass('cvl-hide');
$('#' + parent + ' .cvl-header-fields').addClass('cvl-hide');
$('#' + parent + ' .cvl-footer-fields').addClass('cvl-hide');
} else if (inputValue == 'header') {
$('#' + parent + ' .cvl-content-fields').addClass('cvl-hide');
$('#' + parent + ' .cvl-header-fields').removeClass('cvl-hide');
$('#' + parent + ' .cvl-footer-fields').addClass('cvl-hide');
} else if (inputValue == 'footer') {
$('#' + parent + ' .cvl-content-fields').addClass('cvl-hide');
$('#' + parent + ' .cvl-header-fields').addClass('cvl-hide');
$('#' + parent + ' .cvl-footer-fields').removeClass('cvl-hide');
}
});
Several points to make it more DRY:
Use only one var keyword, and separate the items with commas. Ex. var asdf = 1, sdfg = '', dfgh = true;
Use multiple selectors so you apply the .addClass action only once. See https://api.jquery.com/multiple-selector/
Find a way to get rid of this duplication, such as perhaps adding/using a class to select the right ancestor: .parent().parent().parent().parent().parent().parent()
Don't duplicate strings like 'cvl-hide' Instead make a variable. Many JavaScript minifiers won't touch strings, so you'll end up with this duplication making your overall file larger than it needs to be.
Make variables for duplicate selectors so jQuery doesn't have to do the same lookup twice. For stuff like $('#cvl_mb_services .content-switch') and even for stuff like $(this) which is duplicated.

Jquery - Multiple slideshows on one page using radios

I am trying to get more than one slideshow onto a page. I have to use radios as the trigger. I can't get both to display at the same time, one turns the other off!
Please see this Fiddle.
var current = '';
$('[name="first_inputs"]').change(function() {
if(current.length)
$('#' + current).slideUp();
current = $(this).val();
$('#' + $(this).val()).slideDown();
});
var current = '';
$('[name="second_inputs"]').change(function() {
if(current.length)
$('#' + current).slideUp();
current = $(this).val();
$('#' + $(this).val()).slideDown();
});
I have named them differently and the code asks for them by name - why can't I get both to display? (Sorry, I'm just starting out with this stuff.)
Thank you
David
You were defining two variables with the same name, which caused the variable to interfere with each other. Renaming them fixes it.
https://jsfiddle.net/nhctucg6/32/
var currentFirst = '';
$('[name="first_inputs"]').change(function() {
if(currentFirst.length)
$('#' + currentFirst).slideUp();
currentFirst = $(this).val();
$('#' + $(this).val()).slideDown();
});
var currentSecond = '';
$('[name="second_inputs"]').change(function() {
if(currentSecond.length)
$('#' + currentSecond).slideUp();
currentSecond = $(this).val();
$('#' + $(this).val()).slideDown();
});

Clone DIV and its contents with new ids [duplicate]

This question already has answers here:
Clone <div> and change id
(4 answers)
Closed 9 years ago.
I'm trying to clone a div and the input elements inside it. When I clone it, I would like all the ids to increment by one. I've made a fiddle to show you what I'm doing.
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
$(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount);
});
jsFiddle
So far I've cloned the whole div itself and the ids increment but the elements inside remain the same. How would I get all elements inside the div to increment by one?
You have cloned the entire div without modifying it's contents. Try something like:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
$(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount).find('input').each(function (i, e) {
$(e).attr('id', $(e).attr('id').replace(amount, new_amount));
});
});
DEMO
You can recursively replace all id's using find / replace:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount).clone();
cloned_div.insertAfter('#class-' + amount);
cloned_div.find('[id$="-' + amount + '"]').andSelf().each(function(index, child) {
child.id = child.id.replace("-" + amount, "-" + new_amount);
});
});
See jsFiddle
cloned_div.find('[id$="-' + amount + '"]') will search for all child elements having an id attribute ending on "-" + amount, .andSelf() will include the cloned div as you want to change the id there also. Then simply replace the number part in the id of each child (and self).
Try adding this:
$('#class-' + new_amount + ' input:nth-child(1)').attr('id', 'name-class-' + new_amount);
$('#class-' + new_amount + ' input:nth-child(2)').attr('id', 'number-class-' + new_amount);
$('#class-' + new_amount + ' input:nth-child(3)').attr('id', 'book-class-' + new_amount);
just below your $(cloned_div).clone() statement.
See it in action:
http://jsfiddle.net/ZHHcA/1/
These other answers are close, but the problem with their solutions is the original ID prefixes are being lost: number-class-1 is becoming class-1 which is not ideal.
Here is a better option:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
var $cloned = $(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount);
$cloned.children().each(function(){
var $child = $(this);
var oldID = $child.attr('id');
var newID = oldID.replace(/[0-9]+$/, new_amount); // replace just the number, leave the rest of the ID name in tact
$child.attr('id', newID);
})
});
And a working example

Fading in appended elements one at a time

I have an array with IDs and I am loading elements with these IDs from another page.
$.each(idArr, function() {
var divline = '<div class="line" id="' + this + '">';
var url = 'allitems.php #' + this + ' div';
$('#the-list').append($(divline).load(url).hide().fadeIn());
});
It works fine but I would like the loaded elements to fade in one at a time, or at least not all att once. I cannot figure out how to use .delay with my code. Or is there maybe another way?
Thank you :)
$.each(idArr, function(i,el) {
var divline = $('<div />', {'class':'line', id: el}),
url = 'allitems.php #' + el + ' div';
$('#the-list').append(divline.load(url).hide().delay(i*1000).fadeIn());
});
A simple solution is to use setTimeout :
$.each(idArr, function(i) {
var divline = '<div class="line" id="' + this + '">';
var url = 'allitems.php #' + this + ' div';
setTimeout(function(){
$('#the-list').append($(divline).load(url).hide().fadeIn());
}, i*1000);
});
Try this way:
$(".elements").each(function(i, e) { $(e).delay(i * 400).fadeIn(400); });

Is it possible to use cloneNode to clone multiple divs?

I'm trying to clone to divs in and append them to to other divs (their parents). I'm using clonenode for this but it doesn't seem to work. It clones the div in the first function and appends it to the parent of the div in the second function! Not sure what I'm doing wrong.
Here's the code (*EDIT:*var added):
function cloneQ() {
//Cloning questions and shit
cloneQ.id = (cloneQ.id || 0) + 1;
var question = document.getElementById("question");
var clone = question.cloneNode(true);
var numberOfQuestions = $('.question').length;
var id = "questioncon" + cloneQ.id;
clone.id = id;
question.parentNode.appendChild(clone);
var inid = "question" + cloneQ.id;
var optionid = "optionsdiv" + cloneQ.id;
$('#' + id + ' ' + '.' + 'questionin').attr('id', inid);
$('#' + id + ' ' + '.' + 'options').attr('id', optionid);
$('#' + id + ' h2').html('Question ' + cloneQ.id);
//Question Cloned
}
function cloneforPrint() {
cloneforPrint.id = (cloneforPrint.id || 0) + 1;
var questionprint = document.getElementById("questionprint");
var cloneprint = questionprint.cloneNode(true);
var printid = "questionprint" + cloneforPrint.id;
cloneprint.id = printid;
questionprint.parentNode.appendChild(clone);
var printinid = "thequestionprint" + cloneforPrint.id;
$('#' + printid + ' ' + '.' + 'thequestionprint').attr('id', printinid);
}
LIVE here: http://bit.ly/R8hB2m
Edit : Global vars are the problem.
You aren't putting var in front of your variables, making them global. The cloneForPrint function is picking up vars defined in cloneQ.
Init all the variables properly and you'll get some errors indicating where the problems are.
CloneQ is indeed appending to questions parent, but cloneForPrint then moves it somewhere else.
-- Old answer --
There's not enough here to work out what the problem is. My 1st guess is that the question element has the same parent as the questionprint element.
Based on the code given, cloneQ should definitely append to questions parent. So to give the appearance you've specified the DOM probably doesn't look like what you expect.

Categories

Resources