The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.
Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by Mỹ Lê, 2019-10-29 22:07:01

Head First Javascript

head_first_javascript

Overwhelmed by annoying alerts kill bugs dead

Owen attempts to use alerts to put a watch on the callNum variable and Ttweihndediooduwrssawwishbeatnchkautsteodthaienleyrrtceaspneatsgitewitvaetcchode.
try to figure out what’s going on. However, he runs into a problem in that
it gets tedious having to wade through so many alert boxes en route to the
seventh caller. He’s tried using several alerts in different parts of the code,
but he’s just getting overwhelmed with so many less than helpful pop-up
windows, and doesn’t know where to start...

oaAcfrasollwutNnehudiermdbcveavatlalrwsliuaerebeosnl.lel in, the
jumps
all kinds

Wouldn't it be dreamy if there was a
way to watch variables without having
to go through a pop-up window...

you are here 4   515

Download at WoweBook.Com

there’s a console for this?

Browser debugging consoles can help

Most browsers have a debugging console, really an error console, that is
responsible for displaying errors that occur in a script. Error consoles are
very useful for finding out when something goes wrong in a script, and
in many cases helping to diagnose exactly what went wrong. Firefox in
particular has proven to have an excellent error console.

efBsorpreocwfisainelldryinesgryrnooturatxcaoebnrosrouotlersss.carrieptgreerartors,

coWonen’tsvoehleealFtroeiraetdfryoaxclekearnbreuodgrs.heavily

Error consoles are great
and all, but how do they
help me watch variables?

Error consoles don’t really help at all when it

comes to watching variables.

As handy as error consoles may be, they don’t offer any means
of watching variables. But there’s good news—it’s not outside
the realm of possibility to create your own debug console
from scratch that can serve as a watch window.

516   Chapter 11

Download at WoweBook.Com

kill bugs dead

Build a custom console for debugging

The idea of a custom debug console might sound intimidating at first, but
all it really has to do is display text when asked. The key is that the console
must display the debug information directly on the page, not in an alert
box. A separate pop-up window could be used as long as it doesn’t require
the user to click OK, but it’s simpler and just as effective to show the
debug messages directly on the page.

jsDupseetcbiuabgleldmoewebsustaghgeaersmeaaari.ne displayed
page in a

Each line is
a different
debug message.

Imagine a design of a JavaScript debugging console that allows Owen
to display debugging messages in a list within a dynamically created
area on the page. Draw what you think the necessary components of
this design are, and how they fit together, including a custom JavaScript
object for the debugging console.

you are here 4   517

Download at WoweBook.Com

sharpen solution

TpDdreheosebpiguedngreeCtbdyoungaasgsonildnaegnotcnohoebanjtmseocehltteahsniosaodmn.eed Imagine a design of a JavaScript debugging console that allows
Owen to display debugging messages in a list within a dynamically
DebugConsole created area on the page. Draw what you think the necessary
components of this design are, and how they fit together, including a
custom JavaScript object for the debugging console.

EmneaewcthhloicndaeldlorftaowttshheaeddceeubbsutugogmcmodneissssopallegaeyaMroensag.a()

shaded displayMsg()

The debug console itself is
created on the page as a div.

The shaded property
is a boolean that
gets toggled between
true and false for
tbeoaaccakhlgtdreoerubnnuadgtemcotelshosera.ge

tsTudcdphsreeheeeebbcerauuidtaggHdeleTobcdaHeuoMrTsgndenLsMay’cotnoloLaeenhn,mlseacowtimvcolehheead.einlcetltyhoptsabmoignfyeecosalurtuanphdrstpeeeohtreahtney div Weisaicthhhoiunisnedtdihveiidnduiaetlbsudogewbcnuogncshmoilleedssddaigivve,.

div

...

div div

"callNum: 1" "callNum: 2" "callNum: 3"

518   Chapter 11

Download at WoweBook.Com

kill bugs dead

JavaScript Magnets

The code for the debugging console is missing a few pieces.
Fill in the blanks with the code magnets to finish building the
DebugConsole object.

fun/c/tiCorneaDteebutghCeondseoblueg()co{nsole area ( );
var consoleElem = document. ("hr"));

cccooonnnsssooollleeeEEEllleeemmm...issdttyy=llee"..dfceoobnlutogFr"a;m=il"y#3=33"3m3o3n"o;space";

document.body. (consoleElem);

consoleElem. (document.

// Create the alternating background color property

this. = false;

}

DebugConsole.prototype.displayMsg = function(msg) {
/v/arCrmesagtEeletmheentme=ssdaogceument.createElement("div");

msgElement.appendChild(document. (msg));

msgElement.style.backgroundColor = this.shaded ? "#EEEEEE" : "#FFFFFF";

var consoleElem = document.getElementById( );

consoleElem.appendChild( );

// Toggle the alternating background color property

this.shaded = this.shaded;

}

"div" msgElement "debug" !
createTextNode
shaded appendChild createElement

you are here 4   519

Download at WoweBook.Com

JavaScript magnets solution

JavaScript Magnets Solution

The code for the debugging console is missing a few pieces.
Fill in the blanks with the code magnets to finish building the
DebugConsole object.

fun/c/tiCorneaDteebutghCeondseoblueg()co{nsole area

var consoleElem = document. createElement ( "div" );

cccooonnnsssooollleeeEEEllleeemmm...issdttyy=llee"..dfceoobnlutogFr"a;m=il"y#3=33"3m3o3n"o;space"; Ttgehhteesddaoedcbduumegdecntotonsbtoolhdeeyd,einvwdhisiocafhpmpteheneadnpesadigtet.o

document.body. appendChild (consoleElem); ("hr"));
consoleElem. appendChild (document. createElement

// Create the alternating background color property The first child element
in the debug console is a
The background color starts horizontal rule to divide
this. shaded = false; out false, which results in a the console messages from
the rest of the page.
} white background initially..

DebugConsole.prototype.displayMsg = function(msg) { Atomtehsesadgeebiusgacdodnesdole
/v/arCrmesagtEeletmheentme=ssdaogceument.createElement("div"); (msg));as a child div.
msgElement.appendChild(document. createTextNode

msgElement.style.backgroundColor = this.shaded ? "#EEEEEE" : "#FFFFFF";

var consoleElem = document.getElementById( "debug" ); The background
consoleElem.appendChild( msgElement ); color alternates
// Toggle the alternating background color property between each
message so that
this.shaded = ! this.shaded; the messages are
easier to read.

}

520   Chapter 11

Download at WoweBook.Com

kill bugs dead

Debug your debugger

Owen can’t wait to put the new debug console through its paces to find out

what’s still wrong with the radio call-in script. So he imports the debug.js

file into the page and creates the DebugConsole object in the head of the

page.

<script type="text/javascript"> TDvaheribsiaucbgolCedoeinnscotrlheeaeothbeejseatcdtheoafs a global
// Debug console global variable the page.
var console = new DebugConsole();

...

Unfortunately, things don’t go as planned. When he first attempts to use
the debug console, Owen learns that he has compounded his problems by
introducing an entirely new bug of his own into the new debug console.

I don’t understand how the Tdhoceubmreonwtsebrodisy chlaaismninogptrhoaptertthiees. It seems an
document body doesn’t have entirely new
any properties. Doesn’t it hold bug has been
all of the web page content? introduced
into the
script... ugh!

The line of code that generates the error is just trying to append a child
node (div) to the body of the document, which shouldn’t be a problem.

document.body.appendChild(console);

Something else is amiss, although it definitely appears to have something
to do with the new DebugConsole object.

What could possibly be wrong with this code to cause
the document body to somehow end up empty?

you are here 4   521

Download at WoweBook.Com

watching the time roll away Tlniosohaneadevehadoeilfaabdbetlefhoofeartebtohttdehhyiepscabpogooneditnyiets,n. sto

Waiting on the page

The problem with the debug console has to do with the timing of how a
page loads and when script code has access to the body of the page.

Taalocrhateednua’Hst.lT.l.ylMoarafLedtseiededrleeutmonhentenitlthhsteeahtdeph.aabtgoedy <html>

Ah, so script code that <head>
runs in the head of the
page can’t access HTML <title>BSI Case 2: Winning Caller</title>
elements on the page. <<ssv/cca/rrriiDppcettobnuttsgyyopplceeeo==n""=sttoeenlxxeettw//gjjDlaaeovvbbaauassglccCrroviinappsrttoi""la>ebs(lr)ec;="debug.js"></script>

// Total number of calls
var callNum = 0;

fuv/na/crtIicnoacnlrlecNmhueemnc;tkWtihnenecra(lflornmu,mbcearller, winningNum) {
++callNum;

i/f/faol(Crechmrae.tlcs(lkucNbaufmlmoilrte=(r=a);+wwii"nn,nniecnraglNluemr) { " + callNum + "... today\'s winner!");
} number

else {

} cccv/aaaa/lllrlllReeecerrrasFFFleiiilteeeelllrtdddFh...iesfveeoalclcldaeuulcse=lt(e()=dr);o;"cfNuiemexeltndtc.fagolerlteEtrlh"ee;mennetxBtyIcda(l'lcearller');

}

</script>
</head>

<body>
</b<<o/fdf<C<oyoiair>ronlmmmnplg>cuenltrsairmctncekya===pm"""eercc=:aah"dleb<ilcuiofktn.oWtppriounmnntg"n""eiarvdac(a=lttl"tihuc=oiea"ns=lr=."la"fCedroariarl"odml"i,"noa/cdm>aoelc=lu".mcpeahnlptl".egrme"ettEthlyoepdme=e="n"PttOBeSyxTIt"d">('/c>aller').value, 7)" />
</html>

522   Chapter 11 JavaScript code that executes in the head of the page
doesn’t have access to web page content.
Since the head of a page is loaded before the body, any script code that
runs directly in the head of the page must be careful not to attempt to
access any HTML elements that are in the body of the page. This may
seem like a strange restriction, but it makes sense when you consider that
not all that much code is typically run in the head of the page.

Download at WoweBook.Com

kill bugs dead

But what about functions
that appear in the head?
Aren’t they wrong too?

Not all code in the head of a page is executed in the
head of the page.
Placing code in a function that appears in the head of a page is not the
same as running the code in the head of the page—function code
doesn’t run until the function is called. But code that is placed outside of
a function is executed immediately when the header is loaded. This is the
code that can cause problems.
In the case of the DebugConsole object, it can’t be created directly in
the head of the page because its constructor is very much dependent on
content in the body of the page.

Write down when and where you think the DebugConsole
object should be created to make sure that it can safely access
elements on the page.

you are here 4   523

Download at WoweBook.Com

sharpen solution

Write down when and where you think the DebugConsole
object should be created to make sure that it can safely access
elements on the page.

The browser lets us know when a page has finished loading by firing the
onload event. So the DebugConsole object should be created in response to
the onload event. However, the console variable should still be declared in
the head of the page so that the object is global - we just don’t call the
constructor to actually create the object until the onload event fires.

cmtMohunoetsvioDilnlaegetbuebtsguhgCetohcnerseodaeltebiuoognbjoefct<body onload="console = new DebugConsole();">

TntoohwetDhceoenbosutnglroCuacodtneseodvleeinnotbr. jeescptonisse

The peskiest errors of all: runtime Runtime errors
occur only because
The unloaded document body problem is an example of a runtime of specific conditions
error—an error that only shows its face in certain conditions while that take place while
a script is actually running. Sometimes runtime errors only surface a script is running.
under very specific circumstances, such as a certain type of user input
or a certain number of loop iterations taking place. Runtime errors are
often the toughest errors of all to find because they are so difficult to
predict. Sometimes it’s a challenge just reproducing a runtime error when
someone else encounters it.

wrTbaaetehhvrftieecuoeahnrmdlteeeipdisbmtituaiewngnhgheaceirstdonrsonuoabseraoecsltececcnharebauislptsuosetgaddidswiasebtoadyrnas,ulyn.

524   Chapter 11

Download at WoweBook.Com

kill bugs dead

The JavaScript bug trifecta

Along with runtime errors, two other errors we saw earlier round out the
JavaScript bug trifecta: syntax errors, logic errors, and runtime errors.
Any of these kinds of errors are capable of manifesting themselves in
any script, often at the same time! Understanding their differences is an

important part of being able to successfully find and eradicate them. Syntax error

Runtime error An error resulting from a violation of
the rules of the JavaScript language,
An error revealed only by runtime meaning that the code is unfit to run in
conditions, such as the user entering a the JavaScript intepreter.
certain kind of data into a form that
the script can’t handle or attempting <html>
to access an object before it has been
created or initialized. <head> Case 2: Winning Caller</title>
<title>BSI

<script type="text/javascript" src="debug.js"></script>

<sc/vr/airpDtecbotunygspoecl=oe"nts=eoxlntee/wjgalDvoeabbsauclgrCivopantrs"io>albel(e);

Logic error // Total number of calls
var callNum = 0;
bpawtAoioesnrniongtvidehnigoneorttllrevhaowsrnimioognnidimrtgmgchecde.cebeato,rruuhrditmsnioeneirsdwigstshauhpebcanlieycstcdreihbifd.esoaercSridsnnamotsttomlaeeosonlgetledydhixccteeac,ohdocodetdtfeltotyeeadndskoto fun/c/tiIonncrcehmeecnktWitnhneerc(aflolrmn,umcbaelrler, winningNum) {

var callNum;
++callNum;
console.displayMsg("callNum: " + callNum);

/i/faC(lhceearcltkl(Ncfuaomlrl=earwwi+innn"ni,enrgcNaulml)er{number + callNum + "... today's winner!");
form.submit();

}
else {

Write down the type of error for each of the following error descriptions.

Missing parentheses around the test condition of an if statement.
Forgetting to initialize a counter variable to 0.
Creating a loop that loops beyond the last element in an array.
Forgetting to close a function with a closing curly brace.

you are here 4   525

Download at WoweBook.Com

exercise silution

Write down the type of error for each of the following error descriptions.

Missing parentheses around the test condition of an if statement. Syntax
Forgetting to initialize a counter variable to 0. Logic
Creating a loop that loops beyond the last element in an array. Runtime
Forgetting to close a function with a closing curly brace. Syntax

The call number is showing It’s not a num-bah
up as “not a number.”
That’s pretty strange... With the debug console finally up and running, it’s now possible to take
a look at the callNum variable as the calls come in without having to
sift through all those alerts. And as it turns out, an old problem Owen
ignored has finally come home to roost. The callNum variable is
showing up as NaN, which means it isn’t a number. But why isn’t it?

console.displayMsg("callNum: " + callNum);

AtsehtseisncgualpellNaliunwmeatovfcahrciaoobndlee.

Acotnsloealestistwhoerdkienbgu!g

526   Chapter 11

Download at WoweBook.Com

kill bugs dead

When watching isn’t enough

Sometimes watching a variable creates more questions than
answers. Why is callNum not a number? Why is it not getting
incremented? What’s the point of this debug console if it only
confirms what you already know...that there’s a problem. So how
do we go about finding out specifically what it is?

What now?

It might help to try
eliminating code until the call
number changes in value.

Removing code is a great way to simplify

a script while hunting down bugs.

Sometimes less is more when it comes to JavaScript
debugging. In this case, removing code and watching to
see what changes is an excellent idea. But just deleting
code doesn’t sound all that appetizing since the vast
majority of it will remain as is when you’re finished
debugging. We really need a way to disable code, as
opposed to truly removing it.

you are here 4   527

Download at WoweBook.Com

crippled by comments

Comments as temporary code disablers Comments are
extremely useful
Hiding executable code inside comments is an extremely handy way to disable the for temporarily
code while debugging. This allows code to be selectively pulled out of the execution disabling code.
of a script without actually deleting the code. Think of commenting out code as a
means of subtracting lines or chunks of code as needed to help isolate a bug.

funccotnisoonlec.hdeicskpWlianynMesrg((f"ocraml,lNcuaml:le"r,+ winningNum) {
callNum);

/* Increment the call number
//

var callNum;

++callNum; Hey, the call number is now showing
up as 0. So something in the disabled
// Check for a winner { " + callNum + "... today\'s code is turning it into “not a number.”
if (callNum == winningNum) number
+ ", caller
alert(caller

winner!");
form.submit();

}

els/vce/aarl{RlecesarelFtlieetrlhFdei.evclaadllul=eerd=ofc"iuNemelexdnttf.cogareltltEehlree"m;neenxttBycIadl(l'ecraller');
callerField.focus();
callerField.select();

}

*/

}

Tdfduiihssnpiacslbtamlyieosusnlttebhivlueientredyttechbhoeuimngcgmomeidnneetststahhgeaet.
Tiscsohomndeoeecwtaihsl0ilnNt,gruwaminhshivctianhhrgeimaitbdel.aiesnasbled

What do you think will happen if only the line of code
that increments the call number is added back?

528   Chapter 11

Download at WoweBook.Com

kill bugs dead

Problem solved...sort of

By switching to single-line comments, it becomes possible to be more
selective about the code that is disabled. If the line of code that
increments the callNum variable is added back, the callNum variable
starts working as it should. So one of the remaining lines of disabled code
is causing the problem.

function checkWinner(form, caller, winningNum) {
console.displayMsg("callNum: " + callNum);
Single-line comments
are used so that // Increment the call number UlcinanelclNoomufmmceovnadtreiinagfbilnteahlwelyoirngkceirtnegsm.tehnet
ienndaibvliedduaal nldinedsiscaabnlebde. // var callNum;

++callNum;

// Check for a winner
// if (callNum == winningNum) {
// alert(caller
winner!"); + ", caller number " + callNum + "... today\'s

// form.submit();
// }

// else {

// // Reset the caller field for the next caller
// var callerField = document.getElementById('caller');
// callerField.value = "Next caller";
callerField.focus();
// callerField.select();
// }

}

TwinohcrerkescmaellilnkNteuinimtg’svwasirtuiphapboeleasecfdhintcaoal,llly.

Write down what’s wrong with the callNum bug in the debug
console, along with how to fix it.

you are here 4   529

Download at WoweBook.Com

sharpen solution

Write down what’s wrong with the callNum bug in the debug
console, along with how to fix it.

Another variable named callNum is accidentally created as a local variable
using var inside the checkWinner() function. So the callNum local variable
“hides” the callNum global variable, creating a subtle problem to detect. Since
the local variable isn’t initialized, incrementing it and then comparing it to
the winning number results in “not a number.” The fix is to just remove the
line inside the function that creates the local callNum variable with var.

otcKbhoiledliletlienotrgchaaattltehvsecarBlreiiunaagetble#oesf4. // Increment the call number

var callNum;

++callNum; BacccaayclllliNNrdeuuemmmnot,vavtialnlhrygeiactbfrhlueeena,ctlatiensiseoonaorfiulgosieccnsaoaldltlyevhaeitrnihgtaalbeotnlbedaelnda.med

The dangers of shadowy variables A shadow variable

The callNum bug in the radio call-in script is an example of a shadow occurs when local
variable, which is a variable that accidentally hides another variable with and global variables
the same name. The problem arises when a local variable is created with are created with the
the same name as a global variable. JavaScript creates the local variable same name...not good!
and gives it precedence in the local block of code. So any changes made
to the local variable do not carry over to the global variable—the local Global code
variable effectively casts a shadow over the global variable, temporarily
hiding it from the script.

Global
variable.

Local 5 ++callNum;
variable. Local code

0 callNum This code increments ++callNum;
the global variable,
callNum Same name! resulting in 6.
Tavganlhordibisaarblcelomevda,areriineaissnbuclulernteciimnshgaesnnhintgaesd1dot.-wheetdlhoecal

530   Chapter 11

Download at WoweBook.Com

kill bugs dead

Q: When commenting out code to track down bugs, how do I appears, you slowly disable the code a line at a time until the bug
disappears. The former approach works better if you’re clueless
know how much code to disable? about where a bug is located, while the latter approach works better
if you’ve isolated the bug’s location to some degree.
A: This is a judgment call that you’ll get better at as you get
Q: What if I intend to create a shadow variable? Is it OK then?
more experienced with JavaScript debugging. However, it’s never A: That’s like asking if you intend to break your leg, is it OK?
wrong to err on the side of disabling most, if not all of the code near
a problematic area of a script. And if a really nasty problem arises, And the answer is no. Just because you deliberately bring pain
don’t hesitate to disable all of the script code on a page. And also and suffering onto yourself doesn’t somehow make it acceptable.
don’t forget to temporarily remove any import tags that pull external Besides, there’s plenty of hurt to go around in debugging code that is
code into the page. intended to work perfectly, so you shouldn’t be gunning to up the risk
factor deliberately. So the real answer to the question is that shadow
There is another approach that can work if you’ve already isolated variables introduce such confusion and sneakiness in JavaScript
a bug to a particular section of script code. This approach involves code that they should be avoided in all situations.
disabling a line of code at a time until the bug goes away. So instead
of disabling everything and slowly enabling code until the bug

Case closed! Case closed!

With a healthy dose of patience and some help from his new debugging
skills., Owen closes the case and bags a promotion to JavaScript Detective
at Bug Scene Investigators.

DgdreeibtzuezgclgteidinvgeJasOlvewaueStnch,ript

Twscohrreikpibtnugigsdfcerobemuegplrecatodenisowolcieta.hll-ain you are here 4   531

Download at WoweBook.Com

handy dandy checklist

Owen’s bug-squashing checklist

Make sure parentheses are always matched in pairs.
Mmmaaattkccehhseinudgreinpcapuiarrsilrysobf-rcacuacrerlyesfbaurrl aoincudenesdn.tbaloticoknsooffccooddeehaerlpesailnways
Taursnyedhdfaucrnodcnttsiooisntasevncotaildyn.tcyapuosseibniigdepnrtoifbielermnsaimf etsh—eibr onathmevsaraiarebnle’ts
BaendcocnasriestfuelnlytmwixitthhethtewuoseinoHfTqMuoLtaetstarinbduatepsoisftnreocpehsessa,ry.

Uaaspseopesestccriaoalppmeheecah(n\ai’n)rg.acintsetrrsintgosc, soudcehcahsaaraqcutoetres (t\h”a) torhaavne

Nwperovorebkra,aebsvlyeinwrt, eeonvnde’terdsu.esee i=t when yeorruomrebaunt=y=o. JuarvcaoSdceriwptill not
as an

Maacraecknee’stssucirtree—atathneisodpburjneimtciatl jruhilsaytsabbpepefelioenrscetrtoehaweteoedbnlobpaeafdgoeerveeeleanmttteisenmttspr,itgwinghgeicrtheod.

Dsgaolomnb’etatel hoviennger,nbraeemscuealtuloisncegatlinhveasorloimacebalvel vesarayrniaudbngplelrowebdialilclstvhaaabrdilaeobwbleesthhatevhieor.

532   Chapter 11

Download at WoweBook.Com

kill bugs dead

JavaScriptcross Header Info 1
Header Info 2
Before youUtunrntiytloeudr nPewufzouznled respect of bugs into
etc...
an ant farm purchase, try your hand at this puzzle.

1 2 3
4 6
5
10 9
7
8

11

12

13
14

Across Down

2. Use this to quickly take a peek at a variable. 1. Use these to temporarily disable code.
4. Use apostrophes mixed with these when placing JavaScript 3. Make one of these on a variable name and there will be
strings in HTML attributes. problems.
7. The special window browsers use to display errors. 5. The current Web browser of choice for JavaScript debugging.
10. An error that violates JavaScript language rules. 6. Miss one of these surrounding a block of code and you'll have
12. An error that gives the wrong result despite being perfectly trouble.
legal in JavaScript. 8. The number of bug fragments allowed in a chocolate bar.
13. A variable that hasn't been assigned a value is .......... 9. An error that only reveals itself when a script is running.
14. The custom object Owen created to battle bugs. 11. Use this to code special characters in strings.

you are here 4   533

Download at WoweBook.Com

JavaScriptcross solution

JavaScUrnitpitltecdrPouszszleSolution Header Info 1
Header Info 2

etc...

1C 5F 2A L E R 3T
4Q U O T E S 6C Y

M IU P

M 7E R R O R C O N S O L E

E 8S E L

N IF Y 11E
T XO B 9R
10S Y N T A X RU

Y AN S
CT 12L O G I C

1U3 N D E F I N E D A

SM P

14D E B U G C O N S O L E

Across Down

2. Use this to quickly take a peek at a variable. [ALERT] 1. Use these to temporarily disable code. [COMMENTS]
4. Use apostrophes mixed with these when placing JavaScript 3. Make one of these on a variable name and there will be
strings in HTML attributes. [QUOTES] problems. [TYPO]
7. The special window browsers use to display errors. 5. The current Web browser of choice for JavaScript debugging.
[ERRORCONSOLE] [FIREFOX]
10. An error that violates JavaScript language rules. [SYNTAX] 6. Miss one of these surrounding a block of code and you'll have
12. An error that gives the wrong result despite being perfectly trouble. [CURLYBRACES]
legal in JavaScript. [LOGIC] 8. The number of bug fragments allowed in a chocolate bar.
13. A variable that hasn't been assigned a value is .......... [SIXTY]
[UNDEFINED] 9. An error that only reveals itself when a script is running.
14. The custom object Owen created to battle bugs. [RUNTIME]
[DEBUGCONSOLE] 11. Use this to code special characters in strings. [ESCAPE]
534   Chapter 11

Download at WoweBook.Com

Fold the page vertically Page Bender kill bugs dead
to line up the two brains
and solve the riddle. What do all JavaScript bugs deserve? Hey, it’s cool... I’m
It’s a meeting of the minds! not a bug. Honest.

Cases closed!

CLCOaSsEe D1

CCaLsOeS2ED

Turning the other cheek is an
erroneous approach that might overload

your tolerance for bugs. The overall
ickiness of bugs will cause the debilitation

of your code, which is a problem.

you are here 4   535

Download at WoweBook.Com

Download at WoweBook.Com

12 dynamic data

Touchy-Feely
Web Applications

Don’t let my eyes fool you.
Behind this pretty face is raw
emotion just waiting to get out. In
fact, my dynamic personality is my

biggest asset.

The modern Web is a very responsive place where pages
are expected to react to the user’s every whim. Or at least that’s

the dream of many web users and developers. JavaScript plays a vital role in this
dream through a programming technique known as Ajax that provides a mechanism for
dramatically changing the “feel” of web pages. With Ajax, web pages act much more like
full-blown applications since they are able to quickly load and save data dynamically
while responding to the user in real time without any page refreshes or browser trickery.

this is a new chapter   537

Download at WoweBook.Com

I want more...dynamic data Adding new blog
entries to YouCube
Yearning for dynamic data shouldn’t require
editing the web page.
Remember Ruby, cube puzzle afficionado and blogger? Ruby loves her
JavaScript-powered YouCube blog but she is frustrated with having to edit
the HTML file for the entire page just to add new entries. She’d like to
be able to somehow separate the blog entries from the HTML code that
describes the blog page, freeing her up to focus on the blog content itself.

I’d really like to be
able to add new blog
entries without having
to edit HTML code.

Fcurbuestdrraetaemdebrl,oRgguebry.and tARhduebdyiYnotguoCaeundbeietwwtbehlboegpHaeTgneMt.rLy requires
file for
538   Chapter 12

Download at WoweBook.Com

dynamic data

A data-driven YouCube Ruby’s files for the data- Tatthhopeuahctybhslcioincagganldtlbyahetesaeewpdiaeistrbesatdtpoaerwgefeidt.ilheionut
driven pages are available at
http://www.headfirstlabs.
com/books/hfjs/.

Ruby is onto something. A version of her blog that separates blog content

from web page structure involves dynamic data, data that is fed into a

page dynamically as the page is processed by the browser. Web pages

built out of dynamic data are known as data-driven pages because the

page really just defines a structure that gets filled out by the data. In other

words, the data is in charge of the page’s content. Blog data

<blog>

Web page <<<eatnuitttrhlioeer>s>Y>PouuzCzulbeer-RuTbhye</Baluotghofro>r Cube Puzzlers</title>

<entry>

<date>08/14/2008</date>
<body>Got the
</entry> new cube I ordered. It's a real pearl.</body>

<entry>

<date>08/19/2008</date>
<body>Solved
</entry> the new cube but of course, now I'm bored and shopping

for a new one.</body>

<entry>

<html> <date>08/16/2008</date>
<body>Managed
<head> Cube Puzzlers</title> </entry> to get a headache toiling over the new cube. Gotta nap.</body>
<title>YouCube
- The Blog for

src=”ajax.js”> </script> <entry>
src=”date.js”> </script>
<script ttyyppee==””tteexxtt//jjaavvaassccrriipptt”” <date>08/21/2008</date>
<script <body>Found
</entry> a 7x7x7 cube for sale online. Yikes! That one could be

a beast.</body>

<sc/Dr/aitrpCeetu.tsputtrryoonpmteo(=Dtt”ayhttpieeesx..tfsg/uhejnotacrMvttoaiFnsootcnrhrm(ita)pott+”d=>i1sf)puln+acyt“i/ao”nd(+a)tte{hiisn.gMeMt/DDaDt/eY(Y)YY+ format <entry>
“/” + this.getFullYear();
<date>08/29/2008</date>
<body>Met up
</entry> with some fellow cubers to discuss the prospect of
a 7x7x7
<entry> cube. Mixed feelings.</body>

} <date>08/27/2008</date>

/f/un/Bc/ltoiAgosnsoibBgjlneocgtt(hbecoodpnyrs,otprdeuarcttteio,ersimage) { <body>Went ahead and ordered the scary 7x7x7 cube. Starting a mental
this.body = body; </entry>
tthhiiss..diamtaege==daitmea;ge; exercise regimen to prepare.</body>
<entry>
}
<date>09/3/2008</date>
... <body>Attended
</script> </entry> a rally outside of a local toy store that stopped carrying
</head>
<entry> cube puzzles. Power to the puzzlers!</body>

<date>09/5/2008</date>
<body>Got the
</entry> new 7x7x7 cube. Could be my last blog post for a while...

<entry> </body>

<bo<<<<<<<dhiiidiiy3mnninn>gppvppoYuuuunosttittlurdoCctt=ttau=yy”yydb”ppbpp=eceelee”u==o==l-b””g””oebt”bbaT.ue>uudhptx<ttBentt/ttlgo”doooB”ninngl”iv””(oad>)gli=ii;td”dd”f==s==>o””e””rYsasvoerhiCuacoeuCrhwwbuctarebhelae”xlnP”t”duv”oz/avmz>lna”lualeemuvr=eeas”==l<S””u/esSehaeh=3rao”>crwVhcihAettlwhelexatBB”lRloaovgngad”lEounmdeti=rBs”ila”eobsgl/”e>Eddn=it”srdayib”slaedbdil=se”addb”ilseoadnb=cl”ledidic”ska=ob”nlsceeldai”rcckoh=nB”clslohigoc(wk)B=;l””orga/(n>)d;o”mB/l>og();” /> <date>09/19/2008</date>
</body> <<ibmoadgye>>Wcouwb,e7i7t7.tponogk</miemaagem>onth but the new cube is finally solved!</body>
</html> </entry>

<entry>

<date>09/24/2008</date>
<body>I dreamed
</entry> last night a huge cube was chasing me, and it kept
</entries> yelling
my name backwards... Ybur!</body>

</blog>

JTdcaoyhvdneaaeSmwcfeirocbirpbptwlaoegcgbeoddpcaeaotgnfaetoairsnitntirnsoucHcottTrhupeMroerpLaaptgluiens.g JfdaaoavrftaianpSarcalornciHdpeTtsbsMilinesLgnrdetiWsnhpegeobnibtsplioabigngleteo.

The blog entries are With the help of JavaScript, raw blog data is dynamically merged with
fed to the blog page HTML code to generate a final YouCube page that looks identical to the
from a separate file. original. But this data-driven page is assembled from separate parts: the
structural page and the blog data. With the blog data broken out into its
own file, Ruby is free to manipulate the blog content separate from the
HTML, CSS, and JavaScript code for the web page.

<html> <blog> dueRpadutdibtaayt-tedohnrihsliyevferhnilnaebeswltotogo.
<head>
... <title>...
</head> <author>...
<entries>
<body>
= ... + <entry>
</body> ...
</html>
</entry>

...

</entries>

</blog>

youcube.html blog.xml

you are here 4   539

Download at WoweBook.Com

stitch in time saves nine

Dynamic data sounds
pretty complicated. I bet it
requires a bunch of messy
JavaScript code, right?

Dynamic data requires a little more coding effort up
front but it pays huge returns on the back end.
Although a page driven by dynamic data certainly requires some
additional planning and effort up front, it more than pays for itself
in the long run with quick and easy page updates. Besides, JavaScript
has built-in support for dynamic data thanks to a nifty programming
technique dubbed Ajax.

540   Chapter 12

Download at WoweBook.Com

Ajax is all about communication dynamic data

Ajax makes dynamic data possible by allowing for tiny Ajax allows a web page
“conversations” between the client web browser and web to dynamically receive
server. More specifically, a script is able to ask the server for data from a web server.
some data, like a collection of blog entries, and the server
delivers it using Ajax. The script then takes the blog data Server
and dynamically incorporates it into the page.

TtsehhreevebcrllioegunstidnagwteaAbjfaprxao.gme requests
the web

The client initiates an tarJinhneatedqveuawrieSnmsecctbero,dirpphpiataaogrnresydae.,tlriinivnngeigtstitaahthseeintrgdheeastpthoaensinet, o
Ajax request, and then
waits for a response.

<html> Web browser.
<head>
... <blog> bTrtelhohsegepordsneeadqrtsuvaeew.srtit,rheacntedhivees
</head> <title>...
<author>...
<body> <entries>
... <entry>
</body> ...
</html> </entry>
...
youcube.html </entries>

Client </blog>

Tstehonedtsihneegrvctelhrieenrteb.slopgonddastbay blog.xml

witrUtihetpsethopoonobunltortshegeec,adetpipavhataiegngaegecalitrinneehdsntleotaaasnddtetdra.lvkysee,rs’s What does “XML” mean in the context of blog data?
How do you think it helps with dynamic data?

you are here 4   541

Download at WoweBook.Com

an html by any other name XML is a markup
language used to
An HTML for everything: XML format any kind
of data.
The “ML” in HTML stands for markup language, and it refers to the
fact that HTML uses tags and attributes to create hypertext (the “HT”).
Just as HTML is used to create hypertext web pages, XML is another
markup language that is used to create, well, anything you want. That’s
what the “X” means—anything! The idea is that there are all kinds of
data that could benefit from being stored as tags and attributes. So why
not extend the reach of markup languages to solve other data problems?

<html> Puzzlers</title>

<head> - The Blog for Cube
<title>YouCube
</script>
<script ttyyppee==””tteexxtt//jjaavvaassccrriipptt”” src=”ajax.js”> </script>
<script src=”date.js”>

HTML<sc/Dr/aitrpCeetu.tsputtrryoonpmteo(=Dtt”ayhttpieeesx..tfsg/uhejnotacrMvttoaiFnsootcnrhrm(ita)pott+”d=>i1sf)puln+acyt“i/ao”nd(+a)tte{hiisn.gMeMt/DDaDt/eY(Y)YY+format
“/” + this.getFullYear();

}

/f/un/Bc/ltoiAgosnsoibBgjlneocgtt(hbecoodpnyrs,otprdeuarcttteio,ersimage) { Web page
this.body = body;
tthhiiss..diamtaege==daitmea;ge;

}

...
</script>

</head>

<bo<<<<<<<dhiiidiiy3mnninn>gppvppoYuuuunosttittlurdoCctt=ttau=yy”yydb”ppbpp=eceelee”u==o==l-b””g””oebt”bbaT.ue>uudhptx<ttBentt/ttlgo”doooB”ninngl”iv””(oad>)gli=ii;td”dd”f==s==>o””e””rYsasvoerhiCuacoeuCrhwwbuctarebhelae”xlnP”t”duv”oz/avmz>lna”lualeemuvr=eeas”==l<S””u/esSehaeh=3rao”>crwVhcihAettlwhelexatBB”lRloaovgngad”lEounmdeti=rBs”ila”eobsgl/”e>Eddn=it”srdayib”slaedbdil=se”addb”ilseoadnb=cl”ledidic”ska=ob”nlsceeldai”rcckoh=nB”clslohigoc(wk)B=;l””orga/(n>)d;o”mB/l>og();” />
</body>
</html>

<blog> Shopping transaction
Song list
<<<eatnuitttrhlioeer>s>Y>PouuzCzulbeer-RuTbhye</Baluotghofro>r Cube Puzzlers</title>

<entry>

<date>08/14/2008</date>
<body>Got the
</entry> new cube I ordered. It's a real pearl.</body>

<entry>

<date>08/19/2008</date>
<body>Solved
</entry> the new cube but of course, now I'm bored and shopping

for a new one.</body>

<entry>

<date>08/16/2008</date>
<body>Managed
</entry> to get a headache toiling over the new cube. Gotta nap.</body>

<entry>

<date>08/21/2008</date>
<body>Found
</entry> a 7x7x7 cube for sale online. Yikes! That one could be

a beast.</body>

XML<entry>
<date>08/29/2008</date>
<body>Met up
</entry> with some fellow cubers to discuss the prospect of
a 7x7x7
<entry> cube. Mixed feelings.</body>

<date>08/27/2008</date>
<body>Went ahead
</entry> and ordered the scary 7x7x7 cube. Starting a mental
exercise
<entry> regimen to prepare.</body>

<date>09/3/2008</date>
<body>Attended
</entry> a rally outside of a local toy store that stopped carrying

<entry> cube puzzles. Power to the puzzlers!</body>

<date>09/5/2008</date>
<body>Got the
</entry> new 7x7x7 cube. Could be my last blog post for a while...

<entry> </body>

<date>09/19/2008</date>
<<ibmoadgye>>Wcouwb,e7i7t7.tponogk</miemaagem>onth but the new cube is finally solved!</body>
</entry>

<entry>

<date>09/24/2008</date>
<body>I dreamed
</entry> last night a huge cube was chasing me, and it kept
</entries> yelling
my name backwards... Ybur!</body>

</blog>

Blog entries

What makes XML so powerful is its flexibility. Unlike HTML,
which has a fixed set of tags and attributes, XML doesn’t
define any tags and attributes—it just sets the rules for how tags
and attributes are created and used. It’s up to each particular
application of XML to spell out the specifics of the tags and
attributes that represent the specific data.

542   Chapter 12

Download at WoweBook.Com

dynamic data

XML lets you tag YOUR data YOUR way Similar to HTML code,
athhisieXraMrcLhycoofdeelceomnesinsttss. of
The real beauty of XML is that it can turn anyone into a custom
tagmaker by using a little tag and attribute alchemy to cook up an entirely
custom markup language for any purpose. There are certainly lots of
existing XML languages that have already been created to solve lots of
different problems, and it’s not a bad idea to use one of those if it happens
to fit your needs. But creating a custom markup language of your very
own is a tough temptation to resist.

<movie> Emitaoscvohiewainsspusetncoitqrueoedftwtaihgt.ehin
<title>Gleaming the Cube</title>
<releaseDate>01/13/1989</releaseDate>
<director>Graeme Clifford</director>

<summary>A skateboarder investigates the death of his adopted brother.</summary>

</movie> The movie details
are c<omnotvaiein>edtawgi.thin
Even though you’ve never seen this example XML markup language, the
which is entirely custom, the descriptive tags make it possible to decipher
the data. Even more importantly, the tags are very specific to the data
being stored—it just makes sense to use a tag named <director> when
storing the director of a movie!

Match the following tags with their descriptions, and then write down next to each description if
the tag is an HTML or XML tag.

<itunes:author> Bold text in a web page.
<span> The title of an online news feed.
<title> An input control in a web page.
<strong> Text that is converted to speech for a telephone caller.
<input> The artist of an iTunes podcast.
<prompt> Inline content in a web page.

you are here 4   543

Download at WoweBook.Com

exercise solution

Match the following tags with their descriptions, and then write down next to each description if
the tag is an HTML or XML tag.

XML <itunes:author> Bold text in a web page.
HTML <span> The title of an online news feed.
XML <title> An input control in a web page.
HTML <strong> Text that is converted to speech for a telephone caller.
HTML <input> The artist of an iTunes podcast.
XML <prompt> Inline content in a web page.

XML is just text

Similar to HTML, XML data is just text, which means it is stored in a X.sxtMmorlLefdidleianteafxitliesesntswyiopitnic.halaly
normal plain text file. However, XML files are named with a .xml file
extension, as opposed to the .html or .htm extensions used in HTML files.

So the data-driven
version of YouCube can
be updated by editing
an XML document... cool!

<blog>

<<<eatnuitttrhlioeer>s>Y>PouuzCzulbeer-RuTbhye</Baluotghofro>r Cube Puzzlers</title>

<entry>

<date>08/14/2008</date>
<body>Got the
</entry> new cube I ordered. It's a real pearl.</body>

<entry>

<date>08/19/2008</date>
<body>Solved
</entry> the new cube but of course, now I'm bored and shopping

for a new one.</body>

<entry>

<date>08/16/2008</date>
<body>Managed
</entry> to get a headache toiling over the new cube. Gotta nap.</body>

<entry>

<date>08/21/2008</date>
<body>Found
</entry> a 7x7x7 cube for sale online. Yikes! That one could be

a beast.</body>

XML <blog><entry>
<date>08/29/2008</date>
<body>Met up
</entry> with some fellow cubers to discuss the prospect of
a 7x7x7
<entry> cube. Mixed feelings.</body>

<date>08/27/2008</date>
<body>Went ahead
</entry> and ordered the scary 7x7x7 cube. Starting a mental
exercise
<entry> regimen to prepare.</body>

<date>09/3/2008</date>
<title>...<body>Attended
a rally
</entry>
<entry>
outside of a local toy store that stopped carrying cube puzzles.

Power to the puzzlers!</body>

<date>09/5/2008</date> <author>...
<body>Got the
</entry> new 7x7x7 cube. Could be my last blog post for a while...

<entry> </body>
<date>09/19/2008</date>
<<ibmoadgye>>Wcouwb,e7i7t7.tponogk</miemaagem>onth but the new cube is finally solved!</body> <entries>
<entry>
</entry>
<entry>

<date>09/24/2008</date> ...
<body>I dreamed
</entry> last night a huge cube was chasing me, and it kept
</entries> yelling
my name backwards... Ybur!</body>

</blog> </entry>

...
</entries>

</blog>

blog.xml

544   Chapter 12

Download at WoweBook.Com

dynamic data

XML + HTML = XHTML XHTML is a version of
HTML that adheres to
They may have different file extensions but XML and HTML have a very the more rigid syntax
important connection, and it’s called XHTML. XHTML is a modern rules of XML.
version of HTML that follows the stricter rules of XML. For example,
every starting tag in an XHTML web page must have a closing tag.
HTML plays fast and loose with its syntax, meaning that you can get away
without pairing up tags such as <p> and </p>. XHTML isn’t so forgiving,
and requires such tags to always appear as matched pairs.

HTML XHTML
This is a paragraph of text in HTML.<p> <p>This is a paragraph of text in XHTML.</p>

Ttithhseeelsf<tpai>nrtHtaTogrMiesLndocfootdfeenatuposaeddraenbgorytapeh. TaapgpseacronatsaminaintgchceodntpeanitrsminusXt HaTlwMayLs.

Another important difference between HTML and XHTML involves
empty tags, such as <br>, which must be coded with a space and then a
forward slash at the end to indicate that there is no closing tag.

HTML XHTML
This is just a sentence.<br> This is just a sentence.<br />

TwishitoehfoetumetnptacyofdloienrdewabinrrdeHaTsklaMtshaL.g Areqsupiarceedainndalfloermwpatryd slash are
tags in XHTML.

One more important distinction between HTML and XHTML is that
XHTML requires all attribute values to be enclosed in quotes.

HTML XHTML
<a href=home.html>Go home</a> <a href="home.html">Go home</a>

Ttinhheqeuraouttletesrs,iobwfuhtXiechHvaTvlMuioelLaits.ne’st All XHTML attribute values must
appear within quotes.

Although XHTML doesn’t directly factor into Ruby’s immediate needs in you are here 4   545
terms of modeling blog data in XML, it does illuminate some of the most
important syntax rules of XML, which apply to all XML-based languages,
including Ruby’s custom blog data language.

Download at WoweBook.Com

XHTML vs. XML

Tonight’s talk: HTML and XML drop the dime on web data

HTML: XThaMhseLblae, teanensdtreivfseorcrsamiloluenladtofeXdHHTuTsMMingLL. XML:

You know, you’ve really made things confusing for
me. Here I am the backbone of the Web, and now
many people are confused about me thanks to you.

It’s not my fault that you have tunnel vision, always
thinking about web pages. I broadened my mind,
and in doing so I can represent any kind of data.

But you’re still no good without me because
browsers only display HTML code. They don’t even
know what to make of you.

Hey, I’m a mysterious fella. The truth is I’m a man
without a face—all substance and no appearance. I
need you when it comes time to reveal myself.

How is that possible? Who cares about data with no
appearance?

Wow, you really don’t get out much, do you? The
rest of the world operates on data that can’t be seen
the majority of the time. Bank transactions, political
polls, weather conditions, you name it.

All that stuff can be seen thanks to me—it’s all right
there on the Web.

That’s true, but how do you think it gets stored
before it makes it to a web browser? Not as
paragraphs and tables, I can tell you that. It often
gets stored using me because I provide lots of
structure and context—I make data easy to process.

I see. So are you suggesting that we actually work
together?

Absolutely! I have no concept of what data looks
like. Instead, I focus on what it means. As long as
people keep using web browsers, I’ll continue to
need your help displaying the data I represent.

That’s a huge relief !

546   Chapter 12

Download at WoweBook.Com

dynamic data

XML and the YouCube blog data

XHTML is a great application of XML that is rapidly improving the
structure and reliability of web pages. With respect to the YouCube blog,
however, Ruby needs a custom XML language that models her specific blog
data. This requires assessing the different data required of the blog, and
considering how it might fit into the context of hierarchical XML tags.

<blog> YouCube - The Blog for Cube Puzzlers
<title> Blog.prototype.signature = "by Puzzler Ruby";
<author>
<entries> blog[0] = new Blog("Got the new cube I ordered. It's a real pearl.",
<entry> new Date("08/14/2008"));
<date>
<body>

Invent your own XML language for storing a blog, and use the language
to code a blog entry. Items such as title, date, author, and the entry itself
should be considered.

<blog>

</blog>

you are here 4   547

Download at WoweBook.Com

sharpen solution

Invent your own XML language for storing a blog, and use the
language to code a blog entry. Items such as title, date, author, and
the entry itself should be considered.

iTinsshciedoenetntathiinereedblo<gbl<otigt>le>YouCube - The Blog for Cube Puzzlers</title> The <title> tag title.
<blog> tag. <author>Puzzler Ruby</author> houses the blog

<entries> tGhueesbslowghaatutthaogr?holds

The collection <entry>
of blog entries
is stored within <date>11/14/2007</date>
the <entries>
tag. <body>Got the new cube I ordered. It’s a real pearl.</body>
Each blog entry is
</entry> the <entry> tag. represented by

</entries> Teoawhcenhdrbealstopegecaetnnidtverbytoahdgaysv.eoftheir

</blog>

Q: Why not just store blog data as regular unformatted text? Q: What is the connection between XML and Ajax?
A: You could but then it would put a huge burden on the script A: Ajax was once taken to be an acronym for Asynchronous

code to sift through the data and try to break it apart into separate JavaScript And XML, so XML was at one point directly tied to Ajax.
blog entries with their own dates and bodies. XML adds a predictable That acronym is now considered passé, as the role of Ajax has
structure to data so that you can easily distinguish between separate widened to not always require XML as part of the equation. But the
fields of data, such as unique blog entries with their own dates and reality is that XML still forms the basis of most Ajax applications
because it provides such a great mechanism for modeling data.
Q:bodies, not to mention the title and author of the blog itself.
Is the <entries> tag really necessary in the XML As we find out later in the chapter, there is a connection between
Ajax and XML in the way that JavaScript supports Ajax. JavaScript
A:blog data? doesn’t lock you into using XML as a data format for carrying out Ajax
It isn’t strictly necessary but it does make the data format requests and responses, but it does make them much easier when
more structured and easier to understand. For example, without the handling all but the most trivial of data. So although Ajax purists may
<entries> tag in the previous blog data, it would be impossible claim that XML and Ajax have no real connection to one another, in
to tell that the blog format is capable of supporting multiple practical terms they usually go hand in hand. The old acronym still
<entry> tags but only one <title> and <author> tag. rings true most of the time even if it has fallen out of favor. We’ll
The <entries> tag implies that there is a collection of multiple explore the “asynchronous” part of the acronym a bit later.
blog entries, which gives the data more structure and makes it more
obvious how the data should be used.

548   Chapter 12

Download at WoweBook.Com

dynamic data

I still don’t get it. How does storing data
in a special format make it dynamic?

XML alone isn’t dynamic but it happens to mesh
quite well with both Ajax and the DOM.
XML is the data format most commonly used with Ajax, and
therefore is the logical candidate for representing blog data that will
be sent back and forth from server to client in the data-driven version
of YouCube. It’s the highly structured nature of XML that makes it
so ideal for shuttling data.
And XML’s similarity to HTML (XHTML) makes it possible to
use the DOM to access XML data as a tree of nodes. This means
you can write JavaScript code that traverses a tree of XML nodes,
carefully isolating desired data, and then incorporating it into a web
page dynamically. It’s all these things and more that make XML a
great data storage solution for building dynamic, data-driven pages.

you are here 4   549

Download at WoweBook.Com

adding ajax

Injecting YouCube with Ajax

With a shiny new XML blog document in hand, Ruby is ready to
dynamically load it into the YouCube page with the help of Ajax.

How exactly does
Ajax allow XML data to
be dynamically loaded
into a web page?

2 Server

The server receives
the request and

gets to work
creating a response.

The Request

Ajax revolves around the concept of requests Tbfnliaholmegeecdroeoanqfttuaaet.ishnteinigsXttMhhLee
and responses as the means of carrying out
the communication of data between the client blog.xml
browser and the server.

1

The browser sends
the request to the
server and waits
for a response.

<html>

<head>

atbPblhroleiegorwtdeoatbtosahps,oaewagnneddtidnhgtoeehtbsenhlro’eetgfAohejranaevtxerisirtenesh’tq.euest, ...
</head>

<body>
...
</body>
</html>

youcube.html

550   Chapter 12

Download at WoweBook.Com

dynamic data

3 XTinhMteLheenbtAliojragexfcrioleenstpaeornnetsesr.eotfurtnheed
The server creates a
response for the browser
by packaging up the data
in the blog file.

<blog>
<title>...
<author>...
<entries>
<entry>
...
</entry>
...
</entries>

</blog>

blog.xml

Server The Response

rrJrAeeeasqqvspuuaeoeiSrnrsvcseteerdsrip-dattanso)itddapiesp.rrosseccopermsipesttthAiem(jnaeoxst 4
The browser
unpackages the XML <html>
data in the response <head>
and carefully ...
incorporates it into </head>
the web page.
<body>
cciOnaontndceeegbreotafhsteeetedhXneiMinnwtLeotbhtdephaatebgarHeo,iTwsiMsterL. ...
</body>
</html>

youcube.html

The cJhraaenvaadtSliincngrgipttthheecoArdejesapxroenrssepeqouinsessirtbulen
for
and
within the web page.
What kind of JavaScript code do you think is responsible
for working with Ajax requests and responses?

you are here 4   551

Download at WoweBook.Com

the JavaScript part of the equation

JavaScript to the Ajax rescue: XMLHttpRequest

JavaScript includes a built-in object called XMLHttpRequest that is used to initiate
Ajax requests and handle Ajax responses. This object is fairly complex, containing
several different methods and properties that work together to support Ajax.

readyState TporbhojeeprceetrtabrieuestaintfhteewhseeoaXtrhMeerLthHmetettmphoRostdeqs uaensdt
important ones.
3T0 (h(rueencnienuiivmtiinaeglri)iz,ceodsrt)a,4t1e(l(ooofapdethened),)r.2eq(sueenstt):,
abort()

status XMLHttpRequest Cancel the request.

The HTTP status code of the readyState abort() TnifeheitdshsmeteAotjhbaoexdcriaesnqcouenellslytedu.sed
request, such as 404 (not found)
or 200 (OK). open()
status
Prepare a request by
TtdohegteeseterhmteiwrnoecapifnrotbpheeerutsAieejdsaxto onreadystatechange open() specifying its type and URL,
responseText send() among other things.
responseXML
request has finished
with a valid response.

onreadystatechange send() iTrgwteeohattredoksayenttatohAnwgedjeoastextmhrheevrerteenrhqt.ousoeednsstd
A reference to the function
that is called when the state Send the request to the
of the request changes. server for processing.

TreohhevfaohesnlipdntsdotshlnpeeasrhreoaArptniejesdhafralxpeettrrryreoiencsfiqsecuceusnuasecneltstlidtoeqi.douctnehhwaiiehsnnecgwtnuehhsstetarh-oteemitttsehthviaesetnet responseText
The response data returned
from the server, as a string
of plain text.

responseXML TtsehhreevsederattiwnaotrehptreouArpenjraetxdierbseysspttoohnresee.
The response data
returned from the server,
as an object consisting of
a tree of XML nodes.

552   Chapter 12

Download at WoweBook.Com

dynamic data

XMLHttpRequest is pretty complex

The XMLHttpRequest is incredibly powerful and also surprisingly flexible. The XMLHttpRequest
But with that power and flexibility comes complexity, meaning that even the object is powerful but
most basic of Ajax requests requires a fair amount of JavaScript code. This also somewhat of a
is thanks in part to browser inconsistencies, but it also doesn’t help that the pain to use.
different options available for fine-tuning the object’s behavior can be confusing
when all you really need to do is quickly move some data dynamically.

As an example, consider that the following code is necessary just to create an
XMLHttpRequest object that will work across a variety of browsers:

var request = null; (TocdIbrEihfeje)efactesctriuonepdgbnpeetotcrhhaataeupsspiXetrtoMosdaoiLtcmfhrfeHeyetsbrtaertpnoofRtwelesywqe.rusest
if (window.XMLHttpRequest) {

try {
request = new XMLHttpRequest();

} catch(e) {

request = null;

} Geek Bits
// Now try the ActiveX (IE) version
} else if (window.ActiveXObject) { The problem

try {

request = new ActiveXObject("Msxml2.XMLHTTP"); with creating

// Try the older ActiveX object for older versions of IE an XMLHttpRequest
object is that browsers
} catch(e) { must provide their own
implementations of the
try { object. The good news
is that the methods and
request = new ActiveXObject("Microsoft.XMLHTTP"); properties are consistent
across all browsers—it’s
} catch(e) { the object creation that
has to factor in browser
request = null; differences.

} Tgerrharecoertf-ruhylla-yncddalteinacglh wmstietachthearmnuinesntmtimtieshaeatrnraoalrdlosv.wasncaedscJriapvtaStcoript
}
}

After the XMLHttpRequest object is created, it’s time to set the request

handler function and then open the request. Twhhiesnisthtehesecruvsetromresfpuonncdtsiotnotthhate is called
request.onreadystatechange = handler; request.

request.open(type, url, true); // always asynchronous (true)

dOepteneirnmgintehsewrheaqtuekstindgeotfs riteqrueeasdtyittoisb(eGsEeTnto, ranPdOaSlTso).

When opening a request, you must specify the type ("GET" or "POST"),
as well as the server URL and whether or not the request is asynchronous.
An asynchronous request takes place in the background without
making a script wait, so pretty much all Ajax requests are asynchronous.

you are here 4   553

Download at WoweBook.Com

i get it

Of gets and posts The two types of
requests used with Ajax
The type of an Ajax request is very important, and reflects not only what are GET and POST, the
is being sent to the server, but also the intent of the request. One type of same ones used when
request, also known as a request method, is GET, which is used primarily submitting HTML forms.
to retrieve data from the server without affecting anything on the server.
The other type of request, POST, typically involves sending data to the
server, after which the state of the server usually changes somehow in
response to the data that was sent.

GET POST

UcaspahemsneraervondXfeeugrfcMneotitrnasLfondotrfyahfittlreheadeUitaornrteniRgaetrvtLocihieanneivnfgatshsnlettehrteihvlecsleaeebbrtrs.lesvdoaesogrre.yedn.sSatnGmt’tEatoaTfltrlhoisem esidosnUunoafctsatmrhtaeyhrdbeaeethasostssoopdeetwoh.yrsnevnDecnesaabeardm,u.ltoasPsdiugecaOccsatauShlaanlsyTiatcnsosahitgsidsatlhaalidndvebigwenieensageegrlibrneafvdotfeuntoarhrretraaenmwthetst.aaodtbastlaktoeg

GET Request POST Request

Name of XML blog.xml DIBamotadegy:e::0"9cT/uh2be6es/ae2p0ad0rr8te.apmnsgjust..."
file containing
the entire blog. The GET request Server eTbcnehhtcaeranyugPseOeissSttsTthhoeerrneesdeeqwru. veesbtrlog New blog entry
has no effect on the to be stored on
server because it’s the server.
purely a blog retrieval.

Client <blog> POST Response Client
<<taiuttlheo>r.>.....
<entries>
<entry>
...
</entry>
...
</entries>
</blog>

blog.xml

GET Response

554   Chapter 12

Download at WoweBook.Com

dynamic data

Get or Post? A request with XMLHttpRequest

After deciding on a request type and specifying it when opening the request, it’s
finally time to send the request to the server for processing. The specific code to
submit a request varies according to whether the request is a GET or a POST.

TspheecifGiEedT wrheeqnuetstheanredquUeRstLisaroepened.

request.open("GET", "blog.xml", true); // always asynchronous (true)

request.send(null); XML blog data is
requested from the
Tnohedraetqau, ewsthicish siesntwhwyitthhe blog.xml file on the
argument to send() is null. server via a GET
request.

GET Request

blog.xml

Client POST Request Server

DIBamotadegy:e::0"9cT/uh2be6es/ae2p0ad0rr8te.apmnsgjust..."

A new blog entry is

sent to the server in

sreerqvueers,tsionvtohlveesdadtaatatybpeeinmg ussetntbetoset. a POST request. POST rseeqruveerstscarnidpts,eravreerspUeRciLf,ieidn
case a
The The
the this
when the request is opened.

request.open("POST", "addblogentry.php", true); // always asynchronous (true)

request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

request.send("09/26/2008&These dreams just...&cubeapart.png");

Don’t stress out over all this GET and POST stuff. The request is sent with the
data passed along in the
If you don’t have any experience with GET and POST from argument to the send() method.
HTML, don’t worry about it. They will make more sense
as their roles in YouCube continue to get more solidified.

you are here 4   555

Download at WoweBook.Com

growing pains: simplifying ajax

Make XMLHttpRequest less painful

Although the XMLHttpRequest object is incredibly powerful, it comes The custom
with a fairly steep learning curve, as you no doubt already realize. Not AjaxRequest
only that, but it requires a certain amount of “boilerplate” code that object eases the
has to go into every Ajax application that uses it. For this reason, lots pain of making
of third party libraries have been created to make it easier to use the Ajax requests.
XMLHttpRequest object. Many of these libraries extend the features of
JavaScript, which is great but requires even more learning. MXiancMocAsetLjsasHoxfptRrtetopqphRueeeersqtmtuieeestssithmoopfodlbystjehcet.

For this reason, a helpful strategy for YouCube is to create a minimal
custom object that serves as a convenient assistant to XMLHttpRequest,
allowing us to focus purely on doing things with Ajax, as opposed to
wrestling with the XMLHttpRequest object or mastering some third
party library. This custom object, AjaxRequest, takes a minimalist
approach to making the XMLHttpRequest object more usable.

XMLHttpRequest

readyState abort()
status open()

onreadystatechange

responseText send() AjaxRequest
responseXML getReadyState()

request getStatus()
getResponseText()
The underlying XMLHttpRequest getResponseXML()
object is stored in the request send()
property of the custom
AjaxRequest object.

In addition to the send() method, which we delve into in a moment, the Totwpaohekrenikninshgegonrcdasane(r)deomfsoeefnAtdthjaiohnxdegRdiaeseqrttueaheqiseltuse,rsoetfa.l

constructor for AjaxRequest is where Ajax is dramatically simplified

as compared to using the XMLHttpRequest object alone. This is all it

takes to create an AjaxRequest object that is capable of initiating Ajax

requests in any modern browser: The constructor for
var ajaxReq = new AjaxRequest(); AfajactxoRresqiunesatllatuhteominattricicaallcyies
XofMcLreHatttinpgRetqhueesutndoebrjelycitn.g

556   Chapter 12

Download at WoweBook.Com

dynamic data

JavaScript Magnets

The custom AjaxRequest object wraps up the standard XMLHttpRequest object,
providing a much simpler interface for sending Ajax requests and handling their responses.
Problem is, the send() method of the AjaxRequest object is missing a few key pieces of
code. Use the magnets to finish the code for the method.

AjaixfR/e(/qtuhKeiisslt.l.rpetrqhoueteospttryep!ve=i.osnueusnldlr)e=q{ufeusntction(type, url, handler, postDataType, postData) {
this.request.abort();

// Tack on a dummy parameter to override browser caching
url += "?dummy=" + new Date().getTime();

try {

this.request.onreadystatechange = ;
, true); // always asynchronous (true)
this.request.open( ,

if/(/tySpeen.dtoaLoGwEeTrCraesqeu(e)st=;=n"ogedta"t)a {
involved

this.request.send( );

} else { POST request; the last argument is data
// Send
a

this.request.setRequestHeader("Content-Type", );

this.request.send( );

}

} catch(e) { error communicating with the server.\n" + "Details: " + e);
alert("Ajax

}

}

}

handler url null
type postData
postDataType

you are here 4   557

Download at WoweBook.Com

JavaScript magnets solution

JavaScript Magnets Solution

The custom AjaxRequest object wraps up the standard XMLHttpRequest object,
providing a much simpler interface for sending Ajax requests and handling their responses.
Problem is, the send() method of the AjaxRequest object is missing a few key pieces of
code. Use the magnets to finish the code for the method.

TAspjheaelxlesderenoqduu(te)stimnewittihtsohadrdgseeutnmadeilsnstasn.

AjaixfR/e(/qtuhKeiisslt.l.rpetrqhoueteospttryep!ve=i.osnueusnldlr)e=q{ufeusntction(type, url, handler, postDataType, postData) {
this.request.abort();

// Tack on a dummy parameter to override browser caching The custom handler
url += "?dummy=" + new Date().getTime(); function will get called

try { handler to handle the server’s
; response to the request.
this.request.onreadystatechange =

this.request.open( type , url , true); // always asynchronous (true)

if/(/tySpeen.dtoaLoGwEeTrCraesqeu(e)st=;=n"ogedta"t)a { The type argument to send()
involved determines whether the
request is a GET or a POST.
this.request.send( null );

} else { POST request; the last argument is data
// Send
a

this.request.setRequestHeader("Content-Type", postDataType );

Data is only this.request.send( postData );
sent to the
server when }
the request
is a POST } catch(e) { error communicating with the server.\n" + "Details: " + e);
request. alert("Ajax

}

}

}

Tmceoxehnttissehtrocrndouadcsl.teJoirasvaastnSodcrreoidptthienfritlAehejaalaxojRnagexq.wjusietsht the ajax.js

558   Chapter 12

Download at WoweBook.Com

dynamic data

Making sense of an Ajax request

The custom AjaxRequest object consists of a constructor and several AjaxRequest
methods, one of which is particularly useful. The send() method is used getReadyState()
to prepare and issue an Ajax request to a server in a single call. All Ajax getStatus()
requests issued using send() are either GET or POST requests, which
correspond to HTML form submission requests. The difference is that an
Ajax request doesn’t require a complete reload of a page.

request getResponseText()

send(type, url, handler, postDataType, postData) getResponseXML()
send()

type

The type of the request, GET or POST.

url handler

The URL of the server (blog.xml in The callback function used
the case of YouCube). Data can be to handle the response.
packaged into this URL if necessary.
postData
postDataType
The data to be sent (only for POSTs, not
The type of data being sent (only for required for GETs). POST data can be
POSTs, not required for GETs). submitted in several different formats.

All Ajax requests involve these same pieces of information, although GET Don’t panic
requests skip the last two arguments, which are optional. So the first three over the
arguments to send() are the most important, and are sufficient for most handling of
simple Ajax requests. As an example, the following call to send() uses requests.
the first three arguments to request (GET) XML data from a file named
movies.xml on the server: We’ll get to the ins and outs of
how Ajax requests are handled
The type The URL of the in custom JavaScript code
of request. requested data file. soon enough. For now, just
understand that a custom
ajaxReq.send("GET", "movies.xml", handleRequest); request handler function
must be set for a request, and
This code assumes Twrehilselpbocneussectaotlmloedftuhtneoctrhieaoqnnudetlsehta.tthe that the function is called when
awne’vAejaaxlrReeaqduyesctreoabtjeedct a request is completed.
and stored it in the
ajaxReq variable.

you are here 4   559

Download at WoweBook.Com

may I make a request?

request
The ball enters the server’s court

When the send() method is called on an AjaxRequest object, an
Ajax request is sent to the server, and the web page is left to go about
its business while the server processes the request. This is where the
asynchronous part of Ajax really shines. If the request was synchronous,
the page would be frozen, unable to do anything until the server returns
with a response. But since the request takes place asynchronously, the
page isn’t halted and the user experience isn’t stalled.

blog.xml

Wptahrbhoeoiclupeetastgishteesesiosstweharnelvleobrrweuqseuidneetsosts,go Server
without being stalled.
<html>
<head>
...
</head>

<body>
...
</body>
</html>

youcube.html An asynchronous Ajax
request takes place
Just because the page isn’t frozen while a request is being processed without freezing a page
doesn’t necessarily mean the user can actually do anything productive. while it waits for the
It all depends on the specific page. In the case of YouCube, request to be processed
successfully viewing the blog is entirely dependent on getting the blog by a server.
data back from the server in an Ajax response. So in this case the user
experience is tied to the Ajax response.

 The XMLHttpRequest object is the standard directly with XMLHttpRequest.
object for carrying out Ajax requests but it can be
somewhat messy to use.  Ajax requests always fall into one of two types, GET or
POST, which is determined by the data being sent to
 The custom AjaxRequest object serves as a the server, as well as how the data affects the server.
convenient way to use Ajax without having to deal
 The send() method of the AjaxRequest object

560   Chapter 12

Download at WoweBook.Com

dynamic data

Q: Is the AjaxRequest object occur at any time and don’t necessarily and responses take place in real time, often
A:necessary for carrying out Ajax requests? involve the delivery of HTML data. In fact, without interrupting the usability of a page. In
one of the huge benefits of Ajax is that it can other words, users aren’t stuck waiting for an
No. It’s perfectly fine to use the be used to request any kind of data. entire page to reload when all that needs to
XMLHttpRequest object directly be updated is one small section of the page.
to issue Ajax requests and handle their It’s a big deal that Ajax can handle any kind That section of the page can be loading in
responses. But why would you when of data, but it’s also the size of the data the “background” while someone continues
there is a much easier way thanks to that matters as much as anything. Ajax to read and interact with other parts of the
the AjaxRequest object? The isn’t limited to handling an entire page or
AjaxRequest object doesn’t do document of data at a time. In fact, it’s Q:page.
anything earth-shattering—it’s just a really geared toward the delivery of little What do GET and POST have to
convenience object that helps simplify the bite-sized pieces of data. In doing so, Ajax
task of using Ajax by taking care of the “busy allows a page to dynamically modify itself A:do with all this?
by requesting little chunks of data and then GET and POST determine the
Q:work” involved in assembling Ajax requests. incorporating it into the page. And all of this specifics of how an Ajax request is handled
How is an Ajax request/response happens without the page ever having to be by the server. However, they aren’t
any different than an HTTP request/ any different in terms of being able to
Q:reloaded. dynamically request data of any type at any
A:response? So Ajax makes it possible to time—all of the Ajax benefits apply to both
HTTP requests and responses are dynamically assemble a web page in request types. The main distinction between
used by web browsers to retrieve HTML web GET and POST has to do with whether
pages from web servers. Ajax requests and A:pieces? or not the server undergoes a change in
responses are very similar to HTTP requests Yes! That’s the main idea behind Ajax. state based upon the data, such as storing
and responses except for a couple of key But it’s more than just assembling a page it in a database. If so, a POST is in order.
differences: the Ajax versions can from pieces. It’s also about the timing of Otherwise, go with GET.
when this assembly occurs. Ajax requests

Match each Ajax-related piece of code to what it does.

XMLHttpRequest Retrieves data without changing
GET anything on the server.
send()
AjaxRequest Submits an Ajax request to the server,
POST resulting in a response.

Sends data to the server, somehow
resulting in a change on the server.

The standard JavaScript object that
makes Ajax possible.

The custom object used to simplify
Ajax requests and responses.

you are here 4   561

Download at WoweBook.Com

what’s my purpose solution

Match each Ajax-related piece of code to what it does.

XMLHttpRequest Retrieves data without changing
GET anything on the server.
send()
AjaxRequest Submits an Ajax request to the server,
POST resulting in a response.

Sends data to the server, somehow
resulting in a change on the server.

The standard JavaScript object that
makes Ajax possible.

The custom object used to simplify
Ajax requests and responses.

AjaxRequest

XMLHttpRequest

Tohbejeccut ssteormveAsjaasxRae“qwureasptper”
aXerMaosuLinHedrttttpohRewesqoturakenswdta,itrmhdaAkjainxg. it

GET eaTinthheAejsraeaxnGrde(E)qTumeoesrtthatohPdaOtiSsisTsu. es
send()
blog.xml
Server
DIBamotadegy:e::0"9cT/uh2be6es/ae2p0ad0rr8te.apmnsgjust... "

POST

562   Chapter 12

Download at WoweBook.Com

dynamic data

Interactive pages start with a request object

Regardless of how Ajax is being used or what kind of data it is attempting to
access, any Ajax communication of data begins with a request. So Ruby’s first task
in turning YouCube into a data-driven application is to issue an Ajax request for
the XML file containing the blog data.

It sounds as if I need to create an
AjaxRequest object and then use it to
send a request for the blog data.

1 Create an AjaxRequest object.

2 I ssue a GET request to retrieve
the blog.xml file from the server.

3 Handle the request... ?

Rtsthueebpyf3sir,tsibtlluttiswnso’htesstcuearpnes about
focus on
for now.

Write code to create an AjaxRequest object, and then use it
to submit a request for XML blog data.

you are here 4   563

Download at WoweBook.Com

sharpen solution

Write code to create an AjaxRequest object, and then use it
to submit a request for XML blog data.

1 var ajaxReq = new AjaxRequest();

The Ajax request is a 2 ajaxReq.send(“GET”, “blog.xml”, handleRequest);
GET request since all NwcueosntheoamnodfhleatnhtdihsleemRreeeaqsnupseosnmtsu(e)cihnfuutnnhctetilion.
we’re doing is retrieving TashethXeMULRLfiolefisthseperceifqiueedst.
data from the server.

Call me when you’re done The client script
handles the response
Once an Ajax request is sent, the browser’s role changes—it’s not waiting to an Ajax request
for a response from the server. But because Ajax requests are typically using a custom
carried out asynchronously, the user can continue interacting with the callback function.
page while the browser waits for the response behind the scenes. In other
words, the Ajax request doesn’t halt the page while the request is being
processed on the server. Once the request is finished being processed
on the server, its response is handled in JavaScript code using a callback
function, the request handler.

<blog> Ttsfehhurneevncertrerioestpnliooetnstosheoheniasbanrsdecolnuewststteofhrmre, owrcmeahqlitlcubhheaesctk.
<<taiuttlheo>r.>.....
<entries> Client
<entry>
...
</entry>
.<./.entries>
</blog>

blog.xml

Server Web browser. fuinfc/vt(/aiarojSnatxxomhRrlaeeDnqad.ttlghaeeeRt=eRXqeMauaLjedasyrxtSeR(tse)apqto.{eng(se)etR=de=astp4aon&s&eXaMjLa(x)R.egqe.tgEelteSmteanttussB(y)Ta=g=Na2m0e0()"b{log")[0];
/B/loSge.tprtohteotbylpoeg.-swiigdneatsuirgena=tu"rbey " + getText(xmlData.getElementsByTagName("author")[0]);
1 Create an AjaxRequest object. /vf/aorriCfre(/benv(/lataeoggtrrnCgeeeitr.tteirepTTtsiaueeh=etsxxe=sehtt0[(((ax;itneerm]hennrli.ewttaDgrrya<ebIiittlmeeoaeEoassf.nlgg[[gteeiiBermeB]]ltienl..oEentoggglstrgeee.sy(ttemlBnEEneeyaelltnnTsweertgammystgaDeeBhNnannoy;atttbTmIessjaiem(BBeg+(agyycN+"geTTta)ietaasmmBTgge{aleNN(goxaa"egtmme"(een)oe((t[bn""r0jtbiy]erom")cida)teyg;{s"e[)"i[)]0[.]0g)]e,)t)E)l;ementsByTagName("date")[0])),
2 Issue a GET request to retrieve } e/bl/lsogeCger.t{epTauetsxeht((tnehenewtrbBilleoosgg[(ien]ne.twgreyDtaEatlsee(mageenBttlTsoeBgxytTo(abegjnNetacrmtiee(s"[bio]d.yg"e)t[E0l]e)m)e)n;tsByTagName("date")[0])),
}
the blog.xml file from the server. }
3 H andle the request.
/ddd/ooocccEuuunmmmaeeebnnnlttte...gggteeehttteEEElllbeeelmmmoeeegnnntttbBBBuyyytIIItdddo(((n"""sssvehiaoerwwcarhla"ln)"d.)od.mid"si)as.badlbielsdeadb=l=efdafla=slesf;ea;lse;

// Show the blog
showBlog(5);
}
}

TcahlelbahcakndfleuRncetqiuoenstis() handleRequest();
benetsiurpeplyliecdustboymt, haendscrmipustt.

564   Chapter 12

Download at WoweBook.Com


Click to View FlipBook Version