You may not have any reason to store files or image data as part of your history state,
but structured clones are also used by a number of other HTML5-related standards,
and we’ll see them again throughout this chapter.
In  addition  to  the 
pushState()
method,  the  History  object  also  defines
replaceState()
, which takes the same arguments but replaces the current history state
instead of adding a new state to the browsing history.
When the user navigates to saved history states using the Back or Forward buttons, the
browser fires a popstate event on the Window object. The event object associated with
the event has a property named 
state
, which contains a copy (another structured clone)
of the state object you passed to 
pushState()
.
Example 22-3 is a simple web application—the number guessing game pictured in
Figure 22-1—that uses these HTML5 techniques to save its history, allowing the user
to “go back” to review or redo her guesses.
As this book goes to press, Firefox 4 has made two modifications to the History API
that other browsers may follow. First, Firefox 4 makes the current state available
through the 
state
property of the History object itself, which means that newly loaded
pages do not need to wait for a popstate event. Second, Firefox 4 no longer fires a
popstate event for newly loaded pages that do not have any saved state. This second
change means that the example below does not work quite right in Firefox 4.
Figure 22-1. A number guessing game
Example 22-3. History management with pushState()
<!DOCTYPE html>
<html><head><title>I'm thinking of a number...</title>
<script>
22.2  History Management | 673
Client-Side
JavaScript
Pdf link to attached file - insert, remove PDF links in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Free C# example code is offered for users to edit PDF document hyperlink (url), like inserting and deleting
add hyperlink pdf file; adding an email link to a pdf
Pdf link to attached file - VB.NET PDF url edit library: insert, remove PDF links in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Help to Insert a Hyperlink to Specified PDF Document Page
add link to pdf acrobat; add link to pdf
window.onload = newgame;        // Start a new game when we load
window.onpopstate = popState;   // Handle history events
var state, ui;                  // Globals initialized in newgame()
function newgame(playagain) {   // Begin a new game of guess-the-number
// Set up an object to hold document elements we care about
ui = {
heading: null, // The <h1> at the top of the document.
prompt: null,  // Ask the user to enter a guess.
input: null,   // Where the user enters the guess.
low: null,     // Three table cells for the visual representation
mid: null,     // ...of the range of numbers to guess.
high: null
};
// Look up each of these element ids
for(var id in ui) ui[id] = document.getElementById(id);
// Define an event handler for the input field
ui.input.onchange = handleGuess;
// Pick a random number and initialize game state
state = {
n: Math.floor(99 * Math.random()) + 1,  // An integer: 0 < n < 100
low: 0,            // The lower bound (exclusive) on guesses
high: 100,         // The upper bound (exclusive) on guesses
guessnum: 0,       // How many guesses have been made
guess: undefined   // What the last guess was
};
// Modify document content to display this initial state
display(state);  
// This function is called as the onload event handler, and is also called
// by the Play Again button displayed at the end of a game. The playagain
// argument will be true in that second case. If it is true, then we save
// the new game state. But if we were called in response to a load event,
// we don't save the state. This is because load events will also occur
// when we step backwards through the browser history from some other 
// document into the existing state of a game. If we were to save a new
// initial state, in that case we would overwrite the acutal historical 
// state of the game. In browsers that support pushState(), the load event
// is always followed by a popstate event. So rather than saving state here,
// we wait for the popstate. If it gives us a state object, we just use 
// that. Otherwise, if the popstate has a null state, we know this is
// really a new game and we use replaceState to save the new game state.
if (playagain === true) save(state);
}
// Save game state into browser history with pushState(), if it is supported
function save(state) {  
if (!history.pushState) return; // Do nothing if pushState() not defined
// We'll associate a URL with the saved state. This URL displays the 
// guess number, but does not encode the game state, so it is not useful
// to bookmark. We can't easily put game state in the URL because it would 
// make the secret number visible in the location bar. 
674 | Chapter 22: HTML5 APIs
VB.NET PowerPoint: Read, Edit and Process PPTX File
PowerPoint editing function, please follow attached link directly. one or more slides from PowerPoint file. How to convert PowerPoint to PDF, render PowerPoint
adding links to pdf; pdf links
VB.NET Word: .NET Word Reader & Processor Control SDK | Online
into certain VB.NET Word manipulating application, please follow attached link to find SDK owns the APIs for converting Word document file to PDF, png, gif
add a link to a pdf; adding hyperlinks to a pdf
var url = "#guess" + state.guessnum;
// Now save the state object and the URL
history.pushState(state,  // State object to save
"",     // State title: current browsers ignore this
url);   // State URL: not useful to bookmark
}
// This is the onpopstate event handler that restores historical states.
function popState(event) {
if (event.state) {  // If the event has a state object, restore that state
// Note that event.state is a deep copy of the saved state object
// so we can modify it without altering the saved value.
state = event.state;    // Restore the historical state
display(state);         // Display the restored state
}
else {
// When we load the page for the first time, we'll get a popstate event
// with no state. Replace that null state with our real state: see the
// comment in newgame(). No need to call display() here.
history.replaceState(state, "", "#guess" + state.guessnum);
}
};
// This event handler is invoked each time the user guesses a number.
// It updates the game state, saves it, and displays it.
function handleGuess() {
// Get the user's guess from the input field
var g = parseInt(this.value);
// If it is a number and is in the right range
if ((g > state.low) && (g < state.high)) { 
// Update the state object based on this guess
if (g < state.n) state.low = g;          
else if (g > state.n) state.high = g;
state.guess = g;
state.guessnum++;
// Now save the new state in the browser's history
save(state);
// Modify the document to respond to the user's guess
display(state);
}
else {  // An invalid guess: don't push a new history state
alert("Please enter a number greater than " + state.low +
" and less than " + state.high);
}
}
// Modify the document to display the current state of the game.
function display(state) { 
// Display document heading and title
ui.heading.innerHTML = document.title =
"I'm thinking of a number between " +
state.low + " and " + state.high + ".";
// Display a visual representation of the range of numbers using a table
ui.low.style.width = state.low + "%";
ui.mid.style.width = (state.high-state.low) + "%";
22.2  History Management | 675
Client-Side
JavaScript
VB.NET TIFF: VB.NET Sample Code to Process & Manage TIFF Page
page processing application, please click attached link in the for editing source TIFF file at page powerful & profession imaging controls, PDF document, image
adding a link to a pdf in preview; add url link to pdf
VB.NET TIFF: VB Code to Read Linear and 2D Barcodes from TIFF
type from TIFF document image file by following attached link. 2 of 5 barcodes from TIFF image file. Reading Component allows users scan PDF-417 barcode with a
pdf reader link; add hyperlinks to pdf online
ui.high.style.width = (100-state.high) + "%";
// Make sure the input field is visible, empty, and focused
ui.input.style.visibility = "visible"; 
ui.input.value = "";
ui.input.focus();
// Set the prompt based on the user's most recent guess
if (state.guess === undefined)
ui.prompt.innerHTML = "Type your guess and hit Enter: ";
else if (state.guess < state.n)
ui.prompt.innerHTML = state.guess + " is too low. Guess again: ";
else if (state.guess > state.n)
ui.prompt.innerHTML = state.guess + " is too high. Guess again: ";
else {
// When correct, hide the input field and show a Play Again button.
ui.input.style.visibility = "hidden";  // No more guesses now
ui.heading.innerHTML = document.title = state.guess + " is correct! ";
ui.prompt.innerHTML =
"You Win! <button onclick='newgame(true)'>Play Again</button>";
}
}
</script>
<style>  /* CSS styles to make the game look good */
#prompt { font-size: 16pt; }
table { width: 90%; margin:10px; margin-left:5%; }
#low, #high { background-color: lightgray; height: 1em; }
#mid { background-color: green; }
</style>
</head>
<body><!-- The HTML elements below are the game UI -->
<!-- Game title and textual representation of the range of numbers -->
<h1 id="heading">I'm thinking of a number...</h1>
<!-- a visual representation of the numbers that haven't been ruled out -->
<table><tr><td id="low"></td><td id="mid"></td><td id="high"></td></tr></table>
<!-- Where the user enters their guess -->
<label id="prompt"></label><input id="input" type="text">
</body></html>
22.3  Cross-Origin Messaging
As noted in §14.8, some browser windows and tabs are completely isolated from each
other, and the code running in one is completely unaware of the others. In other cases,
when a script explicitly opens new windows or works with nested frames, the multiple
windows and frames are aware of each other. If they contain documents from the same
web server, scripts in these windows and frames can interact with each other and ma-
nipulate each other’s documents.
Sometimes, however, a script can refer to another Window object, but because the
content in that window is from a different origin, the web browser (following the same-
origin policy) will not allow the script to see the document content of that other win-
dow. For the most part, the browser won’t allow the script to read properties or invoke
676 | Chapter 22: HTML5 APIs
VB.NET PowerPoint: Read & Scan Barcode Image from PPT Slide
to represent one in-memory PowerPoint document file and it image from PPT (.pptx) slide, just follow attached link. VB.NET PPT PDF-417 barcode scanning SDK to
add links to pdf in acrobat; add email link to pdf
C# Word: How to Read Barcodes from Word with C#.NET Library DLL
& read barcode image from source Word file. for reading specific barcode type by clicking attached link. C# Word PDF-417 Barcode Reading Tutorial, Detecting C#
pdf links; add url to pdf
methods of that other window, either. One window method that scripts from different
origins are allowed to invoke is called 
postMessage()
, and this method enables a limited
kind of communication—in the form of asynchronous message passing—between
scripts from different origins. This kind of communication is defined by HTML5 and
is implemented by all current browsers (including IE8 and later). The technique is
known as “cross-document messaging,” but since the API is defined on the Window
object instead of the document, it might be better known as “inter-window message
passing” or “cross-origin messaging.”
The 
postMessage()
method expects two arguments. The first is the message to be sent.
The HTML5 specification says that this can be any primitive value or object that can
be cloned (see “Structured Clones” on page 672), but some current browser imple-
mentations (including Firefox 4 beta) expect strings, so if you want to pass an object
or array as a message you should serialize it with 
JSON.stringify()
(§6.9) first.
The second argument is a string that specifies the expected origin of the destination
window. Include the protocol, hostname, and (optionally) the port portions of a URL
(you can pass a complete URL, but anything other than the protocol, host, and port
will be ignored). This is a security feature: malicious code or ordinary users can navigate
windows to new documents that you don’t expect, so 
postMessage()
won’t deliver your
message if the window contains a document from a different origin than the one you
specified. If the message you are passing doesn’t contain any sensitive information and
you are willing to pass it to code from any origin, you can pass the string 
"*"
as a
wildcard instead. If you want to specify the same origin as the current window, you
can simply use 
"/"
.
If the origins match, the call to 
postMessage()
will result in a message event being fired
at the target Window object. A script in that window can define an event handler
function to be notified of message events. This handler is passed an event object with
the following properties:
data
This is a copy of the message that was passed as the first argument to 
postMessage()
.
source
The Window object from which the message was sent.
origin
A string that specifies the origin (as a URL) from which the message was sent.
Most 
onmessage()
handlers should first check the 
origin
property of their argument
and should ignore messages from unexpected domains.
Cross-origin messaging via 
postMessage()
and the message event can be useful when
you want to include a module or “gadget” from another site within your web page. If
the gadget is simple and self-contained, you can simply isolate it in an 
<iframe>
. Sup-
pose, however, that it is a more complex gadget that defines an API and your web page
has to control it or interact with it somehow. If the gadget is defined as a 
<script>
element, it can expose a normal JavaScript API, but including in your page allows it to
22.3  Cross-Origin Messaging | 677
Client-Side
JavaScript
C# Word: How to Generate Barcodes in C# Word with .NET Library
be easily inserted into MS Word file (.docx C# programming code for individual barcode type, please follow attached link. Create Micro PDF-417 in C# Word, Create
convert excel to pdf with hyperlinks; adding links to pdf
take complete control of the page and its content. It is not uncommon to do this on the
Web today (particularly for web advertising), but it is not really a good idea, even when
you trust the other site.
Cross-origin messaging provides an alternative: the gadget author can package the
gadget within an HTML file that listens for message events and dispatches those events
to the appropriate JavaScript functions. Then the web page that includes the gadget
can interact with it by sending messages with 
postMessage()
. Examples 22-4 and
22-5 demonstrate this. Example 22-4 is a simple gadget, included via 
<iframe>
, that
searches Twitter and displays tweets that match a specified search term. To make this
gadget search for something, the containing page simply sends it the desired search
term as a message.
Example 22-4. A Twitter search gadget, controlled by postMessage()
<!DOCTYPE html>
<!--
This is a Twitter search gadget. Include it in any webpage, inside an
iframe, and ask it to search for things by sending it a query string with
postMessage(). Since it is in an <iframe> and not a <script>, it can't
mess around with the containing document.
-->
<html>
<head>
<style>body { font: 9pt sans-serif; }</style>
<!-- Use jQuery for its jQuery.getJSON() utility -->
<script src="http://code.jquery.com/jquery-1.4.4.min.js"/></script>
<script>
// We ought to just be able to use window.onmessage, but some older browsers
// (e.g., Firefox 3) don't support it, so we do it this way instead.
if (window.addEventListener)
window.addEventListener("message", handleMessage, false);
else 
window.attachEvent("onmessage", handleMessage);   // For IE8
function handleMessage(e) {
// We don't care what the origin of this message is: we're willing
// to search Twitter for anyone who asks us. We do expect the message
// to come from the window that contains us, however.
if (e.source !== window.parent) return;
var searchterm = e.data;  // This is what we were asked to search for
// Use jQuery Ajax utlities and the Twitter search API to find
// tweets matching the message.
jQuery.getJSON("http://search.twitter.com/search.json?callback=?",
{ q: searchterm },
function(data) {   // Called with request results
var tweets = data.results;
// Build an HTML document to display these results
var escaped = searchterm.replace("<", "&lt;");
var html = "<h2>" + escaped + "</h2>";
if (tweets.length == 0) {
html += "No tweets found";
678 | Chapter 22: HTML5 APIs
}
else {
html += "<dl>"; // <dl> list of results
for(var i = 0; i < tweets.length; i++) {
var tweet = tweets[i];
var text = tweet.text;
var from = tweet.from_user;
var tweeturl = "http://twitter.com/#!/" +
from + "/status/" + tweet.id_str;
html += "<dt><a target='_blank' href='" +
tweeturl + "'>" + tweet.from_user +
"</a></dt><dd>" + tweet.text + "</dd>";
}
html += "</dl>";
}
// Set the <iframe> document
document.body.innerHTML = html;
});
}
$(function() {
// Let our container know we're here and ready to search.
// The container can't send any messages to us before it gets this message
// from us because we won't be here to receive the message yet.
// Normally, containers can just wait for an onload event to know that all
// of their <iframe>s have loaded. We send this message for containers that
// want to start searching Twitter even before they get their onload event.
// We don't know the origin of our container, so use * so that the browser
// will deliver it to anyone.
window.parent.postMessage("Twitter Search v0.1", "*");
});
</script>
</head>
<body>
</body>
</html>
Example 22-5 is a simple JavaScript file that can be inserted into any web page that
wants to use the Twitter search gadget. It inserts the gadget into the document and
then adds an event handler to all links in the document so that moving the mouse over
a link calls 
postMessage()
on the gadget’s frame to make the gadget search for the URL
of the link. This allows a user to see what, if anything, people are tweeting about a
website before visiting the site.
Example 22-5. Using the Twitter search gadget with postMessage()
// This file of JS code inserts the Twitter Search Gadget into the document
// and adds an event handler to all links in the document so that when the
// use moves the mouse over them, the gadget searches for the link's URL.
// This allows the user to see what people are tweeting about the link
// destination before clicking on it.
window.addEventListener("load", function() {       // Won't work in IE < 9
var origin = "http://davidflanagan.com";       // Gadget origin
var gadget = "/demos/TwitterSearch.html";      // Gadget path
var iframe = document.createElement("iframe"); // Create the iframe
22.3  Cross-Origin Messaging | 679
Client-Side
JavaScript
iframe.src = origin + gadget;                  // Set its URL
iframe.width = "250";                          // 250 pixels wide
iframe.height = "100%";                        // Full document height
iframe.style.cssFloat = "right";               // Flush right
// Insert the iframe at the start of the document
document.body.insertBefore(iframe, document.body.firstChild);
// Now find all links and hook them up to the gadget
var links = document.getElementsByTagName("a");
for(var i = 0; i < links.length; i++) {
// addEventListener doesn't work in IE8 and before
links[i].addEventListener("mouseover", function() {
// Send the url as the search term, and only deliver it if the
// iframe is still displaying a document from davidflanagan.com
iframe.contentWindow.postMessage(this.href, origin);
}, false);
}
}, false);
22.4  Web Workers
One of the fundamental features of client-side JavaScript is that it is single-threaded: a
browser will never run two event handlers at the same time, and it will never trigger a
timer while an event handler is running, for example. Concurrent updates to applica-
tion state or to the document are simply not possible, and client-side programmers do
not need to think about, or even understand, concurrent programming. A corollary is
that client-side JavaScript functions must not run too long: otherwise they will tie up
the event loop and the web browser will become unresponsive to user input. This is
the reason that Ajax APIs are always asynchronous and the reason that client-side
JavaScript cannot have a simple, synchronous 
load()
or 
require()
function for loading
JavaScript libraries.
The Web Workers specification
1
very carefully relaxes the single-threaded requirement
for client-side JavaScript. The “workers” it defines are effectively parallel threads of
execution. Web workers live in a self-contained execution environment, however, with
no access to the Window or Document object and can communicate with the main
thread only through asynchronous message passing. This means that concurrent mod-
ifications of the DOM are still not possible, but it also means that there is now a way
to use synchronous APIs and write long-running functions that do not stall the event
loop and hang the browser. Creating a new worker is not a heavyweight operation like
opening a new browser window, but workers are not flyweight threads either, and it
does not make sense to create new workers to perform trivial operations. Complex web
1.Web workers were originally part of the HTML5 specification, but they were broken off into an
independent, but closely related specification. At the time of this writing, specification drafts are available
at http://dev.w3.org/html5/workers/ and http://whatwg.org/ww.
680 | Chapter 22: HTML5 APIs
applications may find it useful to create tens of workers, but it is unlikely that an ap-
plication with hundreds or thousands of workers would be practical.
As with any threading API, there are two pieces to the Web Workers specification. The
first is the Worker object: this is what a worker looks like from the outside, to the thread
that creates it. The second is the WorkerGlobalScope: this is the global object for a new
worker, and it is what a worker thread looks like, on the inside, to itself. The subsections
that follow explain both. They are followed by a section of examples.
22.4.1  Worker Objects
To create a new worker, just use the 
Worker()
constructor, passing a URL that specifies
the JavaScript code that the worker is to run:
var loader = new Worker("utils/loader.js");
If you specify a relative URL, it is resolved relative to the URL of the document that
contains the script that called the 
Worker()
constructor. If you specify an absolute URL,
it must have the same origin (same protocol, host, and port) as that containing
document.
Once you have a Worker object, you can send data to it with 
postMessage()
. The value
you pass to 
postMessage()
will be cloned (see “Structured Clones” on page 672), and
the resulting copy will be delivered to the worker via a message event:
loader.postMessage("file.txt");
Note that the 
postMessage()
method of a Worker does not have the origin argument
that the 
postMessage()
method of a Window does (§22.3). Also, the 
postMessage()
method of a Worker correctly clones the message in current browsers, unlike
Window.postMessage()
, which is still restricted to string messages in some important
browsers.
You can receive messages from a worker by listening for message events on the Worker
object:
worker.onmessage = function(e) {
var message = e.data;                    // Get message from event
console.log("URL contents: " + message); // Do something with it
}
If a worker throws an exception and does not catch or handle it itself, that exception
propagates as an event that you can listen for:
worker.onerror = function(e) {
// Log the error message, including worker filename and line number
console.log("Error at " + e.filename + ":" + e.lineno + ": " + 
e.message);
}
Like all event targets, Worker objects define the standard 
addEventListener()
and
removeEventListener()
methods, and you can use these in place of the 
onmessage
and
onerror
properties if you want to manage multiple event handlers.
22.4  Web Workers | 681
Client-Side
JavaScript
The Worker object has just one other method, 
terminate()
, which forces a worker
thread to stop running.
22.4.2  Worker Scope
When you create a new worker with the 
Worker()
constructor, you specify the URL of
a file of JavaScript code. That code is executed in a new, pristine JavaScript execution
environment, completely isolated from the script that created the worker. The global
object for that new execution environment is a WorkerGlobalScope object. A
WorkerGlobalScope is something more than the core JavaScript global object, but less
than a full-blown client-side Window object.
The WorkerGlobalScope object has a 
postMessage()
method and an 
onmessage
event
handler property that are just like those of the Worker object but work in the opposite
direction: calling 
postMessage()
inside a worker generates a message event outside the
worker, and messages sent from outside the worker are turned into events and delivered
to the 
onmessage
handler. Note that since the WorkerGlobalScope is the global object
for a worker, 
postMessage()
and 
onmessage
look like a global function and global vari-
able to worker code.
The 
close()
function allows a worker to terminate itself, and it is similar in effect to
the 
terminate()
method of a Worker object. Note, however, that there is no API on the
Worker object to test whether a worker has closed itself, and there is no 
onclose
event
handler property, either. If you call 
postMessage()
on a worker that has closed, your
message will be discarded silently and no error will be raised. In general, if a worker is
going to 
close()
itself, it may be a good idea to first post some kind of “closing” message.
The most interesting global function defined by WorkerGlobalScope is 
import
Scripts()
: workers use this function to load any library code they require. For example:
// Before we start working, load the classes and utilities we'll need
importScripts("collections/Set.js", "collections/Map.js", "utils/base64.js");
importScripts()
takes one or more URL arguments, each of which should refer to a file
of JavaScript code. Relative URLs are resolved relative to the URL that was passed to
the 
Worker()
constructor. It loads and executes these files one after the other, in the
order in which they were specified. If loading a script causes a network error, or if
executing throws an error of any sort, none of the subsequent scripts are loaded or
executed. A script loaded with 
importScripts()
can itself call 
importScripts()
to load
the files it depends on. Note, however, that 
importScripts()
does not try to keep track
of what scripts have already loaded and does nothing to prevent dependency cycles.
importScripts()
is a synchronous function: it does not return until all of the scripts
have loaded and executed. You can start using the scripts you loaded as soon as 
import
Scripts()
returns: there is no need for a callback or event handler. Once you have
internalized the asynchronous nature of client-side JavaScript, it can seem strange to
go back to simple, synchronous programming again. But that is the beauty of threads:
you can use a blocking function call in a worker without blocking the event loop in the
682 | Chapter 22: HTML5 APIs
Documents you may be interested
Documents you may be interested