~~SLIDESHOW~~
Contact Hour 14: To be discussed on Wednesday 27th February, 2013.
Presenter: Dr Chris P. Jobling.
As a way of getting around browser quirks, the web developer community, including some major players like Google and Yahoo, have developed and released JavaScript libraries. In this session we will explore the idea of a JavaScript library, mention some of the general purpose and specialized open-source libraries that exist, and introduce jQuery, one of the most widely used JavaScript libraries.
JavaScript is a small language that can be covered in about two weeks worth of lectures if you already know a c-like programming language. Unlike technologies like .NET, Java and Cocoa, it doesn't come with large numbers of libraries and objects that we can use to develop web applications. Unfortunately, even for the limited requirement of manipulating the DOM, differences between browsers make JavaScript more challenging than it should be. Fortunately, many of the problems can be solved using JavaScipt itself, and even better, solutions have been made into open source libraries that have been shared on the Internet.
This material, including some of the examples, is based in part on Chapter 11 of Simon Allardice, JavaScript Essential Training (2011), lynda.com, 22 July 2011. URL: http://www.lynda.com/JavaScript-tutorials/Essential-Training-2011/81266-2.html accessed 18 February 2012 and Joe Marini, Essential jQuery Training, lynda.com, 9 January 2009. URL: http://www.lynda.com/jQuery-tutorials/essential-training/48370-2.html accessed 18 February 2012. For a free alternative see Buck Rogers, jQuery Tutorial (200 videos), thenewboston.com, URL: http://thenewboston.org/list.php?cat=32, last accessed 18 February 2012.
Other examples are taken from public sources on the Internet which are cited in the notes.
For a previous version of these notes see Old JavaScript Libraries notes.
At the end of this lecture you should be able to answer these questions:
At the end of this lecture you should be able to answer these questions:
At the end of this lecture you should be able to answer these questions:
jQuery(“document”).ready()
function?For specialized features:
Some JavaScript libraries are more specialized. Rather than be general purpose, things like Lightbox are simply JavaScript libraries for popping up images on your web site. You've probably seen these ones before. They might be for slideshows. They might be for implementing things like drag-and-drop and working with accordions. They could be as simple as a library that just helps you add curved corners to your divs. And some, might be used as polyfills that make standards that are not yet implemented in browsers – such as the full web forms 2 standard – or back-port features such as those introduced in HTML5 to older browsers.
Most of these libraries are open source and they are free. There is no licensing. You simply grab the code and use it, do whatever you want with it. So we encourage you to explore what's available, and new ones are appearing all the time.
To be discussed in a later session.
<script>
tagThe lastest jQuery is always on the Downloading jQuery page. Note, many libraries come in two forms, the development version that includes the code and comments, and a minified version that has been manipulated to make it as small as possible. You would normally download both and use the development version when you are developing code (you can debug scripts easier) and the production code, which saves bandwidth, but is ureadable, for deployed web sites.
Load template_4js.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="utf-8" /> <title> Loading JavaScript libraries</title> <!-- Modernizr loaded first so that it can do it's job --> <script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script> </head> <body> <p>According to current best practice, you should load your scripts last.</p> <p>Order is important!</p> <script src="js/vendor/some_library.js"></script> <script src="js/useful_functions.js"></script> <script src="js/app_scripts.js"></script> <script> // custom per page scripts here </script> </body> </html>
The idea of putting scripts last is that they will be loaded once the HTML has been read and the DOM constructed.
The order that scripts are loaded is important. You should generally load any library files before the scripts that build on those libraries and finally load any page-specific scripts last.
Each script is loaded, using a HTTP GET request, in the order listed. Unlike other assets such as images, no parallel requests are made. The next script is only loaded when the first script has been downloaded and executed. Thus the more scripts there are the longer they will take to load and the longer the delay before the user can start to use the application. Thus, although it is useful for development to have separate files for each library, you should avoid having many scripts in production. Put them together if you can and minify the result to reduce the size of the downloads. Some development tools and frameworks will do this automatically. For example, see the HTML5 Ant Build Script.
Without jQuery (View on jsFiddle):
// Return element var element = document.getElementById("myDiv"); element.className="highlight"; // destructive! // Return an array of elements var elements = document.getElementsByTagName("p"); for (e = 0; e < elements.length; e++) { elements[e].className="highlight"; }
No other selections are possible. Once a single element or set of elements is selected, you have to walk through the DOM to find an manipulate the remaining elements.
document.getElementById
returns element with id=“myDiv”
or null
if there is no such object. document.getElementsByTagName(“p”)
returns an array of the paragraphs in a document or the empty arrayjQuery(selector)
which accepts a string containing a CSS selector which is then used to match a set of elements.Cross-browser support for:
Feature Group | Purpose | Feature Group | Purpose |
---|---|---|---|
Selectors | Using CSS selectors to matching a set of elements in a document | Attributes | Get and set DOM attributes of elements |
Traversing | Moving through the DOM | Manipulation | Changing the DOM |
CSS | Changing the styles of an element using CSS | Events | Cross browser event handling |
Effects | Animation effects | Ajax | Scriptable HTTP requests for partial page updates |
The best place to find out about these is by following the links to the jQuery API Documentation on the main Documentation Page.
Play with this example on jsFiddle
With jQuery:
jQuery("#myDiv").addClass("highlight"); jQuery("p").addClass("highlight");
Here addClass
is not destructive…it adds the class. Same command used for single element and array of element. jQuery takes care of the selection of elements and the iteration through a collection.
There is also a removeClass(class_name)
and a toggleClass(class_name)
function. The first removes the named class (and only the named class); the second toggles the class – adds it if it doesn't exist, removes it if it does.
jQuery("#someId"); // by id jQuery(".someClass"); // by class jQuery("p"); jQuery("a"); jQuery("li");// by tag jquery("p.description"); // combination of tag and class jQuery("p + p"); jQuery("div > p"); // more complex relationships jQuery("a[href~='swansea.ac.uk']"); // by attribute value
See jQuery Selectors for more documentation and examples
If your CSS is a bit rusty:
p.description
matches <p class=“description”>…</p>
p + p
matches a paragraph that is a sibling of a paragraph, that is for<p>First paragraph</p> <p>Second paragraph</p> <p>Third paragraph</p>
jQuery(“p + p”)
would return
["<p>Second paragraph</p>","<p>Third paragraph</p>"];
div > p
returns all the <p>
elements that are direct descendents (children) of a <div>
(the parent).jQuery(“a[href~='swansea.ac.uk']”)
returns all <a>
(anchor or link) elements whose href
attribute contains the string swan.ac.uk
.jQuery("p:first"); // first match jQuery("p:last"); // last match jQuery("p:even"); // even numbered array index (zero base) jQuery("p:contains('interesting')"); jQuery("p:hidden");
These can be combined with any of the other selectors, for example
jQuery("p.description:first"); jQuery("p.description:contains('interesting')");
Most commonly used:
jQuery('a').attr('href'); // getter jQuery('a').attr('href','http://www.swan.ac.uk'); // setter // Setting multiple attributes jQuery('a').attr({href: "http://www.swan.ac.uk", title: "Home page"}); jQuery('p').html(); jQuery('p').html("<span>Some content</span>"); jQuery('#someInput').val(); jQuery('#someInput').val('new value');
Illustrated in this jsFiddle
See jQuery Attributes for more examples and details.
All functions can be used in a getter (no params) or setter mode. Some setters can take a variety of arguments, such as (name, value)
or objects {par1: val1, par2, val2}
used to set multiple values at once.
Functions that help you move around the selection set:
jQuery('p').append('<span>A Span</span>'); var children = jQuery('p').children(); jQuery('li').each(function(index) { alert(index + ': ' + $(this).text()); }); jQuery('p').previous(); jQuery('p').next();
See jsFiddle for a demonstration of these functions.
See jQuery Traversing for more examples and details.
Functions that help you change the currently selected elements.
An example1)
jQuery('p').hide().css({'border', '3px solid red'}).fadeIn(2000);
To play with this example see this jsFiddle
See jQuery Manipulation for more DOM manipulation functions and examples.
The code example includes an example of CSS manipulation and animation. It will select all paragraphs in the document, initially hide them, apply the equivalent css style
p { border: 3px solid red; }
then make each paragraph fade in to the document over a period of 2000 ms (2 seconds).
The function jQuery
is aliased to $
so you will often see the jQuery function written $('<p>')
as opposed to jQuery('<p>')
. So the example would be simplified to
$('<p>').hide().css({'border', '3px solid red'}).fadeIn(2000);
Functions to add and remove classes from elements, change the CSS directly (equivalent to applying a local style setting to the selected elements), and some special functions for obtaining positional information from elements.
jQuery('p').addClass("highlight"); jQuery('p').css("border","3px solid red"); var position = jQuery("#specialDiv").position(); console.log("left = " + position.left + "; top = " + position.top);
See this example in jsFiddle
See jQuery CSS for more ideas.
To play with events, try this jsFiddle
For a full list of events and event properties see jQuery Events
Use the on
function:
jQuery('[type="radio"]').on("click", function() { alert("Button " + $(this).val() + " clicked"}); });
jQuery('#target').click(function() { alert("Target clicked"); }); jQuery("#other").click(function() { $("#target").click(); });
Functions exist for most of the common events, mouse events and key events. The names are the same as for the HTML attributes: e.g. onblur
has jQuery binding function blur
.
</code>
event.type // type of event event.target // original target of the event event.currentTarget // target of the event during bubbling event.pageX // mouse coordinates of event event.pageY event.preventDefault() // stop the default action (e.g. submit) event.stopPropagation() // stop bubbling
Various ways to change the display
jQuery('p').hide(); jQuery('p').hide('slow'); jQuery('p').fadeIn(); jQuery('p').slideDown(4000); jQuery('p').animate({opacity: 0.25, left: '+=50', height: 'toggle'}, 5000, function() { alert('Animation complete') });
Play with animation using this jsFiddle
For more information and examples see jQuery Effects
Will be discussed in the session on AJAX
It has become a convention to alias the jQuery
function to the one-letter variable $
. Thus you will see
$('p').addClass('highlight');
rather than
jQuery('p').addClass('highlight');
but both are equivalent.
In fact there is a definition in the jQuery code:
window.jQuery = window.$ = jQuery;
Recall that and JavaScript variable or function that is added to the window
object is global to the web app.
$(document).ready(function() { // your code here });
Runs the code (e.g. to add classes, event handlers etc) when the DOM is fully loaded.
This is often shortened to this:
$(function() { // your code here });
Notes:
$(“document”).ready()
function will only be called when the DOM is fully loaded and available for processing by JavaScript.$(document).ready()
and they will be executed in the order encountered. This allows you to modularize your code: for example to separate form validation from animation.The jQuery Events example from this document re-implemented as a stand-alone script.
The Markup:
<!DOCTYPE html> <!-- validator.html An example of input validation using the change and submit events --> <html class="no-js" lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Illustrate form input validation</title> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="css/bootstrap.min.css"> <link rel="stylesheet" href="css/bootstrap-responsive.min.css"> <link rel="stylesheet" href="css/main.css"> <script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script> </head> <body> <div class="container"> <h1>Illustrating jQuery</h1> <section> <h2> jQuery Events </h2> <form id="myForm" action="/cgi-bin/echo_params.cgi"> <fieldset> <legend>Types of Plane</legend> <div class="control-group"> <label class="radio"> <input type="radio" name="planeButton" value="152" />Model 152</label> <label class="radio"> <input type="radio" name="planeButton" value="172" />Model 172 (Skyhawk)</label> <label class="radio"> <input type="radio" name="planeButton" value="182" />Model 182 (Skylane)</label> <label class="radio"> <input type="radio" name="planeButton" value="210" />Model 210 (Centurian)</label> </div> </fieldset> </form> </section> <section> <h2>Simplified Event Regsitration</h2> <ol> <li>Add an event listener to button labelled "Target" that shows an alert when it is clicked</li> <li>Add an event listener to button labelled "Other" that clicks the "Target" button.</li> <div class="control-group"> <button id="target" class="btn">Target</button> <button id="other" class="btn">Other</button> </div> </ol> </section> <section> <h2>The jQuery event object</h2> <div id="outer"> <p>The event will bubble out from the button in the inner div. It should stop bubbling before it reaches the outer div and the form should not submit.</p> <div id="inner"> <form name="myForm" action="http://www.google.co.uk/#hl=en" class="form-search"> <div class="input-append"> <input type="text" placeholder="type something" name="q" class="span2 search-query" /> <button class="btn" type="submit">Search</button> </div> </form> </div> <!-- inner --> </div> <!-- outer --> </section> </div> <!-- /container --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <script src="js/vendor/bootstrap.min.js"></script> <script src="js/plugins.js"></script> <!-- Any external JS loaded here --> <script src="jquery_events.js"></script> </body> </html>
The JavaScript:
$(document).ready(function() { // The event handler for a radio button collection var planeChoice = function (plane) { // Produce an alert message about the chosen airplane switch (plane) { case "152": alert("A small two-place airplane for flight training"); break; case "172": alert("The smaller of two four-place airplanes"); break; case "182": alert("The larger of two four-place airplanes"); break; case "210": alert("A six-place high-performance airplane"); break; default: alert("Error in JavaScript function planeChoice"); break; } }; var describeEvent = function(event, source) { console.log("Handler caught " + event.type + " event from " + source); console.log("Original target") console.log(event.target); console.log("Current target"); console.log(event.currentTarget); console.log("Mouse coordinates: [" + event.pageX + ", " + event.pageY + "]"); }; // Register event handlers for radio buttons $('[name="planeButton"]').on("click", function(event) { console.log(describeEvent(event,"planeButton")); plane = $(this).val(); console.log("Button " + plane + " clicked"); planeChoice(plane); }); // Simplified event registration $('#target').click(function(event) { console.log(describeEvent(event,"Target Button")); alert("Target button clicked"); }); $('#other').click(function(event) { console.log(describeEvent(event,"Other Button")); alert("Other button clicked ... now clicking 'target'"); $('#target').click(); }); // The jQuery event object - allows us to explore bubbling jQuery('button[type="submit"]').on("click", function(event) { describeEvent(event, "'Search' button"); // stop form being submitted event.preventDefault(); }); jQuery('#inner').on("click", function(event) { describeEvent(event, "'#inner' div"); // stop bubbling here event.stopPropagation(); }); jQuery('#outer').on("click", function(event) { // should never fire! describeEvent(event, "'#outer' div"); }); });
The HTML is unchanged!
// Form validator re-implemented in jQuery $(document).ready(function() { // The event handler function for the name text box var chkName = function(event) { var myName = event.target; // Test the format of the input name // Allow the spaces after the commas to be optional // Allow the period after the initial to be optional var pos = myName.value.search(/^[A-Z][a-z]+, ?[A-Z][a-z]+, ?[A-Z]\.?$/); if (pos != 0) { alert("The name you entered (" + myName.value + ") is not in the correct form. \n" + "The correct form is: " + "Last name, First name, Middle initial \n" + "Please go back and fix your name"); myName.focus(); myName.select(); return false; } else return true; }; // The event handler function for the phone number text box var chkPhone = function(event) { var myPhone = event.target; // Test the format of the input phone number var pos = myPhone.value.search(/^\d{3}-\d{3}-\d{4}$/); if (pos != 0) { alert("The phone number you entered (" + myPhone.value + ") is not in the correct form. \n" + "The correct form is: ddd-ddd-dddd \n" + "Please go back and fix your phone number"); myPhone.focus(); myPhone.select(); return false; } else return true; }; var validate_form = function(event) { if (! chkName(event) || ! chkPhone(event)) { event.preventDefault(); } }; // Register event handlers $("#custName").change(chkName); $("#phone") .change(chkPhone); $("#submit") .click(validate_form); });
“Query Mobile is a touch-optimized HTML5 UI framework designed to make sites and apps that are accessible on all popular smartphone, tablet and desktop devices.” – jQuery Mobile
See the demos on the home page.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script> <script src="script.js">
</code>
(Versions 1.9.1 of jQuery and 1.10.1 were the latest stable versions at time of last delivery of this session.)
This ensures that the jQuery library is loaded from a host that is closer to the end-user than you are and is likely to be cached, by your browser or an ISP web-cache.
If you have an encrypted site, you need to download your resources from an encrypted source to avoid complaints from your browser. If you use
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script> <script src="script.js">
</code>
The protocol will match whatever the enclosing page was. So if you access the page from http://...
it will get http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
if your page was encypted it will have used https://...
and the library will be loaded using https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
At the end of this lecture you should be able to answer these questions:
At the end of this lecture you should be able to answer these questions:
At the end of this lecture you should be able to answer these questions:
jQuery(“document”).ready()
function?JavaScript MVC Frameworks