Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / docs / source / History.html
1 <html>\r
2 <head>\r
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
4   <title>The source code</title>\r
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
7 </head>\r
8 <body  onload="prettyPrint();">\r
9     <pre class="prettyprint lang-js"><div id="cls-Ext.History"></div>/**\r
10  * @class Ext.History\r
11  * @extends Ext.util.Observable\r
12  * History management component that allows you to register arbitrary tokens that signify application\r
13  * history state on navigation actions.  You can then handle the history {@link #change} event in order\r
14  * to reset your application UI to the appropriate state when the user navigates forward or backward through\r
15  * the browser history stack.\r
16  * @singleton\r
17  */\r
18 Ext.History = (function () {\r
19     var iframe, hiddenField,\r
20         ready = false,\r
21         currentToken,\r
22         ignoreNext = false;\r
23 \r
24     function getHash() {\r
25         var href = top.location.href, i = href.indexOf("#");\r
26         return i >= 0 ? href.substr(i + 1) : null;\r
27     }\r
28 \r
29     function doSave() {\r
30         hiddenField.value = currentToken;\r
31     }\r
32 \r
33     function handleStateChange(token) {\r
34         currentToken = token;\r
35         if(!(token == ignoreNext)){\r
36             Ext.History.fireEvent('change', token);\r
37         }\r
38         ignoreNext = false;\r
39     }\r
40 \r
41     function updateIFrame (token) {\r
42         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');\r
43         try {\r
44             var doc = iframe.contentWindow.document;\r
45             doc.open();\r
46             doc.write(html);\r
47             doc.close();\r
48             return true;\r
49         } catch (e) {\r
50             return false;\r
51         }\r
52     }\r
53 \r
54     function checkIFrame() {\r
55         if (!iframe.contentWindow || !iframe.contentWindow.document) {\r
56             setTimeout(checkIFrame, 10);\r
57             return;\r
58         }\r
59 \r
60         var doc = iframe.contentWindow.document,\r
61             elem = doc.getElementById("state"),\r
62             token = elem ? elem.innerText : null,\r
63             hash = getHash();\r
64 \r
65         setInterval(function () {\r
66 \r
67             doc = iframe.contentWindow.document;\r
68             elem = doc.getElementById("state");\r
69 \r
70             var newtoken = elem ? elem.innerText : null,\r
71                 newHash = getHash();\r
72 \r
73             if (newtoken !== token) {\r
74                 token = newtoken;\r
75                 handleStateChange(token);\r
76                 top.location.hash = token;\r
77                 hash = token;\r
78                 doSave();\r
79             } else if (newHash !== hash) {\r
80                 hash = newHash;\r
81                 updateIFrame(newHash);\r
82             }\r
83 \r
84         }, 50);\r
85 \r
86         ready = true;\r
87 \r
88         Ext.History.fireEvent('ready', Ext.History);\r
89     }\r
90 \r
91     function startUp() {\r
92         currentToken = hiddenField.value ? hiddenField.value : getHash();\r
93 \r
94         if (Ext.isIE) {\r
95             checkIFrame();\r
96         } else {\r
97             var hash = getHash();\r
98             setInterval(function () {\r
99                 var newHash = getHash();\r
100                 if (newHash !== hash) {\r
101                     hash = newHash;\r
102                     handleStateChange(hash);\r
103                     doSave();\r
104                 }\r
105             }, 50);\r
106             ready = true;\r
107             Ext.History.fireEvent('ready', Ext.History);\r
108         }\r
109     }\r
110 \r
111     return {\r
112         <div id="prop-Ext.History-fieldId"></div>/**\r
113          * The id of the hidden field required for storing the current history token.\r
114          * @type String\r
115          * @property\r
116          */\r
117         fieldId: 'x-history-field',\r
118         <div id="prop-Ext.History-iframeId"></div>/**\r
119          * The id of the iframe required by IE to manage the history stack.\r
120          * @type String\r
121          * @property\r
122          */\r
123         iframeId: 'x-history-frame',\r
124 \r
125         events:{},\r
126 \r
127         <div id="method-Ext.History-init"></div>/**\r
128          * Initialize the global History instance.\r
129          * @param {Boolean} onReady (optional) A callback function that will be called once the history\r
130          * component is fully initialized.\r
131          * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser window.\r
132          */\r
133         init: function (onReady, scope) {\r
134             if(ready) {\r
135                 Ext.callback(onReady, scope, [this]);\r
136                 return;\r
137             }\r
138             if(!Ext.isReady){\r
139                 Ext.onReady(function(){\r
140                     Ext.History.init(onReady, scope);\r
141                 });\r
142                 return;\r
143             }\r
144             hiddenField = Ext.getDom(Ext.History.fieldId);\r
145             if (Ext.isIE) {\r
146                 iframe = Ext.getDom(Ext.History.iframeId);\r
147             }\r
148             this.addEvents(\r
149                 <div id="event-Ext.History-ready"></div>/**\r
150                  * @event ready\r
151                  * Fires when the Ext.History singleton has been initialized and is ready for use.\r
152                  * @param {Ext.History} The Ext.History singleton.\r
153                  */\r
154                 'ready',\r
155                 <div id="event-Ext.History-change"></div>/**\r
156                  * @event change\r
157                  * Fires when navigation back or forwards within the local page's history occurs.\r
158                  * @param {String} token An identifier associated with the page state at that point in its history.\r
159                  */\r
160                 'change'\r
161             );\r
162             if(onReady){\r
163                 this.on('ready', onReady, scope, {single:true});\r
164             }\r
165             startUp();\r
166         },\r
167 \r
168         <div id="method-Ext.History-add"></div>/**\r
169          * Add a new token to the history stack. This can be any arbitrary value, although it would\r
170          * commonly be the concatenation of a component id and another id marking the specifc history\r
171          * state of that component.  Example usage:\r
172          * <pre><code>\r
173 // Handle tab changes on a TabPanel\r
174 tabPanel.on('tabchange', function(tabPanel, tab){\r
175     Ext.History.add(tabPanel.id + ':' + tab.id);\r
176 });\r
177 </code></pre>\r
178          * @param {String} token The value that defines a particular application-specific history state\r
179          * @param {Boolean} preventDuplicates When true, if the passed token matches the current token\r
180          * it will not save a new history step. Set to false if the same state can be saved more than once\r
181          * at the same history stack location (defaults to true).\r
182          */\r
183         add: function (token, preventDup, suppressEvent) {\r
184             if(preventDup !== false){\r
185                 if(this.getToken() == token){\r
186                     return true;\r
187                 }\r
188             }\r
189             if(suppressEvent){\r
190                 ignoreNext = token;\r
191             }\r
192             if (Ext.isIE) {\r
193                 return updateIFrame(token);\r
194             } else {\r
195                 top.location.hash = token;\r
196                 return true;\r
197             }\r
198         },\r
199 \r
200         <div id="method-Ext.History-back"></div>/**\r
201          * Programmatically steps back one step in browser history (equivalent to the user pressing the Back button).\r
202          */\r
203         back: function(){\r
204             history.go(-1);\r
205         },\r
206 \r
207         <div id="method-Ext.History-forward"></div>/**\r
208          * Programmatically steps forward one step in browser history (equivalent to the user pressing the Forward button).\r
209          */\r
210         forward: function(){\r
211             history.go(1);\r
212         },\r
213 \r
214         <div id="method-Ext.History-getToken"></div>/**\r
215          * Retrieves the currently-active history token.\r
216          * @return {String} The token\r
217          */\r
218         getToken: function() {\r
219             return ready ? currentToken : getHash();\r
220         }\r
221     };\r
222 })();\r
223 Ext.apply(Ext.History, new Ext.util.Observable());</pre>    \r
224 </body>\r
225 </html>