Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

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]):

<!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>

Open in new window


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:

<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>

Open in new window


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.function(){
$("#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?
SOLUTION
Avatar of Manuel Marienne-Duchêne
Manuel Marienne-Duchêne
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thats why we use jQuery and use ready function and make sure our code runs after page is fully loaded...

<script>
$(document).ready(function() {
  // page is fully loaded at this moment...
});
</script>

Open in new window

Avatar of Bruce Gust

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.function(){
$("#div1").load("demo_text.txt");
});

...correct?
...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?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Julian Hansen
Let's work through this
A) I am assuming this is a typo
function(selectFunction() {
$("#div1").load("demo_text.txt");
}

Open in new window

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>

Open in new window


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!';

Open in new window

And later in your document you have
<div id="fred"></div>

Open in new window

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!';
});

Open in new window

Now our code works wherever it is declared.

We can do a similar thing in jQuery with
$(document).ready(function() {
   ....
});

Open in new window

Or the less verbose version
$(function() {
});

Open in new window

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.
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?
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");
}

Open in new window


this code can work inside/outside "$(document).ready(function() {...}" wihout any issue since it will run on select change after the DOM is ready...

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!');
}

Open in new window

This will work - as will this
$(function() {
   $('select').change(function() {
       externalFn();
   });
  function externalFn()
  {
    alert('Hi There!');
  }
});

Open in new window

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()">

Open in new window

This only has access to functions in the global scope in other words
var 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

Open in new window

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)
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?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial