Code for controlling bookmarks and rollback buttons using Ajax

Source: Internet
Author: User
Tags javascript array

This article describes an open-source javascript library that supports Ajax application bookmarks and rollback buttons. At the end of this Guide, developers will come up with an Ajax solution that is not even processed by Google Maps or Gmail: robust, the available bookmarks and forward and backward actions can work as correctly as other web pages.

Ajax: How to Control bookmarks and rollback buttons this article describes an important achievement. Ajax applications are currently facing the application of bookmarks and rollback buttons, describes a very Simple History Library (Really Simple History), an open-source framework for solving such problems, and provides some examples that can run.

The main problem described in this article is dual. First, a hidden html form is used as the session cache for a large and short-lived client information, this cache is strong for forward rollback on this page. Second, a combination of Anchor Connections and hidden iframes is used to intercept and record historical events of the browser and implement the forward and backward buttons. Both technologies are encapsulated with a simple javascript library for developers to use.

Problems

Bookmarks and rollback buttons can run smoothly on traditional multi-page web applications. When users surf the website, their browser address bar can update URLs, which can be pasted into emails or added to bookmarks for future use. The rollback and Forward buttons can also run normally, which allows users to move between pages they visit.

Ajax applications are different, but they are also mature programs on a single web page. The browser does not do this for Ajax-Ajax captures past events and refreshes the page when the web application clicks each mouse.

In Ajax software such as Gmail, the correct address bar of the browser is like when the user selects and changes the application status, which makes it impossible to bookmark a specific application view. In addition, if the user presses their return button to return the previous operation, they will be surprised to find that the browser will completely leave the web page of the original application.

Solution

The open-source Really Simply History (RSH) Framework solves these problems. It provides Ajax applications with the ability to bookmark and control the forward and backward buttons. RSH is currently in beta version. It runs on Firefox1.0, Netscape7 and later versions, and IE6 and later versions. Safari is not supported yet.

There are several Ajax frameworks that can help us with bookmarks and release history. However, all the frameworks are plagued by several important bugs due to their implementation. In addition, many Ajax history frameworks are integrated and bound to a large library, such as Backbase and Dojo. These frameworks provide different programming models than traditional Ajax applications, forces developers to use a complete set of new methods to obtain the Historical Functions of the browser.

Correspondingly, RSH is a simple model that can be included in an existing Ajax system. In addition, the Really Simple History library uses some techniques to avoid bugs that affect other historical frameworks.

The Really Simple History framework consists of two javascript class libraries: DhtmlHistory and HistoryStorage.

The DhtmlHistory class provides a function to extract history from Ajax applications. Add () events on the Ajax page to the browser, specifying the new address and associated historical data. The DhtmlHistory class uses an anchor hash table to update the current URL of the browser, such as # new-location, and then uses this new URL to associate historical data. Ajax applications register themselves to the historical listener. When the user uses the forward and backward buttons for navigation, the historical events are triggered, providing the browser with a new address and calling add () keep data continuously.

The second type is HistoryStorage, which allows developers to store historical data of any size. Generally, when a user navigating to a new website, the browser will uninstall and clear all the application and javascript status information on this page. If the user returns the result with the rollback button, all data is lost. HistoryStorage class solves this problem. It has an api that contains simple hashtable methods such as put (), get (), and hasKey (). These methods allow developers to store any size of data when they leave the web page. When a user clicks the return button, the data can be accessed through the HistoryStorage class. We can use a hidden form field to automatically save the value of the form field even when the user leaves the web page.

Let's enter a simple example immediately.

Example 1

First, any page that wants to use the Really Simple History framework must contain (include) dhtmlHistory. js script.Copy codeThe Code is as follows: <! -- Load the Really Simple
History framework -->
<Script type = "text/javascript"
Src = "../framework/dhtmlHistory. js">
</Script>

The DHTML History application must also include a specified file named blank.html in the same directory as the AJAX web page. This file is bound by the Really Simple History framework and is required by IE. On the other hand, RSH uses a hidden iframe to track and add changes to the Internet Explorer history. This iframeamerefers to a real address without using blance.html.

The RSH framework creates a global object named dhtmlHistory, which serves as an entry to the history of browser operations. The first step to use dhtmlHistory is to initialize the object after the page is loaded.Copy codeThe Code is as follows: window. onload = initialize;

Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

Then, the developer uses the dhtmlHistory. addListener () method to subscribe to historical change events. This method obtains a javascript callback method. When a DHTML history change event occurs, it receives two independent variables, the new page address, and any optional historical data that can be associated with this event.Copy codeThe Code is as follows: window. onload = initialize;
Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

// Subscribe to DHTML history change
// Events
DhtmlHistory. addListener (historyChange );

The historyChange () method is simple and easy to understand. It is a new address (newLocation) received by a user after navigating to a new address) and an optional historical data historyData associated with the event.Copy codeThe Code is as follows:/** Our callback to receive history change
Events .*/
Function historyChange (newLocation,
HistoryData ){
Debug ("A history change has occurred :"
+ "NewLocation =" + newLocation
+ ", HistoryData =" + historyData,
True );
}

The debug () method used above is a tool function defined in the sample code, which is included in the complete download example. The debug () method simply creates a message on the web page, with 2nd Boolean variables, which are true in the code, controls whether to clear all previous messages before a new debug message is printed.

A developer adds a history event using the add () method. Adding a historical event includes specifying a new address based on historical changes, just like the "edit: SomePage" tag, it also provides an optional historyData value for storing historical data when an event occurs.Copy codeThe Code is as follows: window. onload = initialize;

Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

// Subscribe to DHTML history change
// Events
DhtmlHistory. addListener (historyChange );

// If this is the first time we have
// Loaded the page...
If (dhtmlHistory. isFirstLoad ()){
Debug ("Adding values to browser"
+ "History", false );
// Start adding history
DhtmlHistory. add ("helloworld ",
"Hello World Data ");
DhtmlHistory. add ("foobar", 33 );
DhtmlHistory. add ("boobah", true );

Var complexObject = new Object ();
ComplexObject. value1 =
"This is the first value ";
ComplexObject. value2 =
"This is the second data ";
ComplexObject. value3 = new Array ();
ComplexObject. value3 [0] = "array 1 ";
ComplexObject. value3 [1] = "array 2 ";

DhtmlHistory. add ("complexObject ",
ComplexObject );

After the add () method is called, the new address is immediately displayed as an anchor in the URL bar of your browser. For example, an AJAX web page stays at http://codinginparadise.org/my_ajax_app. after you use dhtmlhistory.add ("helloworld", "Hello World Data", you will see the following address in the URL bar of your browser.Copy codeCode: http://codinginparadise.org/my_ajax_app#helloworld

Then they can make this page a bookmarks. If they use this bookmarks, your AJAX application can read the # helloworld value and use her to initialize the web page. The address values in the Hash are explicitly encoded and decoded by the Really Simple History framework (URL encoded and decoded) (this is to solve the character encoding problem)

HistoryData is more useful for storing more complex states when the AJAX address changes. It is an optional value, which can be any javascript type, such as Number, String, or Object type. One example is to use the rich text editor to save all the text. For example, if a user drifting from this page (or navigating from this page to another page, leave this page. When a user returns to this address, the browser returns this object to the history change listener ).

Developers can provide a completely historyData javascript Object that uses nested objects and arrange arrays to depict complex states. As long as it is allowed by the JavaScript Object Notation, it is allowed in the historical data, including simple data type and null type. DOM objects and programmable browser objects such as XMLHttpRequest are not saved. Note that historyData will not be persistently bookmarked. If the browser is disabled, the browser cache is cleared, or the user clears the history, it will disappear.

The last step to use dhtmlHistory is the isFirstLoad () method. If you navigate to a web page, jump to a different page, and then press the button to return to the starting website, the first page will be completely reloaded and the onload event will be triggered. This can cause destructiveness. When the code first loads the page and wants to initialize the page in some way, it will not refresh the page. The isFirstLoad () method makes it possible to trigger the load event when the user returns to the page recorded in the browser history when loading the page for the first time.

In the example code, we only want to add historical events when loading the page for the first time. If you press the button to return to the page after loading the page for the first time, we do not want to add any historical events again.
Window. onload = initialize;

Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

// Subscribe to DHTML history change
// Events
DhtmlHistory. addListener (historyChange );

// If this is the first time we have
// Loaded the page...
If (dhtmlHistory. isFirstLoad ()){
Debug ("Adding values to browser"
+ "History", false );
// Start adding history
DhtmlHistory. add ("helloworld ",
"Hello World Data ");
DhtmlHistory. add ("foobar", 33 );
DhtmlHistory. add ("boobah", true );

Var complexObject = new Object ();
ComplexObject. value1 =
"This is the first value ";
ComplexObject. value2 =
"This is the second data ";
ComplexObject. value3 = new Array ();
ComplexObject. value3 [0] = "array 1 ";
ComplexObject. value3 [1] = "array 2 ";

DhtmlHistory. add ("complexObject ",
ComplexObject );

Let's continue using the historyStorage class. Similar to dhtmlHistory, historyStorage uses a single global object called historyStorage to display its functions. This object has several methods to disguise it as a hash table, such as put (keyName, keyValue ), get (keyName), and hasKey (keyName ). the key name must be a character, and the key value can be a complex javascript Object or even a character in xml format. In our source code example, we put () simple XML to historyStorage when loading the page for the first time.

Program code window. onload = initialize;

Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

// Subscribe to DHTML history change
// Events
DhtmlHistory. addListener (historyChange );

// If this is the first time we have
// Loaded the page...
If (dhtmlHistory. isFirstLoad ()){
Debug ("Adding values to browser"
+ "History", false );
// Start adding history
DhtmlHistory. add ("helloworld ",
"Hello World Data ");
DhtmlHistory. add ("foobar", 33 );
DhtmlHistory. add ("boobah", true );

Var complexObject = new Object ();
ComplexObject. value1 =
"This is the first value ";
ComplexObject. value2 =
"This is the second data ";
ComplexObject. value3 = new Array ();
ComplexObject. value3 [0] = "array 1 ";
ComplexObject. value3 [1] = "array 2 ";

DhtmlHistory. add ("complexObject ",
ComplexObject );

// Cache some values in the history
// Storage
Debug ("Storing key 'fakexml'"
+ "History storage", false );
Var fakeXML =
'<? Xml version = "1.0 "'
+ 'Encoding= "ISO-8859-1"?> '
+ '<Foobar>'
+ '<Foo-entry/>'
+ '</Foobar> ';
HistoryStorage. put ("fakeXML", fakeXML );
}

Then, if the user drifting from this page (navigation) and returns through the return button, we can use get () to propose the stored value or use haskey () check whether it exists.

Program code window. onload = initialize;

Function initialize (){
// Initialize the DHTML History
// Framework
DhtmlHistory. initialize ();

// Subscribe to DHTML history change
// Events
DhtmlHistory. addListener (historyChange );

// If this is the first time we have
// Loaded the page...
If (dhtmlHistory. isFirstLoad ()){
Debug ("Adding values to browser"
+ "History", false );
// Start adding history
DhtmlHistory. add ("helloworld ",
"Hello World Data ");
DhtmlHistory. add ("foobar", 33 );
DhtmlHistory. add ("boobah", true );

Var complexObject = new Object ();
ComplexObject. value1 =
"This is the first value ";
ComplexObject. value2 =
"This is the second data ";
ComplexObject. value3 = new Array ();
ComplexObject. value3 [0] = "array 1 ";
ComplexObject. value3 [1] = "array 2 ";

DhtmlHistory. add ("complexObject ",
ComplexObject );

// Cache some values in the history
// Storage
Debug ("Storing key 'fakexml'"
+ "History storage", false );
Var fakeXML =
'<? Xml version = "1.0 "'
+ 'Encoding= "ISO-8859-1"?> '
+ '<Foobar>'
+ '<Foo-entry/>'
+ '</Foobar> ';
HistoryStorage. put ("fakeXML", fakeXML );
}

// Retrieve our values from the history
// Storage
Var savedXML =
HistoryStorage. get ("fakeXML ");
SavedXML = prettyPrintXml (savedXML );
Var hasKey =
HistoryStorage. hasKey ("fakeXML ");
Var message =
"HistoryStorage. hasKey ('fakexml') ="
+ HasKey + "<br>"
+ "HistoryStorage. get ('fakexml') = <br>"
+ SavedXML;
Debug (message, false );
}

PrettyPrintXml () is the first tool method in the full example source code example. This method is used to prepare simple xml to be displayed on the web page for debugging.

Note that the data is only persistent when the page history is used. If the browser is closed, or the user opens a new window and enters the address of the ajax application again, historical data is unavailable for these new web pages. Historical data is persisted only when the forward or back button is used, and disappears when the user closes the browser or clears the cache. For more information, see Ajax MAssive Storage System (AMASS ).

Our simple example has been completed. Demo it or download all the source code (download the full source code .)

Example 2

Our 2nd example is a simple example of simulating an ajax email application, called o'reilly Mail, similar to Gmail. o'reilly Mail describes how to use the dhtmlHistory class to control the browser history and how to use historyStorage objects to cache historical data.

O 'Reilly Mail user interface has two parts. On the left side of the page is a menu with different email folders and options, such as Inbox, draft, and so on. When a user selects a menu item, such as the inbox, we use the content of this menu item to update the page on the right. In a practical application, we remotely obtain and display the selected mailbox content. However, in o'reilly Mail, we simply display the selected options.

O 'Reilly Mail uses the Really Simple History framework to add menu changes and update the address bar to the browser History, you can use the back and forward buttons of the browser to bookmark the application and jump to the last changed menu.

We add a special menu item and address book to describe how historyStorage can be used. The address book is a javascript array consisting of contact name emails and addresses. In a real application, we will obtain it from a remote server. However, in o'reilly Mail, we create this array locally, add several name emails and addresses, and store them in the historyStorage object. If the user leaves the web page and returns the address book again, the o'reilly Mail application obtains the address book from the cache, which is better than (having to) accessing the remote server again.

The address book is the program code stored and re-obtained in Our initialize () method/** Our function that initializes when the page
Is finished loading .*/
Function initialize (){
// Initialize the DHTML History framework
DhtmlHistory. initialize ();

// Add ourselves as a DHTML History listener
DhtmlHistory. addListener (handleHistoryChange );

// If we haven't retrieved the address book
// Yet, grab it and then cache it into our
// History storage
If (window. addressBook = undefined ){
// Store the address book as a global
// Object.
// In a real application we wocould remotely
// Fetch this from a server in
// Background.
Window. addressBook =
["Brad Neuberg 'bkn3 @ columbia.edu '",
"John Doe 'johndoe @ example.com '",
"Deanna Neuberg 'Mom @ mom.com '"];

// Cache the address book so it exists
// Even if the user leaves the page and
// Then returns with the back button
HistoryStorage. put ("addressBook ",
AddressBook );
}
Else {
// Fetch the cached address book from
// The history storage
Window. addressBook =
HistoryStorage. get ("addressBook ");
}

The code for handling historical changes is simple. In the following code, handleHistoryChange is called no matter you press the rollback or forward button. We get a new address (newLocation) that uses it to update our user interface to change the status by using a tool named displayLocation O 'Reilly Mail.

Program code ** Handles history change events .*/
Function handleHistoryChange (newLocation,
HistoryData ){
// If there is no location then display
// The default, which is the inbox
If (newLocation = ""){
NewLocation = "section: inbox ";
}

// Extract the section to display from
// The location change; newLocation will
// Begin with the word "section :"
NewLocation =
NewLocation. replace (/section \:/,"");

// Update the browser to respond to this
// DHTML history change
DisplayLocation (newLocation, historyData );
}

/** Displays the given location in
Right-hand side content area .*/
Function displayLocation (newLocation,
SectionData ){
// Get the menu element that was selected
Var selectedElement =
Document. getElementById (newLocation );

// Clear out the old selected menu item
Var menu = document. getElementById ("menu ");
For (var I = 0; I <menu. childNodes. length;
I ++ ){
Var currentElement = menu. childNodes [I];
// See if this is a DOM Element node
If (currentElement. nodeType = 1 ){
// Clear any class name
CurrentElement. className = "";
}
}

// Cause the new selected menu item
// Appear differently in the UI
SelectedElement. className = "selected ";

// Display the new section in the right-hand
// Side of the screen; determine what
// Our sectionData is

// Display the address book differently
// Using our local address data we cached
// Earlier
If (newLocation = "addressbook "){
// Format and display the address book
SectionData = "<p> Your addressbook: </p> ";
SectionData + = "<ul> ";

// Fetch the address book from the cache
// If we don't have it yet
If (window. addressBook = undefined ){
Window. addressBook =
HistoryStorage. get ("addressBook ");
}

// Format the address book for display
For (var I = 0;
I <window. addressBook. length;
I ++ ){
SectionData + = "<li>"
+ Window. addressBook [I]
+ "</Li> ";
}

SectionData + = "</ul> ";
}

// If there is no sectionData, then
// Remotely retrieve it; in this example
// We use fake data for everything but
// Address book
If (sectionData = null ){
// In a real application we wocould remotely
// Fetch this section's content
SectionData = "<p> This is section :"
+ SelectedElement. innerHTML + "</p> ";
}

// Update the content's title and main text
Var contentTitle =
Document. getElementById ("content-title ");
Var contentValue =
Document. getElementById ("content-value ");
ContentTitle. innerHTML =
SelectedElement. innerHTML;
ContentValue. innerHTML = sectionData;
}

Demo) O 'Reilly Mail or download the source code of (download) O 'Reilly Mail.

Conclusion

Now you have learned how to use the Really Simple History API to make your AJAX application respond to bookmarks and forward rollback buttons, and code can be used as materials for creating your own applications. I am eager to expect you to use bookmarks and historical support to complete your AJAX creation.

Copyright Disclaimer: Techtarget is authorized to be released by Matrix. If you need to reprint it, please contact Matrix
Author: Brad Neuberg; boool
Address: http://www.onjava.com/pub/a/onjava/2005/10/26/ajax-handling-bookmarks-and-back-button.html
Address: http://www.matrix.org.cn/resource/article/43/43972_AJAX.html

Resources

· Onjava. com: onjava.com

· Matrix-Java developer community: http://www.matrix.org.cn/

· Download all sample code for this article.
Http://www.onjava.com/onjava/2005/10/26/examples/downloads/examples.zip

· Download the Really Simple History framework.
Http://codinginparadise.org/projects/dhtml_history/latest.zip

· Demo O 'Reilly Mail or download the O' Reilly Mail source code. The full example download also already des more examples for you to play.

· Coding in Paradise: The author's weblog, covering AJAX, DHTML, and Java techniques and new developments in collaborative technologies, such as WikiWikis.
Http://codinginparadise.org/

Thanks
Special thanks to everyone who reviews the Really Simple History framework of this article:
Michael Eakes, Jeremy Sevareid, David Barrett, Brendon Wilson, Dylan Parker, Erik Arvidsson, Alex Russell, Adam Fisk, Alex Lynch, Joseph Hoang Do, Richard MacManus, Garret Wilson, Ray Baxter, chris Messina, and David Weekly.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.