tblznbits
tblznbits

Reputation: 6778

JQuery function not working on element after ID has been changed

I've got a button and I want it to perform one function every odd time that it is clicked (1st, 3rd, 5th, etc) and a second function every even time that it is clicked (2nd, 4th, 6th, etc). I thought the best way to do this would be to change the id of the button and assign two JQuery functions. However, that doesn't seem to work. As you can see in this jsfiddle, when I change the id of the button, the function from the first id still gets called.

  $("#search").click(function() {
    alert("search clicked!");
    $("#search").html("Close Search");
    $("#search").attr("id", "csearch");
  });

  $("#csearch").click(function() {
    alert("csearch clicked!");
    $("#csearch").html("Search");
    $("#csearch").attr("id", "csearch");
  });

Why is that the case? Is it because JQuery essentially binds the function to the button when the document loads, so even though I change the id, the function is still bound?

p.s. I already found another solution to my problem, so I'm not interested in answers in that regard. Just looking to learn a little more about JQuery and Javascript.

Upvotes: 0

Views: 105

Answers (6)

user1684181
user1684181

Reputation: 11

I believe, changing the ID of an element would not be an appropriate idea for this particular scenario. Instead, it's better to use data attributes to accomplish this. For example, Instead of changing the ID, you could change the data attribute value to track it and then you can apply your logic accordingly. This way in future, if you want to add additional behaviour to the button (odd, even and somethingElse), you don't need to write an additional event handler, just need to add one more condition to the same event handler. Going forward, if the behaviours of the button are increasing, you can separate the logic out and put it into one function by passing the behaviour value to it, that way your event handler will be much cleaner and manageable.

Please suggest if anyone has a better solution.

 

$(document).ready(function() {
  $("#search").on("click", function() {
  	var action = $(this).data("action");
    
    if(action === "odd") {
    	$(this).data("action", "even");
      alert("odd");
    }
    else if (action === "even") {
    	$(this).data("action", "odd");
      alert("even");
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div>
  <button id="search" data-action="odd" class="btn btn-default action-button shiny-    bound-input" type="button">
    Search
  </button>
</div>

Upvotes: 0

DinoMyte
DinoMyte

Reputation: 8868

You need to use event delegation, instead of binding when dealing with elements with changing selectors.

$(document).ready(function() {
      $(document).on("click","#search",function() {
        alert("search clicked!");
        $("#search").html("Close Search");
        $("#search").attr("id", "csearch");
      });

      $(document).on("click","#csearch",function() {
        alert("csearch clicked!");
        $("#csearch").html("Search");
        $("#csearch").attr("id", "csearch");
      });
    })

Working example : https://jsfiddle.net/DinoMyte/vxn3ozzb/4/

Upvotes: 0

Marek Woźniak
Marek Woźniak

Reputation: 1786

If you change dynamically data in HTML you have appeal to body, because separator ('#csearch') doesnt exist after load page. Try it:

$(document).ready(function() {
  $('body').on('click','#search', function() {
    alert("search clicked!");
    $("#search").html("Close Search");
    $("#search").attr("id", "csearch");
  });

  $('body').on('click','#csearch', function() {
    alert("csearch clicked!");
    $("#csearch").html("Search");
    $("#csearch").attr("id", "search");
  });
})

Upvotes: 1

fdomn-m
fdomn-m

Reputation: 28611

Look up event delegation - there's plenty of answers on SO that explain it in detail.

As for your solution - just add a data value to the button and toggle it / read it on each click. Then there's no need to change the id, so no need to change the event handler:

$("#search").click(function() {
    var oddeven = $(this).data("oddeven") || 1;
    if (oddeven == 1) {
      alert("search clicked!");
      $(this).html("Close Search");
      $(this).data("oddeven", 2)
    }
    else {
      alert("csearch clicked!");
      $(this).html("Search");
      $(this).data("oddeven", 1)
    }
});

Updated fiddle: https://jsfiddle.net/vxn3ozzb/1/


Alternatively, you could have two buttons and toggle between them:

<button id="search" class="btn btn-default action-button shiny-bound-input" type="button">
  Search
</button>
<button id="csearch" class="btn btn-default action-button shiny-bound-input" type="button" style='display:none'>
  Close Search
</button>

code

$("#search").click(function() {
  alert("search clicked!");
  $(this).hide();
  $("#csearch").show();
});
$("#csearch").click(function() {
  alert("close search clicked!");
  $(this).hide();
  $("#search").show();
});

Fiddle: https://jsfiddle.net/vxn3ozzb/2/

Upvotes: 0

gavgrif
gavgrif

Reputation: 15509

Although you have found another way to go, a nice way to do this is to use the modulus operator (%) which can be used to return a 0 or 1.You could assign a value to the button and on the onclick - pass that value to a function where you check the returned value (ie:var number=value%2) which will give either a 0 if the number is even or a 1 if it is odd. You can then use that to direct the action of the button click - if number ==0 then do this, if it is ==1 then do that.

You then increment the count and reset the value of the button for the next click. That way you do not have to change the id of the button- you just change its behaviour. Just a thought for a method of toggling the effect of a button click :)

Upvotes: 0

Nathan Friend
Nathan Friend

Reputation: 12814

Yes, jQuery will run through your initialization code once, when the document loads, and attach the click handlers to elements currently in the DOM. When your code runs, only the #search element exists - the $("#csearch") selector will match no elements and the click handler won't be assigned to any elements.

A jQuery object references a DOM element by reference, not by id - when you change the id of an element, a jQuery object created previously that pointed to that element will still hold a reference to the element.

Upvotes: 2

Related Questions