Question

This is my page which contains both HTML and Javascript code. No matter how I set the initial value of the ID, it only works once. Which I find very strange!

<!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <!--<meta http-equiv="refresh" content="30" />-->
      <title>Relay Trigger</title>

      <script src="//code.jquery.com/jquery-1.10.2.js"></script>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js></script>
    </head>
    <body>    
    <div id="button">
        <button id="off">OFF</button>
    </div>

    <script type="text/javascript">
    $(document).ready(function(){
    $("#on").click(function(){
        document.getElementById("on").innerHTML="OFF";
        document.getElementById("on").id="off";
        alert(document.getElementById("button").innerHTML)
      });

    $("#off").click(function(){
        document.getElementById("off").innerHTML="ON";
        document.getElementById("off").id="on";
        alert(document.getElementById("button").innerHTML)
      });
    })
    </script>

    </body>
</html>
Was it helpful?

Solution

When you use $("#on").click(function(){/*...*/}, there isn't any element with id on. Then, that event handler isn't attached.

Moreover, when you use $("#off").click(function(){/*...*/}, you add the event handler to the element that, in that moment, has the id off. It doesn't matter if the id changes, the element is still the same and still has the same event handler.

To get the functionality you want, you can use event delegation to an ancestor with a filtering selector:

$("#button")
  .on('click', '#on', function(){
    document.getElementById("on").innerHTML="OFF";
    document.getElementById("on").id="off";
    alert(document.getElementById("button").innerHTML)
  })
  .on('click', '#off', function(){
    document.getElementById("off").innerHTML="ON";
    document.getElementById("off").id="on";
    alert(document.getElementById("button").innerHTML)
  });

Note this can be several times slower.

But a better alternative would be using id="myButton" data-state="off", and

$('#myButton').on('click', function() {
    var state = $(this).data('state');
    $(this).data('state', state==='on' ? 'off' : 'on');
    state = state.toUpperCase();
    $(this).html(state);
    alert(state);
});

OTHER TIPS

Try using a class instead, ID's should not be used like this.

The reason it happens is because when you registered the event handlers - the #on actually did nothing because there was no #on element in the document in that time

You have 2 options here:

  1. set the handler only after you change the id:

    <script type="text/javascript">
    $(document).ready(function(){
    
    $("#off").click(function(){
        document.getElementById("off").innerHTML="ON";
        document.getElementById("off").id="on";
        alert(document.getElementById("button").innerHTML)
    

    $("#on").click(function(){ document.getElementById("on").innerHTML="OFF"; document.getElementById("on").id="off"; alert(document.getElementById("button").innerHTML) }); }); })

  2. use "live" behavior: the live function of jQuery is deprecated - but you can do it by doing:

instead of

$("#on").click(function);

write

$(document).on("click","#on",function);

You're missing a " in your script src.
All you need is

LIVE DEMO

$(function(){ // DOM ready

  $("#on, #off").click(function(){
    var io = this.io ^= 1; // Toggler used as 1/0 boolean
    $(this).text(io?"ON":"OFF").prop('id', io?"on":"off");
  });

});

So inside this simple click function if you need to do more stuff depending on the stored io object value you can do:

PLAYGROUND

if(io){
   // do additional stuff if "on"
}else{
   // do additional stuff if "off"
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top