~bcsaller/juju-gui/charmFind

« back to all changes in this revision

Viewing changes to lib/yui/docs/router/index.html

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<!DOCTYPE html>
2
 
<html lang="en">
3
 
<head>
4
 
    <meta charset="utf-8">
5
 
    <title>Router</title>
6
 
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Maven+Pro:400,700">
7
 
    <link rel="stylesheet" href="../../build/cssgrids/grids-min.css">
8
 
    <link rel="stylesheet" href="../assets/css/main.css">
9
 
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
10
 
    <script src="../../build/yui/yui-min.js"></script>
11
 
</head>
12
 
<body>
13
 
 
14
 
<div id="doc">
15
 
    <h1>Router</h1>
16
 
 
17
 
    
18
 
        <a href="#toc" class="jump">Jump to Table of Contents</a>
19
 
    
20
 
 
21
 
    <div class="yui3-g">
22
 
        <div class="yui3-u-3-4">
23
 
            <div id="main">
24
 
                <div class="content"><div class="intro">
25
 
<p>
26
 
Router provides URL-based same-page routing using <a href="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history">HTML5 history</a> (<code>pushState</code>) or the location hash, depending on what the user's browser supports.
27
 
</p>
28
 
 
29
 
<p>
30
 
This makes it easy to wire up route handlers for different application states while providing full back/forward navigation support and bookmarkable, shareable URLs, all handled entirely on the client.
31
 
</p>
32
 
 
33
 
<p>
34
 
If you've used a server-side routing framework like <a href="http://expressjs.com/">Express</a> or <a href="http://www.sinatrarb.com/">Sinatra</a>, Router will look very familiar to you. This is no accident!
35
 
</p>
36
 
</div>
37
 
 
38
 
<h2 id="getting-started">Getting Started</h2>
39
 
 
40
 
<p>
41
 
To include the source files for Router and its dependencies, first load
42
 
the YUI seed file if you haven't already loaded it.
43
 
</p>
44
 
 
45
 
<pre class="code prettyprint">&lt;script src=&quot;http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.5.1&#x2F;build&#x2F;yui&#x2F;yui-min.js&quot;&gt;&lt;&#x2F;script&gt;</pre>
46
 
 
47
 
 
48
 
<p>
49
 
Next, create a new YUI instance for your application and populate it with the
50
 
modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
51
 
YUI will automatically load any dependencies required by the modules you
52
 
specify.
53
 
</p>
54
 
 
55
 
<pre class="code prettyprint">&lt;script&gt;
56
 
&#x2F;&#x2F; Create a new YUI instance and populate it with the required modules.
57
 
YUI().use(&#x27;router&#x27;, function (Y) {
58
 
    &#x2F;&#x2F; Router is available and ready for use. Add implementation
59
 
    &#x2F;&#x2F; code here.
60
 
});
61
 
&lt;&#x2F;script&gt;</pre>
62
 
 
63
 
 
64
 
<p>
65
 
For more information on creating YUI instances and on the
66
 
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
67
 
documentation for the <a href="../yui/index.html">YUI Global Object</a>.
68
 
</p>
69
 
 
70
 
 
71
 
<h2 id="upgrading-from-yui-34x">Upgrading from YUI 3.4.x</h2>
72
 
 
73
 
<p>
74
 
A beta version of Router was first introduced in YUI 3.4.0, but was named Controller. If you're using Controller in YUI 3.4.0 or 3.4.1, you'll need to make the following changes to your code when upgrading:
75
 
</p>
76
 
 
77
 
<ul>
78
 
  <li>
79
 
    <p>
80
 
    The name of the class has changed from <code>Controller</code> to <code>Router</code>. Change all references to the <code>Controller</code> class and the <code>controller</code> module in your code to refer to the <code>Router</code> class and <code>router</code> module, respectively. To ease migration, <code>Controller</code> is now an alias for <code>Router</code> and will still work, but this alias will be removed in a future release of YUI.
81
 
    </p>
82
 
  </li>
83
 
 
84
 
  <li>
85
 
    <p>
86
 
    The <code>html5</code>, <code>root</code>, and <code>route</code> properties are now attributes. If you were accessing them as properties, update your code to access them as attributes instead. For example, <code>var root = myController.root;</code> becomes <code>var root = myRouter.get(&#x27;root&#x27;);</code>, and <code>myController.root = &#x27;&#x2F;foo&#x27;;</code> becomes <code>myRouter.set(&#x27;root&#x27;, &#x27;&#x2F;foo&#x27;);</code>.
87
 
    </p>
88
 
  </li>
89
 
 
90
 
  <li>
91
 
    <p>
92
 
    The function signature for route handlers has changed. Previously, the second argument passed to all route handlers was the <code>next()</code> function. As of YUI 3.5.0, the second argument is a response object, and the third argument is the <code>next()</code> function. To preserve backwards compatibility, the response object is also a function that will call <code>next()</code>, but you should still update your code to take the new argument order into account.
93
 
    </p>
94
 
  </li>
95
 
</ul>
96
 
 
97
 
<h2 id="url-based-routing-on-the-client">URL-based Routing on the Client?</h2>
98
 
 
99
 
<p>
100
 
You bet! URLs are an excellent way to maintain state in a web app, since they're easy to read, easy to change, and can be bookmarked and shared.
101
 
</p>
102
 
 
103
 
<p>
104
 
Server-side web frameworks use URLs to maintain state by routing them to different pages and by storing information in query strings. These same techniques can now be used by client-side web apps to achieve better parity with server-side logic and to provide a more seamless user experience.
105
 
</p>
106
 
 
107
 
<p>
108
 
Router allows you to define routes that map to callback functions. Whenever the user navigates to a URL that matches a route you've defined, that route's callback function is executed and can update the UI, make Ajax requests, or perform any other necessary actions. See <a href="#routing">Routing</a> for more details on how this works.
109
 
</p>
110
 
 
111
 
<p>
112
 
Often you'll want to change the URL in order to trigger a route handler, perhaps because the user has taken an action that should change the state of your application. Router provides a <code>save()</code> method that sets a new URL and saves it to the user's browser history. There's also a <code>replace()</code> method to replace the current URL in the user's browser history without creating a new entry. The <a href="#updating-the-url">Updating the URL</a> section describes these methods in detail.
113
 
</p>
114
 
 
115
 
<h2 id="sample-urls">Sample URLs</h2>
116
 
 
117
 
<p>
118
 
In browsers that support the HTML5 history API, Router generates real URLs that can gracefully degrade to allow server-side handling of initial pageviews or pageviews without JS enabled. Most modern browsers (including recent versions of Firefox, Chrome, Safari, and Mobile Safari) support HTML5 history.
119
 
</p>
120
 
 
121
 
<p>
122
 
In browsers that don't support the HTML5 history API, Router falls back on using the location hash to store URL information and trigger history changes. This mostly applies only to older browsers and Internet Explorer. Unfortunately, even Internet Explorer 9 doesn't support the HTML5 history API.
123
 
</p>
124
 
 
125
 
<p>
126
 
The table below contains examples of the kinds of URLs Router might generate when the <code>save()</code> method is called on a Router instance, starting from an initial URL of <code>http:&#x2F;&#x2F;example.com&#x2F;</code>.
127
 
</p>
128
 
 
129
 
<table>
130
 
  <thead>
131
 
    <tr>
132
 
      <th>Code</th>
133
 
      <th>HTML5 URL</th>
134
 
      <th>Legacy URL</th>
135
 
    </tr>
136
 
  </thead>
137
 
  <tbody>
138
 
    <tr>
139
 
      <td><code>router.save(&#x27;&#x2F;&#x27;)</code></td>
140
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;</code></td>
141
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;</code></td>
142
 
    </tr>
143
 
 
144
 
    <tr>
145
 
      <td><code>router.save(&#x27;&#x2F;pie&#x2F;yum&#x27;)</code></td>
146
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;pie&#x2F;yum</code></td>
147
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;pie&#x2F;yum</code></td>
148
 
    </tr>
149
 
 
150
 
    <tr>
151
 
      <td><code>router.save(&#x27;&#x2F;pie?type=pecan&amp;icecream=true&#x27;)</code></td>
152
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;pie?type=pecan&amp;icecream=true</code></td>
153
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;pie?type=pecan&amp;icecream=true</code></td>
154
 
    </tr>
155
 
  </tbody>
156
 
</table>
157
 
 
158
 
<h2 id="using-router">Using Router</h2>
159
 
 
160
 
<h3 id="instantiating-router">Instantiating Router</h3>
161
 
 
162
 
<p>
163
 
To begin adding route handlers, the first thing you'll need to do is create a new Router instance.
164
 
</p>
165
 
 
166
 
<pre class="code prettyprint">var router = new Y.Router();</pre>
167
 
 
168
 
 
169
 
<p>
170
 
This is the simplest way of working with Router, but you may also extend <code>Y.Router</code> to create a custom Router class that suits your needs. The <a href="#extending-yrouter">Extending <code>Y.Router</code></a> section explains how to do this.
171
 
</p>
172
 
 
173
 
<h4 id="config-attributes">Config Attributes</h4>
174
 
 
175
 
<p>
176
 
When instantiating Router, you may optionally pass in a config object containing values for any of the following attributes. For more details on these attributes, see Router's <a href="http://yuilibrary.com/yui/docs/api/modules/router.html">API docs</a>.
177
 
</p>
178
 
 
179
 
<table>
180
 
  <thead>
181
 
    <tr>
182
 
      <th>Attribute</th>
183
 
      <th>Default</th>
184
 
      <th>Description</th>
185
 
    </tr>
186
 
  </thead>
187
 
  <tbody>
188
 
    <tr>
189
 
      <td><code>html5</code></td>
190
 
      <td><em>auto</em></td>
191
 
      <td>
192
 
        <p>
193
 
        Whether or not to use HTML5 history (<code>true</code>) or hash-based history (<code>false</code>).
194
 
        </p>
195
 
 
196
 
        <p>
197
 
        Feature detection is used to determine the correct default setting for the current browser, but you may override this to force all browsers to use or not use HTML5 history.
198
 
        </p>
199
 
 
200
 
        <p>
201
 
        Before changing this value, please read <a href="#html5-urls-vs-hash-urls">HTML5 URLs vs. Hash URLs</a> and be sure you fully understand the consequences. It's almost always a better idea to leave it alone.
202
 
        </p>
203
 
      </td>
204
 
    </tr>
205
 
 
206
 
    <tr>
207
 
      <td><code>root</code></td>
208
 
      <td><code>&#x27;&#x27;</code></td>
209
 
      <td>
210
 
        <p>
211
 
        Root path from which all routes should be evaluated. See <a href="#setting-the-root-path">Setting the Root Path</a> for details.
212
 
        </p>
213
 
      </td>
214
 
    </tr>
215
 
 
216
 
    <tr>
217
 
      <td><code>routes</code></td>
218
 
      <td><code>[]</code></td>
219
 
      <td>
220
 
        <p>
221
 
        Array of route objects. This can be used to specify routes at instantiation time, or when extending <code>Y.Router</code>. It can also be used after instantiation to reset all existing routes. To add routes after instantiation without resetting existing routes, use the <code>route()</code> method.
222
 
        </p>
223
 
 
224
 
        <p>
225
 
        Each item in the array must be an object with the following properties:
226
 
        </p>
227
 
 
228
 
        <dl style="margin-top:1em">
229
 
          <dt><code>path</code></dt>
230
 
          <dd>
231
 
            String or regex representing the path to match. See <a href="#routing">Routing</a> for more details.
232
 
          </dd>
233
 
 
234
 
          <dt><code>callback</code></dt>
235
 
          <dd>
236
 
            A function or a string representing the name of a function on the Router instance that should be called when the route is triggered. See <a href="#routing">Routing</a> for more details.
237
 
          </dd>
238
 
        </dl>
239
 
      </td>
240
 
    </tr>
241
 
  </tbody>
242
 
</table>
243
 
 
244
 
<p>
245
 
Here's an example that sets all the configurable attributes at instantiation time:
246
 
</p>
247
 
 
248
 
<pre class="code prettyprint">var router = new Y.Router({
249
 
  html5: false,
250
 
  root : &#x27;&#x2F;mysite&#x27;,
251
 
 
252
 
  routes: [
253
 
    {path: &#x27;&#x2F;&#x27;,    callback: function () { alert(&#x27;Hello!&#x27;); }},
254
 
    {path: &#x27;&#x2F;pie&#x27;, callback: function () { alert(&#x27;Mmm. Pie.&#x27;); }}
255
 
  ]
256
 
});</pre>
257
 
 
258
 
 
259
 
<h4 id="setting-the-root-path">Setting the Root Path</h4>
260
 
 
261
 
<p>
262
 
Let's say the URL for your website is <code>http:&#x2F;&#x2F;example.com&#x2F;mysite&#x2F;</code>. Since Router matches routes based on the URL path, it would look for routes beginning with <code>&#x2F;mysite&#x2F;</code>.
263
 
</p>
264
 
 
265
 
<p>
266
 
You could deal with this by ensuring that all your routes start with <code>&#x2F;mysite&#x2F;</code>, but that's tedious, and it won't work well if you're writing a component that might be used on various sites where you can't anticipate the root path.
267
 
</p>
268
 
 
269
 
<p>
270
 
This is where the <code>root</code> config attribute comes in. If you set <code>root</code> to <code>&#x27;&#x2F;mysite&#x27;</code>, then all routes will be evaluated relative to that root path, as illustrated below.
271
 
</p>
272
 
 
273
 
<p>
274
 
The <code>root</code> must be an absolute path.
275
 
</p>
276
 
 
277
 
<table>
278
 
  <thead>
279
 
    <tr>
280
 
      <th>URL</th>
281
 
      <th>Route (No root)</th>
282
 
      <th>Route (Root: /mysite)</th>
283
 
    </tr>
284
 
  </thead>
285
 
  <tbody>
286
 
    <tr>
287
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;mysite&#x2F;</code></td>
288
 
      <td><code>&#x2F;mysite&#x2F;</code></td>
289
 
      <td><code>&#x2F;</code></td>
290
 
    </tr>
291
 
 
292
 
    <tr>
293
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;mysite&#x2F;pie&#x2F;</code></td>
294
 
      <td><code>&#x2F;mysite&#x2F;pie&#x2F;</code></td>
295
 
      <td><code>&#x2F;pie&#x2F;</code></td>
296
 
    </tr>
297
 
 
298
 
    <tr>
299
 
      <td><code>http:&#x2F;&#x2F;example.com&#x2F;mysite&#x2F;ice-cream&#x2F;yum.html</code></td>
300
 
      <td><code>&#x2F;mysite&#x2F;ice-cream&#x2F;yum.html</code></td>
301
 
      <td><code>&#x2F;ice-cream&#x2F;yum.html</code></td>
302
 
    </tr>
303
 
  </tbody>
304
 
</table>
305
 
 
306
 
<h3 id="extending-yrouter">Extending <code>Y.Router</code></h3>
307
 
 
308
 
<p>
309
 
While <code>Y.Router</code> may be instantiated and used directly, you might find it more convenient to extend the <code>Y.Router</code> class to create a subclass customized for your particular needs.
310
 
</p>
311
 
 
312
 
<p>
313
 
Use the <code>Y.Base.create()</code> method to extend <code>Y.Router</code> and add or override prototype and static members and attributes. You may also optionally specify one or more <a href="../base/index.html#extensions">Base extensions</a> to mix into your new class.
314
 
</p>
315
 
 
316
 
<pre class="code prettyprint">&#x2F;&#x2F; Create a Y.CustomRouter class that extends Y.Router.
317
 
Y.CustomRouter = Y.Base.create(&#x27;customRouter&#x27;, Y.Router, [], {
318
 
  &#x2F;&#x2F; Add or override prototype properties and methods here.
319
 
}, {
320
 
  &#x2F;&#x2F; Add static properties and methods here.
321
 
 
322
 
  ATTRS: {
323
 
    &#x2F;&#x2F; Override default attributes here.
324
 
  }
325
 
});</pre>
326
 
 
327
 
 
328
 
<p>
329
 
One benefit of extending <code>Y.Router</code> is that you can easily add default routes and route handlers to your custom Router class, and they'll be shared by all instances of that class unless overridden at the instance level:
330
 
</p>
331
 
 
332
 
<pre class="code prettyprint">Y.CustomRouter = Y.Base.create(&#x27;customRouter&#x27;, Y.Router, [], {
333
 
  &#x2F;&#x2F; Default route handlers inherited by all CustomRouter instances.
334
 
  index: function (req) {
335
 
    &#x2F;&#x2F; ... handle the &#x2F; route ...
336
 
  },
337
 
 
338
 
  pie: function (req) {
339
 
    &#x2F;&#x2F; ... handle the &#x2F;pie route ...
340
 
  }
341
 
}, {
342
 
  ATTRS: {
343
 
    &#x2F;&#x2F; Evaluate all routes relative to this root path.
344
 
    root: {
345
 
      value: &#x27;&#x2F;mysite&#x27;
346
 
    },
347
 
 
348
 
    &#x2F;&#x2F; Share these default routes with all CustomRouter instances.
349
 
    routes: {
350
 
      value: [
351
 
        {path: &#x27;&#x2F;&#x27;,    callback: &#x27;index&#x27;},
352
 
        {path: &#x27;&#x2F;pie&#x27;, callback: &#x27;pie&#x27;}
353
 
      ]
354
 
    },
355
 
  }
356
 
});
357
 
 
358
 
&#x2F;&#x2F; Create a CustomRouter instance that inherits the defaults and adds to
359
 
&#x2F;&#x2F; them.
360
 
var router = new Y.CustomRouter();
361
 
 
362
 
router.route(&#x27;&#x2F;cheesecake&#x27;, function (req) {
363
 
  &#x2F;&#x2F; ... handle the &#x2F;cheesecake route
364
 
});</pre>
365
 
 
366
 
 
367
 
<p>
368
 
Now all instances of <code>Y.CustomRouter</code> will inherit all the custom defaults and can add to or override them. The <code>router</code> instance created here will handle the <code>&#x2F;</code> and <code>&#x2F;pie</code> routes in addition to its own <code>&#x2F;cheesecake</code> route, and will evaluate all routes from the <code>&#x2F;mysite</code> root path.
369
 
</p>
370
 
 
371
 
<h3 id="routing">Routing</h3>
372
 
 
373
 
<p>
374
 
Use the <code>route()</code> method to add a new route to a Router instance. The first parameter is a path specification or regular expression that the URL path must match, and the second parameter is a callback function or function name to execute when the route is matched.
375
 
</p>
376
 
 
377
 
<pre class="code prettyprint">var router = new Y.Router();
378
 
 
379
 
&#x2F;&#x2F; Add a route using a string as the path specification.
380
 
router.route(&#x27;&#x2F;pie&#x27;, function () {
381
 
  Y.log(&#x27;You visited http:&#x2F;&#x2F;example.com&#x2F;pie&#x27;);
382
 
});
383
 
 
384
 
&#x2F;&#x2F; Add a route using a regular expression as the path specification.
385
 
router.route(&#x2F;^\&#x2F;cake$&#x2F;, function () {
386
 
  Y.log(&#x27;You visited http:&#x2F;&#x2F;example.com&#x2F;cake&#x27;);
387
 
});</pre>
388
 
 
389
 
 
390
 
<p>
391
 
Routes are always evaluated in the order they're added. The first route that matches a given URL is executed, and any subsequent routes that also match the URL will not be executed unless the first route passes control to the next route. See <a href="#chaining-routes">Chaining Routes</a> for more info on executing more than one route for a given URL.
392
 
</p>
393
 
 
394
 
<p>
395
 
When a route callback is specified as a string instead of a function, it's assumed to represent the name of a function on the Router instance.
396
 
</p>
397
 
 
398
 
<pre class="code prettyprint">var router = new Y.Router();
399
 
 
400
 
router.pie = function () {
401
 
  Y.log(&#x27;You visited http:&#x2F;&#x2F;example.com&#x2F;pie&#x27;);
402
 
};
403
 
 
404
 
&#x2F;&#x2F; Add a route using router.pie as the route callback.
405
 
router.route(&#x27;&#x2F;pie&#x27;, &#x27;pie&#x27;);</pre>
406
 
 
407
 
 
408
 
<p>
409
 
As an alternative to using the <code>route()</code> method, routes may be added at instantiation time using the <code>routes</code> config attribute:
410
 
</p>
411
 
 
412
 
<pre class="code prettyprint">var router = new Y.Router({
413
 
  routes: [
414
 
    {path: &#x27;&#x2F;pie&#x27;, callback: function () {
415
 
      Y.log(&#x27;You visited http:&#x2F;&#x2F;example.com&#x2F;pie&#x27;);
416
 
    }},
417
 
 
418
 
    {path: &#x2F;^\&#x2F;cake$&#x2F;, callback: function () {
419
 
      Y.log(&#x27;You visited http:&#x2F;&#x2F;example.com&#x2F;cake&#x27;);
420
 
    }}
421
 
  ]
422
 
});</pre>
423
 
 
424
 
 
425
 
<p>
426
 
This is functionally equivalent to adding the routes via the <code>route()</code> method, except that it will replace any default routes, and the routes are added during the Router's initialization stage rather than after.
427
 
</p>
428
 
 
429
 
<h4 id="paths-placeholders-and-regexps">Paths, Placeholders, and RegExps</h4>
430
 
 
431
 
<p>
432
 
A route path may be specified as either a string or a regular expression. When a string is provided, it's compiled to a regular expression internally. If the regex matches the path portion (not including protocol, domain, query string, etc.) of a URL being dispatched, the route callback will be executed.
433
 
</p>
434
 
 
435
 
<p>
436
 
Path strings may contain placeholders. When a route is matched, the values of these placeholders will be made available to the route callback on the <code>req.params</code> object.
437
 
</p>
438
 
 
439
 
<p>
440
 
A placeholder prefixed by a <code>:</code>, like <code>:pie</code>, will match any character except for a path separator (<code>&#x2F;</code>).
441
 
</p>
442
 
 
443
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;pie&#x2F;:type&#x2F;:slices&#x27;, function (req) {
444
 
  Y.log(&quot;You ordered &quot; + req.params.slices + &quot; slices of &quot;
445
 
      + req.params.type + &quot; pie.&quot;);
446
 
});
447
 
 
448
 
router.save(&#x27;&#x2F;pie&#x2F;apple&#x2F;2&#x27;);
449
 
&#x2F;&#x2F; =&gt; &quot;You ordered 2 slices of apple pie.&quot;
450
 
 
451
 
router.save(&#x27;&#x2F;pie&#x2F;lemon+meringue&#x2F;42&#x27;);
452
 
&#x2F;&#x2F; =&gt; &quot;You ordered 42 slices of lemon meringue pie.&quot;</pre>
453
 
 
454
 
 
455
 
<p>
456
 
A placeholder prefixed by a <code>*</code>, like <code>*path</code>, will match as many characters as it can until the next character after the placeholder, including path separators.
457
 
</p>
458
 
 
459
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;files&#x2F;*path&#x27;, function (req) {
460
 
  Y.log(&quot;You requested the file &quot; + req.params.path);
461
 
});
462
 
 
463
 
router.save(&#x27;&#x2F;files&#x2F;recipes&#x2F;pie&#x2F;pecan.html&#x27;);
464
 
&#x2F;&#x2F; =&gt; &quot;You requested the file recipes&#x2F;pie&#x2F;pecan.html&quot;</pre>
465
 
 
466
 
 
467
 
<p>
468
 
Use <code>*</code> all by itself as a wildcard to match any path at all:
469
 
</p>
470
 
 
471
 
<pre class="code prettyprint">router.route(&#x27;*&#x27;, function () {
472
 
  Y.log(&quot;Wildcard route! I match everything! I&#x27;m craaaaaaazy!&quot;);
473
 
});
474
 
 
475
 
router.save(&#x27;&#x2F;purple&#x2F;monkey&#x2F;dishwasher&#x27;);
476
 
&#x2F;&#x2F; =&gt; &quot;Wildcard route! I match everything! I&#x27;m craaaaaaazy!&quot;
477
 
 
478
 
router.save(&#x27;&#x2F;blue&#x2F;jeans&#x2F;pizza&#x27;);
479
 
&#x2F;&#x2F; =&gt; &quot;Wildcard route! I match everything! I&#x27;m craaaaaaazy!&quot;</pre>
480
 
 
481
 
 
482
 
<p>
483
 
Wildcards can also be used within a path:
484
 
</p>
485
 
 
486
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;purple&#x2F;*&#x27;, function () {
487
 
  Y.log(&quot;I only like purple stuffz!&quot;);
488
 
});
489
 
 
490
 
router.save(&#x27;&#x2F;purple&#x2F;monkey&#x2F;dishwasher&#x27;);
491
 
&#x2F;&#x2F; =&gt; &quot;I only like purple stuffz!&quot;
492
 
 
493
 
router.save(&#x27;&#x2F;purple&#x2F;pants&#x27;);
494
 
&#x2F;&#x2F; =&gt; &quot;I only like purple stuffz!&quot;</pre>
495
 
 
496
 
 
497
 
<p>
498
 
Placeholder names may contain any character in the range <code>[A-Za-z0-9_-]</code> (so <code>:foo-bar</code> is a valid placeholder but <code>:foo bar</code> is not).
499
 
</p>
500
 
 
501
 
<p>
502
 
When a regular expression is used as a path specification, <code>req.params</code> will be an array. The first item in the array is the entire matched string, and subsequent items are captured subpattern matches (if any).
503
 
</p>
504
 
 
505
 
<pre class="code prettyprint">router.route(&#x2F;^\&#x2F;pie\&#x2F;([^\&#x2F;]*)\&#x2F;([^\&#x2F;]*)$&#x2F;, function (req) {
506
 
  Y.log(&quot;You ordered &quot; + req.params[1] + &quot; slices of &quot;
507
 
      + req.params[2] + &quot; pie.&quot;);
508
 
});
509
 
 
510
 
router.save(&#x27;&#x2F;pie&#x2F;maple+custard&#x2F;infinity&#x27;);
511
 
&#x2F;&#x2F; =&gt; &quot;You ordered infinity slices of maple custard pie.&quot;</pre>
512
 
 
513
 
 
514
 
<h4 id="route-callbacks">Route Callbacks</h4>
515
 
 
516
 
<p>
517
 
When a route is matched, the callback function associated with that route will be executed, and will receive three parameters:
518
 
</p>
519
 
 
520
 
<dl>
521
 
  <dt><strong><code>req</code> (Object)</strong></dt>
522
 
  <dd>
523
 
    <p>
524
 
    An object that contains information about the request that triggered the route. It contains the following properties:
525
 
    </p>
526
 
 
527
 
    <dl>
528
 
      <dt><strong><code>params</code> (Object or Array)</strong></dt>
529
 
      <dd>
530
 
        <p>
531
 
        Parameters matched by the route path specification.
532
 
        </p>
533
 
 
534
 
        <p>
535
 
        If a string path was used and contained named parameters, then <code>params</code> will be a hash with parameter names as keys and the matched substrings as values. If a regex path was used, <code>params</code> will be an array of matches starting at index <code>0</code> for the full string matched, then <code>1</code> for the first subpattern match, and so on.
536
 
        </p>
537
 
      </dd>
538
 
 
539
 
      <dt><strong><code>path</code> (String)</strong></dt>
540
 
      <dd>
541
 
        <p>
542
 
        The current URL path matched by the route.
543
 
        </p>
544
 
      </dd>
545
 
 
546
 
      <dt><strong><code>query</code> (Object)</strong></dt>
547
 
      <dd>
548
 
        <p>
549
 
        Hash of query string parameters and values specified in the URL, if any.
550
 
        </p>
551
 
      </dd>
552
 
 
553
 
      <dt><strong><code>url</code> (String)</strong></dt>
554
 
      <dd>
555
 
        <p>
556
 
        The full URL.
557
 
        </p>
558
 
      </dd>
559
 
 
560
 
      <dt><strong><code>src</code> (String)</strong></dt>
561
 
      <dd>
562
 
        <p>
563
 
        What initiated the dispatch.
564
 
        </p>
565
 
 
566
 
        <p>
567
 
        In an HTML5 browser, when the back/forward buttons are used, this property will have a value of "popstate".
568
 
        </p>
569
 
      </dd>
570
 
    </dl>
571
 
  </dd>
572
 
 
573
 
  <dt><strong><code>res</code> (Object)</strong></dt>
574
 
  <dd>
575
 
    <p>
576
 
    An object that contains methods and information that relate to responding to a request.
577
 
    </p>
578
 
 
579
 
    <p>
580
 
    <strong>Note:</strong> For backwards compatibility, the response object is also a function that when called will behave the same as directly calling <code>next()</code>. This backcompat behavior will eventually be removed.
581
 
    </p>
582
 
 
583
 
    <p>
584
 
    The response object contains the following properties (it will eventually contain more, and may be augmented by subclasses or used to pass information from route to route):
585
 
    </p>
586
 
 
587
 
    <dl>
588
 
      <dt><strong><code>req</code> (Object)</strong></dt>
589
 
      <dd>
590
 
        <p>
591
 
        Reference to the request object.
592
 
        </p>
593
 
      </dd>
594
 
    </dl>
595
 
  </dd>
596
 
 
597
 
  <dt><strong><code>next</code> (Function)</strong></dt>
598
 
  <dd>
599
 
    <p>
600
 
    A function that will pass control to the next matching route (if any) when called. If not called, no further routes will be executed.
601
 
    </p>
602
 
  </dd>
603
 
</dl>
604
 
 
605
 
<p>
606
 
Inside a route callback, the <code>this</code> keyword will always refer to the Router instance that executed that route.
607
 
</p>
608
 
 
609
 
<h4 id="chaining-routes">Chaining Routes</h4>
610
 
 
611
 
<p>
612
 
By default, only the first route that matches a URL will be executed, even if there are several routes that match. However, when a route is executed, it will receive a <code>next()</code> function as its third parameter. Calling this function will execute the next matching route if there is one.
613
 
</p>
614
 
 
615
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;pie&#x27;, function (req, res, next) {
616
 
  Y.log(&#x27;Callback #1 executed!&#x27;);
617
 
  next();
618
 
});
619
 
 
620
 
router.route(&#x27;&#x2F;pie&#x27;, function (req) {
621
 
  Y.log(&#x27;Callback #2 executed!&#x27;);
622
 
});
623
 
 
624
 
router.route(&#x27;&#x2F;pie&#x27;, function (req) {
625
 
  Y.log(&#x27;Callback #3 executed!&#x27;);
626
 
});
627
 
 
628
 
router.save(&#x27;&#x2F;pie&#x27;);
629
 
&#x2F;&#x2F; =&gt; &quot;Callback #1 executed!&quot;
630
 
&#x2F;&#x2F; =&gt; &quot;Callback #2 executed!&quot;</pre>
631
 
 
632
 
 
633
 
<p>
634
 
If you want the first route callback to pass some data along to subsequent callbacks, you can attach that data to either the <code>req</code> object or the <code>res</code> object, which are shared between all routes that are executed during a single request.
635
 
</p>
636
 
 
637
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;ice-cream&#x27;, function (req, res, next) {
638
 
  req.flavor = &#x27;cookie dough&#x27;;
639
 
  next();
640
 
});
641
 
 
642
 
router.route(&#x27;&#x2F;ice-cream&#x27;, function (req) {
643
 
  Y.log(&quot;I sure do like &quot; + req.flavor + &quot; ice cream.&quot;);
644
 
});
645
 
 
646
 
router.save(&#x27;&#x2F;ice-cream&#x27;);
647
 
&#x2F;&#x2F; =&gt; &quot;I sure do like cookie dough ice cream.&quot;</pre>
648
 
 
649
 
 
650
 
<p>
651
 
Whether to store data on <code>req</code> or <code>res</code> is up to you, but by convention, data pertaining to the request should be stored on <code>req</code>, and data pertaining to a response or to some other result of that request should be stored on <code>res</code>.
652
 
</p>
653
 
 
654
 
<h3 id="updating-the-url">Updating the URL</h3>
655
 
 
656
 
<p>
657
 
Call the <code>save()</code> or <code>replace()</code> methods to update the URL and store an entry in the browser's history.
658
 
</p>
659
 
 
660
 
<p>
661
 
The only difference between the two is that <code>save()</code> saves a new history entry, while <code>replace()</code> replaces the current history entry.
662
 
</p>
663
 
 
664
 
<pre class="code prettyprint">&#x2F;&#x2F; Save a new history entry.
665
 
router.save(&#x27;&#x2F;cake&#x27;);
666
 
 
667
 
&#x2F;&#x2F; Replace the current history entry with a new one.
668
 
router.replace(&#x27;&#x2F;pie&#x27;);</pre>
669
 
 
670
 
 
671
 
<p>
672
 
Changing the URL in this way will trigger a dispatch, and will execute the first route that matches the new URL (if any). A dispatch will also be triggered automatically whenever the user uses the browser's back or forward buttons.
673
 
</p>
674
 
 
675
 
<p>
676
 
When you need to provide state information to your route handlers, it's best to provide that information as query parameters in the URL. This way, your application's state is always reflected in the current URL, and can be properly restored when a URL is bookmarked or copied.
677
 
</p>
678
 
 
679
 
<pre class="code prettyprint">router.route(&#x27;&#x2F;ice-cream&#x27;, function (req) {
680
 
  var flavor = req.query.flavor;
681
 
 
682
 
  if (flavor === &#x27;vanilla&#x27;) {
683
 
    Y.log(&#x27;Vanilla? How boring.&#x27;);
684
 
  } else if (flavor === &#x27;americone dream&#x27;) {
685
 
    Y.log(&#x27;Mmmm, Colbert-flavored ice cream.&#x27;);
686
 
  } else {
687
 
    Y.log(&#x27;Error! Error! Does not compute!&#x27;);
688
 
  }
689
 
});
690
 
 
691
 
router.save(&#x27;&#x2F;ice-cream?flavor=vanilla&#x27;);
692
 
&#x2F;&#x2F; =&gt; &quot;Vanilla? How boring.&quot;
693
 
 
694
 
router.save(&#x27;&#x2F;ice-cream?flavor=americone+dream&#x27;);
695
 
&#x2F;&#x2F; =&gt; &quot;Mmm, Colbert-flavored ice cream.&quot;
696
 
 
697
 
router.save(&#x27;&#x2F;ice-cream?flavor=kitten&#x27;);
698
 
&#x2F;&#x2F; =&gt; &quot;Error! Error! Does not compute!&quot;</pre>
699
 
 
700
 
 
701
 
<h4 id="capturing-link-clicks">Capturing Link Clicks</h4>
702
 
 
703
 
<p>
704
 
An excellent way to provide progressive enhancement on a page with URLs that can be handled by both the server and the client is to use normal links, and then add a delegated event handler to capture clicks on those links and use client-side routing when JavaScript is available. You can also use this technique to selectively use client-side routing or server-side routing depending on which link is clicked.
705
 
</p>
706
 
 
707
 
<pre class="code prettyprint">&#x2F;&#x2F; This sample requires the &#x60;node-event-delegate&#x60; module.
708
 
YUI().use(&#x27;router&#x27;, &#x27;node-event-delegate&#x27;, function (Y) {
709
 
  &#x2F;&#x2F; ... create a router instance as described in the sections above ...
710
 
 
711
 
  &#x2F;&#x2F; Attach a delegated click handler to listen for clicks on all links on the
712
 
  &#x2F;&#x2F; page.
713
 
  Y.one(&#x27;body&#x27;).delegate(&#x27;click&#x27;, function (e) {
714
 
    &#x2F;&#x2F; Allow the native behavior on middle&#x2F;right-click, or when Ctrl or Command
715
 
    &#x2F;&#x2F; are pressed.
716
 
    if (e.button !== 1 || e.ctrlKey || e.metaKey) {
717
 
      return;
718
 
    }
719
 
 
720
 
    &#x2F;&#x2F; Remove the non-path portion of the URL, and any portion of the path that
721
 
    &#x2F;&#x2F; isn&#x27;t relative to this router&#x27;s root path.
722
 
    var path = router.removeRoot(e.currentTarget.get(&#x27;href&#x27;));
723
 
 
724
 
    &#x2F;&#x2F; If the router has a route that matches this path, then use the
725
 
    &#x2F;&#x2F; router to update the URL and handle the route. Otherwise, let the
726
 
    &#x2F;&#x2F; browser handle the click normally.
727
 
    if (router.hasRoute(path)) {
728
 
      e.preventDefault();
729
 
      router.save(path);
730
 
    }
731
 
  }, &#x27;a&#x27;);
732
 
});</pre>
733
 
 
734
 
 
735
 
<p>
736
 
Now a click on any link, such as <code>&lt;a href=&quot;http:&#x2F;&#x2F;example.com&#x2F;foo&quot;&gt;Click me!&lt;&#x2F;a&gt;</code>, will automatically be handled by the router if there's a matching route. If there's no matching route, or if the user doesn't have JavaScript enabled, the link click will be handled normally by the browser.
737
 
</p>
738
 
 
739
 
<h3 id="to-dispatch-or-not-to-dispatch">To Dispatch or Not to Dispatch?</h3>
740
 
 
741
 
<p>
742
 
Dispatching is what it's called when Router looks for routes that match the current URL and then executes the callback of the first matching route (if any).
743
 
</p>
744
 
 
745
 
<p>
746
 
A dispatch can be triggered in the following ways:
747
 
</p>
748
 
 
749
 
<ul>
750
 
  <li>Automatically, whenever the URL changes after the initial pageview.</li>
751
 
  <li>Manually, by calling the <code>dispatch()</code> method.</li>
752
 
  <li>Manually (but only in HTML5 browsers), by calling the <code>upgrade()</code> method when the URL contains a hash-based route that was copied from a legacy browser.</li>
753
 
</ul>
754
 
 
755
 
<p>
756
 
It's important to remember that if a user bookmarks or copies an HTML5 URL generated by Router and visits that URL later, the full URL will be sent to the server. On the other hand, if a user bookmarks or copies a hash-based URL in a legacy browser and then visits it later, the hash portion of the URL <em>won't</em> be sent to the server.
757
 
</p>
758
 
 
759
 
<p>
760
 
For instance, let's say a user visits your website at <code>http:&#x2F;&#x2F;example.com&#x2F;</code>. On that page, you have the following code:
761
 
</p>
762
 
 
763
 
<pre class="code prettyprint">&lt;button id=&quot;pie&quot;&gt;Click me if you like pie!&lt;&#x2F;button&gt;
764
 
 
765
 
&lt;script&gt;
766
 
YUI().use(&#x27;router&#x27;, &#x27;node&#x27;, function (Y) {
767
 
  var router = new Y.Router();
768
 
 
769
 
  router.route(&#x27;&#x2F;pie&#x27;, function () {
770
 
    &#x2F;&#x2F; Show the user a photo of a delicious pie.
771
 
  });
772
 
 
773
 
  Y.one(&#x27;#pie&#x27;).on(&#x27;click&#x27;, function () {
774
 
    router.save(&#x27;&#x2F;pie&#x27;);
775
 
  });
776
 
});
777
 
&lt;&#x2F;script&gt;</pre>
778
 
 
779
 
 
780
 
<p>
781
 
In an HTML5 browser, when the user clicks the button, Router will change the URL to <code>http:&#x2F;&#x2F;example.com&#x2F;pie</code> and then execute the <code>&#x2F;pie</code> route, but the browser won't contact the server. If the user bookmarks this URL and then loads it again later, the web server will handle the request. If it doesn't recognize the path <code>&#x2F;pie</code>, it may return a 404 error, which would be no good.
782
 
</p>
783
 
 
784
 
<p>
785
 
In a legacy browser, clicking the button will cause the URL to change to <code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;pie</code>, and the <code>&#x2F;pie</code> route will be executed, also without contacting the server. The difference is that if the user bookmarks this URL and loads it later, the hash portion won't be sent to the server. The server will only see <code>http:&#x2F;&#x2F;example.com&#x2F;</code>, so it will be necessary to handle the request on the client as well.
786
 
</p>
787
 
 
788
 
<p>
789
 
There are two ways to deal with this. One way would be to implement server-side logic to handle requests for <code>&#x2F;pie</code> and render the appropriate page. To provide fallback support for hash-based URLs, we can modify the client-side code to call the <code>dispatch()</code> method in legacy browsers, by adding the following:
790
 
</p>
791
 
 
792
 
<pre class="code prettyprint">&#x2F;&#x2F; Always dispatch to an initial route on legacy browsers. Only dispatch to an
793
 
&#x2F;&#x2F; initial route on HTML5 browsers if it&#x27;s necessary in order to upgrade a
794
 
&#x2F;&#x2F; legacy hash URL to an HTML5 URL.
795
 
if (router.get(&#x27;html5&#x27;)) {
796
 
  router.upgrade();
797
 
} else {
798
 
  router.dispatch();
799
 
}</pre>
800
 
 
801
 
 
802
 
<p>
803
 
The benefit of this is that HTML5 URLs will be rendered on the server and won't present any difficulties for search crawlers or users with JS disabled. Meanwhile, hash-based URLs will be handled on the client as long as JS is enabled. The drawback with this method is that it may require maintaining duplicate logic on both the server and the client.
804
 
</p>
805
 
 
806
 
<p>
807
 
The other way to handle this would be to configure the server to render the same initial page for all URLs (it would essentially route all paths to the same page), and always dispatch on the client, regardless of the browser's capabilities:
808
 
</p>
809
 
 
810
 
<pre class="code prettyprint">&#x2F;&#x2F; Dispatch to an initial route on all browsers.
811
 
router.dispatch();</pre>
812
 
 
813
 
 
814
 
<p>
815
 
On the one hand, this solution avoids most of the server-side complexity and keeps all the router logic on the client. On the other, it requires the client to support JavaScript, so it won't play well with search crawlers that can't run JavaScript or users who disable JavaScript.
816
 
</p>
817
 
 
818
 
<h2 id="best-practices">Best Practices</h2>
819
 
 
820
 
<h3 id="html5-urls-vs-hash-urls">HTML5 URLs vs. Hash URLs</h3>
821
 
 
822
 
<p>
823
 
As discussed in <a href="#to-dispatch-or-not-to-dispatch">To Dispatch or Not to Dispatch?</a>, there are benefits and drawbacks to both HTML5 URLs&mdash;that is, URLs generated via the HTML5 history API&mdash;and hash-based URLs. This adds difficulty to any client-side URL-based routing solution, and unfortunately it means you may need to make some tough choices about the architecture of your application.
824
 
</p>
825
 
 
826
 
<p>
827
 
The primary benefit of HTML5 URLs is that they can potentially be handled on the server as well as on the client. This has potential benefits for application architecture (rendering an initial pageview on the server is often faster than rendering it on the client) and for preventing link rot (if you rewrite or replace your application at some point, it's relatively easy to set up server-side redirects to point the old URLs to a new location). That said, HTML5 URLs may require more server-side logic in order to work correctly.
828
 
</p>
829
 
 
830
 
<p>
831
 
Hash-based URLs, on the other hand, can't be handled on the server because browsers don't send the hash portion of a URL to a server. This means they must always be rendered on the client using JavaScript. Even worse, if you eventually rewrite or replace your web app, it's extremely unlikely that you'll be able to keep that old JavaScript around just for the sake of redirecting old URLs, which means any old hash-based URLs in the wild are likely to stop working.
832
 
</p>
833
 
 
834
 
<p>
835
 
In general, the benefits of HTML5 URLs tend to outweigh the drawbacks when compared to hash-based URLs, which is why Router automatically defaults to using HTML5 URLs in browsers that support it. The hash-based URLs generated by Router should be used only as a fallback for legacy browsers.
836
 
</p>
837
 
 
838
 
<h3 id="cross-browser-url-compatibility">Cross-browser URL Compatibility</h3>
839
 
 
840
 
<p>
841
 
It's very important that any URL generated by Router be usable in any browser. If a user of a legacy browser copies a URL and shares it with a friend who uses an HTML5 browser, that URL should still work. And if someone copies an HTML5 URL and shares it with a user of a legacy browser, that needs to work too.
842
 
</p>
843
 
 
844
 
<p>
845
 
When a hash-based URL is loaded in an HTML5 browser and <code>dispatch()</code> or <code>upgrade()</code> are called, Router automatically upgrades the URL to an HTML5 URL. So a URL like <code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;pie</code> will become <code>http:&#x2F;&#x2F;example.com&#x2F;pie</code>, and the HTML5 browser will execute the appropriate route handler.
846
 
</p>
847
 
 
848
 
<p>
849
 
The difference between the <code>dispatch()</code> and <code>upgrade()</code> methods is that <code>dispatch()</code> always dispatches to the first route that matches the current URL, whereas <code>upgrade()</code> will only dispatch if the browser is an HTML5 browser and the URL is a legacy hash-based URL that must be handled on the client in order to upgrade it to an HTML5 URL.
850
 
</p>
851
 
 
852
 
<p>
853
 
When an HTML5 URL like <code>http:&#x2F;&#x2F;example.com&#x2F;pie</code> is loaded in a legacy browser, what happens depends on how your server is configured:
854
 
</p>
855
 
 
856
 
<ul>
857
 
  <li><p>If the server is capable of handling the URL, then it should render the page in the appropriate state, and Router won't need to do anything.</p></li>
858
 
  <li><p>If the server is not capable of handling the URL, then it should render the initial page state and you should call Router's <code>dispatch()</code> method. Router will parse the HTML5 URL and execute the appropriate route, even in a legacy browser.</p></li>
859
 
</ul>
860
 
 
861
 
<p>
862
 
For more on how dispatching works, see <a href="#to-dispatch-or-not-to-dispatch">To Dispatch or Not to Dispatch?</a>.
863
 
</p>
864
 
 
865
 
<h3 id="progressive-enhancement-and-seo">Progressive Enhancement and SEO</h3>
866
 
 
867
 
<p>
868
 
In general, HTML5 URLs that can be rendered by the server when necessary provide the best support for both progressive enhancement (by rendering initial pageviews more quickly, even in browsers with JavaScript disabled) and for search engine optimization (by allowing you to use real, non hash-based URLs that can be crawled by search bots, which may not support JavaScript).
869
 
</p>
870
 
 
871
 
<p>
872
 
Being able to render the same application states both on the server and the client may require you to write duplicate code. However, if you use JavaScript on the server, and in particular if you use <a href="http://nodejs.org/">Node.js</a>, you may be able to share code.
873
 
</p>
874
 
 
875
 
<p>
876
 
Router's routing style and route specification format are intentionally very similar to those of the <a href="http://expressjs.com/">Express.js</a> server-side framework. With a little care, you may be able to use the same route handler code on both the server and the client.
877
 
</p>
878
 
 
879
 
<h4 id="supporting-googles-ajax-crawling-scheme">Supporting Google's Ajax Crawling Scheme</h4>
880
 
 
881
 
<p>
882
 
One of the problems with the hash-based URLs Router uses to support legacy browsers is that most search engines don't distinguish between a URL with a hash fragment and one without. This means that, to a search bot, the URLs <code>http:&#x2F;&#x2F;example.com&#x2F;</code> and <code>http:&#x2F;&#x2F;example.com&#x2F;#&#x2F;pie</code> might look the same, even though they might represent completely different content in your application.
883
 
</p>
884
 
 
885
 
<p>
886
 
Google's <a href="http://code.google.com/web/ajaxcrawling/">Ajax Crawling Scheme</a> specifies a way to make hash-based URLs crawlable by the GoogleBot if you're willing to implement some extra server-side logic.
887
 
</p>
888
 
 
889
 
<p>
890
 
To indicate to the GoogleBot that your hash URLs are crawlable, the hash must be prefixed by <code>#!</code> instead of the default <code>#</code>. You can make Router do this automatically by setting the value of the static <code>Y.HistoryHash.hashPrefix</code> property before initializing any Router instances:
891
 
</p>
892
 
 
893
 
<pre class="code prettyprint">Y.HistoryHash.hashPrefix = &#x27;!&#x27;;</pre>
894
 
 
895
 
 
896
 
<p>
897
 
Next, read Google's <a href="http://code.google.com/web/ajaxcrawling/docs/getting-started.html">getting started guide</a> for a description of how the Ajax crawling scheme works and the additional changes you'll need to make to your application. Most of the changes you'll need to make will have to happen in your server-side logic.
898
 
</p>
899
 
 
900
 
<p>
901
 
Don't skip the server-side changes! Without them, using the <code>#!</code> prefix won't do you any good, and may even hurt the search ranking of your pages.
902
 
</p>
903
 
 
904
 
<h2 id="known-limitations">Known Limitations</h2>
905
 
 
906
 
<ul>
907
 
  <li><p><strong>HTML5 history is not supported by Internet Explorer 9 or lower.</strong> IE10 is the first version of Internet Explorer that supports HTML5 history. Earlier versions will fall back to hash-based history by default.</p></li>
908
 
 
909
 
  <li><p><strong>Android 2.x is forced to use hash-based history due to <a href="http://code.google.com/p/android/issues/detail?id=17471">a bug</a> in Android's HTML5 history implementation.</strong> This bug does not affect Android 3.0 and higher.</p></li>
910
 
 
911
 
  <li><p><strong>Hash-based URLs are case-insensitive in Internet Explorer 8 and 9</strong>. Most browsers follow the HTML5 spec and treat URLs&mdash;including hash-based URLs&mdash;as case-sensitive. IE8 and IE9 ignore case in hash-based URLs, so changing a hash-based URL from <code>&#x2F;foo</code> to <code>&#x2F;Foo</code> won't trigger a dispatch.</p></li>
912
 
 
913
 
  <li><p><strong>Internet Explorer 6 and 7 only retain the most recent hash-based URL from a previous pageview after navigating to another page and returning.</strong> However, history entries created within a single pageview will persist for the duration of that pageview, and bookmarked URLs will still work in all cases.</p></li>
914
 
 
915
 
  <li><p><strong>In Internet Explorer 6 and 7, the page titles displayed for history entries in the browser's history dropdown menu are not correct.</strong> Instead of showing the title of each page, it shows part of the URL of each page.</p></li>
916
 
 
917
 
  <li><p><strong>Internet Explorer (all versions) replaces the current history entry when the hash portion of the URL is manually edited in the URL bar</strong> instead of adding a new history entry as other browsers do. There's unfortunately nothing YUI can do to detect or work around this.</p></li>
918
 
</ul>
919
 
</div>
920
 
            </div>
921
 
        </div>
922
 
 
923
 
        <div class="yui3-u-1-4">
924
 
            <div class="sidebar">
925
 
                
926
 
                    <div id="toc" class="sidebox">
927
 
                        <div class="hd">
928
 
                            <h2 class="no-toc">Table of Contents</h2>
929
 
                        </div>
930
 
 
931
 
                        <div class="bd">
932
 
                            <ul class="toc">
933
 
<li>
934
 
<a href="#getting-started">Getting Started</a>
935
 
</li>
936
 
<li>
937
 
<a href="#upgrading-from-yui-34x">Upgrading from YUI 3.4.x</a>
938
 
</li>
939
 
<li>
940
 
<a href="#url-based-routing-on-the-client">URL-based Routing on the Client?</a>
941
 
</li>
942
 
<li>
943
 
<a href="#sample-urls">Sample URLs</a>
944
 
</li>
945
 
<li>
946
 
<a href="#using-router">Using Router</a>
947
 
<ul class="toc">
948
 
<li>
949
 
<a href="#instantiating-router">Instantiating Router</a>
950
 
<ul class="toc">
951
 
<li>
952
 
<a href="#config-attributes">Config Attributes</a>
953
 
</li>
954
 
<li>
955
 
<a href="#setting-the-root-path">Setting the Root Path</a>
956
 
</li>
957
 
</ul>
958
 
</li>
959
 
<li>
960
 
<a href="#extending-yrouter">Extending <code>Y.Router</code></a>
961
 
</li>
962
 
<li>
963
 
<a href="#routing">Routing</a>
964
 
<ul class="toc">
965
 
<li>
966
 
<a href="#paths-placeholders-and-regexps">Paths, Placeholders, and RegExps</a>
967
 
</li>
968
 
<li>
969
 
<a href="#route-callbacks">Route Callbacks</a>
970
 
</li>
971
 
<li>
972
 
<a href="#chaining-routes">Chaining Routes</a>
973
 
</li>
974
 
</ul>
975
 
</li>
976
 
<li>
977
 
<a href="#updating-the-url">Updating the URL</a>
978
 
<ul class="toc">
979
 
<li>
980
 
<a href="#capturing-link-clicks">Capturing Link Clicks</a>
981
 
</li>
982
 
</ul>
983
 
</li>
984
 
<li>
985
 
<a href="#to-dispatch-or-not-to-dispatch">To Dispatch or Not to Dispatch?</a>
986
 
</li>
987
 
</ul>
988
 
</li>
989
 
<li>
990
 
<a href="#best-practices">Best Practices</a>
991
 
<ul class="toc">
992
 
<li>
993
 
<a href="#html5-urls-vs-hash-urls">HTML5 URLs vs. Hash URLs</a>
994
 
</li>
995
 
<li>
996
 
<a href="#cross-browser-url-compatibility">Cross-browser URL Compatibility</a>
997
 
</li>
998
 
<li>
999
 
<a href="#progressive-enhancement-and-seo">Progressive Enhancement and SEO</a>
1000
 
<ul class="toc">
1001
 
<li>
1002
 
<a href="#supporting-googles-ajax-crawling-scheme">Supporting Google's Ajax Crawling Scheme</a>
1003
 
</li>
1004
 
</ul>
1005
 
</li>
1006
 
</ul>
1007
 
</li>
1008
 
<li>
1009
 
<a href="#known-limitations">Known Limitations</a>
1010
 
</li>
1011
 
</ul>
1012
 
                        </div>
1013
 
                    </div>
1014
 
                
1015
 
 
1016
 
                
1017
 
 
1018
 
                
1019
 
            </div>
1020
 
        </div>
1021
 
    </div>
1022
 
</div>
1023
 
 
1024
 
<script src="../assets/vendor/prettify/prettify-min.js"></script>
1025
 
<script>prettyPrint();</script>
1026
 
 
1027
 
</body>
1028
 
</html>