embient 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- embient (0.0.3)
4
+ embient (0.0.4)
5
5
  emberjs-rails
6
6
  rails (>= 3.1.0)
7
7
 
@@ -37,12 +37,12 @@ GEM
37
37
  multi_json (~> 1.0)
38
38
  arel (3.0.2)
39
39
  builder (3.0.0)
40
- emberjs-rails (2012.1.25)
40
+ emberjs-rails (2012.2.22)
41
41
  hamlbars
42
42
  rails (~> 3.1)
43
43
  erubis (2.7.0)
44
44
  haml (3.1.4)
45
- hamlbars (2012.1.13)
45
+ hamlbars (2012.2.22)
46
46
  haml
47
47
  sprockets
48
48
  tilt
@@ -1,3 +1,3 @@
1
1
  module Embient
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,204 @@
1
+
2
+ (function(exports) {
3
+ var get = Ember.get, set = Ember.set, meta = Ember.meta;
4
+
5
+ /**
6
+ @class
7
+ This is an extension of Ember.ContainerView who's content
8
+ is restricted to a single child dicated by a property
9
+ on another view.
10
+ */
11
+ Ember.Handlebars.FrameView = Ember.ContainerView.extend({
12
+ /**
13
+ The view corresponding to the containing template
14
+ */
15
+ blockContainer: null,
16
+
17
+ /**
18
+ The property on the blockContainer which dictates the
19
+ contents of this container.
20
+ */
21
+ childPath: 'content',
22
+
23
+ /**
24
+ Set up the listener on the view corresponding to the
25
+ containing template
26
+ */
27
+ init: function() {
28
+ this._super();
29
+ var blockContainer = get(this, 'blockContainer');
30
+ blockContainer.addObserver(get(this, 'childPath'), this, 'contentDidUpdate');
31
+ this.contentDidUpdate();
32
+ },
33
+
34
+ /** @private
35
+ Fired when the property specified by contentPath changes on
36
+ the blockContainer
37
+ */
38
+ contentDidUpdate: function() {
39
+ var blockContainer = this.get('blockContainer');
40
+ var view = blockContainer.getPath(get(this, 'childPath'));
41
+ ember_assert(view instanceof Ember.View, "dynamicView's content must be set to a subclass of Ember.View'");
42
+ var childViews = this.get('_childViews');
43
+ var len = childViews.get('length');
44
+ var views = view ? [view] : [];
45
+ childViews.replace(0, len, views);
46
+ },
47
+
48
+ destroy: function() {
49
+ this._super();
50
+ var blockContainer = get(this, 'blockContainer');
51
+ blockContainer.removeObserver(get(this, 'childPath'), this, 'contentDidUpdate');
52
+ }
53
+ });
54
+
55
+ Ember.Handlebars.dynamicViewHelper = Ember.Object.create({
56
+
57
+ findContainingBlock: function(view) {
58
+ if (!view) {
59
+ return view;
60
+ }
61
+ // We are using _parentView here, because we need to go through the virtual YieldViews, so we can treat them differently.
62
+ else if (view instanceof Ember.Handlebars.FrameView) {
63
+ var blockContainer = Ember.get(view, 'blockContainer');
64
+ return this.findContainingBlock(Ember.get(blockContainer, '_parentView'));
65
+ }
66
+ else if (view.isVirtual) {
67
+ return this.findContainingBlock(Ember.get(view, '_parentView'));
68
+ }
69
+ return view;
70
+ },
71
+
72
+ helper: function(name, options) {
73
+ // If no name is provided, use default and swap parameters
74
+ if (name && name.data && name.data.isRenderData) {
75
+ options = name;
76
+ name = false;
77
+ }
78
+
79
+ var blockContainer = Ember.Handlebars.dynamicViewHelper.findContainingBlock(options.data.view);
80
+
81
+ if(name) {
82
+ options.hash.childPath = name;
83
+ }
84
+ options.hash.blockContainer = blockContainer;
85
+ return Ember.Handlebars.helpers.view.call(this, 'Ember.Handlebars.FrameView', options);
86
+ }
87
+
88
+ });
89
+
90
+ Ember.Handlebars.registerHelper('dynamicView', Ember.Handlebars.dynamicViewHelper.helper);
91
+
92
+
93
+
94
+ })({});
95
+
96
+
97
+ (function(exports) {
98
+ var get = Ember.get, set = Ember.set;
99
+
100
+ /**
101
+ @class
102
+ A convenient extension of Ember.State which makes it easy
103
+ to swap out dynamic content during state transitions.
104
+ */
105
+ Ember.LayoutState = Ember.State.extend({
106
+ /**
107
+ Convenience property to bind to.
108
+ */
109
+ active: false,
110
+
111
+ isViewState: true,
112
+
113
+ /**
114
+ The property to set in the nearest parent view
115
+ when this state is entered.
116
+ */
117
+ contentPath: 'content',
118
+
119
+ init: function() {
120
+ // This is currently experimental. We allow
121
+ // the view itself to define it's substates
122
+ // for better encapsulation. To do this, set
123
+ // the layoutStates property.
124
+ var viewClass = get(this, 'viewClass');
125
+ if(viewClass) {
126
+ var layoutStates = get(viewClass, 'proto').layoutStates;
127
+ set(this, 'states', layoutStates);
128
+ }
129
+
130
+ this._super();
131
+ },
132
+
133
+ enter: function(stateManager, transition) {
134
+ this._super(stateManager, transition);
135
+
136
+ set(this, 'active', true);
137
+
138
+ var viewClass = get(this, 'viewClass'), view;
139
+ ember_assert('view cannot be set directly, use viewClass instead', !this.get('view'));
140
+ view = this.createView(stateManager, transition);
141
+ this.set('view', view);
142
+
143
+ if (view) {
144
+ ember_assert('view must be an Ember.View', view instanceof Ember.View);
145
+
146
+
147
+ // if there is another view in the hierarchy then
148
+ // set its content
149
+ var parentView = get(this, 'parentView') || get(stateManager, 'rootView');
150
+ if(parentView) {
151
+ Ember.setPath(parentView, get(this, 'contentPath'), view);
152
+ }
153
+ // otherwise we just append to the rootElement on the
154
+ // state manager
155
+ else {
156
+ var root = stateManager.get('rootElement') || 'body';
157
+ view.appendTo(root);
158
+ }
159
+ }
160
+ },
161
+
162
+ exit: function(stateManager, transition) {
163
+ var view = get(this, 'view');
164
+
165
+ var parentView = get(this, 'parentView') || get(stateManager, 'rootView');
166
+ if(parentView) {
167
+ Ember.setPath(parentView, get(this, 'contentPath'), null);
168
+ }
169
+ else {
170
+ view.remove();
171
+ }
172
+ set(this, 'view', null);
173
+ set(this, 'active', false);
174
+ this._super(stateManager, transition);
175
+ },
176
+
177
+ /**
178
+ Instantiates viewClass. This method can be
179
+ overridden.
180
+ */
181
+ createView: function(stateManager, transition) {
182
+ var viewClass = get(this, 'viewClass');
183
+ ember_assert('viewClass must extend Ember.View', Ember.View.detect(viewClass));
184
+ return viewClass.create();
185
+ },
186
+
187
+ /**
188
+ Recursively find the nearest parent view
189
+ in the state hierarchy
190
+ */
191
+ parentView: Ember.computed(function() {
192
+ var state = this.get('parentState');
193
+ while(state && !state.get('view')) {
194
+ state = state.get('parentState');
195
+ }
196
+ return state && state.get('view');
197
+ }).property()
198
+ });
199
+
200
+ })({});
201
+
202
+
203
+ (function(exports) {
204
+ })({});
@@ -0,0 +1,553 @@
1
+
2
+ (function(exports) {
3
+ var get = Ember.get, set = Ember.set;
4
+
5
+ /**
6
+ Whether the browser supports HTML5 history.
7
+ */
8
+ var supportsHistory = !!(window.history && window.history.pushState);
9
+
10
+ /**
11
+ Whether the browser supports the hashchange event.
12
+ */
13
+ var supportsHashChange = ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7);
14
+
15
+ /**
16
+ @class
17
+ Ember.RouteManager manages the browser location and changes states accordingly
18
+ to the current location. The location can be programmatically set as follows:
19
+
20
+ routeManager.set('location', 'notes/edit/4');
21
+
22
+ Ember.RouteManager also supports HTML5 history, which uses a '/' instead of a
23
+ '#' in the URLs, so that all your website's URLs are consistent.
24
+ */
25
+ Ember.RouteManager = Ember.StateManager.extend({
26
+
27
+ /**
28
+ Set this property to true if you want to use HTML5 history, if available on
29
+ the browser, instead of the location hash.
30
+
31
+ HTML 5 history uses the history.pushState method and the window's popstate
32
+ event.
33
+
34
+ By default it is false, so your URLs will look like:
35
+
36
+ http://domain.tld/my_app#notes/edit/4
37
+
38
+ If set to true and the browser supports pushState(), your URLs will look
39
+ like:
40
+
41
+ http://domain.tld/my_app/notes/edit/4
42
+
43
+ You will also need to make sure that baseURI is properly configured, as
44
+ well as your server so that your routes are properly pointing to your
45
+ SproutCore application.
46
+
47
+ @see http://dev.w3.org/html5/spec/history.html#the-history-interface
48
+ @property
49
+ @type {Boolean}
50
+ */
51
+ wantsHistory: false,
52
+
53
+ /**
54
+ A read-only boolean indicating whether or not HTML5 history is used. Based
55
+ on the value of wantsHistory and the browser's support for pushState.
56
+
57
+ @see wantsHistory
58
+ @property
59
+ @type {Boolean}
60
+ */
61
+ usesHistory: null,
62
+
63
+ /**
64
+ The base URI used to resolve routes (which are relative URLs). Only used
65
+ when usesHistory is equal to true.
66
+
67
+ The build tools automatically configure this value if you have the
68
+ html5_history option activated in the Buildfile:
69
+
70
+ config :my_app, :html5_history => true
71
+
72
+ Alternatively, it uses by default the value of the href attribute of the
73
+ <base> tag of the HTML document. For example:
74
+
75
+ <base href="http://domain.tld/my_app">
76
+
77
+ The value can also be customized before or during the exectution of the
78
+ main() method.
79
+
80
+ @see http://www.w3.org/TR/html5/semantics.html#the-base-element
81
+ @property
82
+ @type {String}
83
+ */
84
+ baseURI: document.baseURI,
85
+
86
+ /** @private
87
+ A boolean value indicating whether or not the ping method has been called
88
+ to setup the Ember.routes.
89
+
90
+ @property
91
+ @type {Boolean}
92
+ */
93
+ _didSetup: false,
94
+
95
+ /** @private
96
+ Internal representation of the current location hash.
97
+
98
+ @property
99
+ @type {String}
100
+ */
101
+ _location: null,
102
+
103
+ /** @private
104
+ Internal method used to extract and merge the parameters of a URL.
105
+
106
+ @returns {Hash}
107
+ */
108
+ _extractParametersAndRoute: function(obj) {
109
+ var params = {}, route = obj.route || '', separator, parts, i, len, crumbs, key;
110
+ separator = (route.indexOf('?') < 0 && route.indexOf('&') >= 0) ? '&' : '?';
111
+ parts = route.split(separator);
112
+ route = parts[0];
113
+ if(parts.length === 1) {
114
+ parts = [];
115
+ } else if(parts.length === 2) {
116
+ parts = parts[1].split('&');
117
+ } else if(parts.length > 2) {
118
+ parts.shift();
119
+ }
120
+
121
+ // extract the parameters from the route string
122
+ len = parts.length;
123
+ for( i = 0; i < len; ++i) {
124
+ crumbs = parts[i].split('=');
125
+ params[crumbs[0]] = crumbs[1];
126
+ }
127
+
128
+ // overlay any parameter passed in obj
129
+ for(key in obj) {
130
+ if(obj.hasOwnProperty(key) && key !== 'route') {
131
+ params[key] = '' + obj[key];
132
+ }
133
+ }
134
+
135
+ // build the route
136
+ parts = [];
137
+ for(key in params) {
138
+ parts.push([key, params[key]].join('='));
139
+ }
140
+ params.params = separator + parts.join('&');
141
+ params.route = route;
142
+
143
+ return params;
144
+ },
145
+
146
+ /**
147
+ The current location hash. It is the part in the browser's location after
148
+ the '#' mark.
149
+
150
+ @property
151
+ @type {String}
152
+ */
153
+ location: Ember.computed(function(key, value) {
154
+ this._skipRoute = false;
155
+ return this._extractLocation(key, value);
156
+ }).property(),
157
+
158
+ _extractLocation: function(key, value) {
159
+ var crumbs, encodedValue;
160
+
161
+ if(value !== undefined) {
162
+ if(value === null) {
163
+ value = '';
164
+ }
165
+
166
+ if( typeof (value) === 'object') {
167
+ crumbs = this._extractParametersAndRoute(value);
168
+ value = crumbs.route + crumbs.params;
169
+ }
170
+
171
+ if(!this._skipPush && (!Ember.empty(value) || (this._location && this._location !== value))) {
172
+ encodedValue = encodeURI(value);
173
+
174
+ if(this.usesHistory) {
175
+ if(encodedValue.length > 0) {
176
+ encodedValue = '/' + encodedValue;
177
+ }
178
+ window.history.pushState(null, null, get(this, 'baseURI') + encodedValue);
179
+ } else if(encodedValue.length > 0 || window.location.hash.length > 0) {
180
+ window.location.hash = encodedValue;
181
+ }
182
+ }
183
+
184
+ this._location = value;
185
+ }
186
+
187
+ return this._location;
188
+ },
189
+
190
+ updateLocation: function(loc) {
191
+ this._skipRoute = true;
192
+ return this._extractLocation('location', loc);
193
+ },
194
+
195
+ /**
196
+ You usually don't need to call this method. It is done automatically after
197
+ the application has been initialized.
198
+
199
+ It registers for the hashchange event if available. If not, it creates a
200
+ timer that looks for location changes every 150ms.
201
+ */
202
+ ping: function() {
203
+ if(!this._didSetup) {
204
+ this._didSetup = true;
205
+ var state;
206
+
207
+ if(get(this, 'wantsHistory') && supportsHistory) {
208
+ this.usesHistory = true;
209
+
210
+ // Move any hash state to url state
211
+ // TODO: Make sure we have a hash before adding slash
212
+ state = window.location.hash.slice(1);
213
+ if(state.length > 0) {
214
+ state = '/' + state;
215
+ window.history.replaceState(null, null, get(this, 'baseURI') + state);
216
+ }
217
+
218
+ this.popState();
219
+ this.popState = jQuery.proxy(this.popState, this);
220
+ jQuery(window).bind('popstate', this.popState);
221
+
222
+ } else {
223
+ this.usesHistory = false;
224
+
225
+ if(get(this, 'wantsHistory')) {
226
+ // Move any url state to hash
227
+ var base = get(this, 'baseURI');
228
+ var loc = (base.charAt(0) === '/') ? document.location.pathname : document.location.href.replace(document.location.hash, '');
229
+ state = loc.slice(base.length + 1);
230
+ if(state.length > 0) {
231
+ window.location.href = base + '#' + state;
232
+ }
233
+ }
234
+
235
+ if(supportsHashChange) {
236
+ this.hashChange();
237
+ this.hashChange = jQuery.proxy(this.hashChange, this);
238
+ jQuery(window).bind('hashchange', this.hashChange);
239
+
240
+ } else {
241
+ // we don't use a Ember.Timer because we don't want
242
+ // a run loop to be triggered at each ping
243
+ var invokeHashChange = function() {
244
+ this.hashChange();
245
+ this._timerId = setTimeout(invokeHashChange, 100);
246
+ };
247
+
248
+ invokeHashChange();
249
+ }
250
+ }
251
+ }
252
+ },
253
+
254
+ destroy: function() {
255
+ if(this._didSetup) {
256
+ if(get(this, 'wantsHistory') && supportsHistory) {
257
+ jQuery(window).unbind('popstate', this.popState);
258
+ } else {
259
+ if(supportsHashChange) {
260
+ jQuery(window).unbind('hashchange', this.hashChange);
261
+ } else {
262
+ clearTimeout(this._timerId);
263
+ }
264
+ }
265
+ }
266
+ this._super();
267
+ },
268
+
269
+ /**
270
+ Ember.RouteManager currently automatically starts listening
271
+ for browser location changes when created.
272
+ */
273
+ init: function() {
274
+ this._super();
275
+ if(!this._didSetup) {
276
+ this.ping();
277
+ }
278
+ },
279
+
280
+ /**
281
+ Observer of the 'location' property that calls the correct route handler
282
+ when the location changes.
283
+ */
284
+ locationDidChange: Ember.observer(function() {
285
+ this.trigger();
286
+ }, 'location'),
287
+
288
+ /**
289
+ Triggers a route even if already in that route (does change the location, if
290
+ it is not already changed, as well).
291
+
292
+ If the location is not the same as the supplied location, this simply lets
293
+ "location" handle it (which ends up coming back to here).
294
+ */
295
+ trigger: function() {
296
+ var location = get(this, 'location'), params, route;
297
+ params = this._extractParametersAndRoute({
298
+ route: location
299
+ });
300
+ location = params.route;
301
+ delete params.route;
302
+ delete params.params;
303
+
304
+ var result = this.getState(location, params);
305
+ if(result) {
306
+ set(this, 'params', result.params);
307
+
308
+ // We switch states in two phases. The point of this is to handle
309
+ // parameter-only location changes. This will correspond to the same
310
+ // state path in the manager, but states with parts with changed
311
+ // parameters should be re-entered:
312
+
313
+ // 1. We go to the earliest clean state. This prevents
314
+ // unnecessary transitions.
315
+ if(result.cleanStates.length > 0) {
316
+ var cleanState = result.cleanStates.join('.');
317
+ this.goToState(cleanState);
318
+ }
319
+ // 2. We transition to the dirty state. This forces dirty
320
+ // states to be transitioned.
321
+ if(result.dirtyStates.length > 0) {
322
+ var dirtyState = result.cleanStates.concat(result.dirtyStates).join('.');
323
+ this.goToState(dirtyState);
324
+ }
325
+ } else {
326
+ var states = get(this, 'states');
327
+ if(states && get(states, "404")) {
328
+ this.goToState("404");
329
+ }
330
+ }
331
+ },
332
+
333
+ getState: function(route, params) {
334
+ var parts = route.split('/');
335
+ parts = parts.filter(function(part) {
336
+ return part !== '';
337
+ });
338
+
339
+ return this._findState(parts, this, [], [], params, false);
340
+ },
341
+
342
+ /** @private
343
+ Recursive helper that the state and the params if a match is found
344
+ */
345
+ _findState: function(parts, state, cleanStates, dirtyStates, params) {
346
+ parts = Ember.copy(parts);
347
+
348
+ var hasChildren = false, name, states, childState;
349
+ // sort desc based on priority
350
+ states = [];
351
+ for(name in state.states) {
352
+ // 404 state is special and not matched
353
+ childState = state.states[name];
354
+ if(name == "404" || !Ember.State.detect(childState) && !( childState instanceof Ember.State)) {
355
+ continue;
356
+ }
357
+ states.push({
358
+ name: name,
359
+ state: childState
360
+ });
361
+ }
362
+ states = states.sort(function(a, b) {
363
+ return (b.state.get('priority') || 0) - (a.state.get('priority') || 0);
364
+ });
365
+
366
+ for(var i = 0; i < states.length; i++) {
367
+ name = states[i].name;
368
+ childState = states[i].state;
369
+ if(!( childState instanceof Ember.State)) {
370
+ continue;
371
+ }
372
+ hasChildren = true;
373
+
374
+ var result = this._matchState(parts, childState, params);
375
+ if(!result) {
376
+ continue;
377
+ }
378
+
379
+ var newParams = Ember.copy(params);
380
+ jQuery.extend(newParams, result.params);
381
+
382
+ var dirty = dirtyStates.length > 0 || result.dirty;
383
+ var newCleanStates = cleanStates;
384
+ var newDirtyStates = dirtyStates;
385
+ if(dirty) {
386
+ newDirtyStates = Ember.copy(newDirtyStates);
387
+ newDirtyStates.push(name);
388
+ } else {
389
+ newCleanStates = Ember.copy(newCleanStates);
390
+ newCleanStates.push(name);
391
+ }
392
+ result = this._findState(result.parts, childState, newCleanStates, newDirtyStates, newParams);
393
+ if(result) {
394
+ return result;
395
+ }
396
+ }
397
+
398
+ if(!hasChildren && parts.length === 0) {
399
+ return {
400
+ state: state,
401
+ params: params,
402
+ cleanStates: cleanStates,
403
+ dirtyStates: dirtyStates
404
+ };
405
+ }
406
+ return null;
407
+ },
408
+
409
+ /** @private
410
+ Check if a state accepts the parts with the params
411
+
412
+ Returns the remaining parts as well as merged params if
413
+ the state accepts.
414
+
415
+ Will also set the dirty flag if the route is the same but
416
+ the parameters have changed
417
+ */
418
+ _matchState: function(parts, state, params) {
419
+ parts = Ember.copy(parts);
420
+ params = Ember.copy(params);
421
+ var dirty = false;
422
+ var route = get(state, 'route');
423
+ if(route) {
424
+ var partDefinitions;
425
+ // route could be either a string or regex
426
+ if( typeof route == "string") {
427
+ partDefinitions = route.split('/');
428
+ } else if( route instanceof RegExp) {
429
+ partDefinitions = [route];
430
+ } else {
431
+ ember_assert("route must be either a string or regexp", false);
432
+ }
433
+
434
+ for(var i = 0; i < partDefinitions.length; i++) {
435
+ if(parts.length === 0) {
436
+ return false;
437
+ }
438
+ var part = parts.shift();
439
+ var partDefinition = partDefinitions[i];
440
+ var partParams = this._matchPart(partDefinition, part);
441
+ if(!partParams) {
442
+ return false;
443
+ }
444
+
445
+ var oldParams = this.get('params') || {};
446
+ for(var param in partParams) {
447
+ dirty = dirty || (oldParams[param] != partParams[param]);
448
+ }
449
+
450
+ jQuery.extend(params, partParams);
451
+ }
452
+ }
453
+
454
+ if(Ember.typeOf(state.willAccept) == 'function') {
455
+ if(!state.willAccept(params)) {
456
+ return false;
457
+ }
458
+ }
459
+
460
+ return {
461
+ parts: parts,
462
+ params: params,
463
+ dirty: dirty
464
+ };
465
+ },
466
+
467
+ /** @private
468
+ Returns params if the part matches the partDefinition
469
+ */
470
+ _matchPart: function(partDefinition, part) {
471
+ // Handle string parts
472
+ if( typeof partDefinition == "string") {
473
+
474
+ switch (partDefinition.slice(0, 1)) {
475
+ // 1. dynamic routes
476
+ case ':':
477
+ var name = partDefinition.slice(1, partDefinition.length);
478
+ var params = {};
479
+ params[name] = part;
480
+ return params;
481
+
482
+ // 2. wildcard routes
483
+ case '*':
484
+ return {};
485
+
486
+ // 3. static routes
487
+ default:
488
+ if(partDefinition == part)
489
+ return {};
490
+ break;
491
+ }
492
+
493
+ return false;
494
+ }
495
+
496
+ // Handle RegExp parts
497
+ return partDefinition.test(part) ? {} : false;
498
+ },
499
+
500
+ /**
501
+ Event handler for the hashchange event. Called automatically by the browser
502
+ if it supports the hashchange event, or by our timer if not.
503
+ */
504
+ hashChange: function(event) {
505
+ var loc = window.location.hash;
506
+ var routes = this;
507
+
508
+ // Remove the '#' prefix
509
+ loc = (loc && loc.length > 0) ? loc.slice(1, loc.length) : '';
510
+
511
+ if(!jQuery.browser.mozilla) {
512
+ // because of bug https://bugzilla.mozilla.org/show_bug.cgi?id=483304
513
+ loc = decodeURI(loc);
514
+ }
515
+
516
+ if(get(routes, 'location') !== loc && !routes._skipRoute) {
517
+ Ember.run.once(function() {
518
+ routes._skipPush = true;
519
+ set(routes, 'location', loc);
520
+ routes._skipPush = false;
521
+ });
522
+
523
+ }
524
+ routes._skipRoute = false;
525
+ },
526
+
527
+ popState: function(event) {
528
+ var routes = this;
529
+ var base = get(routes, 'baseURI'), loc = (base.charAt(0) === '/') ? document.location.pathname : document.location.href;
530
+
531
+ if(loc.slice(0, base.length) === base) {
532
+ // Remove the base prefix and the extra '/'
533
+ loc = loc.slice(base.length + 1, loc.length);
534
+
535
+ if(get(routes, 'location') !== loc && !routes._skipRoute) {
536
+ Ember.run.once(function() {
537
+ routes._skipPush = true;
538
+ set(routes, 'location', loc);
539
+ routes._skipPush = false;
540
+ });
541
+
542
+ }
543
+ }
544
+ routes._skipRoute = false;
545
+ }
546
+
547
+ });
548
+
549
+ })({});
550
+
551
+
552
+ (function(exports) {
553
+ })({});