1<!-- 2@license 3Copyright (c) 2016 The Polymer Project Authors. All rights reserved. 4This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7Code distributed by Google as part of the polymer project is also 8subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9--> 10<link rel="import" href="../polymer/polymer.html"> 11<link rel="import" href="../iron-location/iron-location.html"> 12<link rel="import" href="../iron-location/iron-query-params.html"> 13<link rel="import" href="app-route-converter-behavior.html"> 14 15<!-- 16`app-location` is an element that provides synchronization between the 17browser location bar and the state of an app. When created, `app-location` 18elements will automatically watch the global location for changes. As changes 19occur, `app-location` produces and updates an object called `route`. This 20`route` object is suitable for passing into a `app-route`, and other similar 21elements. 22 23An example of the public API of a route object that describes the URL 24`https://elements.polymer-project.org/elements/app-location`: 25 26 { 27 prefix: '', 28 path: '/elements/app-location' 29 } 30 31Example Usage: 32 33 <app-location route="{{route}}"></app-location> 34 <app-route route="{{route}}" pattern="/:page" data="{{data}}"></app-route> 35 36As you can see above, the `app-location` element produces a `route` and that 37property is then bound into the `app-route` element. The bindings are two- 38directional, so when changes to the `route` object occur within `app-route`, 39they automatically reflect back to the global location. 40 41### Hashes vs Paths 42 43By default `app-location` routes using the pathname portion of the URL. This has 44broad browser support but it does require cooperation of the backend server. An 45`app-location` can be configured to use the hash part of a URL instead using 46the `use-hash-as-path` attribute, like so: 47 48 <app-location route="{{route}}" use-hash-as-path></app-location> 49 50### Integrating with other routing code 51 52There is no standard event that is fired when window.location is modified. 53`app-location` fires a `location-changed` event on `window` when it updates the 54location. It also listens for that same event, and re-reads the URL when it's 55fired. This makes it very easy to interop with other routing code. 56 57So for example if you want to navigate to `/new_path` imperatively you could 58call `window.location.pushState` or `window.location.replaceState` followed by 59firing a `location-changed` event on `window`. i.e. 60 61 window.history.pushState({}, null, '/new_path'); 62 window.dispatchEvent(new CustomEvent('location-changed')); 63 64@element app-location 65@demo demo/index.html 66--> 67<dom-module id="app-location"> 68 <template> 69 <iron-location 70 path="{{__path}}" 71 query="{{__query}}" 72 hash="{{__hash}}" 73 url-space-regex={{urlSpaceRegex}}> 74 </iron-location> 75 <iron-query-params 76 params-string="{{__query}}" 77 params-object="{{queryParams}}"> 78 </iron-query-params> 79 </template> 80 <script> 81 (function() { 82 'use strict'; 83 84 Polymer({ 85 is: 'app-location', 86 87 properties: { 88 /** 89 * A model representing the deserialized path through the route tree, as 90 * well as the current queryParams. 91 */ 92 route: { 93 type: Object, 94 notify: true 95 }, 96 97 /** 98 * In many scenarios, it is convenient to treat the `hash` as a stand-in 99 * alternative to the `path`. For example, if deploying an app to a static 100 * web server (e.g., Github Pages) - where one does not have control over 101 * server-side routing - it is usually a better experience to use the hash 102 * to represent paths through one's app. 103 * 104 * When this property is set to true, the `hash` will be used in place of 105 106 * the `path` for generating a `route`. 107 */ 108 useHashAsPath: { 109 type: Boolean, 110 value: false 111 }, 112 113 /** 114 * A regexp that defines the set of URLs that should be considered part 115 * of this web app. 116 * 117 * Clicking on a link that matches this regex won't result in a full page 118 * navigation, but will instead just update the URL state in place. 119 * 120 * This regexp is given everything after the origin in an absolute 121 * URL. So to match just URLs that start with /search/ do: 122 * url-space-regex="^/search/" 123 * 124 * @type {string|RegExp} 125 */ 126 urlSpaceRegex: { 127 type: String, 128 notify: true 129 }, 130 131 /** 132 * A set of key/value pairs that are universally accessible to branches 133 * of the route tree. 134 */ 135 __queryParams: { 136 type: Object 137 }, 138 139 /** 140 * The pathname component of the current URL. 141 */ 142 __path: { 143 type: String 144 }, 145 146 /** 147 * The query string portion of the current URL. 148 */ 149 __query: { 150 type: String 151 }, 152 153 /** 154 * The hash portion of the current URL. 155 */ 156 __hash: { 157 type: String 158 }, 159 160 /** 161 * The route path, which will be either the hash or the path, depending 162 * on useHashAsPath. 163 */ 164 path: { 165 type: String, 166 observer: '__onPathChanged' 167 } 168 }, 169 170 behaviors: [Polymer.AppRouteConverterBehavior], 171 172 observers: [ 173 '__computeRoutePath(useHashAsPath, __hash, __path)' 174 ], 175 176 __computeRoutePath: function() { 177 this.path = this.useHashAsPath ? this.__hash : this.__path; 178 }, 179 180 __onPathChanged: function() { 181 if (!this._readied) { 182 return; 183 } 184 185 if (this.useHashAsPath) { 186 this.__hash = this.path; 187 } else { 188 this.__path = this.path; 189 } 190 } 191 }); 192 })(); 193 </script> 194</dom-module> 195