@angular-wave/angular.ts 0.4.4 → 0.4.6
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.
- package/Makefile +1 -0
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -12
- package/index.html +3 -74
- package/package.json +1 -1
- package/src/angular.spec.js +5 -0
- package/src/animations/animate-css.js +13 -5
- package/src/animations/animate-queue.js +21 -22
- package/src/animations/animate-runner.js +8 -4
- package/src/animations/animate.md +1 -1
- package/src/animations/animate.spec.js +21 -0
- package/src/animations/animation.js +1 -1
- package/src/binding.spec.js +1 -0
- package/src/core/compile/compile.js +25 -27
- package/src/core/compile/compile.spec.js +266 -17
- package/src/core/controller/controller.js +0 -2
- package/src/core/di/injector.md +1 -1
- package/src/core/di/injector.spec.js +2 -0
- package/src/core/di/internal-injector.js +1 -2
- package/src/core/interpolate/interpolate.js +12 -28
- package/src/core/interpolate/interpolate.spec.js +16 -70
- package/src/core/interval/interval-factory.js +50 -0
- package/src/core/interval/interval.html +18 -0
- package/src/core/interval/interval.js +77 -0
- package/src/core/interval/interval.md +123 -0
- package/src/core/interval/interval.spec.js +280 -0
- package/src/core/interval/interval.test.js +1 -1
- package/src/core/location/location.js +53 -59
- package/src/core/location/location.spec.js +27 -27
- package/src/core/on.spec.js +7 -0
- package/src/core/parse/interpreter.js +7 -10
- package/src/core/parse/parse.js +5 -26
- package/src/core/parse/parse.spec.js +91 -95
- package/src/core/prop.spec.js +60 -4
- package/src/core/q/q.html +18 -0
- package/src/core/q/q.js +472 -0
- package/src/core/q/q.md +211 -0
- package/src/core/q/q.spec.js +2748 -0
- package/src/core/q/q.test.js +12 -0
- package/src/core/sce/sce.spec.js +8 -0
- package/src/core/{model/model.html → scope/scope.html} +1 -1
- package/src/core/scope/scope.js +16 -15
- package/src/core/scope/scope.spec.js +1959 -24
- package/src/core/scope/scope.test.js +12 -0
- package/src/core/timeout/timeout.html +18 -0
- package/src/core/timeout/timeout.js +109 -0
- package/src/core/timeout/timeout.spec.js +354 -0
- package/src/core/timeout/timout.test.js +12 -0
- package/src/core/url-utils/url-utils.spec.js +1 -1
- package/src/directive/aria/aria.js +6 -3
- package/src/directive/aria/aria.spec.js +87 -0
- package/src/directive/attrs/attrs.spec.js +5 -0
- package/src/directive/attrs/boolean.spec.js +15 -0
- package/src/directive/attrs/element-style.spec.js +8 -0
- package/src/directive/attrs/src.spec.js +7 -0
- package/src/directive/bind/bind.spec.js +33 -0
- package/src/directive/bind/bing-html.spec.js +3 -0
- package/src/directive/class/class.js +3 -3
- package/src/directive/class/class.spec.js +75 -9
- package/src/directive/controller/controller.spec.js +13 -0
- package/src/directive/events/click.spec.js +3 -0
- package/src/directive/events/event.spec.js +6 -0
- package/src/directive/events/events.html +1 -0
- package/src/directive/form/form.js +3 -2
- package/src/directive/form/form.spec.js +65 -0
- package/src/directive/if/if.spec.js +4 -0
- package/src/directive/include/include.spec.js +59 -8
- package/src/directive/init/init.js +2 -6
- package/src/directive/init/init.spec.js +2 -0
- package/src/directive/input/input.spec.js +136 -0
- package/src/directive/messages/messages.spec.js +35 -4
- package/src/directive/model/model.js +25 -18
- package/src/directive/model/model.spec.js +49 -2
- package/src/directive/model-options/model-options.spec.js +6 -0
- package/src/directive/non-bindable/non-bindable.spec.js +1 -0
- package/src/directive/observe/observe.js +5 -1
- package/src/directive/observe/observe.spec.js +22 -0
- package/src/directive/observe/test.html +3 -11
- package/src/directive/options/options.spec.js +34 -0
- package/src/directive/ref/href.spec.js +15 -0
- package/src/directive/repeat/repeat.spec.js +135 -8
- package/src/directive/script/script.spec.js +2 -0
- package/src/directive/select/select.js +3 -3
- package/src/directive/select/select.spec.js +96 -0
- package/src/directive/show-hide/show-hide.js +2 -2
- package/src/directive/show-hide/show-hide.spec.js +19 -8
- package/src/directive/style/style.spec.js +7 -0
- package/src/directive/switch/switch.spec.js +5 -5
- package/src/directive/validators/validators.spec.js +1 -0
- package/src/loader.js +1 -0
- package/src/public.js +10 -2
- package/src/router/common/coreservices.js +2 -0
- package/src/router/directives/state-directives.js +14 -6
- package/src/router/directives/state-directives.spec.js +83 -0
- package/src/router/directives/view-directive.js +13 -4
- package/src/router/directives/view-directive.spec.js +71 -25
- package/src/router/hooks/lazy-load.js +2 -2
- package/src/router/hooks/views.js +5 -3
- package/src/router/resolve/resolvable.js +6 -3
- package/src/router/resolve/resolve-context.js +2 -2
- package/src/router/state/state-service.js +4 -4
- package/src/router/state/state.spec.js +5 -2
- package/src/router/state/state.test.js +1 -1
- package/src/router/state/views.js +10 -7
- package/src/router/template-factory.js +6 -3
- package/src/router/template-factory.spec.js +4 -0
- package/src/router/transition/transition-hook.js +1 -1
- package/src/router/transition/transition.js +1 -1
- package/src/router/view-hook.spec.js +2 -2
- package/src/router/view-scroll.js +6 -4
- package/src/services/browser.js +5 -8
- package/src/services/http/http.js +9 -6
- package/src/services/http/http.spec.js +31 -30
- package/src/services/http/template-request.spec.js +10 -0
- package/src/services/http-backend/http-backend.spec.js +3 -3
- package/src/services/template-request.js +4 -2
- package/src/shared/common.js +2 -1
- package/types/core/location/location.d.ts +37 -34
- package/types/core/parse/parse.d.ts +0 -26
- package/types/core/scope/scope.d.ts +11 -11
- package/src/core/model/model.js +0 -944
- package/src/core/model/model.spec.js +0 -3012
- package/types/core/model/model.d.ts +0 -204
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { Angular } from "../../loader";
|
|
2
|
+
import { createInjector } from "../di/injector";
|
|
3
|
+
import { wait } from "../../shared/test-utils";
|
|
4
|
+
|
|
5
|
+
describe("$interval", () => {
|
|
6
|
+
let injector;
|
|
7
|
+
let $interval;
|
|
8
|
+
let $rootScope;
|
|
9
|
+
let errors;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
errors = [];
|
|
13
|
+
window.angular = new Angular();
|
|
14
|
+
window.angular
|
|
15
|
+
.module("myModule", ["ng"])
|
|
16
|
+
.decorator("$exceptionHandler", () => {
|
|
17
|
+
return (exception) => {
|
|
18
|
+
errors.push(exception);
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
injector = createInjector(["myModule"]);
|
|
22
|
+
|
|
23
|
+
$interval = injector.get("$interval");
|
|
24
|
+
$rootScope = injector.get("$rootScope");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should run tasks repeatedly", async () => {
|
|
28
|
+
let counter = 0;
|
|
29
|
+
$interval(() => {
|
|
30
|
+
counter++;
|
|
31
|
+
}, 1);
|
|
32
|
+
expect(counter).toBe(0);
|
|
33
|
+
await wait(15);
|
|
34
|
+
expect(counter).toBeGreaterThanOrEqual(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should call $apply after each task is executed", (done) => {
|
|
38
|
+
const applySpy = spyOn($rootScope, "$apply").and.callThrough();
|
|
39
|
+
|
|
40
|
+
$interval(() => {}, 1);
|
|
41
|
+
expect(applySpy).not.toHaveBeenCalled();
|
|
42
|
+
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
expect(applySpy).toHaveBeenCalled();
|
|
45
|
+
}, 3);
|
|
46
|
+
|
|
47
|
+
applySpy.calls.reset();
|
|
48
|
+
|
|
49
|
+
$interval(() => {}, 1);
|
|
50
|
+
$interval(() => {}, 1);
|
|
51
|
+
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
expect(applySpy).toHaveBeenCalledTimes(3);
|
|
54
|
+
done();
|
|
55
|
+
}, 1);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should allow you to specify a number of iterations", async () => {
|
|
59
|
+
let counter = 0;
|
|
60
|
+
$interval(
|
|
61
|
+
() => {
|
|
62
|
+
counter++;
|
|
63
|
+
},
|
|
64
|
+
1,
|
|
65
|
+
2,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await wait(15);
|
|
69
|
+
expect(counter).toBe(2);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should allow you to specify a number of arguments", (done) => {
|
|
73
|
+
const task1 = jasmine.createSpy("task1");
|
|
74
|
+
const task2 = jasmine.createSpy("task2");
|
|
75
|
+
const task3 = jasmine.createSpy("task3");
|
|
76
|
+
$interval(task1, 1, 2, true, "Task1");
|
|
77
|
+
$interval(task2, 1, 2, true, "Task2");
|
|
78
|
+
$interval(task3, 1, 2, true, "I", "am", "a", "Task3", "spy");
|
|
79
|
+
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
expect(task1).toHaveBeenCalledWith("Task1");
|
|
82
|
+
expect(task2).toHaveBeenCalledWith("Task2");
|
|
83
|
+
expect(task3).toHaveBeenCalledWith("I", "am", "a", "Task3", "spy");
|
|
84
|
+
}, 1);
|
|
85
|
+
|
|
86
|
+
task1.calls.reset();
|
|
87
|
+
task2.calls.reset();
|
|
88
|
+
task3.calls.reset();
|
|
89
|
+
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
expect(task1).toHaveBeenCalledWith("Task1");
|
|
92
|
+
expect(task2).toHaveBeenCalledWith("Task2");
|
|
93
|
+
expect(task3).toHaveBeenCalledWith("I", "am", "a", "Task3", "spy");
|
|
94
|
+
done();
|
|
95
|
+
}, 1);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should return a promise which will be updated with the count on each iteration", async () => {
|
|
99
|
+
const log = [];
|
|
100
|
+
const promise = $interval(() => {
|
|
101
|
+
log.push("tick");
|
|
102
|
+
}, 1);
|
|
103
|
+
|
|
104
|
+
promise.then(
|
|
105
|
+
(value) => {
|
|
106
|
+
log.push(`promise success: ${value}`);
|
|
107
|
+
},
|
|
108
|
+
(err) => {
|
|
109
|
+
log.push(`promise error: ${err}`);
|
|
110
|
+
},
|
|
111
|
+
(note) => {
|
|
112
|
+
log.push(`promise update: ${note}`);
|
|
113
|
+
},
|
|
114
|
+
);
|
|
115
|
+
expect(log).toEqual([]);
|
|
116
|
+
|
|
117
|
+
await wait(5);
|
|
118
|
+
expect(log[0]).toEqual("tick");
|
|
119
|
+
expect(log[1]).toEqual("tick");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("should return a promise which will be resolved after the specified number of iterations", async () => {
|
|
123
|
+
const log = [];
|
|
124
|
+
const promise = $interval(
|
|
125
|
+
() => {
|
|
126
|
+
log.push("tick");
|
|
127
|
+
},
|
|
128
|
+
1,
|
|
129
|
+
2,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
promise.then(
|
|
133
|
+
(value) => {
|
|
134
|
+
log.push(`promise success: ${value}`);
|
|
135
|
+
},
|
|
136
|
+
(err) => {
|
|
137
|
+
log.push(`promise error: ${err}`);
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
expect(log).toEqual([]);
|
|
141
|
+
await wait(15);
|
|
142
|
+
expect(log).toEqual(["tick", "tick", "promise success: 2"]);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe("exception handling", () => {
|
|
146
|
+
it("should delegate exception to the $exceptionHandler service", (done) => {
|
|
147
|
+
errors = [];
|
|
148
|
+
$interval(() => {
|
|
149
|
+
throw "Test Error";
|
|
150
|
+
}, 10);
|
|
151
|
+
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
expect(errors).toContain("Test Error");
|
|
154
|
+
done();
|
|
155
|
+
}, 20);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("should call $apply even if an exception is thrown in callback", (done) => {
|
|
159
|
+
const applySpy = spyOn($rootScope, "$apply").and.callThrough();
|
|
160
|
+
|
|
161
|
+
$interval(() => {
|
|
162
|
+
throw "Test Error2";
|
|
163
|
+
}, 10);
|
|
164
|
+
expect(applySpy).not.toHaveBeenCalled();
|
|
165
|
+
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
expect(applySpy).toHaveBeenCalled();
|
|
168
|
+
done();
|
|
169
|
+
}, 11);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe("cancel", () => {
|
|
174
|
+
it("should cancel tasks", (done) => {
|
|
175
|
+
const task1 = jasmine.createSpy("task1", 1);
|
|
176
|
+
const task2 = jasmine.createSpy("task2", 1);
|
|
177
|
+
const task3 = jasmine.createSpy("task3", 1);
|
|
178
|
+
let promise1;
|
|
179
|
+
let promise3;
|
|
180
|
+
|
|
181
|
+
promise1 = $interval(task1, 2);
|
|
182
|
+
$interval(task2, 1);
|
|
183
|
+
promise3 = $interval(task3, 3);
|
|
184
|
+
|
|
185
|
+
$interval.cancel(promise3);
|
|
186
|
+
$interval.cancel(promise1);
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
expect(task1).not.toHaveBeenCalled();
|
|
189
|
+
expect(task2).toHaveBeenCalled();
|
|
190
|
+
expect(task3).not.toHaveBeenCalled();
|
|
191
|
+
done();
|
|
192
|
+
}, 1);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("should cancel the promise", (done) => {
|
|
196
|
+
const promise = $interval(() => {}, 1);
|
|
197
|
+
const log = [];
|
|
198
|
+
promise.then(
|
|
199
|
+
(value) => {
|
|
200
|
+
log.push(`promise success: ${value}`);
|
|
201
|
+
},
|
|
202
|
+
(err) => {
|
|
203
|
+
log.push(`promise error: ${err}`);
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
expect(log).toEqual([]);
|
|
207
|
+
|
|
208
|
+
setTimeout(() => {
|
|
209
|
+
$interval.cancel(promise);
|
|
210
|
+
}, 1);
|
|
211
|
+
|
|
212
|
+
setTimeout(() => {
|
|
213
|
+
$rootScope.$apply(); // For resolving the promise -
|
|
214
|
+
// necessary since q uses $rootScope.evalAsync.
|
|
215
|
+
|
|
216
|
+
expect(log).toEqual(["promise error: canceled"]);
|
|
217
|
+
done();
|
|
218
|
+
}, 2);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("should return true if a task was successfully canceled", (done) => {
|
|
222
|
+
const task1 = jasmine.createSpy("task1");
|
|
223
|
+
const task2 = jasmine.createSpy("task2");
|
|
224
|
+
let promise1;
|
|
225
|
+
let promise2;
|
|
226
|
+
|
|
227
|
+
promise1 = $interval(task1, 1, 1);
|
|
228
|
+
setTimeout(() => {
|
|
229
|
+
promise2 = $interval(task2, 1, 1);
|
|
230
|
+
|
|
231
|
+
expect($interval.cancel(promise1)).toBe(false);
|
|
232
|
+
expect($interval.cancel(promise2)).toBe(true);
|
|
233
|
+
done();
|
|
234
|
+
}, 1);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("should not throw an error when given an undefined promise", () => {
|
|
238
|
+
expect($interval.cancel()).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("should throw an error when given a non-$interval promise", () => {
|
|
242
|
+
const promise = $interval(() => {}).then(() => {});
|
|
243
|
+
expect(() => {
|
|
244
|
+
$interval.cancel(promise);
|
|
245
|
+
}).toThrowError(/badprom/);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("should not trigger digest when cancelled", () => {
|
|
249
|
+
const watchSpy = jasmine.createSpy("watchSpy");
|
|
250
|
+
$rootScope.$watch(watchSpy);
|
|
251
|
+
|
|
252
|
+
const t = $interval();
|
|
253
|
+
$interval.cancel(t);
|
|
254
|
+
expect(watchSpy).not.toHaveBeenCalled();
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe("$window delegation", () => {
|
|
259
|
+
it("should use $window.setInterval instead of the global function", () => {
|
|
260
|
+
const setIntervalSpy = spyOn(window, "setInterval");
|
|
261
|
+
|
|
262
|
+
$interval(() => {}, 1);
|
|
263
|
+
expect(setIntervalSpy).toHaveBeenCalled();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("should use $window.clearInterval instead of the global function", (done) => {
|
|
267
|
+
const clearIntervalSpy = spyOn(window, "clearInterval");
|
|
268
|
+
|
|
269
|
+
$interval(() => {}, 1, 1);
|
|
270
|
+
setTimeout(() => {
|
|
271
|
+
expect(clearIntervalSpy).toHaveBeenCalled();
|
|
272
|
+
|
|
273
|
+
clearIntervalSpy.calls.reset();
|
|
274
|
+
$interval.cancel($interval(() => {}, 1));
|
|
275
|
+
expect(clearIntervalSpy).toHaveBeenCalled();
|
|
276
|
+
done();
|
|
277
|
+
}, 1);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
@@ -5,7 +5,7 @@ const TEST_URL = "src/core/interval/interval.html";
|
|
|
5
5
|
test("unit tests contain no errors", async ({ page }) => {
|
|
6
6
|
await page.goto(TEST_URL);
|
|
7
7
|
await page.content();
|
|
8
|
-
await page.waitForTimeout(
|
|
8
|
+
await page.waitForTimeout(500);
|
|
9
9
|
await expect(page.locator(".jasmine-overall-result")).toHaveText(
|
|
10
10
|
/0 failures/,
|
|
11
11
|
);
|
|
@@ -2,7 +2,6 @@ import { JQLite } from "../../shared/jqlite/jqlite";
|
|
|
2
2
|
import { urlResolve } from "../url-utils/url-utils";
|
|
3
3
|
import {
|
|
4
4
|
encodeUriSegment,
|
|
5
|
-
isBoolean,
|
|
6
5
|
isDefined,
|
|
7
6
|
isNumber,
|
|
8
7
|
isObject,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
toInt,
|
|
14
13
|
toKeyValue,
|
|
15
14
|
} from "../../shared/utils";
|
|
15
|
+
import { ScopePhase } from "../scope/scope";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @typedef {Object} DefaultPorts
|
|
@@ -42,6 +42,8 @@ export class Location {
|
|
|
42
42
|
* @param {string} appBaseNoFile application base URL stripped of any filename
|
|
43
43
|
*/
|
|
44
44
|
constructor(appBase, appBaseNoFile) {
|
|
45
|
+
const parsedUrl = urlResolve(appBase);
|
|
46
|
+
|
|
45
47
|
/** @type {string} */
|
|
46
48
|
this.appBase = appBase;
|
|
47
49
|
|
|
@@ -67,16 +69,17 @@ export class Location {
|
|
|
67
69
|
this.$$replace = false;
|
|
68
70
|
|
|
69
71
|
/** @type {import('../url-utils/url-utils').HttpProtocol} */
|
|
70
|
-
this.$$protocol =
|
|
72
|
+
this.$$protocol = parsedUrl.protocol;
|
|
71
73
|
|
|
72
74
|
/** @type {string} */
|
|
73
|
-
this.$$host =
|
|
75
|
+
this.$$host = parsedUrl.hostname;
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
78
|
* The port, without ":"
|
|
77
79
|
* @type {number}
|
|
78
80
|
*/
|
|
79
|
-
this.$$port =
|
|
81
|
+
this.$$port =
|
|
82
|
+
toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
|
|
80
83
|
|
|
81
84
|
/**
|
|
82
85
|
* The pathname, beginning with "/"
|
|
@@ -329,7 +332,6 @@ export class Location {
|
|
|
329
332
|
// so the modification window is narrow.
|
|
330
333
|
this.$$state = isUndefined(state) ? null : state;
|
|
331
334
|
this.$$urlUpdatedByLocation = true;
|
|
332
|
-
|
|
333
335
|
return this;
|
|
334
336
|
}
|
|
335
337
|
|
|
@@ -360,7 +362,6 @@ export class LocationHtml5Url extends Location {
|
|
|
360
362
|
super(appBase, appBaseNoFile);
|
|
361
363
|
this.$$html5 = true;
|
|
362
364
|
this.basePrefix = basePrefix || "";
|
|
363
|
-
parseAbsoluteUrl(appBase, this);
|
|
364
365
|
}
|
|
365
366
|
|
|
366
367
|
/**
|
|
@@ -443,10 +444,7 @@ export class LocationHtml5Url extends Location {
|
|
|
443
444
|
export class LocationHashbangUrl extends Location {
|
|
444
445
|
constructor(appBase, appBaseNoFile, hashPrefix) {
|
|
445
446
|
super(appBase, appBaseNoFile);
|
|
446
|
-
this.appBase = appBase;
|
|
447
|
-
this.appBaseNoFile = appBaseNoFile;
|
|
448
447
|
this.hashPrefix = hashPrefix;
|
|
449
|
-
parseAbsoluteUrl(appBase, this);
|
|
450
448
|
}
|
|
451
449
|
|
|
452
450
|
/**
|
|
@@ -543,26 +541,28 @@ export class LocationHashbangUrl extends Location {
|
|
|
543
541
|
}
|
|
544
542
|
}
|
|
545
543
|
|
|
546
|
-
export
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
544
|
+
export class LocationProvider {
|
|
545
|
+
constructor() {
|
|
546
|
+
this.hashPrefixValue = "!";
|
|
547
|
+
this.html5ModeConfig = {
|
|
548
|
+
enabled: false,
|
|
549
|
+
requireBase: true,
|
|
550
|
+
rewriteLinks: true,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
553
|
|
|
554
554
|
/**
|
|
555
555
|
* The default value for the prefix is `'!'`.
|
|
556
|
-
* @param {string=} prefix Prefix for hash part (containing path and search)
|
|
557
|
-
* @returns {
|
|
556
|
+
* @param {string=} prefix - Prefix for hash part (containing path and search)
|
|
557
|
+
* @returns {string|LocationProvider} current value if used as getter or itself (chaining) if used as setter
|
|
558
558
|
*/
|
|
559
|
-
|
|
560
|
-
if (
|
|
561
|
-
|
|
559
|
+
hashPrefix(prefix) {
|
|
560
|
+
if (typeof prefix !== "undefined") {
|
|
561
|
+
this.hashPrefixValue = prefix;
|
|
562
562
|
return this;
|
|
563
563
|
}
|
|
564
|
-
return
|
|
565
|
-
}
|
|
564
|
+
return this.hashPrefixValue;
|
|
565
|
+
}
|
|
566
566
|
|
|
567
567
|
/**
|
|
568
568
|
* @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
|
|
@@ -584,30 +584,29 @@ export function LocationProvider() {
|
|
|
584
584
|
*
|
|
585
585
|
* @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
|
|
586
586
|
*/
|
|
587
|
-
|
|
588
|
-
if (
|
|
589
|
-
|
|
587
|
+
html5Mode(mode) {
|
|
588
|
+
if (typeof mode === "boolean") {
|
|
589
|
+
this.html5ModeConfig.enabled = mode;
|
|
590
590
|
return this;
|
|
591
591
|
}
|
|
592
|
-
if (isObject(mode)) {
|
|
593
|
-
if (isBoolean(mode.enabled)) {
|
|
594
|
-
html5Mode.enabled = mode.enabled;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if (isBoolean(mode.requireBase)) {
|
|
598
|
-
html5Mode.requireBase = mode.requireBase;
|
|
599
|
-
}
|
|
600
592
|
|
|
601
|
-
|
|
602
|
-
|
|
593
|
+
if (typeof mode === "object") {
|
|
594
|
+
if (typeof mode.enabled === "boolean")
|
|
595
|
+
this.html5ModeConfig.enabled = mode.enabled;
|
|
596
|
+
if (typeof mode.requireBase === "boolean")
|
|
597
|
+
this.html5ModeConfig.requireBase = mode.requireBase;
|
|
598
|
+
if (
|
|
599
|
+
typeof mode.rewriteLinks === "boolean" ||
|
|
600
|
+
typeof mode.rewriteLinks === "string"
|
|
601
|
+
) {
|
|
602
|
+
this.html5ModeConfig.rewriteLinks = mode.rewriteLinks;
|
|
603
603
|
}
|
|
604
|
-
|
|
605
604
|
return this;
|
|
606
605
|
}
|
|
607
|
-
return
|
|
608
|
-
}
|
|
606
|
+
return this.html5ModeConfig;
|
|
607
|
+
}
|
|
609
608
|
|
|
610
|
-
|
|
609
|
+
$get = [
|
|
611
610
|
"$rootScope",
|
|
612
611
|
"$browser",
|
|
613
612
|
"$rootElement",
|
|
@@ -626,8 +625,8 @@ export function LocationProvider() {
|
|
|
626
625
|
const initialUrl = /** @type {string} */ ($browser.url());
|
|
627
626
|
let appBase;
|
|
628
627
|
|
|
629
|
-
if (html5Mode.enabled) {
|
|
630
|
-
if (!baseHref && html5Mode.requireBase) {
|
|
628
|
+
if (this.html5Mode.enabled) {
|
|
629
|
+
if (!baseHref && this.html5Mode.requireBase) {
|
|
631
630
|
throw $locationMinErr(
|
|
632
631
|
"nobase",
|
|
633
632
|
"$location in HTML5 mode requires a <base> tag to be present!",
|
|
@@ -641,7 +640,11 @@ export function LocationProvider() {
|
|
|
641
640
|
}
|
|
642
641
|
const appBaseNoFile = stripFile(appBase);
|
|
643
642
|
|
|
644
|
-
$location = new LocationMode(
|
|
643
|
+
$location = new LocationMode(
|
|
644
|
+
appBase,
|
|
645
|
+
appBaseNoFile,
|
|
646
|
+
`#${this.hashPrefix}`,
|
|
647
|
+
);
|
|
645
648
|
$location.$$parseLinkUrl(initialUrl, initialUrl);
|
|
646
649
|
|
|
647
650
|
$location.$$state = $browser.state();
|
|
@@ -668,7 +671,7 @@ export function LocationProvider() {
|
|
|
668
671
|
}
|
|
669
672
|
|
|
670
673
|
$rootElement.on("click", (event) => {
|
|
671
|
-
const { rewriteLinks } = html5Mode;
|
|
674
|
+
const { rewriteLinks } = this.html5Mode;
|
|
672
675
|
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
|
|
673
676
|
// currently we open nice url link and redirect then
|
|
674
677
|
|
|
@@ -767,10 +770,11 @@ export function LocationProvider() {
|
|
|
767
770
|
afterLocationChange(oldUrl, oldState);
|
|
768
771
|
}
|
|
769
772
|
});
|
|
773
|
+
if ($rootScope.$$phase === ScopePhase.NONE) $rootScope.$digest();
|
|
770
774
|
});
|
|
771
775
|
|
|
772
776
|
// update browser
|
|
773
|
-
|
|
777
|
+
function browserUpdate() {
|
|
774
778
|
if (initializing || $location.$$urlUpdatedByLocation) {
|
|
775
779
|
$location.$$urlUpdatedByLocation = false;
|
|
776
780
|
|
|
@@ -818,7 +822,9 @@ export function LocationProvider() {
|
|
|
818
822
|
|
|
819
823
|
// we don't need to return anything because $evalAsync will make the digest loop dirty when
|
|
820
824
|
// there is a change
|
|
821
|
-
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
setTimeout(() => browserUpdate());
|
|
822
828
|
|
|
823
829
|
return $location;
|
|
824
830
|
|
|
@@ -830,6 +836,7 @@ export function LocationProvider() {
|
|
|
830
836
|
$location.$$state,
|
|
831
837
|
oldState,
|
|
832
838
|
);
|
|
839
|
+
browserUpdate();
|
|
833
840
|
}
|
|
834
841
|
},
|
|
835
842
|
];
|
|
@@ -882,19 +889,6 @@ function normalizePath(pathValue, searchValue, hashValue) {
|
|
|
882
889
|
return path + (search ? `?${search}` : "") + hash;
|
|
883
890
|
}
|
|
884
891
|
|
|
885
|
-
/**
|
|
886
|
-
* @param {string} absoluteUrl
|
|
887
|
-
* @param {Location} locationObj
|
|
888
|
-
*/
|
|
889
|
-
function parseAbsoluteUrl(absoluteUrl, locationObj) {
|
|
890
|
-
const parsedUrl = urlResolve(absoluteUrl);
|
|
891
|
-
|
|
892
|
-
locationObj.$$protocol = parsedUrl.protocol;
|
|
893
|
-
locationObj.$$host = parsedUrl.hostname;
|
|
894
|
-
locationObj.$$port =
|
|
895
|
-
toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
892
|
function parseAppUrl(url, locationObj, html5Mode) {
|
|
899
893
|
if (/^\s*[\\/]{2,}/.test(url)) {
|
|
900
894
|
throw $locationMinErr("badpath", 'Invalid url "{0}".', url);
|