javascript - jQuery on/off method for click event fails from external script -


this works when script embedded. why work 2 clicks when code in external script?

embedded case:

<html>     <head>   <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> </head>     <body>   <h1 id="title" onclick="saygoodbye();"> hello </h1> </body>     <script type="text/javascript">   function saygoodbye() {     console.log("goodbye");     $("#title").html("goodbye");     $("#title").click(function() {       $("#title").html("hello");       $("#title").off("click");     });   }; </script>     </html> 

external file tested follows:

<body>   <h1 id="title"> hello </h1> </body> 

external javascript file:

function saygoodbye() {   console.log('goodbye');   $('#title').html('goodbye');   $('#title').click(function() {     $('#title').html('hello');     $('#title').off('click');   }); };  $(function(){    $('#title').on('click', saygoodbye); }); 

the problem has nothing file being external or embedded.

you've changed code, , that's why stopped working. keep html code identical original 1 <h1 id="title" onclick="saygoodbye();"> hello </h1>.

since you've changed, that's reason it's not working anymore.

when adding event listeners via javascript's addeventlistener or jquery's on, must pass function reference, , never function execution. if use (), function called immediately, , returned value of passed other function you're calling.

for example, if that:

function num() {   return 5; }  console.log(num);   // log 'function num()' console.log(num()); // log 5 

since saygoodbye function returns nothing, value passed jquery's on undefined.

function num() {    var y = 5;    y = y + 10; }  console.log(num);   // log 'function num() ' console.log(num()); // log 'undefined' 

when put in html onclick="saygoodbye();", you're in fact saying:

element.onclick = function() {   saygoodbye(); } 

it automatically wrap code anonymous function, , pass reference event.


tl;dr

your code isn't working because you're using:

$('#title').on('click', saygoodbye()); 

which evaluates/calls function immediately, because parenthesis present.

instead, should supply callback function name:

$('#title').on('click', saygoodbye); 

or anonymous function:

$('#title').on('click', function() {   saygoodbye(); }); 

update

after changing question, seems simple problem.

where defining <script src="externalscript.js"></script>?

you should placing @ same place embedded 1 was. if you've put head tag, evaluated before h1#test loaded, , then, won't find element, , don't add event listener it.

but if want/need put inside head tag, then, must wrap code load event listener. if using vanilla javascript, be:

document.addeventlistener('domcontentloaded', function() {   // code }); 

but since you're using jquery, can use $(document).ready:

$(document).ready(function() {   // code }); 

and there shorthand it, that's wrap $();:

$(function() {   // code }); 

note: i've realised biggest problem here don't understand difference between doing <h1 id="title" onclick="saygoodbye();"> hello </h1>, , adding event handler through jquery.

your first example working way expected, because when do:

$("#title").html("goodbye"); $("#title").click(function() {   $("#title").html("hello");   $("#title").off("click"); }); 

you're saying:

  1. change innerhtml property of element id title 'goodbye'
  2. add click event handler that:

    2.1 change innerhtml property of element id title 'hello'

    2.2 remove jquery event handlers event click

so, going happen:

  1. when click first time

    1.1 h1 change 'goodbye'

    1.2 , there new click event handler it

  2. when click second time

    2.1 fire same event again firstly, h1 change 'goodbye'

    2.2 there new click event handler it

    2.3 event handler added on 1.2 fired

    2.4 then, h1 change hello

    2.5 , remove jquery click event handlers of it

so, when click third time, when page loaded, because event handler placed html code still remains, jquery event handlers attached h1 removed.

that said, 3rd same 1st, 4th same 2nd, , on.


when stop attaching event handler html code, , start attaching through jquery, code stops working because:

  1. when click first time

    1.1 h1 change 'goodbye'

    1.2 , there new click event handler it

  2. when click second time

    2.1 fire same event again firstly, h1 change 'goodbye'

    2.2 there new click event handler it

    2.3 event handler added on 1.2 fired

    2.4 then, h1 change hello

    2.5 , remove click event handlers of it

as can see, pretty same example above. there 1 big difference: when 2.5 happens, don't have click event handlers attached h1 anymore, since you've removed of them there.

that happens, because when pass 1 parameter jquery's off method, you're saying "remove jquery's event handlers type of event" (in case, click). so, remove both event handler attached saygoodbye , 1 you've created anonymous function.

in first example, doesn't happen, because jquery doesn't know event you've attached via html code, never removes it, , code works way expect.

so, if want work jquery only, code should like:

$(function(){   function saygoodbye() {     $('#title')       .html('goodbye')       .off('click', saygoodbye)       .on('click', sayhello);   }    function sayhello() {     $('#title')       .html('hello')       .off('click', sayhello)       .on('click', saygoodbye);   }    $('#title').on('click', saygoodbye); }); 

Comments