Bruce Gust
asked on
Quick AJAX question...
I"m starting in the shallow end of the pool here and trying to work my way into some more complicated / practical usages of AJAX.
I'm using this as a starting point (W3 Schools [https://www.w3schools.com/jquery/jquery_ajax_load.asp]):
Because of the project I'm working on, I wanted to take this same example, but use a <select> to trigger the code.
I tried this:
<select onchange="selectFunction() ">
<option></option>
<option>change text</option>
</select>
...with the new Javascript being:
function(selectFunction() {
$("#div1").load("demo_text .txt");
}
It worked, but only if I put the JavaScript code at the bottom of the page. Prior to that I was getting an error that said "selectFunction is undefined."
Here's the code:
Based on my limited understanding of JavaScript, it's not uncommon to get these types of errors if the script goes looking for an id or a div and the page hasn't completed loading yet. THAT is why I get the error that says "selectFunction is undefined."
On the other hand, if I code it like this:
$("#mySelect").change.func tion(){
$("#div1").load("demo_text .txt");
});
...it works just fine.
The reason - and tell me if I'm accurate - is because when you code it that way, you're now using the XMLHttpRequestObject and benefiting from the AJAX dynamic. Beforehand, you were simply coding it using JavaScript and things were getting lost prior to the page being loaded.
Correct?
I'm using this as a starting point (W3 Schools [https://www.w3schools.com/jquery/jquery_ajax_load.asp]):
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("#div1").load("demo_test.txt");
});
});
</script>
</head>
<body>
<div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
<button>Get External Content</button>
</body>
</html>
Because of the project I'm working on, I wanted to take this same example, but use a <select> to trigger the code.
I tried this:
<select onchange="selectFunction()
<option></option>
<option>change text</option>
</select>
...with the new Javascript being:
function(selectFunction() {
$("#div1").load("demo_text
}
It worked, but only if I put the JavaScript code at the bottom of the page. Prior to that I was getting an error that said "selectFunction is undefined."
Here's the code:
<html>
<head>
<title>Health Summary</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<style>
body {
font-family: Arial, Helvetica;
font-size:12pt;
}
</style>
</head>
<script>
$(document).ready(function() {
function selectFunction() {
$("#div1").load("demo_text.txt");
}
});
</script>
<html>
<body>
<div id="div1">and...</div>
<br><br>
<select id="mySelect" onchange="selectFunction()">
<option></option>
<option>change text</option>
</select>
</body>
<html>
Based on my limited understanding of JavaScript, it's not uncommon to get these types of errors if the script goes looking for an id or a div and the page hasn't completed loading yet. THAT is why I get the error that says "selectFunction is undefined."
On the other hand, if I code it like this:
$("#mySelect").change.func
$("#div1").load("demo_text
});
...it works just fine.
The reason - and tell me if I'm accurate - is because when you code it that way, you're now using the XMLHttpRequestObject and benefiting from the AJAX dynamic. Beforehand, you were simply coding it using JavaScript and things were getting lost prior to the page being loaded.
Correct?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I've not doubt that works, but what I'm trying to confirm is my understanding as to why it DIDN'T work to begin with. Apart from coding it using JQuery and the AJAX dynamic, I'm reloading the page. If I want to avoid that altogether, I have to code it using this:
$("#mySelect").change.func tion(){
$("#div1").load("demo_text .txt");
});
...correct?
$("#mySelect").change.func
$("#div1").load("demo_text
});
...correct?
ASKER
...because even when I code it like this:
<script>
$(document).ready(function () {
function selectFunction() {
$("#div1").load("demo_text .txt");
}
});
</script>
<html>
<body>
<div id="div1">and...</div>
<br><br>
<select id="mySelect" onchange="selectFunction() ">
<option></option>
<option>change text</option>
</select>
</body>
<html>
I still got an error. Even with "document.ready...", you still have to use JQuery and the built in XMLRequestObject for this to work.
Right?
<script>
$(document).ready(function
function selectFunction() {
$("#div1").load("demo_text
}
});
</script>
<html>
<body>
<div id="div1">and...</div>
<br><br>
<select id="mySelect" onchange="selectFunction()
<option></option>
<option>change text</option>
</select>
</body>
<html>
I still got an error. Even with "document.ready...", you still have to use JQuery and the built in XMLRequestObject for this to work.
Right?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Let's work through this
A) I am assuming this is a typo
B) this works fine irrespective of where the function goes
Lets look at this in more detail
You correctly hit on the bit about the script running before the html is ready. For instance if you do this
To get around this we can place the script after the <div> and the script will work - however it is leaving the door open for some nasties to walk in later on in development.
So what we do is we put script that is dependent on document structure into a document ready.
In JavaScript this would be something like this
We can do a similar thing in jQuery with
The use of jQuery on it's own does not make the code run differently with respect to Document load - only the above methods have an effect.
Now back to your code. This is slightly different because you are binding an event handler (onChange) as an attribute on the element. This calls a function.
Now document ready is no longer needed because when the onChange event fires it will be because the <select> has been defined - it calls a function only on the firing of that event so where / when the function is declared is basically irrelevant. You can declare the function inside or outside of a document ready - it makes no difference. Outside is probably better.
Hopefully that clears up some of the misconceptions.
A) I am assuming this is a typo
function(selectFunction() {
$("#div1").load("demo_text.txt");
}
If not then it is invalid code and the cause of your error - probably a manifestation of some partial understanding of what is going on.B) this works fine irrespective of where the function goes
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("#div1").load("demo_test.txt");
});
});
function selectFunction() {
$("#div1").load("demo_text.txt");
}
</script>
</head>
<body>
<div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
<button>Get External Content</button>
<select onchange="selectFunction()">
<option></option>
<option>change text</option>
</select>
</body>
</html>
Lets look at this in more detail
You correctly hit on the bit about the script running before the html is ready. For instance if you do this
document.getElementById('fred').innerHTML = 'Boo!';
And later in your document you have <div id="fred"></div>
You are going to get an undefined because the browser calls it as it sees it - so the script runs immediately and no div so undefined.To get around this we can place the script after the <div> and the script will work - however it is leaving the door open for some nasties to walk in later on in development.
So what we do is we put script that is dependent on document structure into a document ready.
In JavaScript this would be something like this
window.addEventListener('load', function() {
document.getElementById('fred').innerHTML = 'Boo!';
});
Now our code works wherever it is declared.We can do a similar thing in jQuery with
$(document).ready(function() {
....
});
Or the less verbose version$(function() {
});
In either case any of the document ready's can have JavaScript or jQuery code.The use of jQuery on it's own does not make the code run differently with respect to Document load - only the above methods have an effect.
Now back to your code. This is slightly different because you are binding an event handler (onChange) as an attribute on the element. This calls a function.
Now document ready is no longer needed because when the onChange event fires it will be because the <select> has been defined - it calls a function only on the firing of that event so where / when the function is declared is basically irrelevant. You can declare the function inside or outside of a document ready - it makes no difference. Outside is probably better.
Hopefully that clears up some of the misconceptions.
ASKER
Julian! I went back and looked at my code and the thing that made the difference was putting the:
function selectFunction() {
$("#div1").load("demo_text .txt");
}
OUTSIDE the $(document).ready(function () {
If it was inside, it failed and I got an error. If it was outside, it worked just fine.
Why?
function selectFunction() {
$("#div1").load("demo_text
}
OUTSIDE the $(document).ready(function
If it was inside, it failed and I got an error. If it was outside, it worked just fine.
Why?
If it was inside, it failed and I got an error. If it was outside, it worked just fine.
function selectFunction() {
$("#div1").load("demo_text.txt");
}
this code can work inside/outside "$(document).ready(functio
and you should not get any error unless you miss brackets or some copy paste errors...
When you create a function inside $(document).ready, it's guaranteed that it won't be called before the document has loaded. Of course, it can only be called from that event handler itself (somewhere later in the event handler).
f it was inside, it failed and I got an error. If it was outside, it worked just fine.This has to do with scoping. I may have erred in my explanation.
If you have this setup
$(function() {
$('select').change(function() {
externalFn();
});
});
function externalFn()
{
alert('Hi There!');
}
This will work - as will this$(function() {
$('select').change(function() {
externalFn();
});
function externalFn()
{
alert('Hi There!');
}
});
Reason being the change handler inside the $function is a child scope of the window - where externalFn is defined so it has sight on the function if it is either inside or outside the $(function) - externalFn is global and so visible everywhere.In your scenario when you do this
<select onchange="externalFn()">
This only has access to functions in the global scope in other wordsvar a = 123;
$(function() {
console.log(a); // => 123
console.log(a); // => 123
var b = 100
console.log(b); // => 100
})
console.log(a); // => 123
console.log(b); // => undefined
So short answer - when you put the function inside the $(function you make it part of the $(function() scope which is not visible from outside the $(function - (refer the console.log(b) line 9 above)
ASKER
I get it!
"Scope" would be similar to "Visibility," as far as Public, Private and Protected. Bottom line: It's what your syntax "see" and therefore process.
When I choose to trigger functionality using an inline approach...
<select onchange="selectFunction">
...I need to ensure that "selectFunction" mechanism is available in a global context. In this case I would have to position it outside the $(document).ready(function () for it to be "seen" by the SELECT.
My understanding up to this point was that you use $(document).ready(function () as a good practice to ensure that you're not risking the chance of certain variables and functionality to be referenced prior to the page having fully loaded. While that is true, anything within the $(document).ready(function () fence line is still "local" to that body of code. If I'm attempting to trigger functions that require a global access, I'm going to get an error.
That's why when I moved...
function selectFunction() {
$("#div1").load("demo_text .txt");
}
...outside the $(document).ready(function (), it worked.
Correct?
"Scope" would be similar to "Visibility," as far as Public, Private and Protected. Bottom line: It's what your syntax "see" and therefore process.
When I choose to trigger functionality using an inline approach...
<select onchange="selectFunction">
...I need to ensure that "selectFunction" mechanism is available in a global context. In this case I would have to position it outside the $(document).ready(function
My understanding up to this point was that you use $(document).ready(function
That's why when I moved...
function selectFunction() {
$("#div1").load("demo_text
}
...outside the $(document).ready(function
Correct?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Open in new window