Except where otherwise noted, the contents of this document are Copyright 2012 Marty Stepp, Jessica Miller, and Victoria Kirst. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.
var things = ['a', 'b', 'c', 'd', 'e'];
for (idx in things) {
console.log(idx + ', ' + things[idx]);
}
0, a 1, b 2, c 3, d 4, e
var myfunc = function(a, x) {
return a * b;
};
var x = myfunc(2, 3); // 6
function apply(a, b, f) {
return f(a, b);
}
var x = apply(2, 3, myfunc); // 6
function getAlert(str) {
return function() {
alert(str);
}
}
var myAlertFunc = getAlert("What's up!");
function getAlert(str) {
var prefix = "Roy: ";
return function() {
alert(prefix + str);
}
}
var myAlertFunc = getAlert("What's up!");
myAlertFunc(); // "Roy: What's up!"
. syntax
var x = {
'a': 97,
'b': 98,
'c': 99,
'd': 199,
'mult': function(a, b) {
return a * b;
}
};
var things = {'a': 97, 'b': 98, 'c': 99 };
for (key in things) {
console.log(key + ', ' + things[key]);
}
a, 97 b, 98 c, 99
There is no chapter about jQuery in our course book. Learning jQuery will be an exercise in your ability to navigate online APIs and documentation:
JavaScript is a powerful language, but it has many flaws:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
jQuery is so powerful in part because of these design principles
window.onloadWe cannot use the DOM before the page has been constructed. jQuery gives us a more compatibile way to do this.
window.onload = function() {
// do stuff with the DOM
}
$(document).ready(function() {
// do stuff with the DOM
});
$(function() {
// do stuff with the DOM
});
We will be working on a bouncing images example.
document and other DOM objects (* = HTML5):
| name | description |
|---|---|
getElementById
|
returns array of descendents with the given tag, such as "div"
|
getElementsByTagName
|
returns array of descendents with the given tag, such as "div"
|
getElementsByName
|
returns array of descendents with the given name attribute (mostly useful for accessing form controls)
|
querySelector *
|
returns the first element that would be matched by the given CSS selector string |
querySelectorAll *
|
returns an array of all elements that would be matched by the given CSS selector string |
highlight all paragraphs in the document:
var allParas = document.querySelectorAll("p");
for (var i = 0; i < allParas.length; i++) {
allParas[i].style.backgroundColor = "yellow";
}
<body> <p>This is the first paragraph</p> <p>This is the second paragraph</p> <p>You get the idea...</p> </body>
highlight all paragraphs inside of the section with ID "address":
var addrParas = document.querySelectorAll("#address p");
for (var i = 0; i < addrParas.length; i++) {
addrParas[i].style.backgroundColor = "yellow";
}
<p>This won't be returned!</p>
<div id="address">
<p>1234 Street</p>
<p>Atlanta, GA</p>
</div>
// identifying a single elemnt var list = document.getElementById("mylist"); // identifying a group of elements var specials = document.querySelectorAll("li.special");
The $ aka jQuery function selects elements from the DOM using most any CSS selector.
// id selector
var elem = $("#myid");
// group selector
var elems = $("#myid, p");
// context selector
var elems = $("#myid < div p");
// complex selector
var elems = $("#myid < h1.special:not(.classy)");
| DOM method | jQuery equivalent |
|---|---|
getElementById("id")
|
$("#id")
|
getElementsByTagName("tag")
|
$("tag")
|
getElementsByName("somename")
|
$("[name='somename']")
|
querySelector("selector")
|
$("selector")
|
querySelectorAll("selector")
|
$("selector")
|
p tags that have no children, but only if they don't have a class of ignorediv tags with a child that has a class of specialh1, h2, h3, h4, h5, h6)li.#square and periodically change it's position in a random direction.jQuery object or the $ function depending on the context$ function always (even for ID selectors) returns an array-like object called a jQuery object.// false document.getElementById("id") == $("#myid"); document.querySelectorAll("p") == $("p"); // true document.getElementById("id") == $("#myid")[0]; document.getElementById("id") == $("#myid").get(0); document.querySelectorAll("p")[0] == $("p")[0];
$ as a wrapper$ adds extra functionality to DOM elements$ will give it the jQuery upgrade
// convert regular DOM objects to a jQuery object
var elem = document.getElementById("myelem");
elem = $(elem);
var elems = document.querySelectorAll(".special");
elems = $(elems);
querySelectorAll() and querySelector() on any DOM
object.
var list = document.getElementsByTagName("ul")[0];
var specials = list.querySelectorAll('li.special');
find / context parameterjQuery gives two identical ways to do contextual element identification
var elem = $("#myid");
// These are identical
var specials = $("li.special", elem);
var specials = elem.find("li.special");
<p> This is a paragraph of text with a <a href="/path/page.html">link in it</a>. </p>
element nodes (HTML tag)
text nodes (text in a block element)
attribute nodes (attribute/value pair)
every node's DOM object has the following properties:
| name(s) | description |
|---|---|
firstChild, lastChild
|
start/end of this node's list of children |
childNodes
|
array of all this node's children |
nextSibling, previousSibling
|
neighboring nodes with the same parent |
parentNode
|
the element that contains this node |
<p id="foo">This is a paragraph of text with a <a href="/path/to/another/page.html">link</a>.</p>
<div> <p> This is a paragraph of text with a <a href="page.html">link</a>. </p> </div>
div above have?"\n\t" (before/after the paragraph)a tag?
#box childrenbox element and change their position.
var elems = document.querySelectorAll("li");
for (var i = 0; i < elems.length; i++) {
var e = elems[i];
// do stuff with e
}
$("li").each(function(idx, e) {
// do stuff with e
});
for each loop on either because they are not technically arrays, just array-like objects.
$("li").each(function(idx, e) {
// do stuff with e
});
false to exit the loop early$ if we want
$("li").each(function(idx, e) {
e = $(e);
// do stuff with e
});
this keyword refers to the same selected element as e, so this is better jQuery
$("li").each(function() {
// do stuff with this
});
DOM nodes have fields that correspond to the attributes in HTML tags. There are a few exceptions
| HTML attributes | DOM fields |
|---|---|
title |
.title |
id |
.id |
class |
.className |
style="prop: value" |
.style.prop = value |
function highlightField() {
// turn text yellow and make it bigger
var elem = document.getElementById("id");
if (!elem.className) {
elem.className = "highlight";
} else if (elem.className.indexOf("invalid") < 0) {
elem.className += " highlight";
}
}
className property corresponds to HTML class attributeclassName is just a string, not an array like we would want
function highlightField() {
// turn text yellow and make it bigger
if (!$("#myid").hasClass("invalid")) {
$("#myid").addClass("highlight");
}
}
addClass, removeClass, hasClass, toggleClass manipulate CSS classesclassName DOM property, but don't have to manually split by spaces
<button id="clickme">Color Me</button>
window.onload = function() {
document.getElementById("clickme").onclick = changeColor;
};
function changeColor() {
var clickMe = document.getElementById("clickme");
clickMe.style.color = "red";
}
| Property | Description |
|---|---|
style
|
lets you set any CSS style property for an element |
camelCasedNames
backgroundColor, borderLeftWidth, fontFamily.style when setting styles
var clickMe = document.getElementById("clickme");
clickMe.color = "red";
clickMe.style.color = "red";
likeThis, not like-this
clickMe.style.font-size = "14pt";clickMe.style.fontSize = "14pt";
clickMe.style.width = 200;clickMe.style.width = "200px"; clickMe.style.padding = "0.5em";
<button id="clickme">Click Me</button>
window.onload = function() {
document.getElementById("#clickme").onclick = biggerFont;
};
function biggerFont() {
var size = parseInt(document.getElementById("#clickme").style.fontSize);
size += 4;
document.getElementById("#clickMe").style.fontSize = size + "pt";
}
style property lets you set any CSS style for an element
function biggerFont() {
// turn text yellow and make it bigger
var size = parseInt($("#clickme").css("font-size"));
$("#clickme").css("font-size", size + 4 + "pt");
}
css function of the jQuery object allows reading pre-existing stylesfont-size syntax instead of fontSizecss(property) gets the property value, css(property, value) sets the property value// bad!$("#main").css("top", $("#main").css("top") + 100 + "px");
"200px" + 100 + "px" , "200px100px"
// correct
$("#main").css("top", parseInt($("#main").css("top")) + 100 + "px");
square directly in the center of it's parent.#square change direction when it reaches the boundary of it's parent.
function okayClick() {
this.style.color = "red";
this.className = "highlighted";
}
.highlighted { color: red; }
<ul> <li style="font-size: 10px">10px font size</li> <li style="font-size: 20px">20px font size</li> <li style="font-size: 30px">30px font size</li> </ul>
$("li").css("font-size"); // returns '10px'
$("li").css("font-size", "15px"); // sets all selected elements to '8px'
<ul> <li style="font-size: 15px">10px font size</li> <li style="font-size: 15px">20px font size</li> <li style="font-size: 15px">30px font size</li> </ul>
Many jQuery object methods are overloaded
$("#myid").css(propertyName);
$("#myid").css(propertyName, value);
$("#myid").css({
'propertyName1': value1,
'propertyName2': value2,
...
});
$("#myid").css(propertyName, function(idx, oldValue) {
return newValue;
});
What do you think the multi-modifier syntax is?
// bad jQuery$("#main").css("top", parseInt($("#main").css("top")) + 100 + "px");
$("#main").css("top", function(idx, old) {
return parseInt(old) + 100 + "px";
}); // good jQuery
When there is no other return to make, jQuery methods return the same jQuery object back to you
| method | return type |
|---|---|
$("#myid"); |
jQuery object |
$("#myid").children(); |
jQuery object |
$("#myid").css("margin-left"); |
String |
$("#myid").css("margin-left", "10px"); |
jQuery object |
$("#myid").addClass("special"); |
jQuery object |
$("#main").css("color", "red"); $("#main").attr("id", "themainarea"); $("#main").addClass("special");
The implictly returned jQuery object allows for chaining of method calls.
$("img")
.css("color", "red")
.addClass("special")
.src = "foo.png";
Expression return value at each line:
// [<img />, ...] // [<img style="color: red" />, ...] // [<img class="special" style="color: red" />, ...] // cannot chain further because this is an assignment :(
divs with a class of square to the html.background-color of each square when it hits a wall.attr() function
$("img") // poor jQuery style
.css("color", "red")
.addClass("special")
.src = "foo.png";
$("img") // good jQuery style
.css("color", "red")
.addClass("special")
.attr("src", "foo.png");
// we could chain further right here
Suppose you already have a jQuery object, e.g. $("#myid")
| jQuery method | functionality |
|---|---|
.hide() |
toggle CSS display: none on |
.show() |
toggle CSS display: none off |
.empty() |
remove everything inside the element, innerHTML = "" |
.html() |
get/set the innerHTML without escaping html tags |
.text() |
get/set the innerHTML, HTML escapes the text first |
.val() |
get/set the value of a form input, select, textarea, ... |
.height() |
get/set the height in pixels, returns a Number |
.width() |
get/set the width in pixels, return a Number |
innerHTML hackingWhy not just code the previous example this way?
document.getElementById("myid").innerHTML += "<p>A paragraph!</p>";
" and '
document.getElementById("myid").innerHTML += "<p style='color: red; " +
"margin-left: 50px;' " +
"onclick='myOnClick();'>" +
"A paragraph!</p>";
| name | description |
|---|---|
document.createElement("tag")
|
creates and returns a new empty DOM node representing an element of that type |
document.createTextNode("text")
|
creates and returns a text node containing given text |
// create a new <h2> node
var newHeading = document.createElement("h2");
newHeading.innerHTML = "This is a heading";
newHeading.style.color = "green";
Every DOM element object has these methods:
| name | description |
|---|---|
appendChild(node)
|
places given node at end of this node's child list |
insertBefore(new, old)
|
places the given new node in this node's child list just before old child
|
removeChild(node)
|
removes given node from this node's child list |
replaceChild(new, old)
|
replaces given child with new node |
var p = document.createElement("p");
p.innerHTML = "A paragraph!";
document.getElementById("myid").appendChild(p);
var bullets = document.getElementsByTagName("li");
for (var i = 0; i < bullets.length; i++) {
if (bullets[i].innerHTML.indexOf("child") >= 0) {
bullets[i].parentNode.removeChild(bullets[i]);
}
}
removeChild method to remove the given child from the page
The $ function to the rescue again
var newElement = $("<div>");
$("#myid").append(newElement);
jQuery programmers typically 1 line it
$("#myid").append($("<div>"));
The previous example becomes this with jQuery
var bullets = document.getElementsByTagName("li"); for (var i = 0; i < bullets.length; i++) { if (bullets[i].innerHTML.indexOf("children") >= 0) { bullets[i].parentNode.removeChild(bullets[i]); } }
$("li:contains('child')").remove();
.square divs to the page using jQuery.divs to be img tags with a src of laughing_man.jpg.
$("<p id='myid' class='special'>My paragraph is awesome!</p>")
$("<p>")
.attr("id", "myid")
.addClass("special")
.text("My paragraph is awesome!");
$("<p>", {
"id": "myid",
"class": "special",
"text": "My paragraph is awesome!"
});
$ function signatures$(function);
$("selector", [context]);
$(elements);
$("<html>", [properties]);
Here is what it might look like if you tried to insert an image before each special
span tag in a div using the DOM's API.
var spans = document.querySelectorAll("#ex1 span.special");
for (var i = 0; i < spans.length; i++) {
var img = document.createElement("img");
img.src = "images/laughing_man.jpg";
img.alt = "laughing man";
img.style.verticalAlign = "middle";
img.style.border = "2px solid black";
img.onclick = function() {
alert("clicked");
}
spans[i].insertBefore(img, spans[i].firstChild);
}
$("#ex2 span.special").each(function(i, elem) {
var img = $("<img>")
.attr("src", "images/laughing_man.jpg")
.attr("alt", "laughing man")
.css("vertical-align", "middle")
.css("border", "2px solid black")
.click(function() {
alert("clicked");
});
$(elem).prepend(img);
});
$("#ex3 span.special").prepend($("<img>", {
"src": "images/laughing_man.jpg",
"alt": "laughing man",
"css": {
"vertical-align": "middle",
"border": "2px solid black"
},
"click": function() {
alert("clicked");
}
}));