]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/history/history-html5.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / history / history-html5.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('history-html5', function(Y) {
9
10 /**
11  * Provides browser history management using the HTML5 history API.
12  *
13  * @module history
14  * @submodule history-html5
15  * @since 3.2.0
16  */
17
18 /**
19  * <p>
20  * Provides browser history management using the HTML5 history API.
21  * </p>
22  *
23  * <p>
24  * When calling the <code>add()</code>, <code>addValue()</code>,
25  * <code>replace()</code>, or <code>replaceValue()</code> methods on
26  * <code>HistoryHTML5</code>, the following additional options are supported:
27  * </p>
28  *
29  * <dl>
30  *   <dt><strong>title (String)</strong></dt>
31  *   <dd>
32  *     Title to use for the new history entry. Browsers will typically display
33  *     this title to the user in the detailed history window or in a dropdown
34  *     menu attached to the back/forward buttons. If not specified, the title
35  *     of the current document will be used.
36  *   </dd>
37  *
38  *   <dt><strong>url (String)</strong></dt>
39  *   <dd>
40  *     URL to display to the user for the new history entry. This URL will be
41  *     visible in the browser's address bar and will be the bookmarked URL if
42  *     the user bookmarks the page. It may be a relative path ("foo/bar"), an
43  *     absolute path ("/foo/bar"), or a full URL ("http://example.com/foo/bar").
44  *     If you specify a full URL, the origin <i>must</i> be the same as the 
45  *     origin of the current page, or an error will occur. If no URL is
46  *     specified, the current URL will not be changed.
47  *   </dd>
48  * </dl>
49  *
50  * @class HistoryHTML5
51  * @extends HistoryBase
52  * @constructor
53  * @param {Object} config (optional) Configuration object. The following
54  *   <code>HistoryHTML5</code>-specific properties are supported in addition to
55  *   those supported by <code>HistoryBase</code>:
56  *
57  * <dl>
58  *   <dt><strong>enableSessionFallback (Boolean)</strong></dt>
59  *   <dd>
60  *     <p>
61  *     Set this to <code>true</code> to store the most recent history state in
62  *     sessionStorage in order to seamlessly restore the previous state (if any)
63  *     when <code>HistoryHTML5</code> is instantiated after a
64  *     <code>window.onpopstate</code> event has already fired.
65  *     </p>
66  *
67  *     <p>
68  *     By default, this setting is <code>false</code>.
69  *     </p>
70  *   </dd>
71  * </dl>
72  */
73
74 var HistoryBase     = Y.HistoryBase,
75     doc             = Y.config.doc,
76     win             = Y.config.win,
77     sessionStorage,
78     useHistoryHTML5 = Y.config.useHistoryHTML5,
79
80     JSON = Y.JSON || win.JSON, // prefer YUI JSON, but fall back to native
81
82     ENABLE_FALLBACK = 'enableSessionFallback',
83     SESSION_KEY     = 'YUI_HistoryHTML5_state',
84     SRC_POPSTATE    = 'popstate',
85     SRC_REPLACE     = HistoryBase.SRC_REPLACE;
86
87 function HistoryHTML5() {
88     HistoryHTML5.superclass.constructor.apply(this, arguments);
89 }
90
91 Y.extend(HistoryHTML5, HistoryBase, {
92     // -- Initialization -------------------------------------------------------
93     _init: function (config) {
94         Y.on('popstate', this._onPopState, win, this);
95
96         HistoryHTML5.superclass._init.apply(this, arguments);
97
98         // If window.onload has already fired and the sessionStorage fallback is
99         // enabled, try to restore the last state from sessionStorage. This
100         // works around a shortcoming of the HTML5 history API: it's impossible
101         // to get the current state if the popstate event fires before you've
102         // subscribed to it. Since popstate fires immediately after onload,
103         // the last state may be lost if you return to a page from another page.
104         if (config && config[ENABLE_FALLBACK] && YUI.Env.windowLoaded) {
105             // Gecko will throw an error if you attempt to reference
106             // sessionStorage on a page served from a file:// URL, so we have to
107             // be careful here.
108             //
109             // See http://yuilibrary.com/projects/yui3/ticket/2529165
110             try {
111                 sessionStorage = win.sessionStorage;
112             } catch (ex) {}
113
114             this._loadSessionState();
115         }
116     },
117
118     // -- Protected Methods ----------------------------------------------------
119
120     /**
121      * Returns a string unique to the current URL pathname that's suitable for
122      * use as a session storage key.
123      *
124      * @method _getSessionKey
125      * @return {String}
126      * @protected
127      */
128     _getSessionKey: function () {
129         return SESSION_KEY + '_' + win.location.pathname;
130     },
131
132     /**
133      * Attempts to load a state entry stored in session storage.
134      *
135      * @method _loadSessionState
136      * @protected
137      */
138     _loadSessionState: function () {
139         var lastState = JSON && sessionStorage &&
140                 sessionStorage[this._getSessionKey()];
141
142         if (lastState) {
143             try {
144                 this._resolveChanges(SRC_POPSTATE, JSON.parse(lastState) || null);
145             } catch (ex) {}
146         }
147     },
148
149     /**
150      * Stores the specified state entry in session storage if the
151      * <code>enableSessionFallback</code> config property is <code>true</code>
152      * and either <code>Y.JSON</code> or native JSON support is available and
153      * session storage is supported.
154      *
155      * @method _storeSessionState
156      * @param {mixed} state State to store. May be any type serializable to
157      *   JSON.
158      * @protected
159      */
160     _storeSessionState: function (state) {
161         if (this._config[ENABLE_FALLBACK] && JSON && sessionStorage) {
162             sessionStorage[this._getSessionKey()] = JSON.stringify(state || null);
163         }
164     },
165
166     /**
167      * Overrides HistoryBase's <code>_storeState()</code> and pushes or replaces
168      * a history entry using the HTML5 history API when necessary.
169      *
170      * @method _storeState
171      * @param {String} src Source of the changes.
172      * @param {Object} newState New state to store.
173      * @param {Object} options Zero or more options.
174      * @protected
175      */
176     _storeState: function (src, newState, options) {
177         if (src !== SRC_POPSTATE) {
178             win.history[src === SRC_REPLACE ? 'replaceState' : 'pushState'](
179                 newState, options.title || doc.title || '', options.url || null
180             );
181         }
182
183         this._storeSessionState(newState);
184         HistoryHTML5.superclass._storeState.apply(this, arguments);
185     },
186
187     // -- Protected Event Handlers ---------------------------------------------
188
189     /**
190      * Handler for popstate events.
191      *
192      * @method _onPopState
193      * @param {Event} e
194      * @protected
195      */
196     _onPopState: function (e) {
197         var state = e._event.state;
198
199         this._storeSessionState(state);
200         this._resolveChanges(SRC_POPSTATE, state || null);
201     }
202 }, {
203     // -- Public Static Properties ---------------------------------------------
204     NAME: 'historyhtml5',
205
206     /**
207      * Constant used to identify state changes originating from
208      * <code>popstate</code> events.
209      *
210      * @property SRC_POPSTATE
211      * @type String
212      * @static
213      * @final
214      */
215     SRC_POPSTATE: SRC_POPSTATE
216 });
217
218 if (!Y.Node.DOM_EVENTS.popstate) {
219     Y.Node.DOM_EVENTS.popstate = 1;
220 }
221
222 Y.HistoryHTML5 = HistoryHTML5;
223
224 /**
225  * <p>
226  * If <code>true</code>, the <code>Y.History</code> alias will always point to
227  * <code>Y.HistoryHTML5</code> when the history-html5 module is loaded, even if
228  * the current browser doesn't support HTML5 history.
229  * </p>
230  *
231  * <p>
232  * If <code>false</code>, the <code>Y.History</code> alias will always point to
233  * <code>Y.HistoryHash</code> when the history-hash module is loaded, even if
234  * the current browser supports HTML5 history.
235  * </p>
236  *
237  * <p>
238  * If neither <code>true</code> nor <code>false</code>, the
239  * <code>Y.History</code> alias will point to the best available history adapter
240  * that the browser supports. This is the default behavior.
241  * </p>
242  *
243  * @property useHistoryHTML5
244  * @type boolean
245  * @for config
246  * @since 3.2.0
247  */
248
249 // HistoryHTML5 will always win over HistoryHash unless useHistoryHTML5 is false
250 // or HTML5 history is not supported.
251 if (useHistoryHTML5 === true || (useHistoryHTML5 !== false &&
252         HistoryBase.html5)) {
253     Y.History = HistoryHTML5;
254 }
255
256
257 }, '3.3.0' ,{optional:['json'], requires:['event-base', 'history-base', 'node-base']});