@angular-wave/angular.ts 0.0.57 → 0.0.58
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/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/animations/animate-css.html +9 -3
- package/src/animations/raf-scheduler.js +37 -12
- package/src/directive/if/if-animate-css.html +65 -0
- package/src/directive/if/if.js +9 -0
- package/src/directive/if/if.spec.js +0 -123
- package/src/directive/if/if.test.js +102 -0
- package/src/directive/include/include.js +26 -11
- package/src/directive/include/include.md +3 -2
- package/src/directive/model/model.js +41 -10
- package/src/shared/jqlite/jqlite.js +1 -1
- package/types/animations/raf-scheduler.d.ts +31 -2
- package/types/directive/if/if.d.ts +7 -8
- package/types/shared/jqlite/jqlite.d.ts +2 -2
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
/* The starting CSS styles for the enter animation */
|
|
26
26
|
.fade.ng-enter {
|
|
27
27
|
transition: 0.5s linear all;
|
|
28
|
-
background-color:
|
|
28
|
+
background-color: unset;
|
|
29
29
|
opacity: 0;
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -44,12 +44,18 @@
|
|
|
44
44
|
/* The finishing CSS styles for the leave animation */
|
|
45
45
|
.fade.ng-leave.ng-leave-active {
|
|
46
46
|
opacity: 0;
|
|
47
|
-
background-color:
|
|
47
|
+
background-color: unset;
|
|
48
48
|
}
|
|
49
49
|
</style>
|
|
50
50
|
</head>
|
|
51
51
|
<body ng-app="test">
|
|
52
|
-
<div ng-if="bool" class="fade" data-animate="true">
|
|
52
|
+
<div ng-if="bool" id="data-animate" class="fade" data-animate="true">
|
|
53
|
+
Fade me in out
|
|
54
|
+
</div>
|
|
55
|
+
<div ng-if="bool" id="animate" class="fade" animate="true">
|
|
56
|
+
Fade me in out
|
|
57
|
+
</div>
|
|
58
|
+
<div ng-if="bool" id="no-animate" class="fade">Fade me in out</div>
|
|
53
59
|
<button ng-click="bool=true">Fade In!</button>
|
|
54
60
|
<button ng-click="bool=false">Fade Out!</button>
|
|
55
61
|
</body>
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} Scheduler
|
|
3
|
+
* @property {Function} waitUntilQuiet - Function to wait until the animation frame is quiet.
|
|
4
|
+
* @property {Array<Function>} queue - The queue of tasks to be processed.
|
|
5
|
+
* @property {Function} scheduler - The function to add tasks to the queue and schedule the next tick.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a requestAnimationFrame scheduler.
|
|
10
|
+
* @returns {Scheduler} The scheduler object.
|
|
11
|
+
*/
|
|
1
12
|
export const $$rAFSchedulerFactory = [
|
|
2
13
|
() => {
|
|
3
|
-
|
|
4
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @type {Array<Array<Function>>}
|
|
16
|
+
*/
|
|
17
|
+
let queue = [];
|
|
18
|
+
/**
|
|
19
|
+
* @type {number|null}
|
|
20
|
+
*/
|
|
21
|
+
let cancelFn = null;
|
|
5
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Processes the next tick of the animation frame.
|
|
25
|
+
*/
|
|
6
26
|
function nextTick() {
|
|
7
27
|
if (!queue.length) return;
|
|
8
28
|
|
|
@@ -11,13 +31,18 @@ export const $$rAFSchedulerFactory = [
|
|
|
11
31
|
|
|
12
32
|
if (!cancelFn) {
|
|
13
33
|
window.requestAnimationFrame(() => {
|
|
14
|
-
|
|
34
|
+
cancelFn = null;
|
|
35
|
+
nextTick();
|
|
15
36
|
});
|
|
16
37
|
}
|
|
17
38
|
}
|
|
18
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Adds tasks to the queue and schedules the next tick.
|
|
42
|
+
* @param {Array<Function>} tasks - The tasks to be added to the queue.
|
|
43
|
+
*/
|
|
19
44
|
function scheduler(tasks) {
|
|
20
|
-
//
|
|
45
|
+
// Make a copy since RAFScheduler mutates the state
|
|
21
46
|
// of the passed in array variable and this would be difficult
|
|
22
47
|
// to track down on the outside code
|
|
23
48
|
queue = queue.concat(tasks);
|
|
@@ -26,16 +51,16 @@ export const $$rAFSchedulerFactory = [
|
|
|
26
51
|
|
|
27
52
|
queue = scheduler.queue = [];
|
|
28
53
|
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* The motivation here is that animation code can request more time from the scheduler
|
|
34
|
-
* before the next wave runs. This allows for certain DOM properties such as classes to
|
|
35
|
-
* be resolved in time for the next animation to run.
|
|
54
|
+
/**
|
|
55
|
+
* Waits until the animation frame is quiet before running the provided function.
|
|
56
|
+
* Cancels any previous animation frame requests.
|
|
57
|
+
* @param {Function} fn - The function to run when the animation frame is quiet.
|
|
36
58
|
*/
|
|
37
59
|
scheduler.waitUntilQuiet = (fn) => {
|
|
38
|
-
if (cancelFn)
|
|
60
|
+
if (cancelFn !== null) {
|
|
61
|
+
window.cancelAnimationFrame(cancelFn);
|
|
62
|
+
cancelFn = null;
|
|
63
|
+
}
|
|
39
64
|
|
|
40
65
|
cancelFn = window.requestAnimationFrame(() => {
|
|
41
66
|
cancelFn = null;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>AngularTS Playwright test template</title>
|
|
6
|
+
|
|
7
|
+
<link rel="shortcut icon" type="image/png" href="/images/favicon.ico" />
|
|
8
|
+
<script type="module" src="/src/index.js"></script>
|
|
9
|
+
<script>
|
|
10
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
11
|
+
window.angular
|
|
12
|
+
.module("test", ["ngAnimate"])
|
|
13
|
+
.directive("svgContainer", () => ({
|
|
14
|
+
template: "<svg ng-transclude></svg>",
|
|
15
|
+
replace: true,
|
|
16
|
+
transclude: true,
|
|
17
|
+
}));
|
|
18
|
+
});
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style>
|
|
22
|
+
.fade {
|
|
23
|
+
background-color: red;
|
|
24
|
+
}
|
|
25
|
+
/* The starting CSS styles for the enter animation */
|
|
26
|
+
.fade.ng-enter {
|
|
27
|
+
transition: 0.5s linear all;
|
|
28
|
+
background-color: unset;
|
|
29
|
+
opacity: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The finishing CSS styles for the enter animation */
|
|
33
|
+
.fade.ng-enter.ng-enter-active {
|
|
34
|
+
opacity: 1;
|
|
35
|
+
background-color: red;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* The starting CSS styles for the leave animation */
|
|
39
|
+
.fade.ng-leave {
|
|
40
|
+
transition: 0.5s linear all;
|
|
41
|
+
opacity: 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* The finishing CSS styles for the leave animation */
|
|
45
|
+
.fade.ng-leave.ng-leave-active {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
background-color: unset;
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
50
|
+
</head>
|
|
51
|
+
<body ng-app="test">
|
|
52
|
+
<div ng-if="bool" id="data-animate" class="fade" data-animate="true">
|
|
53
|
+
Fade me in out
|
|
54
|
+
</div>
|
|
55
|
+
<div ng-if="bool" id="animate" class="fade" animate="true">
|
|
56
|
+
Fade me in out
|
|
57
|
+
</div>
|
|
58
|
+
<div ng-if="bool" id="no-animate" class="fade">Fade me in out</div>
|
|
59
|
+
|
|
60
|
+
<button ng-click="bool=true">Fade In!</button>
|
|
61
|
+
<button ng-click="bool=false">Fade Out!</button>
|
|
62
|
+
|
|
63
|
+
<svg-container><circle id="circle" ng-if="bool"></circle></svg-container>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
package/src/directive/if/if.js
CHANGED
|
@@ -3,6 +3,12 @@ import { getBlockNodes } from "../../shared/jqlite/jqlite";
|
|
|
3
3
|
import { hasAnimate } from "../../shared/utils";
|
|
4
4
|
|
|
5
5
|
ngIfDirective.$inject = ["$animate"];
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* TODO // Add type for animate service
|
|
9
|
+
* @param {*} $animate
|
|
10
|
+
* @returns {import("../../types").Directive}
|
|
11
|
+
*/
|
|
6
12
|
export function ngIfDirective($animate) {
|
|
7
13
|
return {
|
|
8
14
|
multiElement: true,
|
|
@@ -10,6 +16,9 @@ export function ngIfDirective($animate) {
|
|
|
10
16
|
priority: 600,
|
|
11
17
|
terminal: true,
|
|
12
18
|
restrict: "A",
|
|
19
|
+
/**
|
|
20
|
+
* TODO add type for $transclude service
|
|
21
|
+
*/
|
|
13
22
|
link($scope, $element, $attr, _ctrl, $transclude) {
|
|
14
23
|
/** @type {{clone: import("../../shared/jqlite/jqlite").JQLite }} */
|
|
15
24
|
let block;
|
|
@@ -275,128 +275,5 @@ describe("ngIf", () => {
|
|
|
275
275
|
);
|
|
276
276
|
});
|
|
277
277
|
});
|
|
278
|
-
|
|
279
|
-
// TODO ANIMATIONS
|
|
280
|
-
// describe("and animations", () => {
|
|
281
|
-
// let body = document.getElementById("dummy");
|
|
282
|
-
// let element;
|
|
283
|
-
// let $rootElement;
|
|
284
|
-
|
|
285
|
-
// function html(content) {
|
|
286
|
-
// $rootElement.html(content);
|
|
287
|
-
// element = $rootElement.children().eq(0);
|
|
288
|
-
// return element;
|
|
289
|
-
// }
|
|
290
|
-
|
|
291
|
-
// afterEach(() => {
|
|
292
|
-
// dealoc(body);
|
|
293
|
-
// dealoc(element);
|
|
294
|
-
// });
|
|
295
|
-
|
|
296
|
-
// // beforeEach(
|
|
297
|
-
// // module(
|
|
298
|
-
// // ($animateProvider, $provide) =>
|
|
299
|
-
// // function ($animate) {
|
|
300
|
-
// // $animate.enabled(true);
|
|
301
|
-
// // },
|
|
302
|
-
// // ),
|
|
303
|
-
// // );
|
|
304
|
-
|
|
305
|
-
// it("should fire off the enter animation", () => {
|
|
306
|
-
// body.innerHTML =
|
|
307
|
-
// "<div>" + '<div ng-if="value"><div>Hi</div></div>' + "</div>";
|
|
308
|
-
|
|
309
|
-
// let item;
|
|
310
|
-
// const $scope = $rootScope.$new();
|
|
311
|
-
// element = $compile(body)($scope);
|
|
312
|
-
|
|
313
|
-
// $rootScope.$digest();
|
|
314
|
-
// $scope.$apply("value = true");
|
|
315
|
-
|
|
316
|
-
// item = $animate.queue.shift();
|
|
317
|
-
// expect(item.event).toBe("enter");
|
|
318
|
-
// expect(item.element.text()).toBe("Hi");
|
|
319
|
-
|
|
320
|
-
// expect(element.children().length).toBe(1);
|
|
321
|
-
// });
|
|
322
|
-
|
|
323
|
-
// it("should fire off the leave animation", () => {
|
|
324
|
-
// let item;
|
|
325
|
-
// const $scope = $rootScope.$new();
|
|
326
|
-
// element = $compile(
|
|
327
|
-
// html("<div>" + '<div ng-if="value"><div>Hi</div></div>' + "</div>"),
|
|
328
|
-
// )($scope);
|
|
329
|
-
// $scope.$apply("value = true");
|
|
330
|
-
|
|
331
|
-
// item = $animate.queue.shift();
|
|
332
|
-
// expect(item.event).toBe("enter");
|
|
333
|
-
// expect(item.element.text()).toBe("Hi");
|
|
334
|
-
|
|
335
|
-
// expect(element.children().length).toBe(1);
|
|
336
|
-
// $scope.$apply("value = false");
|
|
337
|
-
|
|
338
|
-
// item = $animate.queue.shift();
|
|
339
|
-
// expect(item.event).toBe("leave");
|
|
340
|
-
// expect(item.element.text()).toBe("Hi");
|
|
341
|
-
|
|
342
|
-
// expect(element.children().length).toBe(0);
|
|
343
|
-
// });
|
|
344
|
-
|
|
345
|
-
// it("should destroy the previous leave animation if a new one takes place", () => {
|
|
346
|
-
// module(($provide) => {
|
|
347
|
-
// $provide.decorator("$animate", ($delegate, $$q) => {
|
|
348
|
-
// const emptyPromise = $$q.defer().promise;
|
|
349
|
-
// emptyPromise.done = () => {};
|
|
350
|
-
|
|
351
|
-
// $delegate.leave = function () {
|
|
352
|
-
// return emptyPromise;
|
|
353
|
-
// };
|
|
354
|
-
// return $delegate;
|
|
355
|
-
// });
|
|
356
|
-
// });
|
|
357
|
-
// inject(($compile, $rootScope, $animate) => {
|
|
358
|
-
// let item;
|
|
359
|
-
// const $scope = $rootScope.$new();
|
|
360
|
-
// element = $compile(
|
|
361
|
-
// html("<div>" + '<div ng-if="value">Yo</div>' + "</div>"),
|
|
362
|
-
// )($scope);
|
|
363
|
-
|
|
364
|
-
// $scope.$apply("value = true");
|
|
365
|
-
|
|
366
|
-
// let destroyed;
|
|
367
|
-
// const inner = element.children(0);
|
|
368
|
-
// inner.on("$destroy", () => {
|
|
369
|
-
// destroyed = true;
|
|
370
|
-
// });
|
|
371
|
-
|
|
372
|
-
// $scope.$apply("value = false");
|
|
373
|
-
|
|
374
|
-
// $scope.$apply("value = true");
|
|
375
|
-
|
|
376
|
-
// $scope.$apply("value = false");
|
|
377
|
-
|
|
378
|
-
// expect(destroyed).toBe(true);
|
|
379
|
-
// });
|
|
380
|
-
// });
|
|
381
|
-
|
|
382
|
-
// it("should work with svg elements when the svg container is transcluded", () => {
|
|
383
|
-
// // module(($compileProvider) => {
|
|
384
|
-
// // $compileProvider.directive("svgContainer", () => ({
|
|
385
|
-
// // template: "<svg ng-transclude></svg>",
|
|
386
|
-
// // replace: true,
|
|
387
|
-
// // transclude: true,
|
|
388
|
-
// // });
|
|
389
|
-
// // });
|
|
390
|
-
|
|
391
|
-
// element = $compile(
|
|
392
|
-
// '<svg-container><circle ng-if="flag"></circle></svg-container>',
|
|
393
|
-
// )($rootScope);
|
|
394
|
-
// $rootScope.flag = true;
|
|
395
|
-
// $rootScope.$apply();
|
|
396
|
-
|
|
397
|
-
// const circle = element.find("circle");
|
|
398
|
-
// expect(circle[0].toString()).toMatch(/SVG/);
|
|
399
|
-
// });
|
|
400
|
-
// });
|
|
401
278
|
});
|
|
402
279
|
});
|
|
@@ -10,3 +10,105 @@ test("unit tests contain no errors", async ({ page }) => {
|
|
|
10
10
|
/0 failures/,
|
|
11
11
|
);
|
|
12
12
|
});
|
|
13
|
+
|
|
14
|
+
test.describe("animations", () => {
|
|
15
|
+
test("it should add enter and leave classes when animation is enabled", async ({
|
|
16
|
+
page,
|
|
17
|
+
}) => {
|
|
18
|
+
await page.goto("src/directive/if/if-animate-css.html");
|
|
19
|
+
await page.content();
|
|
20
|
+
// when if attribute has `data-animate` set to true
|
|
21
|
+
await page.click('button:has-text("Fade In!")');
|
|
22
|
+
let animated = await page.locator("#data-animate");
|
|
23
|
+
|
|
24
|
+
await expect(animated).toBeVisible();
|
|
25
|
+
await expect(animated).toHaveClass(/ng-enter/);
|
|
26
|
+
await expect(animated).toHaveClass(/ng-enter-active/);
|
|
27
|
+
|
|
28
|
+
// Wait for the transition to complete
|
|
29
|
+
await page.waitForTimeout(500);
|
|
30
|
+
await expect(animated).not.toHaveClass(/ng-enter/);
|
|
31
|
+
await expect(animated).not.toHaveClass(/ng-enter-active/);
|
|
32
|
+
|
|
33
|
+
await page.click('button:has-text("Fade Out!")');
|
|
34
|
+
await expect(animated).toHaveClass(/ng-leave/);
|
|
35
|
+
await expect(animated).toHaveClass(/ng-leave-active/);
|
|
36
|
+
await page.waitForTimeout(500);
|
|
37
|
+
// should be invisible
|
|
38
|
+
await expect(animated).not.toBeVisible();
|
|
39
|
+
|
|
40
|
+
// when if attribute has `animate` set to true
|
|
41
|
+
await page.click('button:has-text("Fade In!")');
|
|
42
|
+
animated = await page.locator("#animate");
|
|
43
|
+
|
|
44
|
+
await expect(animated).toBeVisible();
|
|
45
|
+
await expect(animated).toHaveClass(/ng-enter/);
|
|
46
|
+
await expect(animated).toHaveClass(/ng-enter-active/);
|
|
47
|
+
|
|
48
|
+
// Wait for the transition to complete
|
|
49
|
+
await page.waitForTimeout(500);
|
|
50
|
+
await expect(animated).not.toHaveClass(/ng-enter/);
|
|
51
|
+
await expect(animated).not.toHaveClass(/ng-enter-active/);
|
|
52
|
+
|
|
53
|
+
await page.click('button:has-text("Fade Out!")');
|
|
54
|
+
await expect(animated).toHaveClass(/ng-leave/);
|
|
55
|
+
await expect(animated).toHaveClass(/ng-leave-active/);
|
|
56
|
+
await page.waitForTimeout(500);
|
|
57
|
+
// should be invisible
|
|
58
|
+
await expect(animated).not.toBeVisible();
|
|
59
|
+
|
|
60
|
+
// when if attribute has no animate antributes
|
|
61
|
+
await page.click('button:has-text("Fade In!")');
|
|
62
|
+
let nonAnimated = await page.locator("#no-animate");
|
|
63
|
+
|
|
64
|
+
await expect(nonAnimated).toBeVisible();
|
|
65
|
+
await expect(nonAnimated).not.toHaveClass(/ng-enter/);
|
|
66
|
+
await expect(nonAnimated).not.toHaveClass(/ng-enter-active/);
|
|
67
|
+
|
|
68
|
+
// Wait for the transition to complete
|
|
69
|
+
await page.waitForTimeout(100);
|
|
70
|
+
|
|
71
|
+
await page.click('button:has-text("Fade Out!")');
|
|
72
|
+
// should be instantly invisible
|
|
73
|
+
await expect(nonAnimated).not.toBeVisible();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("should destroy the previous leave animation if a new one takes place", async ({
|
|
77
|
+
page,
|
|
78
|
+
}) => {
|
|
79
|
+
await page.goto("src/directive/if/if-animate-css.html");
|
|
80
|
+
await page.content();
|
|
81
|
+
// when if attribute has `data-animate` set to true
|
|
82
|
+
await page.click('button:has-text("Fade In!")');
|
|
83
|
+
let animated = await page.locator("#data-animate");
|
|
84
|
+
|
|
85
|
+
await expect(animated).toBeVisible();
|
|
86
|
+
await expect(animated).toHaveClass(/ng-enter/);
|
|
87
|
+
await expect(animated).toHaveClass(/ng-enter-active/);
|
|
88
|
+
|
|
89
|
+
// Wait for the transition to complete
|
|
90
|
+
await page.waitForTimeout(500);
|
|
91
|
+
await expect(animated).not.toHaveClass(/ng-enter/);
|
|
92
|
+
await expect(animated).not.toHaveClass(/ng-enter-active/);
|
|
93
|
+
|
|
94
|
+
await page.click('button:has-text("Fade Out!")');
|
|
95
|
+
await page.click('button:has-text("Fade In!")');
|
|
96
|
+
// should be visible
|
|
97
|
+
await page.waitForTimeout(500);
|
|
98
|
+
await expect(animated).toBeVisible();
|
|
99
|
+
await expect(animated).not.toHaveClass(/ng-leave/);
|
|
100
|
+
await expect(animated).not.toHaveClass(/ng-leave-active/);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("should work with svg elements when the svg container is transcluded", async ({
|
|
104
|
+
page,
|
|
105
|
+
}) => {
|
|
106
|
+
await page.goto("src/directive/if/if-animate-css.html");
|
|
107
|
+
await page.content();
|
|
108
|
+
await page.click('button:has-text("Fade In!")');
|
|
109
|
+
await page.waitForTimeout(600);
|
|
110
|
+
let animated = await page.locator("#circle");
|
|
111
|
+
await expect(animated).not.toHaveClass(/ng-enter/);
|
|
112
|
+
await expect(animated).not.toHaveClass(/ng-enter-active/);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { isDefined } from "../../shared/utils";
|
|
2
2
|
import { buildFragment } from "../../shared/jqlite/jqlite";
|
|
3
|
+
import { hasAnimate } from "../../shared/utils";
|
|
4
|
+
import { domInsert } from "../../core/animate/animate";
|
|
3
5
|
|
|
4
6
|
export const ngIncludeDirective = [
|
|
5
7
|
"$templateRequest",
|
|
@@ -17,6 +19,15 @@ export const ngIncludeDirective = [
|
|
|
17
19
|
const autoScrollExp = attr.autoscroll;
|
|
18
20
|
|
|
19
21
|
return (scope, $element, _$attr, ctrl, $transclude) => {
|
|
22
|
+
function maybeScroll() {
|
|
23
|
+
if (
|
|
24
|
+
isDefined(autoScrollExp) &&
|
|
25
|
+
(!autoScrollExp || scope.$eval(autoScrollExp))
|
|
26
|
+
) {
|
|
27
|
+
$anchorScroll();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
let changeCounter = 0;
|
|
21
32
|
let currentScope;
|
|
22
33
|
let previousElement;
|
|
@@ -31,9 +42,14 @@ export const ngIncludeDirective = [
|
|
|
31
42
|
currentScope = null;
|
|
32
43
|
}
|
|
33
44
|
if (currentElement) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
if (hasAnimate(currentElement[0])) {
|
|
46
|
+
$animate.leave(currentElement).done((response) => {
|
|
47
|
+
if (response !== false) previousElement = null;
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
currentElement.remove();
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
previousElement = currentElement;
|
|
38
54
|
currentElement = null;
|
|
39
55
|
}
|
|
@@ -41,13 +57,7 @@ export const ngIncludeDirective = [
|
|
|
41
57
|
|
|
42
58
|
scope.$watch(srcExp, (src) => {
|
|
43
59
|
const afterAnimation = function (response) {
|
|
44
|
-
|
|
45
|
-
response !== false &&
|
|
46
|
-
isDefined(autoScrollExp) &&
|
|
47
|
-
(!autoScrollExp || scope.$eval(autoScrollExp))
|
|
48
|
-
) {
|
|
49
|
-
$anchorScroll();
|
|
50
|
-
}
|
|
60
|
+
response !== false && maybeScroll();
|
|
51
61
|
};
|
|
52
62
|
|
|
53
63
|
const thisChangeId = ++changeCounter;
|
|
@@ -70,7 +80,12 @@ export const ngIncludeDirective = [
|
|
|
70
80
|
// directives to non existing elements.
|
|
71
81
|
const clone = $transclude(newScope, (clone) => {
|
|
72
82
|
cleanupLastIncludeContent();
|
|
73
|
-
|
|
83
|
+
if (hasAnimate(clone[0])) {
|
|
84
|
+
$animate.enter(clone, null, $element).done(afterAnimation);
|
|
85
|
+
} else {
|
|
86
|
+
domInsert(clone, null, $element);
|
|
87
|
+
maybeScroll();
|
|
88
|
+
}
|
|
74
89
|
});
|
|
75
90
|
|
|
76
91
|
currentScope = newScope;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/\*\*
|
|
2
2
|
|
|
3
|
-
- @ngdoc directive
|
|
4
3
|
- @name ngInclude
|
|
5
4
|
- @restrict ECA
|
|
6
5
|
- @scope
|
|
@@ -22,7 +21,9 @@
|
|
|
22
21
|
- policy may further restrict whether the template is successfully loaded.
|
|
23
22
|
- For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
|
|
24
23
|
- access on some browsers.
|
|
25
|
-
-
|
|
24
|
+
- The `enter` and `leave` animation effects can be enabled for the element by
|
|
25
|
+
setting data attribute (`data-*`) or custom attribute `animate` to `true` attribute.
|
|
26
|
+
|
|
26
27
|
- @animations
|
|
27
28
|
- | Animation | Occurs |
|
|
28
29
|
- |----------------------------------|-------------------------------------|
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
isPromiseLike,
|
|
16
16
|
isUndefined,
|
|
17
17
|
isFunction,
|
|
18
|
+
hasAnimate,
|
|
18
19
|
} from "../../shared/utils";
|
|
19
20
|
import {
|
|
20
21
|
addSetValidityMethod,
|
|
@@ -335,11 +336,21 @@ NgModelController.prototype = {
|
|
|
335
336
|
|
|
336
337
|
$$updateEmptyClasses(value) {
|
|
337
338
|
if (this.$isEmpty(value)) {
|
|
338
|
-
|
|
339
|
-
|
|
339
|
+
if (hasAnimate(this.$$element[0])) {
|
|
340
|
+
this.$$animate.removeClass(this.$$element, NOT_EMPTY_CLASS);
|
|
341
|
+
this.$$animate.addClass(this.$$element, EMPTY_CLASS);
|
|
342
|
+
} else {
|
|
343
|
+
this.$$element[0].classList.remove(NOT_EMPTY_CLASS);
|
|
344
|
+
this.$$element[0].classList.add(EMPTY_CLASS);
|
|
345
|
+
}
|
|
340
346
|
} else {
|
|
341
|
-
|
|
342
|
-
|
|
347
|
+
if (hasAnimate(this.$$element[0])) {
|
|
348
|
+
this.$$animate.removeClass(this.$$element, EMPTY_CLASS);
|
|
349
|
+
this.$$animate.addClass(this.$$element, NOT_EMPTY_CLASS);
|
|
350
|
+
} else {
|
|
351
|
+
this.$$element[0].classList.remove(EMPTY_CLASS);
|
|
352
|
+
this.$$element[0].classList.add(NOT_EMPTY_CLASS);
|
|
353
|
+
}
|
|
343
354
|
}
|
|
344
355
|
},
|
|
345
356
|
|
|
@@ -357,8 +368,13 @@ NgModelController.prototype = {
|
|
|
357
368
|
$setPristine() {
|
|
358
369
|
this.$dirty = false;
|
|
359
370
|
this.$pristine = true;
|
|
360
|
-
|
|
361
|
-
|
|
371
|
+
if (hasAnimate(this.$$element[0])) {
|
|
372
|
+
this.$$animate.removeClass(this.$$element, EMPTY_CLASS);
|
|
373
|
+
this.$$animate.addClass(this.$$element, PRISTINE_CLASS);
|
|
374
|
+
} else {
|
|
375
|
+
this.$$element[0].classList.remove(EMPTY_CLASS);
|
|
376
|
+
this.$$element[0].classList.add(PRISTINE_CLASS);
|
|
377
|
+
}
|
|
362
378
|
},
|
|
363
379
|
|
|
364
380
|
/**
|
|
@@ -375,8 +391,13 @@ NgModelController.prototype = {
|
|
|
375
391
|
$setDirty() {
|
|
376
392
|
this.$dirty = true;
|
|
377
393
|
this.$pristine = false;
|
|
378
|
-
|
|
379
|
-
|
|
394
|
+
if (hasAnimate(this.$$element[0])) {
|
|
395
|
+
this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
|
|
396
|
+
this.$$animate.addClass(this.$$element, DIRTY_CLASS);
|
|
397
|
+
} else {
|
|
398
|
+
this.$$element[0].classList.remove(PRISTINE_CLASS);
|
|
399
|
+
this.$$element[0].classList.add(DIRTY_CLASS);
|
|
400
|
+
}
|
|
380
401
|
this.$$parentForm.$setDirty();
|
|
381
402
|
},
|
|
382
403
|
|
|
@@ -395,7 +416,12 @@ NgModelController.prototype = {
|
|
|
395
416
|
$setUntouched() {
|
|
396
417
|
this.$touched = false;
|
|
397
418
|
this.$untouched = true;
|
|
398
|
-
|
|
419
|
+
if (hasAnimate(this.$$element[0])) {
|
|
420
|
+
this.$$animate.setClass(this.$$element, UNTOUCHED_CLASS, TOUCHED_CLASS);
|
|
421
|
+
} else {
|
|
422
|
+
this.$$element[0].classList.remove(TOUCHED_CLASS);
|
|
423
|
+
this.$$element[0].classList.add(UNTOUCHED_CLASS);
|
|
424
|
+
}
|
|
399
425
|
},
|
|
400
426
|
|
|
401
427
|
/**
|
|
@@ -412,7 +438,12 @@ NgModelController.prototype = {
|
|
|
412
438
|
$setTouched() {
|
|
413
439
|
this.$touched = true;
|
|
414
440
|
this.$untouched = false;
|
|
415
|
-
|
|
441
|
+
if (hasAnimate(this.$$element[0])) {
|
|
442
|
+
this.$$animate.setClass(this.$$element, TOUCHED_CLASS, UNTOUCHED_CLASS);
|
|
443
|
+
} else {
|
|
444
|
+
this.$$element[0].classList.remove(UNTOUCHED_CLASS);
|
|
445
|
+
this.$$element[0].classList.add(TOUCHED_CLASS);
|
|
446
|
+
}
|
|
416
447
|
},
|
|
417
448
|
|
|
418
449
|
/**
|
|
@@ -1209,7 +1209,7 @@ export function startingTag(elementStr) {
|
|
|
1209
1209
|
|
|
1210
1210
|
/**
|
|
1211
1211
|
* Return the DOM siblings between the first and last node in the given array.
|
|
1212
|
-
* @param {Array} nodes An array-like object
|
|
1212
|
+
* @param {JQLite|Array} nodes An array-like object
|
|
1213
1213
|
* @returns {JQLite} the inputted object or a JQLite collection containing the nodes
|
|
1214
1214
|
*/
|
|
1215
1215
|
export function getBlockNodes(nodes) {
|
|
@@ -1,5 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} Scheduler
|
|
3
|
+
* @property {Function} waitUntilQuiet - Function to wait until the animation frame is quiet.
|
|
4
|
+
* @property {Array<Function>} queue - The queue of tasks to be processed.
|
|
5
|
+
* @property {Function} scheduler - The function to add tasks to the queue and schedule the next tick.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Creates a requestAnimationFrame scheduler.
|
|
9
|
+
* @returns {Scheduler} The scheduler object.
|
|
10
|
+
*/
|
|
1
11
|
export const $$rAFSchedulerFactory: (() => {
|
|
2
|
-
(tasks:
|
|
12
|
+
(tasks: Array<Function>): void;
|
|
3
13
|
queue: any[];
|
|
4
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Waits until the animation frame is quiet before running the provided function.
|
|
16
|
+
* Cancels any previous animation frame requests.
|
|
17
|
+
* @param {Function} fn - The function to run when the animation frame is quiet.
|
|
18
|
+
*/
|
|
19
|
+
waitUntilQuiet(fn: Function): void;
|
|
5
20
|
})[];
|
|
21
|
+
export type Scheduler = {
|
|
22
|
+
/**
|
|
23
|
+
* - Function to wait until the animation frame is quiet.
|
|
24
|
+
*/
|
|
25
|
+
waitUntilQuiet: Function;
|
|
26
|
+
/**
|
|
27
|
+
* - The queue of tasks to be processed.
|
|
28
|
+
*/
|
|
29
|
+
queue: Array<Function>;
|
|
30
|
+
/**
|
|
31
|
+
* - The function to add tasks to the queue and schedule the next tick.
|
|
32
|
+
*/
|
|
33
|
+
scheduler: Function;
|
|
34
|
+
};
|