It seems that this code:
$(function(){
$('.show_hide_login').toggle(
function (){
alert('show');
$("div#fullpage").show();
$("div#loginbox").show();
},
function (){
alert('hide');
$("div#loginbox").hide();
$("div#fullpage").hide();
}
); });
Any idea on why it would be running twice when I click on either link (two, one is a div and one is an anchor)?
How many elements do you have with the .show_hide_login class? I'll guess you have two of those. In which case, $('.show_hide_login') result contains two elements, and toggle() is executed for each of them.
This isn't an answer to your question, but you could clean up your code a bit like so:
$(function() {
$('.show_hide_login').toggle(
function() {
alert('show');
$("#loginbox,#fullpage").show();
}, function() {
alert('hide');
$("#loginbox,#fullpage").hide();
});
});
As to your actual problem, I suspect Nick's guessed the culprit. Check out this demo to see the result of binding the same event twice: http://jsfiddle.net/9jPLv/
In addition to adding an alert prior to the binding of the toggle event, you could add in an unbind() and see if that solves the problem, like so:
$('.show_hide_login').unbind().toggle(
If that solves it, the toggle binding is definitely being run twice, so you'd just have to figure out why.
my answer is just a kind of checkpoint,i had the same issue but for different reason. I did include the script file in base page as well as child page. this resulted in toggle running twice if you have this problem check that the script is added only once.
It might be the same issue i was having.
so if you got an element with a script tag in it - then you move that containing element or wrap it with another tag in jquery - then the ready function in jquery is executed again - thus binding a second toggle function to your element.
as suggested $('.show_hide_login').unbind().toggle( is a workaround that does work, but better to try moving your javascript code to the head or bottom of the page.
Related
I've come across an issue where jQuery events fire twice after $.load() is called. The event handler is placed in the load() callback function, and this seems to be the only place where events fire twice on the script.
I've tried adding event.stopPropogation() and event.preventDefault(), as these seem to be common suggestions with jQuery events firing more than one. I'm not sure if my code is bubbling improperly or what. Any feedback would be helpful.
Here's an extract of some of the code where you see the behavior.
$("div.questions").load("question_source.php #simplified_a", function(){
...
// Line 1
$("#some_id").change(function(){
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
// event.stopPropagation();
// event.preventDefault();
});
You can clearly see the event firing twice with the console.log bit I've got in there. Any advice would be appreciated!
EDIT
OK, I checked through everything on the live page based on some of the suggestions, and there's definitely only one <div id="questions"> in existence when the problem is occurring. So, it doesn't appear to be an HTML problem.
I also checked to see if the event was actually being called twice, and as far as I can tell, the event is only being called once.
Now, I added a .on() event attached to the document which is called on the dynamically created elements, and that only fires once. .on() is not called within the .load() callback. Here's an example used on one of the other input boxes on the page which works without any problems:
$(document).on('change', "#SWA_mothers_income", function(){
console.log("mothers income changes from on()");
});
So, that works properly, but when tested on the same input within the .load() callback function, it fires twice, regardless of how it's called. So, it seems to me that it's almost certainly an issue with .load(). I wouldn't exactly call myself an expert in this, so if someone can figure out the issue, I'd love to know the answer. As it stands, I'm going to rewrite this code using .on().
SECOND EDIT
Adding $("#some_id").unbind('change');
before the 'change(function()) bit did the trick!
add this line
$("#some_id").unbind('change');
before
$("#some_id").change(function(){});
I'm not saying this will solve your problems but you need to pass in the event to reference it.
$("#some_id").change(function(event){
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
event.stopPropagation();
event.preventDefault();
});
It's possible that you have two divs with a class of 'questions', so you could be binding the change function twice.
If you update your change function to the below, this will unbind the change event before re-adding it. This will make sure you only have the function bound once;
$("#some_id").unbind('change').change(function(event) {
event.preventDefault();
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
});
I wrote an alternative to the jQuery Accordion, as that didn't offer multiple open section support (any idea why they opted to not include support for that? What's the history there?). I did some research on StackOverflow, as well on Google to see what other options others came up. I needed something that could be used on the fly on multiple elements.
After seeing several solutions and experimenting with them, in the end, I wrote my own version (based on Kevin's solution from http://forum.jquery.com/topic/accordion-multiple-sections-open-at-once , but heavily modified).
jsFiddle can be found here: http://jsfiddle.net/3jacu/1/
Inline Code:
$(document).ready(function(){
$.fn.togglepanels = function(){
return this.each(function(){
h4handler = $(this).find("h4");
$(h4handler).prepend('<div class="accordionarrow">▼</div>');
$(h4handler).click(function() {
$(h4handler).toggle(
function() {
barclicked = $(this);
$(barclicked).find(".accordionarrow").html('►');
$(barclicked).next().slideUp('slow');
window.console && console.log('Closed.');
return false;
},
function() {
barclicked = $(this);
$(barclicked).find(".accordionarrow").html('▼');
$(barclicked).next().slideDown('slow');
window.console && console.log('Open.');
return false;
}
);
});
});
};
$("#grouplist").togglepanels(); }
Oddly, the accordion arrow at the right side stopped working once I pasted it in jsFiddle, while it works in my local copy.
In any case, the issue is that toggling isn't working as expected, and when it does, it fires duplicate toggle events which result in it closing, opening, then ultimately closing the section and it won't open from that point on (it toggles open then closes back). That's assuming it works! At first, it won't work as it doesn't respond. I think there's a logic error somewhere I'm missing.
From what I wrote/see in the code, it searches the given handle for the corresponding tag (in this case, h4), pops the handle into a variable. It then adds the arrow to the h4 tag while applying the accordionarrow class (which floats it to the right). It then adds a click event to it, which will toggle (using jQuery's toggle function) between two functions when h4 is clicked.
I suspect the problem here is that I may be mistakenly assuming jQuery's toggle function will work fine for toggling between two functions, that I'll have to implement my own toggle code. Correct me if I'm wrong though!
I'm trying to write the code so it'll be as efficient as possible, so feedback on that also would be appreciated.
Thanks in advance for your time, assistance, and consideration!
You have the toggle binding (which is deprecated by the way) inside of the click binding, so a new event handler is getting attached every time you click the header.
As a random aside you should also fire events within the plugin (where you have the console lines would make sense) so that external code can react to state changes.
I believe your issue is the $(h4handler).click(function() { you have wrapped around the toggle listener. Essentially what this was doing was making so every click of the tab was adding the toggle listener, which was then also firing an event. Removing the click listener will have the behaviour you expect.
You forgot to paste the trailing characters ); to close the function call to jQuery function ready. Fixed: http://jsfiddle.net/LeZuse/3jacu/2/
UPDATE: I've just realised I did not really answer your question.
You are duplicating the .toggle functionality with binding another .click handler.
The doc about .toggle says:
Description: Bind two or more handlers to the matched elements, to be executed on alternate clicks.
Which means the click event is already built in.
NOTE: You should use local variables instead of global, so your plugin won't pollute the window object. Use the var keyword for this:
var h4handler = $(this).find("h4");
I have a div that when the page is loaded is set to display:none;. I can open it up using this simple code:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'block'});
});
Once it's opened, I'd like the user to be able to close it so I tried using the .is(':visible') function and then wrapping my original code in an if statment but this time using display:none;
if($('.field-group-format-wrapper').is(':visible')){
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'none'});
});
}
This does not seem to work though and I am not getting any syntax errors that I know of.
I also tried this:
if ($('.field-group-format-wrapper').is(':visible'))
$(".field-group-format-toggler").click(function () {
$(".field-group-format-wrapper").css({'display':'none'});
});
... but that did not work either.
You can just use the toggle function:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").toggle();
});
This will show the '.field-group-format-wrapper' elements if they are currently hidden and hide them if they're currently visible.
FYI the reason your code snippet in your question wasn't working is because you're only checking the visibility of the elements on dom ready, rather than on each click - so the event handler to show the elements will never be attached.
I guess your function is only being called on page load at which time all divs are hidden.
Why not check the visibility in the click event handler?
$('.field-group-format-toggler').click(function(){
var $wrapper = $('.field-group-format-wrapper'); //Maybe $(this).parent()?
if($wrapper.is(':visible'))
$wrapper.hide();
else
$wrapper.show();
As already mentioned, you can use the toggle function to achieve what you want.
To add a bit of extra information, when attaching events like you're doing, you're actually using a subscription model.
Registering an event puts it in a queue of events subscribed to that handler. In this case, when you add the second event to change the CSS, you're adding an event, not overwriting the first one.
Whilst thing isn't actually causing your problem, it's worth being aware of.
I have a problem that happens only on a specific computer(FFX 3.6.13,Windows 7,jQuery 1.4.3).
Sometimes document.ready is fired but when trying to get elements to attach the event handlers,the elements don't exist!
the code goes something like this:
$(function(){
window.initStart = true;
$("#id_of_element").click(function()...);
window.initEnd = $("#id_of_element");
});
the window.initStart/End are there for debugging,sometimes this code runs just fine,but sometimes window.initEnd is just a empty jQuery set(length == 0).
What this means is that document.ready is always fired,but sometimes it is fired before elements are available.
Does anybody had this problem? what could the problem be?
One way that you could try to get around this would be with using .live instead of .click. The following code
$('#idOfDiv').live('click', function() { doStuff(); });
will attach the input function to the click event of everything that is dropped on the page with an id of 'idOfDiv' as soon as it makes it to the page. Whereas .click executes immediately, this should be attached no matter what time the divs make it to the page.
Cheers
There's an article on SitePoint that demonstrates how to sense when certain dom elements are available.
Also I know this is a version specific issue, but if you were on Jquery 1.5 the deferred objects stuff would be useful here.
Here's a snippet of my code:
$(".item").click(function () {
alert("clicked!");
});
And I have (hypothetically; in actuality it's far more complicated) the following on my page:
<img src="1.jpg" />
However, when I click the image, I do not get an alert.
What is my mistake?
Is your selector actually matching anything? Try using the jQuery debug plugin (http://jquery.glyphix.com/) and doing this:
$(".item").debug().click(function() {
alert("clicked!");
});
.debug() will log whatever is matched to the Firebug console (you are using firebug, right? :-) ) without "breaking the chain" so you can use it inline like this.
If that turns out correctly, there may be some issue with the browser navigating to "#" before it can show your alert. Try using the .preventDefault() method on the event object to prevent this behavior:
$(".item").click(function(evt) {
evt.preventDefault();
alert("clicked!");
});
First question - are you adding the element to be clicked dynamically? If it is,
you should use the live event since that will take care dynamically created elements.
http://docs.jquery.com/Events/live#typefn
Use bind.
$(".item").bind("click", function(e) { ... });
modifying the selector?
$(".item > img")
I had this problem recently after adding a context menu jquery plugin. The pluging was binding to the click event of the body and then unbinding click event - it seemed to remove all bindings to click event for all elements. Maybe a suggestion to turn off plugins or check you're not unbinding click for a parent element yourself.
The code you have posted is correct, so I suspect there's something else going on that you haven't considered.
Firstly, if there was an error somewhere (even not in that exact bit of code) that might cause it to stop working. Put an alert just after this line to check that it runs.
Check that no other elements are catching the event and stopping it from propagating. This has bitten me before in the past... If there's anything else handling a click which has stopPropagation() or return false in it, that might be the problem.
One thing I've found (though only with links going elsewhere) is that adding return false; in may help, if it's just firing the anchor off instead of evaluating the alert. I can't really say why this would be the case, but that's a solution I found to a similar problem recently.