Very simply put : the line currentItem.toggleClass('open'); doesn't seem to work.
More precisely, when inspecting the results with firebug, I can see the class "open" flashing (appearing and immediately disappearing) on the relevant element. So it's like the function is actually triggered twice (of course I only click once).
Can somebody explain me why this is and how to prevent it?
Here is my jQuery code :
$('div.collapse ul.radio_list li input[type=radio]').click(function (event) {
var currentTree = $(this).parent().parent().parent();
var currentItem = $(this).parent().parent();
var currentGroup = currentItem.attr('rel');
$(this).parents('ul').children('li').removeClass('select');
if ($(this).is(':checked')) {
currentItem.addClass('select');
}
currentItem.toggleClass('open');
var currentLevel = 0;
if (currentItem.is('.level1')) {currentLevel = 1;}
if (currentItem.is('.level2')) {currentLevel = 2;}
if (currentItem.is('.level3')) {currentLevel = 3;}
var nextLevel = currentLevel + 1;
currentTree.children('li').filter('li[rel ^=' + currentGroup + '].level' + nextLevel).animate({'height': 'show', 'opacity': 'show'}, 250).addClass('currentChild');
});
And here is a part of my HTML code, slightly simplified for better readability (not very pretty I know, but I only have a limited control on the HTML output) :
<div class="col_left collapse">
<ul class="radio_list" rel="7">
<li class="onglet level0" rel="group1">
<span class="onglet level0">
<input type="radio" />
<label>Services Pratiques</label></span>
<input type="hidden" value="1">
</li>
Thanks in advance.
Problem solved: the JS file was actually included twice in the HTML head, which caused the function to be triggered twice with each click.
I had a similar problem on my site, and I found that I had accidently duplicated the toggleclass hook all the way at the bottom, when first messing around with it. Oops! Make sure to look for double calls!
I had a similar problem doing this:
html:
<a>JS-link</a>
js:
$('a').click(function(event) {
... my stuff ...
# Forgot to do event.preventDefault(); !!
}
results in clicks being register twice!
I had the same issue and realized I had accidentally bound the function twice. I had originally meant to move the code from one javascript file to another but accidentally left the original in its place.
Related
My first time writing my own javascript/jQuery for-loop and I'm running into trouble.
Basically, I have a series of divs which are empty, but when a button is clicked, the divs turn into input fields for the user. The input fields are there at the outset, but I'm using CSS to hide them and using JS/jQuery to evaluate the css property and make them visible/hide upon a button click.
I can do this fine by putting an id tag on each of the 7 input fields and writing out the jQuery by hand, like this:
$('#tryBTN').click(function(){
if ( $('#password').css('visibility') == 'hidden' )
$('#password').css('visibility','visible');
else
$('#password').css('visibility','hidden');
}
Copy/pasting that code 7 times and just swapping out the div IDs works great, however, being more efficient, I know there's a way to put this in a for-loop.
Writing this code as a test, it worked on the first one just fine:
$('#tryBTN').click(function() {
for(i = 1; i <= 7; i++) {
if($('#input1').css('visibility') == 'hidden')
$('#input1').css('visibility', 'visible');
}
});
But again, this only works for the one id. So I changed all the HTML id tags from unique ones to like id="intput1" - all the way out to seven so that I could iterate over the tags with an eval. I came up with this:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
if ($(eval('input' + i)).css('visibility') == 'hidden')
$('input' + i).css('visibility', 'visible');
}
});
When I put in the eval stuff - it doesn't work. Not sure what I'm doing wrong. A sample of the HTML looks like this:
<form>
<div class="form-group">
<label for="page">Description: Specifies page to return if paging is selected. Defaults to no paging.</label>
<input type="text" class="form-control" id="input7" aria-describedby="page">
</div>
</form>
You were forgetting the #:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
var el = $('#input' + i); // <-- The needed `#`
if (el.css('visibility') == 'hidden') {
el.css('visibility', 'visible');
}
}
});
#Intervalia's answer explains the simple error in your code (the missing #), and the comments explain why you should never use eval() unless you absolutely know it's the right tool for the job - which is very rare.
I would like to add a suggestion that will simplify your code and make it more reliable.
Instead of manually setting sequential IDs on each of your input elements, I suggest giving them all a common class. Then you can let jQuery loop through them and you won't have to worry about updating the 7 if you ever add or remove an item.
This class can be in addition to any other classes you already have on the elements. I'll call it showme:
<input type="text" class="form-control showme" aria-describedby="page">
Now you can use $('.showme') to get a jQuery object containing all the elments that have this class.
If you have to run some logic on each matching element, you would use .each(), like this:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
if( $(element).css('visibility') == 'hidden' ) {
$(element).css( 'visibility', 'visible' );
}
});
});
But you don't need to check whether an element has visibility:hidden before changing it to visibility:visible. You can just go ahead and set the new value. So you can simplify the code to:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
$(element).css( 'visibility', 'visible' );
});
});
And now that the only thing we're doing inside the loop is setting the new visibility, we don't even need .each(), since jQuery will do the loop for us when we call .css(). (Thanks #TemaniAfif for the reminder.)
So the code becomes very simple:
$('#tryBTN').click( function() {
$('.showme').css( 'visibility', 'visible' );
});
i need to have a back button on my slide to return to the previous div. I did several test but without success.
there is my JS
function SlideOut(element) {
$(".opened").removeClass("opened");
$("#" + element).addClass("opened");
$("#content").removeClass().addClass(element);
}
$("#content div").click(function () {
var move = $(this).attr('data-move');
SlideOut(move);
});
There is the demo link:
http://jsfiddle.net/VA5Pv/
thanks
You could create a history. I edited the fiddle with some dirty code but the idea is there:
var history = [];
var last;
$("#content div").click(function () {
var move = $(this).attr('data-move');
if (last) history.push(last);
last = move;
SlideOut(move);
});
$("#back").click(function () {
SlideOut(history.pop());
return false;
});
http://jsfiddle.net/VA5Pv/1/
Basically: store the "move" variable in a history array. When you want to go back, pop the last value out of the history array.
Reset
If you just want to return to the initial state (no slides opened), just add the following:
$('button.close').click(function() {
$('.opened').removeClass('opened');
});
Tracking a full history is overkill in this case.
Demo: http://jsfiddle.net/VA5Pv/4/
History
Several answers suggested using a history. Most of them used an array which keeps track of the slides the user opened and then simply pop from that to "go back".
var history = [];
$('#content div').click(function() {
var move = $(this).attr('data-move');
history.push(move);
SlideOut();
});
$('button.close').click(function() {
history.pop();
SlideOut();
});
function SlideOut() {
var element = history[history.length - 1];
// ... same as before ...
}
This would be necessary if you wanted to allow the user to open any number of slides in any order and always present them with a button to go back to the previously opened slide.
Sequence
Another solution could have been to store all the slide IDs in an array and keep a counter that tells you at which slide you are. Going back would mean decrementing the counter if it is not already at zero and then switching to that particular slide.
This would be useful if you were trying to create something like a presentation where each slide is opened in sequence and the transitions are entirely linear.
This is why I asked you to clarify what you were trying to build. Depending on the use case, the solutions could have been vastly different and far more complex than what you were actually looking for.
Thanks for accepting my answer and welcome to StackOverflow. Feel free to upvote any answers you found helpful even if they did not answer your question sufficiently.
try the following:
$('.anim button').click(function(){$(this).parent().removeClass('opened');});
I assigned this to the button in div rouge. But the target could be anything in that div you want the user to click on ...
see here: JSfiddle
Here is the DEMO
<div id="fullContainer">
<div id="right" class="anim"></div>
<div id="rouge" class="anim">Hello world!
<button class="close">Close</button>
</div>
</div>
<div id="centerContainer">
<div id="relativeContainer">
<div id="content">
<div data-move="right">Open Right</div>
<div data-move="rouge">Open Rouge</div>
<div id="back">Back</div>
</div>
function SlideOut(element) {
if(element == undefined) {
$('#back').hide();
}
$(".opened").removeClass("opened");
$("#" + element).addClass("opened");
$("#content").removeClass().addClass(element);
}
$("#content div").click(function () {
var move = $(this).attr('data-move');
$('#back').show();
SlideOut(move);
});
In Javascript, I'm trying to create a user script that will automatically click on a 'Blue Button'. Normally, I would do this:
var bluebutton = "document.getElementById("blue_button")"
if (bluebutton) {
bluebutton.onclick();
}
But NOW, the blue button does not have its own obvious ID. It's ID is randomized, and could be either button1, button2, or button3.
Here's the HTML that I'm talking about:
<div class="button_slot">
<div id="button1" style="cursor:pointer; padding-left:30px" onclick="buttonsubmit('button1')" onmouseover="infopane.display('Blue Button','I'm a blue button!')" onmouseout="infopane.clear()">
<div class="button_slot">
<div id="button2" style="cursor:pointer; padding-left:30px" onclick="buttonsubmit('button2')" onmouseover="infopane.display('Red Button','I'm a red button!')" onmouseout="infopane.clear()">
<div class="button_slot">
<div id="button3" style="cursor:pointer; padding-left:30px" onclick="buttonsubmit('button3')" onmouseover="infopane.display('Yellow Button','I'm a yellow button!')" onmouseout="infopane.clear()">
After a bit of reading, I've concluded that the only way to direct my onclick() to the correct element/string is by using ".toString().match(name)" as shown below:
function clickbutton(name) {
var button_list = document.querySelectorAll('.button_slot > div');
for (var i=0; i<button_list.length; i++) {
var button = button_list[i];
if (button.onmouseover && button.onmouseover.toString().match(name)) {
button.onmouseover();
button.onclick();
break;
}
}
}
clickbutton('Blue');
(note: sometimes I use clickbutton('Red'); or clickbutton('Yellow'); just to experiemen)
Now here's the problem. This method works so horribly... Sometimes, my script completely misses the button (as in, nothing gets clicked) EVEN THOUGH there is definitely a string with the word 'Blue' in it.
If someone could identify what I'm doing wrong, or perhaps even suggest a more effective method, I would appreciate it so much! Thank you!
First, I'm not sure why you can't give each button an ID which corresponds to it's color, because I believe that would be the easiest way to achieve this. But assuming that, for some reason, your button ID's must be randomized (or for that matter, maybe they don't even have an ID).
In this case, what I would do is give each button a data-button-type attribute, for instance:
<div data-button-type="Blue" id="..." style="..." onclick="..." onmouseover="..." onmouseout="...">
Now, I can check the attribute when looking for which button to click, for example:
function clickbutton(name) {
var button_list = document.querySelectorAll('.button_slot > div');
for (var i=0; i<button_list.length; i++) {
var button = button_list[i];
if (button.getAttribute('data-button-type') == name) {
button.onmouseover();
button.onclick();
break;
}
}
}
clickbutton('Blue');
I'm pretty sure you want to use indexOf although I think its most likely a timing issue.
First just try invoking it in a setTimeout function, so the document has (probably) loaded fully when you execute. It would explain it sometimes working sometimes not.
setTimeout(function(){ clickbutton(name) }, 3000);
I would do:
var clickButton = function(name){
var button_list = document.querySelectorAll('.button_slot > div');
for(var i = 0; i < button_list.length; i++){
var button = button_list[i];
if(button.getAttribute('onmouseover').indexOf(name) !== -1){
button.onclick.apply(); // They seem to have parameters in your example?
}
break;
}
}
setTimeout(function(){ clickButton('blah') }, 3000);
As a first attempt...
I'm making a form where the users fill in a title which they can size up or down. I have a preview window that changes when they click on the "size up button". But I want to store this in a hidden form to get the value when posting.
HTML - FORM
<input id="title" name="title" />
<input id="titlesize" name="titlesize" value="50" />
<div id="sizeUp">Size up!</div>
HTML - PREVIEW WINDOW
<h2 id="titlepreview" style="font-size: 50px;">Title</h2>
Javascript
$(document).ready(function() {
$("#sizeUp").click(function() {
$("#titlepreview").css("font-size","+=5"),
$("#titlesize").val("+=5"); // <-- Here's the problem
});
Any ideas?
Try this using the .val( function(index, value) ):
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5"),
$("#titlesize").val(function (index, value) {
return parseInt(value, 10) + 5;
});
});
});
FIDDLE DEMO
You need parseInt to handle strings as numbers.
$("#sizeUp").click(function () {
var obj = $("#titlesize");
var value = parseInt(obj.val());
obj.val(value + 5);
});
OK, I'm not entirely sure where the problem is here, but here's a way of going about it anyway:
If you want a range of sizes so you can't get a title too big or small, you could (while this is long-winded) make a css class for each size.
Then, you could use JqueryUI's .addClass() and .removeClass. With these you could do something like:
$("#sizeupbutton").click(function(e){
$(#title).removeClass("size45");
$(#title).addClass("size50");
});
Sorry if I've completely got your question wrong, but good luck!
Edit: OK, now i think i understand what you want, I would advise you check out Vucko's answer below.
you can get variable like this:
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5");
var up=parseInt(($("#titlepreview").css("font-size")),10);
$("#titlesize").val(up);
});
});
example:fiddle
I am trying to use a code snippet I found online to implement charcount. It works for one single text area. I have multiple text areas with different count limits. Here is the code that works for one single form.
Javascript:
function countChar(val,count,focus){
var len = val.value.length;
var lim=count;
var focussed=focus;
if (len >= lim) {
$('#charNum').text(lim - len);
$('#charNum').addClass('exceeded');
/* val.value = val.value.substring(0, lim);*/
}else {
if(focussed===0){
$('#charNum').html('<a> </a>');
}
else {
$('#charNum').text(lim - len);
$('#charNum').removeClass('exceeded');
}
}
};
HTML:
<div id='charNum' class='counter'> </div>
<textarea id='description' name='description' onkeyup=\"countChar(this,200,1)\" onblur=\"countChar(this,200,0)\" rows='10' cols='20'></textarea>
If I have two text areas, how can I modify this code to work ? I know how to get the id of the div in the script, But I dont know how to correctly update the counter div, say #charNum1, and #charNum2. Appreciate some hints. Thanks
EDIT:
I was thinking, I can name the counter div as "Charnum+divName" if that helps
If you attach your event handler(s) with jQuery you can use this within the handler to refer to whichever element the event was triggered on, thus avoiding having to hardcode element ids inside your function.
I'd suggest adding an attribute with the max chars allowed and removing the inline event handlers:
<div id='charNum' class='counter'> </div>
<textarea id='description' name='description' data-maxChars="200" rows='10' cols='20'></textarea>
<div id='charNum2' class='counter'> </div>
<textarea id='otherfield' name='otherfield' data-maxChars="400" rows='10' cols='20'></textarea>
Then:
$(document).ready(function() {
$("textarea[data-maxChars]").on("keyup blur", function(e) {
var $this = $(this),
$counter = $this.prev(),
len = $this.val().length,
maxChars = +$this.attr("data-maxChars");
$counter.text(maxChars - len).toggleClass("exceeded", len > maxChars);
});
});
Demo: http://jsfiddle.net/nnnnnn/GTyW3/
If each textarea is going to have it's own div, you can just add an extra parameter to the countChar function which would be the name of the div. So you'd have something like:
function countChar(val,count,focus, charCountDiv)
then, instead of hardcoding it in the function, the jQuery would be:
$(charCountDiv)
That should do what I think you are looking to do.