Difference between revisions of "JavaScript"

From CSE330 Wiki
Jump to: navigation, search
m (Reverted edits by Shane (Talk) to last revision by Todd)
(Undo revision 1031 by Shane (Talk))
Line 1: Line 1:
= Javascript =
+
JavaScript is the most widely used scripting language for implementing client-side functionality in Web applicationsUnlike PHP, JavaScript code is interpreted and executed in a client's web browser (not on the web server).
Javascript is one of the most widely used scripting languages for preforming client-side functions in the web environmentThat is, the javascript code is interpreted and executed in a client's web browser.. not on the web server.  It is vaguely similar to Java, in that it is an object oriented language, but it was designed to be simpler for non-programmers to be able to accomplish common web processing tasks.
 
  
You should start by reading the w3schools javascript tutorial, which covers most of the important features of the language:
+
== JavaScript?  Did you mean Java? ==
  
http://www.w3schools.com/js/default.asp
+
'''JavaScript''' is a prototype-based programming language focussed on web interactivity.  It was first introduced in Netscape Navigator, and it in turn gave rise to what is now '''[http://www.ecmascript.org/ ECMAScript]'''.  Originally, JavaScript was called "LiveScript".  Sun, the developer of Java at the time, wanted a language that would complement its compiled Java language, and so LiveScript was renamed JavaScript.
  
Another great tutorial can be found at:
+
Beyond that, '''Java and JavaScript are as similar as Ham and Hamster.'''
  
http://www.quirksmode.org/js/contents.html
+
Java and JavaScript have similar syntax, but the under workings are quite different. For example, Java requires strict typing, but JavaScript allows for dynamic typing. Java is object-oriented, but JavaScript is prototype-oriented.  Java is compiled, but JavaScript is interpreted.
  
Since the javascript code runs in the web browser, you'll have to use web browser tools for all debugging.  Generally speaking, if you have syntax or runtime errors in your javascript, the web browser will report nothing but not attempt to run the script.  So if it appears that your code is doing nothing, then it's likely a syntax error of some sort.  Fortunately, in Firefox, you can use the error console to view warnings and errors produced as javascripts are executed.  Go to Tools->Error Console to access it.  This is most useful for simple syntatic debugging.  If you need a more serious debugger, you can use [http://getfirebug.com/ Firebug] for Firefox.
+
== JavaScript Language Components ==
  
=Asynchronous Javascript And XML=
+
This section highlights some features of the JavaScript language that differentiate it from other languages.  For a more comprehensive JavaScript tutorial, the following tutorials are both quality:
AJAX, Asynchronous Javascript And XML, is a group of related web development techniques, standards, and technologies used on the client (web browser) side of the standard web server-client communication model.  Although other languages can be used, the most common is to use javascript to send asynchronous requests to the web server in order to retrieve XML data that the javascript then uses to produce dynamic, fast, user-friendly web pagesThe key idea is that a large fraction of the work happens at the web browser, and larger requests happen behind the scenes, keeping waiting times for data to come back over the network to a minimum.  AJAX is generally also associated with higher-level APIs and libraries that aid in producing cleaner user interfaces for web applications.
 
  
The javascript ''XMLHttpRequest'' object is used to exchange data with the web servers without needing to reload the entire web page in the browserThis ''XMLHttpRequest'' object is now supported by all major browsers, although some browsers implement support in slightly different ways, leading to different behavior of the same code on different platforms.  For this course, you should focus on supporting Firefox, but in any real production website it's very important to do validation testing using all of the major browsers including Firefox, Internet Explorer, Safari, and Opera as a minimum.
+
* [http://docs.webplatform.org/wiki/javascript/tutorials WebPlatform]: Great for learning JavaScript for the first timeAdvocates best practices for modern JavaScript development.
 +
* [http://www.quirksmode.org/js/contents.html QuirksMode]: More advanced than the WebPlatform tutorial, but it thoroughly covers the most powerful aspects of pure JavaScript and gives unparalleled advice on browser compatibility.
  
== XMLHttpRequest Object ==
+
Advice: Do '''NOT''' Google for "JavaScript Tutorial". The first few hits advocate bad or outdated practices.  Stick with the ones listed here.
  
The ''XMLHttpRequest'' object handles communication with the web servers.  To use it, you must first initialize a variable to be an instance of the ''XMLHttpRequest'' class.
+
=== Variables and Scope ===
  
  var xmlHttp;
+
To define a variable in JavaScript, use the '''var''' keyword.
  xmlHttp=new XMLHttpRequest();
 
  
Once you have an ''XMLHttpRequest'', you can use it to send requests to a server. Initially, you need to connect to the server side page you are interested in:
+
<source lang="javascript">
 +
var foo = "bar";
 +
</source>
  
  xmlHttp.open("METHOD","REMOTE_URL", ASYNCRONOUS_FLAG);
+
All variables are objects. In the case above, the variable '''foo''' is an object of the class '''String'''.
  
where METHOD is "GET" or "POST", REMOTE_URL is the page that you are going to send requests to, and ASYNCRONOUS_FLAG is true or false to indicate whether the calls should be made asynchronously or synchronously. In asynchronous communication, the client can do other things while waiting for the server response, whereas in synchronous communication, the client blocks execution and waits until the response comes back before proceeding.  Once the object has been opened, you can then use the ''send'' method to send a request to the server. Note that you do not explicitly set data fields to send, because it is contained in the URL request.
+
Notice that like PHP, you do not have to explicitly define a type for a variable like '''int''' or '''String'''; this is because JavaScript and PHP are ''dynamically typed languages''.
  
  xmlHttp.send(null);
+
JavaScript code can access any variable higher in the “function tree”, but not vice-versa.  This is called '''scope'''. ''All functions create their own scope.''
  
The ''XMLHttpRequest'' object has an attribute, ''readyState'', that stores the current state of the request.
+
When you reference a variable, JavaScript will look up through the "function tree" until it finds the variable you asked for.  This means that you could define variables of the same name as global variables inside of functions. For demonstration of concept:
  
<table class="ex" border="1" width="50%" cellpadding="2" cellspacing="0" id="table7">
+
<source lang="javascript">
<tr><th align="left" width="10%">State</th><th align="left">Description</th></tr>
+
var a = "hello";
<tr><td>0</td><td>The request is not initialized</td></tr>
+
var b = "world";
<tr><td>1</td><td>The request has been set up</td></tr>
 
<tr><td>2</td><td>The request has been sent</td></tr>
 
<tr><td>3</td><td>The request is in process</td></tr>
 
<tr><td>4</td><td>The request is complete</td></tr>
 
</table>
 
  
For example, when a request is sent, the state is set to ''2''.  Every time the state changes, javascript automatically calls a function specified by the ''onreadystatechange'' attribute.  So, before calling a remote site, you should setup a new function:
+
function sayGoodByeWorld(){
 +
var a = "goodbye";
  
xmlHttp.onreadystatechange=function()
+
alert(a); // goodbye
  {
+
alert(b); // world
  alert('state changed to '+xmlHttp.readyState);
+
}
}
+
 
 +
sayGoodByeWorld();
 +
 
 +
alert(a); // hello
 +
</source>
 +
 
 +
=== Object Literals ===
 +
 
 +
A very common way of storing and transporting data in JavaScript is by using objects. You can define an object with certain properties using an '''object literal''':
 +
 
 +
<source lang="javascript">
 +
var apple = {
 +
color: "red",
 +
flavor: "sweet",
 +
season: "autumn"
 +
}
 +
 
 +
alert(apple.color);  // red
 +
</source>
 +
 
 +
=== Functions ===
 +
 
 +
To define a function in JavaScript, use the '''function''' keyword.
 +
 
 +
<source lang="javascript">
 +
function sayHello(){
 +
alert("Hello World");
 +
}
 +
 
 +
sayHello(); // call the function
 +
</source>
 +
 
 +
Pass a parameter to a function like this:
  
This is how asynchronous requests are handled. Once you send a request, you access the response only through the ''onreadystatechange'' function. Meanwhile, your client page can be doing other things. If you are waiting for a response from the server, you should check whether the ''readyState'' is ''4'', corresponding to the request being completed. The server's response is returned as part of the ''XMLHttpRequest' ''responseText'' attribute.
+
<source lang="javascript">
 +
function sayHello(name){
 +
alert("Hello, "+name);
 +
}
  
xmlHttp.onreadystatechange=function()
+
sayHello("Todd"); // call the function and pass an argument
{
+
</source>
  if(xmlHttp.readyState==4)
 
  {
 
    .... do some cool stuff ...
 
  }
 
}
 
  
For example, if you have following html file, server.html:
+
In JavaScript, functions are objects.  This means that they can be assigned to variables, manipulated on the fly, and even passed as arguments to other functions!  As we will see in a couple sections, this is an extremely important feature of JavaScript that makes it such a robust language for web development.
  
<code>
+
If you want to define a scope-specific function, you can assign it to a variable like this:
<pre>
 
hello world
 
</pre>
 
</code>
 
  
This server page just prints the hello world message.
+
<source lang="javascript">
 +
var sayHello = function(){
 +
alert("Hello World");
 +
}
  
Here is an AJAX implementation that gets the message from the server and prints it.
+
sayHello(); // call the function
 +
</source>
  
<code>
+
=== Closures ===
<pre>
 
&lt;html>
 
&lt;body>
 
&lt;script>
 
  var xmlHttp;
 
  xmlHttp=new XMLHttpRequest();
 
  
  xmlHttp.open("GET","server.html",true);
+
A '''closure''' is a way to separate a certain snippet of JavaScript code from the global scope. This is useful if you do not want to "muck up" global variables. Closures are nothing more than anonymous functions that are called as soon as they are created:
  
  xmlHttp.onreadystatechange=function()
+
<source lang="javascript">
  {
+
​var a = "hello";
    if(xmlHttp.readyState==4)
 
    {
 
      var pElement=document.getElementById("msg");
 
      pElement.innerHTML=xmlHttp.responseText;
 
    }
 
  }
 
  
  xmlHttp.send(null);
+
(​​​​function(){
&lt;/script>
+
var b = "world";
&lt;p id="msg">&lt;/p>
+
&lt;/body>
+
alert(a); // hello
&lt;/html>
+
alert(b); // world
 +
})();
  
</pre>
+
alert(a); // hello
</code>
+
alert(b);​ // ReferenceError: b is not defined​​​​​​​​​​​​​​​
 +
</source>
  
==Sending Parameters==
+
Most JavaScript libraries (like jQuery) write all of their code in a closure. What this means is that except for one or two variable names (jQuery or $), everything associated with the library is completely self-contained.
The parameters are sent either in the url (to, for example, a PHP page) or through the ''send'' function.
 
Consider following PHP code that takes two parameters, multiplies them and return the result.
 
  
multiply.php
+
=== Prototypal Inheritance ===
<code>
 
<pre>
 
&lt;? echo $_GET["x"]*$_GET["y"]; ?>
 
</pre>
 
</code>
 
  
We can then use AJAX to get the multiplication of two numbers:
+
JavaScript implements '''prototypal inheritance''', as opposed to a language like Java or C++, which implements '''classical inheritance'''.  JavaScript is one of only a handful of languages implementing prototype-based inheritance.
  
multiply-ajax.php
+
Here's how it works. Every callable object (function) has a '''prototype'''.  When instances of that object are created, their properties and methods are copied (inherited) from the prototype.  Additionally, changes made to the prototype later in the program are "copied" to every instance.
<code>
+
 
<pre>
+
For example, if you wanted to make a method on all strings that added a “!”, you could modify String’s prototype:
&lt;html>
 
&lt;body>
 
&lt;script>
 
function multiply ()
 
{
 
  var xmlHttp;
 
  xmlHttp=new XMLHttpRequest();
 
  var x,y;
 
  x=document.getElementById("input_x").value;
 
  y=document.getElementById("input_y").value;
 
  xmlHttp.open("GET","multiply.php?x="+x+"&y="+y,true);
 
  
  xmlHttp.onreadystatechange=function()
+
<source lang="javascript">
  {
+
String.prototype.bang = function(){
    if(xmlHttp.readyState==4)
+
return this+"!"; // Notice: the context is the instance itself
    {
 
      var pElement=document.getElementById("msg");
 
      pElement.innerHTML=xmlHttp.responseText;
 
    }
 
  }
 
  xmlHttp.send(null);
 
 
}
 
}
&lt;/script>
 
x:&lt;input id="input_x" type="text"/ >&lt;br>
 
y:&lt;input id="input_y" type="text"/>&nbsp;&nbsp;
 
&lt;a href="javascript:multiply();">Multiply&lt;/a>
 
&lt;br>
 
------------------------&lt;/br>
 
Result:
 
&lt;p id="msg">&lt;/p>
 
&lt;/body>
 
&lt;/html>
 
</pre>
 
</code>
 
  
Note that the x and y values are sent as part of the url as GET parameters. You can also send them as part of the ''send'' function, provided that your receiving page uses POST parameters.
+
alert("Hello".bang()); // alerts Hello!
 +
</source>
  
multiply-post.php
+
To "extend" an object, just copy its prototype to a new object.  However, since classical inheritance and prototypal inheritance are different concepts, copying prototypes may have results that you don't expect.  [http://beej.us/blog/data/javascript-prototypes-inheritance/ This article] seems to have a pretty good explanation with example implementations.
<code>
 
<pre>
 
&lt;? echo $_POST["x"]*$_POST["y"]; ?>
 
</pre>
 
</code>
 
  
multiply-ajax-post.php
+
=== Context ===
<code>
+
 
<pre>
+
Every function is called on a certain object, which is not necessarily the same object in which it was defined. This is called '''context'''.
&lt;html>
 
&lt;body>
 
&lt;script>
 
function multiply()
 
{
 
  var xmlHttp;
 
  xmlHttp=new XMLHttpRequest();
 
  var x,y;
 
  x=document.getElementById("input_x").value;
 
  y=document.getElementById("input_y").value;
 
  var req="x="+x+"&y="+y;
 
  
  xmlHttp.open("POST","multiply-post.php",true);
+
To call a function on an arbitrary context, use either '''call''' or '''apply'''. ''call'' takes a list of arguments, while ''apply'' takes them all in an array.
  
  xmlHttp.onreadystatechange=function()
+
To access the current context, use the '''this''' keyword. Demonstration of concept:
  {
 
    if(xmlHttp.readyState==4)
 
    {
 
      var pElement=document.getElementById("msg");
 
      pElement.innerHTML=xmlHttp.responseText;
 
    }
 
  }
 
  
  xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+
<source lang="javascript">
  xmlHttp.setRequestHeader("Content-length", req.length);
+
var sayThisColor = function(){
  xmlHttp.setRequestHeader("Connection", "close");
+
alert(this.color);
  xmlHttp.send(req);
 
 
}
 
}
&lt;/script>
 
x:&lt;input id="input_x" type="text"/ >&lt;br>
 
y:&lt;input id="input_y" type="text"/>&nbsp;&nbsp;
 
&lt;a href="javascript:multiply();">Multiply&lt;/a>
 
&lt;br>
 
------------------------&lt;/br>
 
Result:
 
&lt;p id="msg">&lt;/p>
 
&lt;/body>
 
&lt;/html>
 
</pre>
 
</code>
 
  
=jQuery=
+
var apple = { color: "red" }
 +
 
 +
sayThisColor();  // undefined
 +
sayThisColor.call(apple); // red
 +
</source>
 +
 
 +
== Events ==
 +
 
 +
Events are really what make JavaScript such a powerful language for web development.
 +
 
 +
Rather than being thread based, JavaScript is event based.  Since all JavaScript code runs in a single thread, '''there are no concurrency issues'''.  When an event occurs, JavaScript automatically calls the ''event callback'' as soon as all previous events' callbacks have finished executing.
 +
 
 +
Code in the form of a '''callback function''' is associated with events via a '''listener'''.  For example, the following JavaScript causes ''sayHello()'' (the callback function) to be run whenever the button with ID "hello" is clicked (the event):
  
jQuery is a fairly lightweight javascript library that has a number of particularly useful features.  Even thought it's only been around for a few years now, it has gained a lot of momentum in the web development community.  jQuery provides a simple interface to easily modify CSS attributes on all the elements in the HTML document, has simplified AJAX integration, and is accompanied by a number of handy user interface related APIs.  You can get a good overview of jQuery in the jQuery [http://docs.jquery.com/Tutorials:How_jQuery_Works Tutorials], and there is a short summary on [http://en.wikipedia.org/wiki/JQuery Wikipedia].  Of course, there are plenty of other tutorials a google search away.
+
<source lang="javascript">
 +
var sayHello = function(){
 +
alert("Hello World");
 +
}
  
To use jQuery in your javascript, you need to include the jQuery javascript library, which is just another javascript file.  It's freely available online at the jQuery [http://docs.jquery.com/Downloading_jQuery website]. Assuming you've downloaded the file to your web server, put it in the directory with your PHP and HTML files, and renamed it ''jquery.js'', you include it by adding this line to the head section of your HTML of PHP file:
+
document.getElementById("hello").addEventListener("click", sayHello, false);
 +
</source>
  
<script type="text/javascript" src="jquery.js"></script>
+
{{JSFiddleExample
 +
|title=Binding Callbacks to a Button Click
 +
|fiddle_id=L8c4Z
 +
|cse330=true
 +
|desc=In this example, notice how we bind the callback function when the ''DOMContentLoaded'' event fires.  This is because JavaScript requires that the button has been parsed by the browser before it can add event listeners to it.
 +
}}
  
You can also link to the jQuery library directly on other websites as mentioned in the above tutorials.  The trade-off is that having a local copy will load faster, but then requires you to manage the library files your self (e.g., downloading new versions).
+
The '''addEventListener''' method takes three parameters:
 +
* The event type
 +
* The callback function
 +
*: The callback function is passed one parameter: the event object.
 +
* A boolean representing bubble (false) or capture (true) phase
 +
*: You usually want Bubble phase. For more information on event phase, see [[#Special Topic: Event Phase]]
  
A few code snippets are given below, but the best way to learn about all the features of jQuery is to head to the [http://jquery.com jQuery website] and look through the tutorials, references, and examples there.
+
Note that versions of Internet Explorer prior to version 9 required that you use a different, albeit similar, function for assigning event listeners called '''attachEvent'''.  attachEvent takes the same arguments as addEventListener, except you need to put '''on''' before the event type (e.g. "onclick"), and the third argument (phase) is not necessary.
  
The ''$'' symbol is used to denote jQuery functionality.  You can use it to call jQuery functions, access HTML document elements in order to read or write values, or modify style information via CSS for a range of document elements.  For example, here is some code that sets up a function to be called whenever the user clicks on a link:
+
It is perfectly valid to use an '''anonymous function''' as your callback function:
  
<code>
+
<source lang="javascript">
<pre>
+
document.getElementById("hello").addEventListener("click", function(event){
$("a").click( function(event)
+
alert("Hello, World!  Event Type: "+event.type);
{
+
}, false);
  event.preventDefault();
+
</source>
  $(this).hide("slow");
 
} );
 
</pre>
 
</code>
 
  
The above code leverages many useful javascript and jQuery features.  ''$("a")'' is the jQuery way of selecting all HTML ''a'' elements.  That is, in this case, all elements in the HTML document that are ''<a>'' tags.  The ''click'' function is invoked for all such ''a'' elements in the document.  The argument to the ''click'' function is another function that is to be called when the selected elements are clicked by the user.  The ''event'' argument to this user-defined function is a default argument sent to functions which handle user actions like clicking a mouse button.  In this example, the code calls another function, ''preventDefault()'' on the event passed to stop the standard action on that event.  Here that means stopping the web browser from following the link that the user clicked on.  Finally, the ''$(this)'' variable is the jQuery way of accessing the current encapsulating object, as in Java.  This example calls the jQuery hide function on the object to make the object (again, in this case, ''this'' is referring to the ''<a>'' tag that the user clicked) disappear from the browser.  The script also passes an argument to the hide function to make the link disappear slowly as described in the API [http://docs.jquery.com/Hide documentation].
+
QuirksMode has perhaps the best series of articles about the ins and outs of JavaScript events on the internet: http://www.quirksmode.org/js/contents.html#events
  
jQuery also comes with some easy to use widgets for building better user interfaces.  One of the handiest is the [http://docs.jquery.com/UI/Dialog dialog] widget that pops-up an in-browser dialog window.  To use the dialog functions, you need to include a few more javascript libraries in your HTML header block like so:
+
=== The Event Object ===
  
<code>
+
Callback functions are passed one argument: an ''event object''. You see above that one property of the event object is ''event.type''To see the full list of properties of the event object, you could run the code:
<pre>
 
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/start/jquery-ui.css"
 
   
 
type="text/css" rel="Stylesheet" /> <!-- We need the style sheet linked
 
above or the dialogs/other parts of jquery-ui won't display correctly!-->
 
  
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script><!-- The main library.
+
<source lang="javascript">
Note: must be listed before the jquery-ui library -->
+
document.getElementById("my_btn").addEventListener("click", function(event){
 +
var strout = "";
 +
for(var i in event){
 +
strout += i + ": " + event[i] + "\n";
 +
}
 +
console.log(strout);
 +
}, false);
 +
</source>
  
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.min.js"></script><!-- jquery-UI
+
Some of the most useful properties and methods include:
hosted on Google's Ajax CDN-->
+
* '''event.target''' references the object on which the event occurred.
<!-- Note: you can download the javascript file from the link
+
* '''event.currentTarget''' references the object whose listener is currently being processed.
 +
*: ''Note:'' event.target and event.currentTarget might be the same or might be different, depending on whether you are listening for bubbled events.
 +
* '''event.preventDefault()''' stops the normal result of the event from being executed.  For example, if you listen for a form's ''submit'' event, you can call event.preventDefault() to stop the form from being submitted.
 +
* '''event.stopPropagation()''' prevents any other event listeners from being executed.  For more detail, read the section on Event Phase below.
  
provided on the google doc, or simply provide its URL
+
For more detail on the event object, see [http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#interface-Event the W3C specification].
  
in the src attribute (microsoft and google also host the jQuery
+
'''Note:''' If your callback function does not take any parameters, it will still run; you just won't have as easy of access to the event object.
  
library-->
+
=== Special Topic: Event Phase ===
<script type="text/javascript">
 
  // your code goes here
 
</script>
 
</pre>
 
</code>
 
  
You can then use the ''$().dialog()'' function to make dialog boxes.  The ''dialog'' function can take many arguments to customize its behavior and add standard elements like buttons; see the documentation for details.  The content of the dialog box is typically placed in a ''div'' container and then that container is hidden when the document loadsYou can put any elements in the ''div'' and they will be displayed as normal in the dialog box.  Here is a full example:
+
In JavaScript, events occur in two phases: '''Capture Phase''' and '''Bubble Phase'''.  Consider the following HTML document:
  
<code>
+
<source lang="html4strict">
<pre>
+
<!DOCTYPE html>
<html>
+
<html>
<head>
+
<head><title>Event Test</title></head>
  <style>
 
    #mydialog { display:none }
 
  </style>
 
  <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/start/jquery-ui.css"
 
  type="text/css" rel="Stylesheet" />
 
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
 
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.min.js"></script>
 
  <script type="text/javascript">
 
    function showdialog()
 
    {
 
      $("#mydialog").dialog();
 
    }
 
  </script>
 
</head>
 
 
<body>
 
<body>
   <input type="button" value="Show Dialog" onclick=showdialog() />
+
   <div id="box">
  <div id="mydialog" title="Howdy">Look at me!</div>
+
    <button id="btn">
 +
      Hello
 +
    </button>
 +
  </div>
 
</body>
 
</body>
 
</html>
 
</html>
</pre>
+
</source>
</code>
+
 
 +
Suppose the user clicks on the "Hello" button.  Events will be fired in the following order:
 +
 
 +
# Capture Phase CLICK on the Document
 +
# Capture Phase CLICK on the Body
 +
# Capture Phase CLICK on the Div#box
 +
# Capture Phase CLICK on the Button#btn
 +
# Bubble Phase CLICK on the Button#btn
 +
# Bubble Phase CLICK on the Div#box
 +
# Bubble Phase CLICK on the Body
 +
# Bubble Phase CLICK on the Document
 +
 
 +
{{JSFiddleExample
 +
|title=Using Capture Phase to Enable or Disable a Toolbar
 +
|fiddle_id=r32Dz
 +
|desc=We bind an event in the capture phase to the div with ID ''toolbar''.  When ''e.stopPropagation()'' is called, the event does not reach the buttons in the toolbar.
 +
}}
 +
 
 +
Graphically, here is the order in which an event occurs in three generic nested elements:
 +
 
 +
[[File:EventPhase.gif]]
 +
 
 +
Why is this useful?  Suppose you have a control panel (toolbar, etc) that you want to temporarily deactivate.  (For example, Bold/Italic/Underline buttons on a graphic text editor that currently has no content.)  You could keep bubble phase event listeners on your buttons, but prevent those events from occurring by stopping the event in the capture phase on the parent element before the event reaches your buttons!  Example:
 +
 
 +
<source lang="javascript">
 +
var disableToolbarFunc = function(e){
 +
e.stopPropogation();
 +
}
 +
 
 +
// To disable toolbar:
 +
document.getElementById("box").addEventListener("click", disableToolbarFunc, true);
 +
 
 +
// To re-enable toolbar:
 +
document.getElementById("box").removeEventListener("click", disableToolbarFunc, true);
 +
</source>
 +
 
 +
'''Word of caution:''' Like many great things in web development, capture phase does not work in versions of Internet Explorer prior to version 9.  There is no elegant substitution for older versions of Internet Explorer.
 +
 
 +
== Document Object Model ==
 +
 
 +
The '''Document Object Model (DOM)'''  is what enables JavaScript to manipulate the content of your web page.
 +
 
 +
=== Nodes and Traversing the DOM ===
 +
 
 +
Each element on your page, whether it is a <nowiki><p>, <img/></nowiki>, a string of text, or even an attribute, is called a '''node'''.
 +
 
 +
Every node, except for the document itself, has exactly one parent.  A single node may have multiple children.
 +
 
 +
Consider the following HTML code:
 +
 
 +
<source lang="html4strict">
 +
<ul id="my-list">
 +
<li class="fruits">Apples</li>
 +
<li class="citrus">Oranges and <strong>Lemons</strong></li>
 +
<li class="berries">Cherries</li>
 +
</ul>
 +
</source>
 +
 
 +
Here, the ul with ID "my-list" has three child '''element nodes''' (the three li's) as well as four child '''text nodes''' (the whitespace counts as a text node) and a child '''attribute node'''.  The second LI has one child '''text node''' as well as one child '''element node''' and one child '''attribute node'''.
 +
 
 +
The DOM can be traversed in JavaScript.  First, let's look at an example.
 +
 
 +
<source lang="javascript">
 +
e = document.getElementById("my-list").getElementsByClassName("citrus")[0].lastChild.nodeName;
 +
alert(e);
 +
</source>
 +
 
 +
{{JSFiddleExample
 +
|title=Currently Selected Radio Button
 +
|fiddle_id=SHcng
 +
|desc=In pure JavaScript, in order to determine the currently selected radio button, it is necessary to iterate over an array of pointers to all possible radio buttons, and stop when you find one that is "checked".
 +
}}
 +
 
 +
The above snippet gets the element with class name '''citrus''' that is a child of the element with ID '''my-list''' (the second LI in the example above), and alerts the type of its second child node (which in this case is '''STRONG''').
 +
 
 +
Some common methods for traversing the DOM include:
 +
 
 +
* Node.parentNode
 +
* Node.childNodes - returns an array of nodes
 +
* Node.firstChild - same as Node.childNodes[0]
 +
* Node.lastChild - same as Node.childNodes[Node.childNodes.length-1]
 +
* Node.previousSibling
 +
* Node.nextSibling
 +
 
 +
You can also search for child (including all descendants) using one of the following methods:
 +
 
 +
* Node.getElementsByTagName("tag-name") - returns an array of element nodes having the tag name '''tag-name''' that are descendants of Node
 +
* Node.getElementById("id") - returns a single node having the ID '''id''' that is a descendant of Node
 +
* Node.getElementsByName("what-name") - returns an array of element nodes having their '''name''' attribute set to '''what-name'''.  Useful for radio buttons and other form elements.
 +
* Node.getElementsByClassName("class") - returns an array of nodes having the class '''class'''
 +
*: '''Note:''' As of October 2012, 82% of the browser market supports Node.getElementsByClassName ([http://caniuse.com/getelementsbyclassname more info]).  In order to support the other 18%, you need to either add your own getElementsByClassName to Node's prototype or use a JavaScript library like jQuery or MooTools.
 +
 
 +
It is common in JavaScript to have long statements like the one in the example above, where you call methods on several objects in sequence.
 +
 
 +
=== Creating, Moving, and Removing Nodes ===
 +
 
 +
You will frequently find yourself wanting to modify the DOM.  JavaScript provides methods that help you do this.
 +
 
 +
Consider the same HTML as above.  If you wanted to add another element to the list, you could use this code:
 +
 
 +
<source lang="javascript">
 +
var newLi = document.createElement("li");  // creates a node with the tag name li
 +
newLi.appendChild(document.createTextNode("Broccoli"));
 +
newLi.setAttribute("class", "veggies");
 +
document.getElementById("my-list").appendChild(newLi);
 +
</source>
 +
 
 +
If you wanted to remove the apples from the list, you could do:
 +
 
 +
<source lang="javascript">
 +
var apple = document.getElementById("my-list").getElementsByClassName("fruits")[0];
 +
document.getElementById("my-list").removeChild(apple);
 +
</source>
 +
 
 +
If you wanted to move the apples to the end of the list, you could do this:
 +
 
 +
<source lang="javascript">
 +
var apple = document.getElementById("my-list").getElementsByClassName("fruits")[0];
 +
document.getElementById("my-list").appendChild(apple);
 +
</source>
 +
 
 +
Notice that '''Node.append()''' both removes a node from its previous location ''and'' appends it to its new location, which is always going to be as the last child of the parent node.
 +
 
 +
In summary, here are the methods to know from this section:
 +
 
 +
* Node.append(otherNode) - removes otherNode from its current location in the DOM (if applicable) and then adds it as the last child of Node
 +
* Node.removeChild(otherNode) - removes otherNode, a child of Node, from the DOM
 +
* document.createElement("tag-name") - create a new node with the tag name "tag-name"
 +
* document.createTextNode("text") - create a node containing only the string '''text'''
 +
* Node.setAttribute("attribute", "value") - sets the attribute node of name "attribute" to "value"
 +
 
 +
=== DOM Shortcuts ===
 +
 
 +
In the above sections, we have been creating, reading, modifying, and deleting Nodes.  This is the most "correct" way to change the content of a web page from inside JavaScript.
 +
 
 +
This section documents a few shortcuts that are not as "pure" as using Nodes but can be less confusing and cumbersome.
 +
 
 +
{{JSFiddleExample
 +
|title=Displaying Information
 +
|fiddle_id=Q3BPZ
 +
|desc=This example shows how to use some of the shortcut methods for using JavaScript to display information on the page.
 +
}}
 +
 
 +
==== textContent ====
 +
 
 +
Using textContent to display information is probably the easiest method out there.  For example, the following code overwrites whatever is in the element with ID "holder" with the string "Hello World":
 +
 
 +
<source lang="javascript">
 +
document.getElementById("holder").textContent = "Hello World";
 +
</source>
 +
 
 +
If you wanted to instead append the text, simply use '''+=''' instead of '''=''':
 +
 
 +
<source lang="javascript">
 +
document.getElementById("holder").textContent += " -  Later, he said Hello World  - ";
 +
</source>
 +
 
 +
Note that textContent displays strings literally; that is, it does not allow for HTML.  Setting the textContent property also removes any HTML that may have already been in that element.
 +
 
 +
==== innerHTML ====
 +
 
 +
If you need to use HTML in your output but don't want to use the method described earlier in this section, a straightforward strategy is to use the innerHTML property of an element. For example, the following code would add a paragraph saying "Hello World" to the element with ID "holder":
 +
 
 +
<source lang="javascript">
 +
document.getElementById("holder").innerHTML += "<p>Hello World</p>";
 +
</source>
 +
 
 +
'''Important:''' You need to be careful to prevent XSS-type attacks if you display information innerHTML.  You should be sure, for example, that your JSON data is sanitized on the server.
 +
 
 +
==== DOM Manipulation using jQuery ====
 +
 
 +
jQuery's approach is a cross between the W3C Node model and a more traditional .innerHTML approach.  Here is how you would add a paragraph saying "Hello World" to the element with ID "holder" in jQuery:
 +
 
 +
<source lang="javascript">
 +
var code_to_insert = $("<p>Hello World</p>");
 +
$("#holder").append(code_to_insert);
 +
</source>
 +
 
 +
=== Inspecting the DOM ===
 +
 
 +
Various browsers and browser plugins allow you, the developer, to look at the DOM of your web page and find what properties and methods are associated with each node.  Some options include:
 +
 
 +
* '''Firebug'''.  Firebug is a plugin for Firefox that is a toolkit full of web developer tools, one of which is a DOM inspector.  To inspect the DOM of a web page, simply open the Firebug window while viewing the web page.
 +
* '''WebKit Inspector'''.  The WebKit Inspector, which is available in both Chrome and Safari, enables you to see the DOM tree and relationships between elements.  However, its DOM inspection tools are not as robust as those of Firebug.
 +
* '''Opera Dragonfly'''.  The web browser Opera comes with a web developer toolkit similar to the WebKit Inspector called Dragonfly.  It is important that you test your sites in Opera, because although Opera has only a small fraction of the desktop browser market, it is second only to WebKit on the mobile market.
 +
 
 +
== Asynchronous Javascript And XML ==
 +
 
 +
Asynchronous Javascript And XML, or '''''AJAX''''', is a group of related web development techniques, standards, and technologies used on the client (web browser) side of the standard web server-client communication model.
 +
 
 +
Here's the general concept: JavaScript is used to send requests to the web server in the background and retrieve data, without the need to refresh the page.  The result: dynamic, fast, user-friendly web pages.
 +
 
 +
The requests are performed ''asynchronously'': this means that the end user can continue interacting with your web page while the server data is being loaded.
 +
 
 +
The key idea is that a large fraction of the work happens at the web browser, and larger requests happen behind the scenes, keeping waiting times for data to come back over the network to a minimum.  AJAX is generally also associated with higher-level APIs and libraries that aid in producing cleaner user interfaces for web applications.
 +
 
 +
=== The XMLHttpRequest Object ===
 +
 
 +
The JavaScript specification defines the '''XMLHttpRequest''' object, which is used to exchange data with the web servers without needing to reload the entire web page in the browser.
 +
 
 +
'''Note:''' All modern browsers support the XMLHttpRequest object as specified by the W3C.  However, if you wish to support older browsers (e.g., Netscape Navigator or Internet Explorer prior to version 9), you need to do some additional work on the back end.  ''In this class, your JavaScript needs to work in only Firefox and Chrome.''
 +
 
 +
==== Initializing an XMLHttpRequest Object ====
 +
 
 +
As stated above, the XMLHttpRequest object handles communication with the web servers.  To use it, you must first initialize a variable to be an instance of the '''XMLHttpRequest''' "class".
 +
 
 +
<source lang="javascript">
 +
var xmlHttp = new XMLHttpRequest();
 +
</source>
 +
 
 +
Next, use your XMLHttpRequest instance to open a connection to your server.
 +
 
 +
<source lang="javascript">
 +
xmlHttp.open("METHOD", "URL_OF_SERVER_SCRIPT", ASYNCRONOUS_FLAG);
 +
// METHOD: either GET or POST.
 +
// URL_OF_SERVER_SCRIPT: the path to your server-side script relative to the current page.  For example, process_ajax.php
 +
// ASYNCRONOUS_FLAG: Should be true in order to perform the request asynchronously.  (Having a value of false will freeze the browser until the request is completed.)
 +
</source>
 +
 
 +
'''Note:''' For security reasons, you cannot perform AJAX requests to other domains, unless that domain has a special security policy set up to enable such requests.
 +
 
 +
==== Sending Data ====
 +
 
 +
===== GET Data =====
 +
 
 +
To send GET data, append the information to the end of the URL_OF_SERVER_SCRIPT, as you would normally do, and then call xmlHttp.send(), passing ''null'' as the parameter:
 +
 
 +
<source lang="javascript">
 +
var xmlHttp = new XMLHttpRequest();
 +
xmlHttp.open("GET", "process_ajax.php?var1=val1&var2=val2", true);
 +
xmlHttp.send(null);
 +
</source>
 +
 
 +
===== POST Data =====
 +
 
 +
To send POST data, pass a URL-encoded string to xmlHttp.send().  You also need to change the MIME Type of the outgoing request.
 +
 
 +
<source lang="javascript">
 +
var xmlHttp = new XMLHttpRequest();
 +
xmlHttp.open("POST", "process_ajax.php", true);
 +
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 +
xmlHttp.send("var1=val1&var2=val2");
 +
</source>
 +
 
 +
==== Listening for a Response ====
 +
 
 +
XMLHttpRequest will fire an [[#Events|event]] when the request has been completed.  We therefore need to use a '''[[#Events|callback function]]''' in order to listen for the '''load''' event on the XMLHttpRequest object.
 +
 
 +
The server's plain text response is available as the '''responseText''' property of your XMLHttpRequest instance, which is available in the '''target''' property of the event.  For example:
 +
 
 +
<source lang="javascript">
 +
var xmlHttp = new XMLHttpRequest();
 +
xmlHttp.open("GET", "hello.txt", true);
 +
xmlHttp.addEventListener("load", ajaxCallback, false);
 +
xmlHttp.send(null);
 +
 
 +
// ...
 +
 
 +
function ajaxCallback(event){
 +
alert( "Your file contains the text: " + event.target.responseText );
 +
}
 +
</source>
 +
 
 +
===== Browser Support =====
 +
 
 +
Many examples that you find when Googling for "AJAX" use the '''onreadystatechange''' property of the XMLHttpRequest instance to react on the completion of the request, rather than using an event listener.  This approach works, and it is required for comprehensive browser support, but it is no longer recommended for future use in modern web applications.  The implementation of XMLHttpRequest documented here (so-called "XHR level 2") works in the following browsers:
 +
* Firefox 3.5+ (Jun 2009)
 +
* Safari 5+ (Jun 2010)
 +
* Chrome 7+ (Sep 2010)
 +
* Opera 12+ (May 2012)
 +
* Internet Explorer 10+ (unreleased)
 +
Together, browsers supporting XHR level 2 account for more than half of the market as of October 2012.
 +
 
 +
==== Response Formats ====
 +
 
 +
More often than not, a plaintext response form the server is not very helpful: you want to transmit more information than simply a single string of text.  There are two good options to get more information from a single AJAX request.
 +
 
 +
===== XML =====
 +
 
 +
Your server can respond with an XML document (whence, ''XMLHttpRequest'').  An '''XML document''' uses syntax that is extremely close to HTML  For example:
 +
 
 +
<source lang="xml">
 +
<?xml version="1.0" standalone="yes" ?>
 +
<note>
 +
  <date year="2013" month="02" day="14" />
 +
  <to>Sally</to>
 +
  <message>Happy Valentine's Day!</message>
 +
  <from>Your Secret Admirer</from>
 +
</note>
 +
</source>
 +
 
 +
Like HTML, XML has a DOM that can be traversed in JavaScript.
 +
 
 +
If you make an AJAX request to a script generating an XML document, the root XML node is accessible in the '''responseXML''' property.
 +
 
 +
<source lang="javascript">
 +
function ajaxCallback(event){
 +
var xmlDocument = event.target.responseXML;
 +
 +
alert(xmlDocument.getElementsByTagName("to")[0].textContent);  // Sally (in the case of the example XML above)
 +
}
 +
</source>
 +
 
 +
===== JSON =====
 +
 
 +
JavaScript Object Notation, or '''JSON''', is a rising standard interface format because of its lightweight syntax that makes it especially useful for AJAX requests.
 +
 
 +
The JSON syntax closely follows the syntax for [[#Object Literals|object literals]].  For example:
 +
 
 +
<source lang="javascript">
 +
{
 +
  "apple": {
 +
      "color": "red",
 +
      "flavor": "sweet"
 +
  },
 +
  "lemon": {
 +
      "color": "yellow",
 +
      "flavor": "sour"
 +
  }
 +
}
 +
</source>
 +
 
 +
Usually when JSON is transferred over the internet, it is condensed down to one line, like this:
 +
 
 +
<source lang="javascript">
 +
{"apple":{"color":"red","flavor":"sweet"},"lemon":{"color":"yellow","flavor":"sour"}}
 +
</source>
 +
 
 +
In JavaScript, you can convert a JSON string to an object using '''JSON.parse()'''.  For example:
 +
 
 +
<source lang="javascript">
 +
var jsonData = JSON.parse('{"apple":{"color":"red","flavor":"sweet"},"lemon":{"color":"yellow","flavor":"sour"}}');
 +
 
 +
alert(jsonData.apple.color);  // red
 +
</source>
 +
 
 +
Here's how to use it in conjunction with your AJAX response callback:
 +
 
 +
<source lang="javascript">
 +
function ajaxCallback(event){
 +
var jsonData = JSON.parse(event.target.responseText);
 +
 +
alert(jsonData.lemon.flavor);  // sour (in the case of the example JSON above)
 +
}
 +
</source>
 +
 
 +
Here is a graphic to illustrate the JSON process.
 +
 
 +
[[File:JSON-Flowchart.png‎]]
 +
 
 +
=== Examples ===
 +
 
 +
==== Logging In a User ====
 +
 
 +
Suppose you had the following PHP script:
 +
 
 +
<source lang="php" line>
 +
<?php
 +
// login_ajax.php
 +
 
 +
header("Content-Type: application/json"); // Since we are sending a JSON response here (not an HTML document), set the MIME Type to application/json
 +
 
 +
$username = $_POST['username'];
 +
$password = $_POST['password'];
 +
 
 +
// Check to see if the username and password are valid.  (You learned how to do this in Module 3.)
 +
 
 +
if( /* valid username and password */ ){
 +
session_start();
 +
$_SESSION['username'] = $username;
 +
$_SESSION['token'] = substr(md5(rand()), 0, 10);
 +
 
 +
echo json_encode(array(
 +
"success" => true
 +
));
 +
exit;
 +
}else{
 +
echo json_encode(array(
 +
"success" => false,
 +
"message" => "Incorrect Username or Password"
 +
));
 +
exit;
 +
}
 +
?>
 +
</source>
 +
 
 +
'''Note:''' This example uses PHP's very handy '''json_encode()''' function to translate an associative array into a JSON object.  This means that you can access in JavaScript the same structure that you made in PHP!
 +
 
 +
And suppose you had the following HTML content:
 +
 
 +
<source lang="html4strict" line>
 +
<input type="text" id="username" placeholder="Username" />
 +
<input type="password" id="password" placeholder="Password" />
 +
<button id="login_btn">Log In</button>
 +
 
 +
<script type="text/javascript" src="ajax.js"></script> <!-- load the JavaScript file -->
 +
</source>
 +
 
 +
You could use the following JavaScript code to prepare, send, and receive a request from the server to see if the user is logged in, without ever having to refresh the page.
 +
 
 +
<source lang="javascript" line>
 +
// ajax.js
 +
 
 +
function loginAjax(event){
 +
var username = document.getElementById("username").value; // Get the username from the form
 +
var password = document.getElementById("password").value; // Get the password from the form
 +
 
 +
// Make a URL-encoded string for passing POST data:
 +
var dataString = "username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password);
 +
 +
var xmlHttp = new XMLHttpRequest(); // Initialize our XMLHttpRequest instance
 +
xmlHttp.open("POST", "login_ajax.php", true); // Starting a POST request (NEVER send passwords as GET variables!!!)
 +
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // It's easy to forget this line for POST requests
 +
xmlHttp.addEventListener("load", function(event){
 +
var jsonData = JSON.parse(event.target.responseText); // parse the JSON into a JavaScript object
 +
if(jsonData.success){  // in PHP, this was the "success" key in the associative array; in JavaScript, it's the .success property of jsonData
 +
alert("You've been Logged In!");
 +
}else{
 +
alert("You were not logged in.  "+jsonData.message);
 +
}
 +
}, false); // Bind the callback to the load event
 +
xmlHttp.send(dataString); // Send the data
 +
}
 +
 
 +
document.getElementById("login_btn").addEventListener("click", loginAjax, false); // Bind the AJAX call to button click
 +
</source>
 +
 
 +
'''Note:''' The above example uses an '''anonymous function''' (a function without a name that is declared in an attribute) as the callback.  If you are using a certain callback function only once in your program, this is a perfectly valid approach to reduce the amount of code you need to write.
 +
 
 +
==== Loading Data from an XML File for Display in HTML ====
 +
 
 +
Suppose you have a file '''note.xml''' that contains the following information:
 +
 
 +
<source lang="xml" line>
 +
<?xml version="1.0" standalone="yes" ?>
 +
<note>
 +
  <date year="2013" month="02" day="14" />
 +
  <to>Sally</to>
 +
  <message>Happy Valentine's Day!</message>
 +
  <from>Your Secret Admirer</from>
 +
</note>
 +
</source>
 +
 
 +
Further, suppose you had an HTML element with ID '''note''':
 +
 
 +
<source lang="html4strict" line>
 +
<div id="note"></div>
 +
</source>
 +
 
 +
You could load this XML file and then display it inside of your HTML document like this:
 +
 
 +
<source lang="javascript" line>
 +
function getNoteAjax(event){
 +
// The XMLHttpRequest is simple this time:
 +
var xmlHttp = new XMLHttpRequest();
 +
xmlHttp.open("GET", "note.xml", true);
 +
xmlHttp.addEventListener("load", getNoteCallback, false);
 +
xmlHttp.send(null);
 +
}
 +
 
 +
function getNoteCallback(event){
 +
var htmlParent = document.getElementById("note"); // Get the HTML element into which we want to write the note
 +
var xmlDocument = event.target.responseXML; // Get the XML root node from the response
 +
 +
// Find the <date/> element from the XML response.  We expect only 1 such element, so we can call
 +
// xmlDocument.getElementsByTagName() and then get the first (and only) element in the array all in
 +
// one step.  This is called chaining.
 +
var xmlDateElement = xmlDocument.getElementsByTagName("date")[0];
 +
 +
// Put together a YYYY-MM-DD type date into a string based on the attributes of the <date/> element.
 +
var dateString = xmlDateElement.getAttribute("year") + "-" + xmlDateElement.getAttribute("month")
 +
+ "-" + xmlDateElement.getAttribute("day");
 +
 +
// Get the content of the <to>, <message>, and <from> tags.  Again, you can use a chain to do this in one line for each.
 +
var to = xmlDocument.getElementsByTagName("to")[0].textContent;
 +
var message = xmlDocument.getElementsByTagName("message")[0].textContent;
 +
var from = xmlDocument.getElementsByTagName("from")[0].textContent;
 +
 +
// Make a <strong> tag, append the date string as its content, and then append it to the HTML element.
 +
var htmlDateObj = document.createElement("strong");
 +
htmlDateObj.appendChild(document.createTextNode(dateString));
 +
htmlParent.appendChild(htmlDateObj);
 +
 +
// Make a <p> tag to contain the note.
 +
var htmlParagraphObj = document.createElement("p");
 +
htmlParagraphObj.appendChild(document.createTextNode("Dear "+to+",")); // First append the greeting
 +
htmlParagraphObj.appendChild(document.createElement("br")); // Append a couple line feeds
 +
htmlParagraphObj.appendChild(document.createElement("br"));
 +
htmlParagraphObj.appendChild(document.createTextNode(message)); // Write the message itself
 +
htmlParagraphObj.appendChild(document.createElement("br")); // Append a couple more line feeds
 +
htmlParagraphObj.appendChild(document.createElement("br"));
 +
htmlParagraphObj.appendChild(document.createTextNode("Love, "+from)); // Finally, append the salutation
 +
htmlParent.appendChild(htmlParagraphObj); // Append the newly engineered <p> to the HTML element.
 +
}
 +
 
 +
document.addEventListener("DOMContentLoaded", getNoteAjax, false); // Bind the AJAX call to page load
 +
</source>
  
To understand the page, start at the bottom.  There is a ''div'' element with a title and some string content.  It also has a unique id (the ids can be anything you want) which is used to identify this particular element in the rest of the document.  This div's id is ''mydialog''.  Above that is a button input.  The only thing special about it is the ''onclick'' attribute which specifies a javascript function to call when the button is clicked by a user.  In this case, the function is ''showdialog()'' which is a user defined javascript function contained in the document header.  All the function does is access the document element with id ''mydialog'' (the ''#identifier'' is the jQuery way of accessing an individual element based on the assigned id in the element attribute list), and build a dialog box from itHere, the dialog box will have the title ''Howdy'' from the title attribute in the ''mydialog'' element, and have a text string ''Look at me!''.  Finally, at the top of the document is the ''style'' section, which is a normal HTML/CSS section describing appearance of parts of the document.  There is only one entry, again describing the document element with id ''mydialog''.  One style attribute is set, namely the ''display'' attribute is set to ''none'' to indicate that the element should not be displayed.  Otherwise, the ''mydialog'' div would be displayed like any other part of the document rather than being used solely for our dialog box.
+
This example uses a lot of techniques documented in the [[#Document Object Model]] section aboveThe resulting DOM will be something like this:
  
Here is another example of using jQuery to do simple animations by moving an image across the browser window:
+
<source lang="html4strict">
 +
<div id="note">
 +
  <strong>2013-02-14</strong>
 +
  <p>Dear Sally,<br /><br />Happy Valentine's Day!<br /><br />Love, Your Secret Admirer</p>
 +
</div>
 +
</source>
  
<code>
+
If you think that this is a lot of code to produce a relatively simple output, you are not alone. You will learn how to do this job in much fewer lines when you learn about [[jQuery]].
<pre>
 
&lt;html>                                                                 
 
&lt;head>                                                                 
 
&lt;script type="text/javascript" src="http://code.jquery.com/jquery-latest.js">&lt;/script>         
 
&lt;script type="text/javascript">                                       
 
  // these are for storing target locations
 
  var targetLeft=0;
 
  var targetTop=0;
 
  function moveTarget()
 
  {
 
    targetLeft+=10; //increase target location
 
    targetTop+=10;
 
    $("#target").css("top",targetTop); //move target to (top,left)
 
    $("#target").css("left",targetLeft);
 
    if(targetLeft&lt;200)
 
    { //stop if we reached left=200
 
      window.setTimeout("moveTarget()",200); //set the next timer
 
    }
 
  }
 
  $(document).ready( function()
 
  { //at the beginning create a clock timeout
 
    window.setTimeout("moveTarget()",200); //call this function in 200 ms.
 
  });
 
&lt;/script>                                                             
 
&lt;/head>                                                               
 
&lt;body>                                                                 
 
&lt;!-- this is my target-->                                       
 
&lt;img id="target"  src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/180px-Smiley.svg.png" style="position:relative"/>
 
&lt;/body>                                                               
 
&lt;/html>
 
</pre>
 
</code>
 
  
=Other Resources=
+
[[Category:Module 6]]
There are a number of other w3schools tutorials and references that you may find useful, including [http://www.w3schools.com/php/default.asp PHP] (note the PHP and AJAX section), [http://www.w3schools.com/htmldom/default.asp DOM], [http://www.w3schools.com/ajax/default.asp AJAX], and [http://www.w3schools.com/css/default.asp CSS].  Many other resources exist around the web, and you should feel free to incorporate any existing libraries or other javascript or AJAX-related tools.  For example, the [http://code.google.com/apis/ajaxlibs/ Google AJAX APIs].
 

Revision as of 04:18, 15 March 2013

JavaScript is the most widely used scripting language for implementing client-side functionality in Web applications. Unlike PHP, JavaScript code is interpreted and executed in a client's web browser (not on the web server).

JavaScript? Did you mean Java?

JavaScript is a prototype-based programming language focussed on web interactivity. It was first introduced in Netscape Navigator, and it in turn gave rise to what is now ECMAScript. Originally, JavaScript was called "LiveScript". Sun, the developer of Java at the time, wanted a language that would complement its compiled Java language, and so LiveScript was renamed JavaScript.

Beyond that, Java and JavaScript are as similar as Ham and Hamster.

Java and JavaScript have similar syntax, but the under workings are quite different. For example, Java requires strict typing, but JavaScript allows for dynamic typing. Java is object-oriented, but JavaScript is prototype-oriented. Java is compiled, but JavaScript is interpreted.

JavaScript Language Components

This section highlights some features of the JavaScript language that differentiate it from other languages. For a more comprehensive JavaScript tutorial, the following tutorials are both quality:

  • WebPlatform: Great for learning JavaScript for the first time. Advocates best practices for modern JavaScript development.
  • QuirksMode: More advanced than the WebPlatform tutorial, but it thoroughly covers the most powerful aspects of pure JavaScript and gives unparalleled advice on browser compatibility.

Advice: Do NOT Google for "JavaScript Tutorial". The first few hits advocate bad or outdated practices. Stick with the ones listed here.

Variables and Scope

To define a variable in JavaScript, use the var keyword.

var foo = "bar";

All variables are objects. In the case above, the variable foo is an object of the class String.

Notice that like PHP, you do not have to explicitly define a type for a variable like int or String; this is because JavaScript and PHP are dynamically typed languages.

JavaScript code can access any variable higher in the “function tree”, but not vice-versa. This is called scope. All functions create their own scope.

When you reference a variable, JavaScript will look up through the "function tree" until it finds the variable you asked for. This means that you could define variables of the same name as global variables inside of functions. For demonstration of concept:

var a = "hello";
var b = "world";

function sayGoodByeWorld(){
	var a = "goodbye";

	alert(a); // goodbye
	alert(b); // world
}

sayGoodByeWorld();

alert(a); // hello

Object Literals

A very common way of storing and transporting data in JavaScript is by using objects. You can define an object with certain properties using an object literal:

var apple = {
	color: "red",
	flavor: "sweet",
	season: "autumn"
}

alert(apple.color);  // red

Functions

To define a function in JavaScript, use the function keyword.

function sayHello(){
	alert("Hello World");
}

sayHello(); // call the function

Pass a parameter to a function like this:

function sayHello(name){
	alert("Hello, "+name);
}

sayHello("Todd"); // call the function and pass an argument

In JavaScript, functions are objects. This means that they can be assigned to variables, manipulated on the fly, and even passed as arguments to other functions! As we will see in a couple sections, this is an extremely important feature of JavaScript that makes it such a robust language for web development.

If you want to define a scope-specific function, you can assign it to a variable like this:

var sayHello = function(){
	alert("Hello World");
}

sayHello(); // call the function

Closures

A closure is a way to separate a certain snippet of JavaScript code from the global scope. This is useful if you do not want to "muck up" global variables. Closures are nothing more than anonymous functions that are called as soon as they are created:

var a = "hello";

(​​​​function(){
	var b = "world";
	
	alert(a); // hello
	alert(b); // world
})();

alert(a); // hello
alert(b); // ReferenceError: b is not defined​​​​​​​​​​​​​​​

Most JavaScript libraries (like jQuery) write all of their code in a closure. What this means is that except for one or two variable names (jQuery or $), everything associated with the library is completely self-contained.

Prototypal Inheritance

JavaScript implements prototypal inheritance, as opposed to a language like Java or C++, which implements classical inheritance. JavaScript is one of only a handful of languages implementing prototype-based inheritance.

Here's how it works. Every callable object (function) has a prototype. When instances of that object are created, their properties and methods are copied (inherited) from the prototype. Additionally, changes made to the prototype later in the program are "copied" to every instance.

For example, if you wanted to make a method on all strings that added a “!”, you could modify String’s prototype:

String.prototype.bang = function(){
	return this+"!"; // Notice: the context is the instance itself
}

alert("Hello".bang()); // alerts Hello!

To "extend" an object, just copy its prototype to a new object. However, since classical inheritance and prototypal inheritance are different concepts, copying prototypes may have results that you don't expect. This article seems to have a pretty good explanation with example implementations.

Context

Every function is called on a certain object, which is not necessarily the same object in which it was defined. This is called context.

To call a function on an arbitrary context, use either call or apply. call takes a list of arguments, while apply takes them all in an array.

To access the current context, use the this keyword. Demonstration of concept:

var sayThisColor = function(){
	alert(this.color);
}

var apple = { color: "red" }

sayThisColor();   // undefined
sayThisColor.call(apple); // red

Events

Events are really what make JavaScript such a powerful language for web development.

Rather than being thread based, JavaScript is event based. Since all JavaScript code runs in a single thread, there are no concurrency issues. When an event occurs, JavaScript automatically calls the event callback as soon as all previous events' callbacks have finished executing.

Code in the form of a callback function is associated with events via a listener. For example, the following JavaScript causes sayHello() (the callback function) to be run whenever the button with ID "hello" is clicked (the event):

var sayHello = function(){
	alert("Hello World");
}

document.getElementById("hello").addEventListener("click", sayHello, false);

Example: Binding Callbacks to a Button Click

View in JSFiddle

In this example, notice how we bind the callback function when the DOMContentLoaded event fires. This is because JavaScript requires that the button has been parsed by the browser before it can add event listeners to it.

The addEventListener method takes three parameters:

  • The event type
  • The callback function
    The callback function is passed one parameter: the event object.
  • A boolean representing bubble (false) or capture (true) phase
    You usually want Bubble phase. For more information on event phase, see #Special Topic: Event Phase

Note that versions of Internet Explorer prior to version 9 required that you use a different, albeit similar, function for assigning event listeners called attachEvent. attachEvent takes the same arguments as addEventListener, except you need to put on before the event type (e.g. "onclick"), and the third argument (phase) is not necessary.

It is perfectly valid to use an anonymous function as your callback function:

document.getElementById("hello").addEventListener("click", function(event){
	alert("Hello, World!  Event Type: "+event.type);
}, false);

QuirksMode has perhaps the best series of articles about the ins and outs of JavaScript events on the internet: http://www.quirksmode.org/js/contents.html#events

The Event Object

Callback functions are passed one argument: an event object. You see above that one property of the event object is event.type. To see the full list of properties of the event object, you could run the code:

document.getElementById("my_btn").addEventListener("click", function(event){
	var strout = "";
	for(var i in event){
		strout += i + ": " + event[i] + "\n";
	}
	console.log(strout);
}, false);

Some of the most useful properties and methods include:

  • event.target references the object on which the event occurred.
  • event.currentTarget references the object whose listener is currently being processed.
    Note: event.target and event.currentTarget might be the same or might be different, depending on whether you are listening for bubbled events.
  • event.preventDefault() stops the normal result of the event from being executed. For example, if you listen for a form's submit event, you can call event.preventDefault() to stop the form from being submitted.
  • event.stopPropagation() prevents any other event listeners from being executed. For more detail, read the section on Event Phase below.

For more detail on the event object, see the W3C specification.

Note: If your callback function does not take any parameters, it will still run; you just won't have as easy of access to the event object.

Special Topic: Event Phase

In JavaScript, events occur in two phases: Capture Phase and Bubble Phase. Consider the following HTML document:

<!DOCTYPE html>
<html>
<head><title>Event Test</title></head>
<body>
  <div id="box">
    <button id="btn">
      Hello
    </button>
  </div>
</body>
</html>

Suppose the user clicks on the "Hello" button. Events will be fired in the following order:

  1. Capture Phase CLICK on the Document
  2. Capture Phase CLICK on the Body
  3. Capture Phase CLICK on the Div#box
  4. Capture Phase CLICK on the Button#btn
  5. Bubble Phase CLICK on the Button#btn
  6. Bubble Phase CLICK on the Div#box
  7. Bubble Phase CLICK on the Body
  8. Bubble Phase CLICK on the Document

Example: Using Capture Phase to Enable or Disable a Toolbar

View in JSFiddle

We bind an event in the capture phase to the div with ID toolbar. When e.stopPropagation() is called, the event does not reach the buttons in the toolbar.

Graphically, here is the order in which an event occurs in three generic nested elements:

EventPhase.gif

Why is this useful? Suppose you have a control panel (toolbar, etc) that you want to temporarily deactivate. (For example, Bold/Italic/Underline buttons on a graphic text editor that currently has no content.) You could keep bubble phase event listeners on your buttons, but prevent those events from occurring by stopping the event in the capture phase on the parent element before the event reaches your buttons! Example:

var disableToolbarFunc = function(e){
	e.stopPropogation();
}

// To disable toolbar:
document.getElementById("box").addEventListener("click", disableToolbarFunc, true);

// To re-enable toolbar:
document.getElementById("box").removeEventListener("click", disableToolbarFunc, true);

Word of caution: Like many great things in web development, capture phase does not work in versions of Internet Explorer prior to version 9. There is no elegant substitution for older versions of Internet Explorer.

Document Object Model

The Document Object Model (DOM) is what enables JavaScript to manipulate the content of your web page.

Nodes and Traversing the DOM

Each element on your page, whether it is a <p>, <img/>, a string of text, or even an attribute, is called a node.

Every node, except for the document itself, has exactly one parent. A single node may have multiple children.

Consider the following HTML code:

<ul id="my-list">
	<li class="fruits">Apples</li>
	<li class="citrus">Oranges and <strong>Lemons</strong></li>
	<li class="berries">Cherries</li>
</ul>

Here, the ul with ID "my-list" has three child element nodes (the three li's) as well as four child text nodes (the whitespace counts as a text node) and a child attribute node. The second LI has one child text node as well as one child element node and one child attribute node.

The DOM can be traversed in JavaScript. First, let's look at an example.

e = document.getElementById("my-list").getElementsByClassName("citrus")[0].lastChild.nodeName;
alert(e);

Example: Currently Selected Radio Button

View in JSFiddle

In pure JavaScript, in order to determine the currently selected radio button, it is necessary to iterate over an array of pointers to all possible radio buttons, and stop when you find one that is "checked".

The above snippet gets the element with class name citrus that is a child of the element with ID my-list (the second LI in the example above), and alerts the type of its second child node (which in this case is STRONG).

Some common methods for traversing the DOM include:

  • Node.parentNode
  • Node.childNodes - returns an array of nodes
  • Node.firstChild - same as Node.childNodes[0]
  • Node.lastChild - same as Node.childNodes[Node.childNodes.length-1]
  • Node.previousSibling
  • Node.nextSibling

You can also search for child (including all descendants) using one of the following methods:

  • Node.getElementsByTagName("tag-name") - returns an array of element nodes having the tag name tag-name that are descendants of Node
  • Node.getElementById("id") - returns a single node having the ID id that is a descendant of Node
  • Node.getElementsByName("what-name") - returns an array of element nodes having their name attribute set to what-name. Useful for radio buttons and other form elements.
  • Node.getElementsByClassName("class") - returns an array of nodes having the class class
    Note: As of October 2012, 82% of the browser market supports Node.getElementsByClassName (more info). In order to support the other 18%, you need to either add your own getElementsByClassName to Node's prototype or use a JavaScript library like jQuery or MooTools.

It is common in JavaScript to have long statements like the one in the example above, where you call methods on several objects in sequence.

Creating, Moving, and Removing Nodes

You will frequently find yourself wanting to modify the DOM. JavaScript provides methods that help you do this.

Consider the same HTML as above. If you wanted to add another element to the list, you could use this code:

var newLi = document.createElement("li");  // creates a node with the tag name li
newLi.appendChild(document.createTextNode("Broccoli"));
newLi.setAttribute("class", "veggies");
document.getElementById("my-list").appendChild(newLi);

If you wanted to remove the apples from the list, you could do:

var apple = document.getElementById("my-list").getElementsByClassName("fruits")[0];
document.getElementById("my-list").removeChild(apple);

If you wanted to move the apples to the end of the list, you could do this:

var apple = document.getElementById("my-list").getElementsByClassName("fruits")[0];
document.getElementById("my-list").appendChild(apple);

Notice that Node.append() both removes a node from its previous location and appends it to its new location, which is always going to be as the last child of the parent node.

In summary, here are the methods to know from this section:

  • Node.append(otherNode) - removes otherNode from its current location in the DOM (if applicable) and then adds it as the last child of Node
  • Node.removeChild(otherNode) - removes otherNode, a child of Node, from the DOM
  • document.createElement("tag-name") - create a new node with the tag name "tag-name"
  • document.createTextNode("text") - create a node containing only the string text
  • Node.setAttribute("attribute", "value") - sets the attribute node of name "attribute" to "value"

DOM Shortcuts

In the above sections, we have been creating, reading, modifying, and deleting Nodes. This is the most "correct" way to change the content of a web page from inside JavaScript.

This section documents a few shortcuts that are not as "pure" as using Nodes but can be less confusing and cumbersome.

Example: Displaying Information

View in JSFiddle

This example shows how to use some of the shortcut methods for using JavaScript to display information on the page.

textContent

Using textContent to display information is probably the easiest method out there. For example, the following code overwrites whatever is in the element with ID "holder" with the string "Hello World":

document.getElementById("holder").textContent = "Hello World";

If you wanted to instead append the text, simply use += instead of =:

document.getElementById("holder").textContent += " -  Later, he said Hello World  - ";

Note that textContent displays strings literally; that is, it does not allow for HTML. Setting the textContent property also removes any HTML that may have already been in that element.

innerHTML

If you need to use HTML in your output but don't want to use the method described earlier in this section, a straightforward strategy is to use the innerHTML property of an element. For example, the following code would add a paragraph saying "Hello World" to the element with ID "holder":

document.getElementById("holder").innerHTML += "<p>Hello World</p>";

Important: You need to be careful to prevent XSS-type attacks if you display information innerHTML. You should be sure, for example, that your JSON data is sanitized on the server.

DOM Manipulation using jQuery

jQuery's approach is a cross between the W3C Node model and a more traditional .innerHTML approach. Here is how you would add a paragraph saying "Hello World" to the element with ID "holder" in jQuery:

var code_to_insert = $("<p>Hello World</p>");
$("#holder").append(code_to_insert);

Inspecting the DOM

Various browsers and browser plugins allow you, the developer, to look at the DOM of your web page and find what properties and methods are associated with each node. Some options include:

  • Firebug. Firebug is a plugin for Firefox that is a toolkit full of web developer tools, one of which is a DOM inspector. To inspect the DOM of a web page, simply open the Firebug window while viewing the web page.
  • WebKit Inspector. The WebKit Inspector, which is available in both Chrome and Safari, enables you to see the DOM tree and relationships between elements. However, its DOM inspection tools are not as robust as those of Firebug.
  • Opera Dragonfly. The web browser Opera comes with a web developer toolkit similar to the WebKit Inspector called Dragonfly. It is important that you test your sites in Opera, because although Opera has only a small fraction of the desktop browser market, it is second only to WebKit on the mobile market.

Asynchronous Javascript And XML

Asynchronous Javascript And XML, or AJAX, is a group of related web development techniques, standards, and technologies used on the client (web browser) side of the standard web server-client communication model.

Here's the general concept: JavaScript is used to send requests to the web server in the background and retrieve data, without the need to refresh the page. The result: dynamic, fast, user-friendly web pages.

The requests are performed asynchronously: this means that the end user can continue interacting with your web page while the server data is being loaded.

The key idea is that a large fraction of the work happens at the web browser, and larger requests happen behind the scenes, keeping waiting times for data to come back over the network to a minimum. AJAX is generally also associated with higher-level APIs and libraries that aid in producing cleaner user interfaces for web applications.

The XMLHttpRequest Object

The JavaScript specification defines the XMLHttpRequest object, which is used to exchange data with the web servers without needing to reload the entire web page in the browser.

Note: All modern browsers support the XMLHttpRequest object as specified by the W3C. However, if you wish to support older browsers (e.g., Netscape Navigator or Internet Explorer prior to version 9), you need to do some additional work on the back end. In this class, your JavaScript needs to work in only Firefox and Chrome.

Initializing an XMLHttpRequest Object

As stated above, the XMLHttpRequest object handles communication with the web servers. To use it, you must first initialize a variable to be an instance of the XMLHttpRequest "class".

var xmlHttp = new XMLHttpRequest();

Next, use your XMLHttpRequest instance to open a connection to your server.

xmlHttp.open("METHOD", "URL_OF_SERVER_SCRIPT", ASYNCRONOUS_FLAG);
// METHOD: either GET or POST.
// URL_OF_SERVER_SCRIPT: the path to your server-side script relative to the current page.  For example, process_ajax.php
// ASYNCRONOUS_FLAG: Should be true in order to perform the request asynchronously.  (Having a value of false will freeze the browser until the request is completed.)

Note: For security reasons, you cannot perform AJAX requests to other domains, unless that domain has a special security policy set up to enable such requests.

Sending Data

GET Data

To send GET data, append the information to the end of the URL_OF_SERVER_SCRIPT, as you would normally do, and then call xmlHttp.send(), passing null as the parameter:

var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", "process_ajax.php?var1=val1&var2=val2", true);
xmlHttp.send(null);
POST Data

To send POST data, pass a URL-encoded string to xmlHttp.send(). You also need to change the MIME Type of the outgoing request.

var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", "process_ajax.php", true);
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send("var1=val1&var2=val2");

Listening for a Response

XMLHttpRequest will fire an event when the request has been completed. We therefore need to use a callback function in order to listen for the load event on the XMLHttpRequest object.

The server's plain text response is available as the responseText property of your XMLHttpRequest instance, which is available in the target property of the event. For example:

var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", "hello.txt", true);
xmlHttp.addEventListener("load", ajaxCallback, false);
xmlHttp.send(null);

// ...

function ajaxCallback(event){
	alert( "Your file contains the text: " + event.target.responseText );
}
Browser Support

Many examples that you find when Googling for "AJAX" use the onreadystatechange property of the XMLHttpRequest instance to react on the completion of the request, rather than using an event listener. This approach works, and it is required for comprehensive browser support, but it is no longer recommended for future use in modern web applications. The implementation of XMLHttpRequest documented here (so-called "XHR level 2") works in the following browsers:

  • Firefox 3.5+ (Jun 2009)
  • Safari 5+ (Jun 2010)
  • Chrome 7+ (Sep 2010)
  • Opera 12+ (May 2012)
  • Internet Explorer 10+ (unreleased)

Together, browsers supporting XHR level 2 account for more than half of the market as of October 2012.

Response Formats

More often than not, a plaintext response form the server is not very helpful: you want to transmit more information than simply a single string of text. There are two good options to get more information from a single AJAX request.

XML

Your server can respond with an XML document (whence, XMLHttpRequest). An XML document uses syntax that is extremely close to HTML For example:

<?xml version="1.0" standalone="yes" ?>
<note>
  <date year="2013" month="02" day="14" />
  <to>Sally</to>
  <message>Happy Valentine's Day!</message>
  <from>Your Secret Admirer</from>
</note>

Like HTML, XML has a DOM that can be traversed in JavaScript.

If you make an AJAX request to a script generating an XML document, the root XML node is accessible in the responseXML property.

function ajaxCallback(event){
	var xmlDocument = event.target.responseXML;
	
	alert(xmlDocument.getElementsByTagName("to")[0].textContent);  // Sally (in the case of the example XML above)
}
JSON

JavaScript Object Notation, or JSON, is a rising standard interface format because of its lightweight syntax that makes it especially useful for AJAX requests.

The JSON syntax closely follows the syntax for object literals. For example:

{
   "apple": {
      "color": "red",
      "flavor": "sweet"
   },
   "lemon": {
      "color": "yellow",
      "flavor": "sour"
   }
}

Usually when JSON is transferred over the internet, it is condensed down to one line, like this:

{"apple":{"color":"red","flavor":"sweet"},"lemon":{"color":"yellow","flavor":"sour"}}

In JavaScript, you can convert a JSON string to an object using JSON.parse(). For example:

var jsonData = JSON.parse('{"apple":{"color":"red","flavor":"sweet"},"lemon":{"color":"yellow","flavor":"sour"}}');

alert(jsonData.apple.color);  // red

Here's how to use it in conjunction with your AJAX response callback:

function ajaxCallback(event){
	var jsonData = JSON.parse(event.target.responseText);
	
	alert(jsonData.lemon.flavor);  // sour (in the case of the example JSON above)
}

Here is a graphic to illustrate the JSON process.

JSON-Flowchart.png

Examples

Logging In a User

Suppose you had the following PHP script:

 1 <?php
 2 // login_ajax.php
 3 
 4 header("Content-Type: application/json"); // Since we are sending a JSON response here (not an HTML document), set the MIME Type to application/json
 5 
 6 $username = $_POST['username'];
 7 $password = $_POST['password'];
 8 
 9 // Check to see if the username and password are valid.  (You learned how to do this in Module 3.)
10 
11 if( /* valid username and password */ ){
12 	session_start();
13 	$_SESSION['username'] = $username;
14 	$_SESSION['token'] = substr(md5(rand()), 0, 10);
15 
16 	echo json_encode(array(
17 		"success" => true
18 	));
19 	exit;
20 }else{
21 	echo json_encode(array(
22 		"success" => false,
23 		"message" => "Incorrect Username or Password"
24 	));
25 	exit;
26 }
27 ?>

Note: This example uses PHP's very handy json_encode() function to translate an associative array into a JSON object. This means that you can access in JavaScript the same structure that you made in PHP!

And suppose you had the following HTML content:

1 <input type="text" id="username" placeholder="Username" />
2 <input type="password" id="password" placeholder="Password" />
3 <button id="login_btn">Log In</button>
4 
5 <script type="text/javascript" src="ajax.js"></script> <!-- load the JavaScript file -->

You could use the following JavaScript code to prepare, send, and receive a request from the server to see if the user is logged in, without ever having to refresh the page.

 1 // ajax.js
 2 
 3 function loginAjax(event){
 4 	var username = document.getElementById("username").value; // Get the username from the form
 5 	var password = document.getElementById("password").value; // Get the password from the form
 6 
 7 	// Make a URL-encoded string for passing POST data:
 8 	var dataString = "username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password);
 9 	
10 	var xmlHttp = new XMLHttpRequest(); // Initialize our XMLHttpRequest instance
11 	xmlHttp.open("POST", "login_ajax.php", true); // Starting a POST request (NEVER send passwords as GET variables!!!)
12 	xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // It's easy to forget this line for POST requests
13 	xmlHttp.addEventListener("load", function(event){
14 		var jsonData = JSON.parse(event.target.responseText); // parse the JSON into a JavaScript object
15 		if(jsonData.success){  // in PHP, this was the "success" key in the associative array; in JavaScript, it's the .success property of jsonData
16 			alert("You've been Logged In!");
17 		}else{
18 			alert("You were not logged in.  "+jsonData.message);
19 		}
20 	}, false); // Bind the callback to the load event
21 	xmlHttp.send(dataString); // Send the data
22 }
23 
24 document.getElementById("login_btn").addEventListener("click", loginAjax, false); // Bind the AJAX call to button click

Note: The above example uses an anonymous function (a function without a name that is declared in an attribute) as the callback. If you are using a certain callback function only once in your program, this is a perfectly valid approach to reduce the amount of code you need to write.

Loading Data from an XML File for Display in HTML

Suppose you have a file note.xml that contains the following information:

1 <?xml version="1.0" standalone="yes" ?>
2 <note>
3   <date year="2013" month="02" day="14" />
4   <to>Sally</to>
5   <message>Happy Valentine's Day!</message>
6   <from>Your Secret Admirer</from>
7 </note>

Further, suppose you had an HTML element with ID note:

1 <div id="note"></div>

You could load this XML file and then display it inside of your HTML document like this:

 1 function getNoteAjax(event){
 2 	// The XMLHttpRequest is simple this time:
 3 	var xmlHttp = new XMLHttpRequest();
 4 	xmlHttp.open("GET", "note.xml", true);
 5 	xmlHttp.addEventListener("load", getNoteCallback, false);
 6 	xmlHttp.send(null);
 7 }
 8 
 9 function getNoteCallback(event){
10 	var htmlParent = document.getElementById("note"); // Get the HTML element into which we want to write the note
11 	var xmlDocument = event.target.responseXML; // Get the XML root node from the response
12 	
13 	// Find the <date/> element from the XML response.  We expect only 1 such element, so we can call
14 	// xmlDocument.getElementsByTagName() and then get the first (and only) element in the array all in
15 	// one step.  This is called chaining.
16 	var xmlDateElement = xmlDocument.getElementsByTagName("date")[0];
17 	
18 	// Put together a YYYY-MM-DD type date into a string based on the attributes of the <date/> element.
19 	var dateString = xmlDateElement.getAttribute("year") + "-" + xmlDateElement.getAttribute("month")
20 		+ "-" + xmlDateElement.getAttribute("day");
21 	
22 	// Get the content of the <to>, <message>, and <from> tags.  Again, you can use a chain to do this in one line for each.
23 	var to = xmlDocument.getElementsByTagName("to")[0].textContent;
24 	var message = xmlDocument.getElementsByTagName("message")[0].textContent;
25 	var from = xmlDocument.getElementsByTagName("from")[0].textContent;
26 	
27 	// Make a <strong> tag, append the date string as its content, and then append it to the HTML element.
28 	var htmlDateObj = document.createElement("strong");
29 	htmlDateObj.appendChild(document.createTextNode(dateString));
30 	htmlParent.appendChild(htmlDateObj);
31 	
32 	// Make a <p> tag to contain the note.
33 	var htmlParagraphObj = document.createElement("p");
34 	htmlParagraphObj.appendChild(document.createTextNode("Dear "+to+",")); // First append the greeting
35 	htmlParagraphObj.appendChild(document.createElement("br")); // Append a couple line feeds
36 	htmlParagraphObj.appendChild(document.createElement("br"));
37 	htmlParagraphObj.appendChild(document.createTextNode(message)); // Write the message itself
38 	htmlParagraphObj.appendChild(document.createElement("br")); // Append a couple more line feeds
39 	htmlParagraphObj.appendChild(document.createElement("br"));
40 	htmlParagraphObj.appendChild(document.createTextNode("Love, "+from)); // Finally, append the salutation
41 	htmlParent.appendChild(htmlParagraphObj); // Append the newly engineered <p> to the HTML element.
42 }
43 
44 document.addEventListener("DOMContentLoaded", getNoteAjax, false); // Bind the AJAX call to page load

This example uses a lot of techniques documented in the #Document Object Model section above. The resulting DOM will be something like this:

<div id="note">
  <strong>2013-02-14</strong>
  <p>Dear Sally,<br /><br />Happy Valentine's Day!<br /><br />Love, Your Secret Admirer</p>
</div>

If you think that this is a lot of code to produce a relatively simple output, you are not alone. You will learn how to do this job in much fewer lines when you learn about jQuery.