Click handler fired only once - javascript

I have a set of links that I iterate over and add click handlers. Each link when clicked, fires an ajax request which upon success creates a div containing response data, and appends it to the DOM. The newly appended div (a floating div similar to a small lightbox) however, is removed when the user clicks close(on the div) or clicks anywhere else on the screen. I have a simple script below to monitor this change, but the click handler fires only once and does not work until after a page refresh. What am I doing incorrectly?
var monitorChange = function () {
//Check if div has been appended to the dom and if so continue to monitor it
if ( $('div.justappended').length > 0 )
{
setTimeout(monitorChange,100);
}
else
{
//div has been removed from the dom
alert('div removed');
//...do additional stuff here
}
};
$( 'span.someElements' ).each( function () {
var that = $(this);
$(that).click( monitorChange );
});

From what I understand, you are looking to have your on click event still work with ajax generated code. You need to use the live command in this case. http://api.jquery.com/live/
$('span.someElements').live('click', monitorChange);

Related

onClick function used on dynamic content not working properly

I hit a problem with the onclick function when i add divs with ids like "n_block"+(1-~). When I use the jquery zoom function on the objects to make them smaller or bigger onClick doesn't work anymore. I'm not really good at programming so the code might be kind of confusing.
Heres the code i use for the onClick of items:
$(document).on("click",function (e, ui){
//When the document gets clicked, check if one of the items was clicked.
if($(e.target).is($("#n_block" + cloneCount1)) || $(e.target).is($("#n_block" + cloneCount1+ " span"))){
//Set current item.
var item = $("#n_block" + cloneCount1);
//Set style to current item.
item.css("border-color", "Black");
item.css("border-width","2px");
item.css("background-color", "floralwhite");
jsPlumb.repaintEverything();
//Check if key Delete was pressed while item selected & delete that item with his children.
$('html').keydown(function(e){
if(item.css("border-width")=="2px"){
if(e.keyCode == 46) {
/* Prevents line bugging*/
jsPlumb.detachEveryConnection();
jsPlumb.deleteEveryEndpoint();
var razred = getClass(item, "b_"),
id = item.prop("id");
item.remove();
if(razred == "b_2"){
$(".ovoj."+id).remove();
}
else if (razred == "b_4"){
$(".ovojLoop."+id).remove();
$(".empty_block_c."+id).remove();
}
if ( $('.objects').find('div').length == 2) {
$(".objects").empty();
$(".objects").append('<div class="b_s" id="start_block">START</div><p id="start_text">Insert symbols here!</p><div class="b_s" id="end_block">STOP</div> ');
}else{
/* Connects objects together with line. ****/
povezi(cloneCount, tip_crte, ".objects");
}
}
jsPlumb.repaintEverything();
}
});
}
// If item is not clicked set this css to the current item.
else{
$("#n_block" + cloneCount1).css("border-width","1px");
jsPlumb.repaintEverything();
}
});
And heres the zoom code for zooming in when button is clicked:
var currentZoom = 1.0;
$(".zoomin").click(function (){
//Detaches the connections from item to item.
jsPlumb.detachEveryConnection();
jsPlumb.deleteEveryEndpoint();
//Prevents spamming of button, animates the objects
$(".project").stop().animate({ "zoom": currentZoom += .1}, "slow", function() {
if(!$(".objects").children().is($("p"))){
povezi(cloneCount, tip_crte, ".objects");
}
});
});
Use event delegation for binding events to dynamically added elements.
$(document).on('click', ".zoomin", function (){
//Your code.
});
When you use normal .click() to bind event to an element, then that even gets bound to only those elements which exist in the DOM at the moment of the execution of code. Using event delegation, you can tell jQuery that we need to add the handler to every '.zoomin' element which comes inside a particular element no matter when it is added.
The solution depends when exactly is the script which tries to bind the events are executed.
For Eg: Lets assume this script is in document ready function of jquery
$(document).ready(function(){
$(".zoomin").click(function (){
//your logic here
});
});
Here this script is executed when the page HTML is completed loading into the browser. Now when the script executes it tries to find a element with the class zoomin and if found it will add a event to that element and move on. If the element is not found the script just moves on. So we should actually take care of when the script is executed and is the intended element available at that particular instant of time. If the element is not yet available in the HTML (element might come in later dynamically using jquery) we have 2 options to bind event to the element.
1) Execute the script when the element is being added into the HTML: Lets say I have a event which brings up a pop up with some image. Now I want to zoomin and zoomout the image. Since the image in the popup is added dynamically and I have control of when its being added, I can do this.
$(document).ready(function(){
$('.ViewImage').on('click',function(){
// some code is executed which brings up the popup
// now we know that the image is added into html we can now run the script
$(".zoomin").click(function (){
//your logic here
});
});
});
2) We have no Clue/ Control when the element is added into HTML but still want to bind a event to it: This is scenario where we have no control on when the element is being added or not sure where it is being added from (might be from some external plugin used etc) or not having control at all on the element which is added. Thats when we use this syntax as suggested by #Rejith R Krishnan
$(document).on('click', ".zoomin", function (){
//Your code.
});
This will work on all the elements which are in the HTML at the time of execution of the script and on the elements which will be added in the future with the class name zoomin. So this script can be placed inside/ outside of jquery document ready event

Which Click event handler is to use when changing the content dynamically in jQuery?

I have a small application in jQuery, which takes the href value of an anchor element and inserts that as a div's Id. The div is a basic popup window which is only visible if it's triggered.
The popup window on gets triggered if a anchor tag gets clicked with the same href value as the id of the popup div.
HTML Code:
Item 1
Item 2
Item 3
<div class="popup"></div>
jQuery Code:
var items = ["#item1", "#item2", "#item3"];
$.each(items, function()
{
$(document).on("click", this, function(e)
{
e.preventDefault();
var href = $(this).attr("href");
var length = href.length;
var anchor = href.substring(1, length);
var popup = $(".popup").attr("id", anchor);
});
});
Problem:
The popup window should be triggered once the client clicks on any of the anchors above. However it only gets triggered, on the second click. I guess the first one sets the Id and the second opens is, with the set value.
I have also tried to use another type of click event and it worked for the first click. The event, which have been working was:
$(this).on("click", function(e)
{
// Stuff goes here as above
});
My problem is that I cannot use this type of event handler, because I will be changing the content of the anchor href's dynamically with jQuery.
Question:
How is it possilbe to make the original code working as I expect, so the client should only click once to the anchor tag to get the popup window? Anything else I should consider as well?
$('#item1').on("click", function(e)
{
// Stuff goes here as above
});
$('#item2').on("click", function(e)
{
// Stuff goes here as above
});

jquery code not executing from script, but executing from dev panel

http://www.henrybuilt.com/trade2/resource.php?id=100
Check out the link above. Login: asdf, asdf
EDIT: Click on bamboo on the link above once you've logged in. Thanks.
The following code (which toggles a 'popup' window (div)) won't execute on the page, but will work when copied and pasted in the dev panel.
$(".maintypedata img").click(function() {
console.log("test");
if(open == false) {
var src = $(this).attr("src");
$(".popup").html("<img src='"+src+"'/>");
open = true;
$(this).addClass("selected");
$(".popup").slideFadeToggle(function() {
});
}
});
How can I make it run from the script?
The click handler you've shown is bound to any ".maintypedata img" elements that exist when that code runs. But, the img elements in question are appended to the document dynamically after the "Bamboo" option is clicked. So you need to either run that .click() code after the elements are appended (which is what you were doing by running it from the console) or change it to work as a delegated event handler:
$(".maintypedata").on("click", "img", function() {
console.log("test");
if(open == false) {
var src = $(this).attr("src");
$(".popup").html("<img src='"+src+"'/>");
open = true;
$(this).addClass("selected");
$(".popup").slideFadeToggle(function() {
});
}
});
That is, bind the click handler to an element that exists initially, in this case ".maintypedata", but specify a selector in the second parameter to .on() and jQuery will only run your handler if the clicked item matches that second select at the time of the event.
(A delegated handler is also more efficient than binding the same handler to lots of separate elements, but that's just an added bonus.)

JQuery Event repeating in dynamic content

In a page of a website I'm making, the press of a button imports the contents of a another php page and appends it onto the page. However, that other page contains JQuery, and the click event($( ".ExpandRoleButton").click) repeats itself on previous elements every time I import the content. So if I add 3 elements;
Element 1: Repeats the click event 3 times
Element 2: Repeats the click event 2 times
Element 3: Runs the click event once
$("#AjouterPiece").click(function()
{
$.blockUI({ message: '<img src="images/ChargementGeant.gif"/><br/><h1>Un moment svp.</h1>' });
$.post("wizardincl/piste.php", {newPiste: newPiste}, function(data)
{
$("#wizardPistes").append(data);
$.unblockUI();
$(".divNewPiste").fadeTo(300, 1);
$("#nbExemplaires").attr("max", newPiste);
newPiste++
$( ".ExpandRoleButton").click(function()
{
if ($(this).hasClass('RetractRoleButton'))
{
$(this).find('img').attr('src', 'images/ExpandPetitNoir.png');
var that = $(this);
$(this).parent().parent().parent().parent().next().slideUp(500, function() {
that.parent().parent().parent().parent().css('border-bottom', '1px solid #FF790B');
});
$(this).removeClass('RetractRoleButton');
}
else
{
$(this).parent().parent().parent().parent().css('border-bottom', 'none');
$(this).find('img').attr('src', 'images/ExpandPetitNoirRetour.png');
$(this).parent().parent().parent().parent().next().slideDown(500);
$(this).addClass('RetractRoleButton');
}
});
});
});
Currently, part of the JQuery website seems down and after some search, I can't find anything to solve the problem. Is there any way to keep the code from repeating itself like this?
This is because you are binding the event to multiple event handlers. The first time #AjouterPiece is clicked, all .ExpandRoleButton buttons get binded to an onclick handler.
The next time #AjouterPiece is clicked, it gets binded again.
To prevent this, you must unbind the click handlers using the following code before binding it
$( ".ExpandRoleButton").unbind('click')
You can pass in the event with .click(function(e) {...}) and then call e.stopImmediatePropagation() to fire only the current handler, but that only addresses the symptom, not the real problem.
Edit: make sure you are only binding the new instance of the button by adding a context to your selector, like $('.ExpandRoleButton', data). Since you are matching on a class, that selector will grab all the buttons on the page; the context allows you to select only the one inside your result.
A good practice ( solely to prevent issues like this from occurring, unintended multiple click handlers added ) is to..
$(".selector").off('click').on('click', function...
or
$(".selector").unbind('click')...
$(".selector").bind('click')...

Infinite Scroll + .on() function trouble

I'm trying to have dynamically loaded content (via the Infinite Scroll script: http://www.infinite-scroll.com/ ) be styled when triggered by an "inview" custom event ( https://github.com/protonet/jquery.inview ).
My code looks like this:
$(document).on("inview", ".attachment-portfoliosmall", function(e) {
if( $.data( this, "styleappended" ) ) {
return true;
}
$.data( this, "styleappended", true );
$(".attachment-portfoliosmall").css('visibility','visible').hide().fadeIn('slow');
$(".attachment-portfoliosmall").parent(".portfoliopreload").css("background", "none");
});
As you can clearly see, the $.data routine is used in order to ensure that the .on() event handler isn't executed more than once for each element in the selection filter.
This code works great in theory, EXCEPT that once the dynamically loaded content on the next page is appended to the document, the .on() routine is being run on every single element a second time, rather than just the newly added elements.
On my website, if you scroll to the next page, you will see all the elements fade out and back in again, which is caused by the .on() event handler.
How can I prevent it from being executed on the previously handled elements on the previous page(s)?
here's what I mean in my comment.
$(document).on("inview", ".attachment-portfoliosmall", function(e) {
var $this = $(this);
if(!$this.hasClass('loaded')) {
$this.addClass('loaded');
$this.css('visibility','visible').hide().fadeIn('slow');
$this.parent(".portfoliopreload").css("background", "none");
}
});
Something like that might work for you.

Categories

Resources