Reputation: 39
[EDIT: I tried to put only the relevant portion of my code here. I understand that led to confusion. Sorry about that. Here is a snippet I could create causing the same issue. Adding the snippet here:]
Once snippet is loaded, click on the button.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello">
Some text
<script>
jQuery(document).ready(function () {
func();
});
var a = 5;
function func() {
alert("Value is FIVE. Integer value: " +a);
}
</script>
</div>
<div id="mybtn" style="border: 2px solid black; padding:5px; background-color: yellow; width: 100px">CLICK</div>
<script>
var data = " \
Some text2 \
<script> \
jQuery(document).ready(function () { \
func(); \
}); \
var a = 6; \
function func() { \
alert('Value is SIX. Integer value: ' +a); \
} \
<\/script> ";
$('#mybtn').on('click', function(e) {
$('#hello').html(data);
});
</script>
I expected to see SIX 6 (or maybe FIVE 5) on clicking the button. But see SIX 5. Interesting that the new function is being called but old value (5) is being used. In my actual code, I had my func() way below where I was calling it and was also calling it in a settimeout(func... ). Trying to understand what is happening.
Upvotes: 3
Views: 2602
Reputation: 34178
This has to do with the JavaScript parsing and execution of the new script on the page. When the function executions, when the NEW document ready triggers the func execution the OLD values are still in place.
To detail, these occur in sequence (roughly)
a
value still in place (the 5)a
value is replaced with the NEW value of 6 (no further calls with the NEW value are executedSee here how I changed the snippet. I added two alert('a:'+a);\
in your code. NOW execute it an you see the sequence of alerts:
The SECOND one alerts the 6 after it has changed.
var data = " \
Some text2 \
<script> \
jQuery(document).ready(function () { \
func(); \
}); \
alert('a:'+a);\
var a = 6; \
alert('a:'+a);\
function func() { \
alert('Value is SIX. Integer value: ' +a); \
} \
<\/script> ";
$('#mybtn').on('click', function(e) {
$('#hello').html(data);
console.dir($('#hello').html());
});
NOTE:
Move this var a = 6; \
BEFORE the document ready in the string and it gets executed first.
Think of that as if you had this:
var a = 6; \
func(); \
EDIT2: document ready
Review the jQuery source; when $(document).ready()
fires the first time, it will unbind from the functions that were previously registered (e.g. forgetting them). As such, calling jQuery.ready()
manually (like you have) a second time does not re-trigger the same function calls again. SO you do not really need that wrapper in script loaded after it has fired on a page as it simply does an immediate execution of the code inside the NEW document ready since your NEW bound function executes then is unbound.
Upvotes: 1
Reputation: 42054
UPDATE
According to the changes in the question the new problem is the position where you declare the new value for the variable a.
Because:
jQuery(document).ready(function () {
executes the code when document is ready, and because your document is already ready when you substitute the html of hello element, on the first click you get the value 5 and only after you get the new value. From the second time, because the html is changed, when you click you activate just the ready function. The solution is to declare the variable a in the data string immediately before the document ready.
You may use the added button "describe function" to see by yourself the content of the script contained in the hello div.
To better understand I added a string as a parameter to your func function in order to understand how and when it's called.
Updated snippet:
$(document).on('click', '#btn2', function (e) {
$('body').append('<br>var a is: ' + a + ' func() is: ' + func.toString())
.append('<br><div style="border: double;">hello HTML: ' + $('#hello')[0].outerHTML.replace(/</g, '<')
.replace(/>/g, '>') + '</div>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello">
Some text
<script>
jQuery(document).ready(function () {
func("inside ready");
});
var a = 5;
function func(str) {
alert("FIRST: " + str + " Value is FIVE. Integer value: " +a);
}
</script>
</div>
<div id="mybtn" style="border: 2px solid black; padding:5px; background-color: yellow; width: 100px">CLICK</div>
<script>
var data = " \
Some text2 \
<script> \
var a = 6; /* HERE!!!!!!!!!!!!!!*/\
jQuery(document).ready(function () { \
func('inside second ready'); \
}); \
function func(str) { \
alert('SECOND: ' + str + ' Value is SIX. Integer value: ' +a); \
} \
<\/script> ";
$('#mybtn').on('click', function(e) {
$('#hello').html(data);
});
</script>
<button id="btn2">Describe function</button>
I created and tested a possible similiar situation, and it works for me:
$(function () {
var newcode = '<script>' +
'var var1 = 3;' +
'function func() {' +
' console.log("VALA is 4");' +
' console.log("VALB is " + var1);' +
'}';
$('#btn1').on('click', function (e) {
$.getJSON('https://api.github.com/users', function(data) {
$('#box1').html(newcode);
});
});
$('#btn2').on('click', function (e) {
func();
$('body').append('<br>var var1 is: ' + var1 + ' func() is: ' + func.toString());
});
});
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<div id="box1">
<script>
var var1 = 2;
function func() {
console.log("VALA is 1");
console.log("VALB is " + var1);
}
</script>
</div>
<button id="btn1">Simulate Ajax Call</button>
<button id="btn2">Call function</button>
Upvotes: 1