Project

General

Profile

1
/**
2
 * @license Angular v4.4.6
3
 * (c) 2010-2017 Google, Inc. https://angular.io/
4
 * License: MIT
5
 */
6
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, Directive, ElementRef, EventEmitter, Host, Inject, Injectable, InjectionToken, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, NgModule, NgModuleRef, Optional, Pipe, Renderer, TemplateRef, Version, ViewContainerRef, WrappedValue, isDevMode, ɵisListLikeIterable, ɵisObservable, ɵisPromise, ɵstringify } from '@angular/core';
7

    
8
/**
9
 * @license
10
 * Copyright Google Inc. All Rights Reserved.
11
 *
12
 * Use of this source code is governed by an MIT-style license that can be
13
 * found in the LICENSE file at https://angular.io/license
14
 */
15
/**
16
 * This class should not be used directly by an application developer. Instead, use
17
 * {\@link Location}.
18
 *
19
 * `PlatformLocation` encapsulates all calls to DOM apis, which allows the Router to be platform
20
 * agnostic.
21
 * This means that we can have different implementation of `PlatformLocation` for the different
22
 * platforms that angular supports. For example, `\@angular/platform-browser` provides an
23
 * implementation specific to the browser environment, while `\@angular/platform-webworker` provides
24
 * one suitable for use with web workers.
25
 *
26
 * The `PlatformLocation` class is used directly by all implementations of {\@link LocationStrategy}
27
 * when they need to interact with the DOM apis like pushState, popState, etc...
28
 *
29
 * {\@link LocationStrategy} in turn is used by the {\@link Location} service which is used directly
30
 * by the {\@link Router} in order to navigate between routes. Since all interactions between {\@link
31
 * Router} /
32
 * {\@link Location} / {\@link LocationStrategy} and DOM apis flow through the `PlatformLocation`
33
 * class they are all platform independent.
34
 *
35
 * \@stable
36
 * @abstract
37
 */
38
class PlatformLocation {
39
    /**
40
     * @abstract
41
     * @return {?}
42
     */
43
    getBaseHrefFromDOM() { }
44
    /**
45
     * @abstract
46
     * @param {?} fn
47
     * @return {?}
48
     */
49
    onPopState(fn) { }
50
    /**
51
     * @abstract
52
     * @param {?} fn
53
     * @return {?}
54
     */
55
    onHashChange(fn) { }
56
    /**
57
     * @abstract
58
     * @return {?}
59
     */
60
    pathname() { }
61
    /**
62
     * @abstract
63
     * @return {?}
64
     */
65
    search() { }
66
    /**
67
     * @abstract
68
     * @return {?}
69
     */
70
    hash() { }
71
    /**
72
     * @abstract
73
     * @param {?} state
74
     * @param {?} title
75
     * @param {?} url
76
     * @return {?}
77
     */
78
    replaceState(state, title, url) { }
79
    /**
80
     * @abstract
81
     * @param {?} state
82
     * @param {?} title
83
     * @param {?} url
84
     * @return {?}
85
     */
86
    pushState(state, title, url) { }
87
    /**
88
     * @abstract
89
     * @return {?}
90
     */
91
    forward() { }
92
    /**
93
     * @abstract
94
     * @return {?}
95
     */
96
    back() { }
97
}
98
/**
99
 * \@whatItDoes indicates when a location is initialized
100
 * \@experimental
101
 */
102
const LOCATION_INITIALIZED = new InjectionToken('Location Initialized');
103

    
104
/**
105
 * @license
106
 * Copyright Google Inc. All Rights Reserved.
107
 *
108
 * Use of this source code is governed by an MIT-style license that can be
109
 * found in the LICENSE file at https://angular.io/license
110
 */
111
/**
112
 * `LocationStrategy` is responsible for representing and reading route state
113
 * from the browser's URL. Angular provides two strategies:
114
 * {\@link HashLocationStrategy} and {\@link PathLocationStrategy}.
115
 *
116
 * This is used under the hood of the {\@link Location} service.
117
 *
118
 * Applications should use the {\@link Router} or {\@link Location} services to
119
 * interact with application route state.
120
 *
121
 * For instance, {\@link HashLocationStrategy} produces URLs like
122
 * `http://example.com#/foo`, and {\@link PathLocationStrategy} produces
123
 * `http://example.com/foo` as an equivalent URL.
124
 *
125
 * See these two classes for more.
126
 *
127
 * \@stable
128
 * @abstract
129
 */
130
class LocationStrategy {
131
    /**
132
     * @abstract
133
     * @param {?=} includeHash
134
     * @return {?}
135
     */
136
    path(includeHash) { }
137
    /**
138
     * @abstract
139
     * @param {?} internal
140
     * @return {?}
141
     */
142
    prepareExternalUrl(internal) { }
143
    /**
144
     * @abstract
145
     * @param {?} state
146
     * @param {?} title
147
     * @param {?} url
148
     * @param {?} queryParams
149
     * @return {?}
150
     */
151
    pushState(state, title, url, queryParams) { }
152
    /**
153
     * @abstract
154
     * @param {?} state
155
     * @param {?} title
156
     * @param {?} url
157
     * @param {?} queryParams
158
     * @return {?}
159
     */
160
    replaceState(state, title, url, queryParams) { }
161
    /**
162
     * @abstract
163
     * @return {?}
164
     */
165
    forward() { }
166
    /**
167
     * @abstract
168
     * @return {?}
169
     */
170
    back() { }
171
    /**
172
     * @abstract
173
     * @param {?} fn
174
     * @return {?}
175
     */
176
    onPopState(fn) { }
177
    /**
178
     * @abstract
179
     * @return {?}
180
     */
181
    getBaseHref() { }
182
}
183
/**
184
 * The `APP_BASE_HREF` token represents the base href to be used with the
185
 * {\@link PathLocationStrategy}.
186
 *
187
 * If you're using {\@link PathLocationStrategy}, you must provide a provider to a string
188
 * representing the URL prefix that should be preserved when generating and recognizing
189
 * URLs.
190
 *
191
 * ### Example
192
 *
193
 * ```typescript
194
 * import {Component, NgModule} from '\@angular/core';
195
 * import {APP_BASE_HREF} from '\@angular/common';
196
 *
197
 * \@NgModule({
198
 *   providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
199
 * })
200
 * class AppModule {}
201
 * ```
202
 *
203
 * \@stable
204
 */
205
const APP_BASE_HREF = new InjectionToken('appBaseHref');
206

    
207
/**
208
 * @license
209
 * Copyright Google Inc. All Rights Reserved.
210
 *
211
 * Use of this source code is governed by an MIT-style license that can be
212
 * found in the LICENSE file at https://angular.io/license
213
 */
214
/**
215
 * \@whatItDoes `Location` is a service that applications can use to interact with a browser's URL.
216
 * \@description
217
 * Depending on which {\@link LocationStrategy} is used, `Location` will either persist
218
 * to the URL's path or the URL's hash segment.
219
 *
220
 * Note: it's better to use {\@link Router#navigate} service to trigger route changes. Use
221
 * `Location` only if you need to interact with or create normalized URLs outside of
222
 * routing.
223
 *
224
 * `Location` is responsible for normalizing the URL against the application's base href.
225
 * A normalized URL is absolute from the URL host, includes the application's base href, and has no
226
 * trailing slash:
227
 * - `/my/app/user/123` is normalized
228
 * - `my/app/user/123` **is not** normalized
229
 * - `/my/app/user/123/` **is not** normalized
230
 *
231
 * ### Example
232
 * {\@example common/location/ts/path_location_component.ts region='LocationComponent'}
233
 * \@stable
234
 */
235
class Location {
236
    /**
237
     * @param {?} platformStrategy
238
     */
239
    constructor(platformStrategy) {
240
        /**
241
         * \@internal
242
         */
243
        this._subject = new EventEmitter();
244
        this._platformStrategy = platformStrategy;
245
        const browserBaseHref = this._platformStrategy.getBaseHref();
246
        this._baseHref = Location.stripTrailingSlash(_stripIndexHtml(browserBaseHref));
247
        this._platformStrategy.onPopState((ev) => {
248
            this._subject.emit({
249
                'url': this.path(true),
250
                'pop': true,
251
                'type': ev.type,
252
            });
253
        });
254
    }
255
    /**
256
     * @param {?=} includeHash
257
     * @return {?}
258
     */
259
    path(includeHash = false) {
260
        return this.normalize(this._platformStrategy.path(includeHash));
261
    }
262
    /**
263
     * Normalizes the given path and compares to the current normalized path.
264
     * @param {?} path
265
     * @param {?=} query
266
     * @return {?}
267
     */
268
    isCurrentPathEqualTo(path, query = '') {
269
        return this.path() == this.normalize(path + Location.normalizeQueryParams(query));
270
    }
271
    /**
272
     * Given a string representing a URL, returns the normalized URL path without leading or
273
     * trailing slashes.
274
     * @param {?} url
275
     * @return {?}
276
     */
277
    normalize(url) {
278
        return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url)));
279
    }
280
    /**
281
     * Given a string representing a URL, returns the platform-specific external URL path.
282
     * If the given URL doesn't begin with a leading slash (`'/'`), this method adds one
283
     * before normalizing. This method will also add a hash if `HashLocationStrategy` is
284
     * used, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
285
     * @param {?} url
286
     * @return {?}
287
     */
288
    prepareExternalUrl(url) {
289
        if (url && url[0] !== '/') {
290
            url = '/' + url;
291
        }
292
        return this._platformStrategy.prepareExternalUrl(url);
293
    }
294
    /**
295
     * Changes the browsers URL to the normalized version of the given URL, and pushes a
296
     * new item onto the platform's history.
297
     * @param {?} path
298
     * @param {?=} query
299
     * @return {?}
300
     */
301
    go(path, query = '') {
302
        this._platformStrategy.pushState(null, '', path, query);
303
    }
304
    /**
305
     * Changes the browsers URL to the normalized version of the given URL, and replaces
306
     * the top item on the platform's history stack.
307
     * @param {?} path
308
     * @param {?=} query
309
     * @return {?}
310
     */
311
    replaceState(path, query = '') {
312
        this._platformStrategy.replaceState(null, '', path, query);
313
    }
314
    /**
315
     * Navigates forward in the platform's history.
316
     * @return {?}
317
     */
318
    forward() { this._platformStrategy.forward(); }
319
    /**
320
     * Navigates back in the platform's history.
321
     * @return {?}
322
     */
323
    back() { this._platformStrategy.back(); }
324
    /**
325
     * Subscribe to the platform's `popState` events.
326
     * @param {?} onNext
327
     * @param {?=} onThrow
328
     * @param {?=} onReturn
329
     * @return {?}
330
     */
331
    subscribe(onNext, onThrow, onReturn) {
332
        return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
333
    }
334
    /**
335
     * Given a string of url parameters, prepend with '?' if needed, otherwise return parameters as
336
     * is.
337
     * @param {?} params
338
     * @return {?}
339
     */
340
    static normalizeQueryParams(params) {
341
        return params && params[0] !== '?' ? '?' + params : params;
342
    }
343
    /**
344
     * Given 2 parts of a url, join them with a slash if needed.
345
     * @param {?} start
346
     * @param {?} end
347
     * @return {?}
348
     */
349
    static joinWithSlash(start, end) {
350
        if (start.length == 0) {
351
            return end;
352
        }
353
        if (end.length == 0) {
354
            return start;
355
        }
356
        let /** @type {?} */ slashes = 0;
357
        if (start.endsWith('/')) {
358
            slashes++;
359
        }
360
        if (end.startsWith('/')) {
361
            slashes++;
362
        }
363
        if (slashes == 2) {
364
            return start + end.substring(1);
365
        }
366
        if (slashes == 1) {
367
            return start + end;
368
        }
369
        return start + '/' + end;
370
    }
371
    /**
372
     * If url has a trailing slash, remove it, otherwise return url as is. This
373
     * method looks for the first occurence of either #, ?, or the end of the
374
     * line as `/` characters after any of these should not be replaced.
375
     * @param {?} url
376
     * @return {?}
377
     */
378
    static stripTrailingSlash(url) {
379
        const /** @type {?} */ match = url.match(/#|\?|$/);
380
        const /** @type {?} */ pathEndIdx = match && match.index || url.length;
381
        const /** @type {?} */ droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0);
382
        return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx);
383
    }
384
}
385
Location.decorators = [
386
    { type: Injectable },
387
];
388
/**
389
 * @nocollapse
390
 */
391
Location.ctorParameters = () => [
392
    { type: LocationStrategy, },
393
];
394
/**
395
 * @param {?} baseHref
396
 * @param {?} url
397
 * @return {?}
398
 */
399
function _stripBaseHref(baseHref, url) {
400
    return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url;
401
}
402
/**
403
 * @param {?} url
404
 * @return {?}
405
 */
406
function _stripIndexHtml(url) {
407
    return url.replace(/\/index.html$/, '');
408
}
409

    
410
/**
411
 * @license
412
 * Copyright Google Inc. All Rights Reserved.
413
 *
414
 * Use of this source code is governed by an MIT-style license that can be
415
 * found in the LICENSE file at https://angular.io/license
416
 */
417
/**
418
 * \@whatItDoes Use URL hash for storing application location data.
419
 * \@description
420
 * `HashLocationStrategy` is a {\@link LocationStrategy} used to configure the
421
 * {\@link Location} service to represent its state in the
422
 * [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax)
423
 * of the browser's URL.
424
 *
425
 * For instance, if you call `location.go('/foo')`, the browser's URL will become
426
 * `example.com#/foo`.
427
 *
428
 * ### Example
429
 *
430
 * {\@example common/location/ts/hash_location_component.ts region='LocationComponent'}
431
 *
432
 * \@stable
433
 */
434
class HashLocationStrategy extends LocationStrategy {
435
    /**
436
     * @param {?} _platformLocation
437
     * @param {?=} _baseHref
438
     */
439
    constructor(_platformLocation, _baseHref) {
440
        super();
441
        this._platformLocation = _platformLocation;
442
        this._baseHref = '';
443
        if (_baseHref != null) {
444
            this._baseHref = _baseHref;
445
        }
446
    }
447
    /**
448
     * @param {?} fn
449
     * @return {?}
450
     */
451
    onPopState(fn) {
452
        this._platformLocation.onPopState(fn);
453
        this._platformLocation.onHashChange(fn);
454
    }
455
    /**
456
     * @return {?}
457
     */
458
    getBaseHref() { return this._baseHref; }
459
    /**
460
     * @param {?=} includeHash
461
     * @return {?}
462
     */
463
    path(includeHash = false) {
464
        // the hash value is always prefixed with a `#`
465
        // and if it is empty then it will stay empty
466
        let /** @type {?} */ path = this._platformLocation.hash;
467
        if (path == null)
468
            path = '#';
469
        return path.length > 0 ? path.substring(1) : path;
470
    }
471
    /**
472
     * @param {?} internal
473
     * @return {?}
474
     */
475
    prepareExternalUrl(internal) {
476
        const /** @type {?} */ url = Location.joinWithSlash(this._baseHref, internal);
477
        return url.length > 0 ? ('#' + url) : url;
478
    }
479
    /**
480
     * @param {?} state
481
     * @param {?} title
482
     * @param {?} path
483
     * @param {?} queryParams
484
     * @return {?}
485
     */
486
    pushState(state, title, path, queryParams) {
487
        let /** @type {?} */ url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
488
        if (url.length == 0) {
489
            url = this._platformLocation.pathname;
490
        }
491
        this._platformLocation.pushState(state, title, url);
492
    }
493
    /**
494
     * @param {?} state
495
     * @param {?} title
496
     * @param {?} path
497
     * @param {?} queryParams
498
     * @return {?}
499
     */
500
    replaceState(state, title, path, queryParams) {
501
        let /** @type {?} */ url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
502
        if (url.length == 0) {
503
            url = this._platformLocation.pathname;
504
        }
505
        this._platformLocation.replaceState(state, title, url);
506
    }
507
    /**
508
     * @return {?}
509
     */
510
    forward() { this._platformLocation.forward(); }
511
    /**
512
     * @return {?}
513
     */
514
    back() { this._platformLocation.back(); }
515
}
516
HashLocationStrategy.decorators = [
517
    { type: Injectable },
518
];
519
/**
520
 * @nocollapse
521
 */
522
HashLocationStrategy.ctorParameters = () => [
523
    { type: PlatformLocation, },
524
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [APP_BASE_HREF,] },] },
525
];
526

    
527
/**
528
 * @license
529
 * Copyright Google Inc. All Rights Reserved.
530
 *
531
 * Use of this source code is governed by an MIT-style license that can be
532
 * found in the LICENSE file at https://angular.io/license
533
 */
534
/**
535
 * \@whatItDoes Use URL for storing application location data.
536
 * \@description
537
 * `PathLocationStrategy` is a {\@link LocationStrategy} used to configure the
538
 * {\@link Location} service to represent its state in the
539
 * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the
540
 * browser's URL.
541
 *
542
 * If you're using `PathLocationStrategy`, you must provide a {\@link APP_BASE_HREF}
543
 * or add a base element to the document. This URL prefix that will be preserved
544
 * when generating and recognizing URLs.
545
 *
546
 * For instance, if you provide an `APP_BASE_HREF` of `'/my/app'` and call
547
 * `location.go('/foo')`, the browser's URL will become
548
 * `example.com/my/app/foo`.
549
 *
550
 * Similarly, if you add `<base href='/my/app'/>` to the document and call
551
 * `location.go('/foo')`, the browser's URL will become
552
 * `example.com/my/app/foo`.
553
 *
554
 * ### Example
555
 *
556
 * {\@example common/location/ts/path_location_component.ts region='LocationComponent'}
557
 *
558
 * \@stable
559
 */
560
class PathLocationStrategy extends LocationStrategy {
561
    /**
562
     * @param {?} _platformLocation
563
     * @param {?=} href
564
     */
565
    constructor(_platformLocation, href) {
566
        super();
567
        this._platformLocation = _platformLocation;
568
        if (href == null) {
569
            href = this._platformLocation.getBaseHrefFromDOM();
570
        }
571
        if (href == null) {
572
            throw new Error(`No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.`);
573
        }
574
        this._baseHref = href;
575
    }
576
    /**
577
     * @param {?} fn
578
     * @return {?}
579
     */
580
    onPopState(fn) {
581
        this._platformLocation.onPopState(fn);
582
        this._platformLocation.onHashChange(fn);
583
    }
584
    /**
585
     * @return {?}
586
     */
587
    getBaseHref() { return this._baseHref; }
588
    /**
589
     * @param {?} internal
590
     * @return {?}
591
     */
592
    prepareExternalUrl(internal) {
593
        return Location.joinWithSlash(this._baseHref, internal);
594
    }
595
    /**
596
     * @param {?=} includeHash
597
     * @return {?}
598
     */
599
    path(includeHash = false) {
600
        const /** @type {?} */ pathname = this._platformLocation.pathname +
601
            Location.normalizeQueryParams(this._platformLocation.search);
602
        const /** @type {?} */ hash = this._platformLocation.hash;
603
        return hash && includeHash ? `${pathname}${hash}` : pathname;
604
    }
605
    /**
606
     * @param {?} state
607
     * @param {?} title
608
     * @param {?} url
609
     * @param {?} queryParams
610
     * @return {?}
611
     */
612
    pushState(state, title, url, queryParams) {
613
        const /** @type {?} */ externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams));
614
        this._platformLocation.pushState(state, title, externalUrl);
615
    }
616
    /**
617
     * @param {?} state
618
     * @param {?} title
619
     * @param {?} url
620
     * @param {?} queryParams
621
     * @return {?}
622
     */
623
    replaceState(state, title, url, queryParams) {
624
        const /** @type {?} */ externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams));
625
        this._platformLocation.replaceState(state, title, externalUrl);
626
    }
627
    /**
628
     * @return {?}
629
     */
630
    forward() { this._platformLocation.forward(); }
631
    /**
632
     * @return {?}
633
     */
634
    back() { this._platformLocation.back(); }
635
}
636
PathLocationStrategy.decorators = [
637
    { type: Injectable },
638
];
639
/**
640
 * @nocollapse
641
 */
642
PathLocationStrategy.ctorParameters = () => [
643
    { type: PlatformLocation, },
644
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [APP_BASE_HREF,] },] },
645
];
646

    
647
/**
648
 * @license
649
 * Copyright Google Inc. All Rights Reserved.
650
 *
651
 * Use of this source code is governed by an MIT-style license that can be
652
 * found in the LICENSE file at https://angular.io/license
653
 */
654

    
655
/**
656
 * @license
657
 * Copyright Google Inc. All Rights Reserved.
658
 *
659
 * Use of this source code is governed by an MIT-style license that can be
660
 * found in the LICENSE file at https://angular.io/license
661
 */
662
/**
663
 * \@experimental
664
 * @abstract
665
 */
666
class NgLocalization {
667
    /**
668
     * @abstract
669
     * @param {?} value
670
     * @return {?}
671
     */
672
    getPluralCategory(value) { }
673
}
674
/**
675
 * Returns the plural category for a given value.
676
 * - "=value" when the case exists,
677
 * - the plural category otherwise
678
 *
679
 * \@internal
680
 * @param {?} value
681
 * @param {?} cases
682
 * @param {?} ngLocalization
683
 * @return {?}
684
 */
685
function getPluralCategory(value, cases, ngLocalization) {
686
    let /** @type {?} */ key = `=${value}`;
687
    if (cases.indexOf(key) > -1) {
688
        return key;
689
    }
690
    key = ngLocalization.getPluralCategory(value);
691
    if (cases.indexOf(key) > -1) {
692
        return key;
693
    }
694
    if (cases.indexOf('other') > -1) {
695
        return 'other';
696
    }
697
    throw new Error(`No plural message found for value "${value}"`);
698
}
699
/**
700
 * Returns the plural case based on the locale
701
 *
702
 * \@experimental
703
 */
704
class NgLocaleLocalization extends NgLocalization {
705
    /**
706
     * @param {?} locale
707
     */
708
    constructor(locale) {
709
        super();
710
        this.locale = locale;
711
    }
712
    /**
713
     * @param {?} value
714
     * @return {?}
715
     */
716
    getPluralCategory(value) {
717
        const /** @type {?} */ plural = getPluralCase(this.locale, value);
718
        switch (plural) {
719
            case Plural.Zero:
720
                return 'zero';
721
            case Plural.One:
722
                return 'one';
723
            case Plural.Two:
724
                return 'two';
725
            case Plural.Few:
726
                return 'few';
727
            case Plural.Many:
728
                return 'many';
729
            default:
730
                return 'other';
731
        }
732
    }
733
}
734
NgLocaleLocalization.decorators = [
735
    { type: Injectable },
736
];
737
/**
738
 * @nocollapse
739
 */
740
NgLocaleLocalization.ctorParameters = () => [
741
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
742
];
743
let Plural = {};
744
Plural.Zero = 0;
745
Plural.One = 1;
746
Plural.Two = 2;
747
Plural.Few = 3;
748
Plural.Many = 4;
749
Plural.Other = 5;
750
Plural[Plural.Zero] = "Zero";
751
Plural[Plural.One] = "One";
752
Plural[Plural.Two] = "Two";
753
Plural[Plural.Few] = "Few";
754
Plural[Plural.Many] = "Many";
755
Plural[Plural.Other] = "Other";
756
/**
757
 * Returns the plural case based on the locale
758
 *
759
 * \@experimental
760
 * @param {?} locale
761
 * @param {?} nLike
762
 * @return {?}
763
 */
764
function getPluralCase(locale, nLike) {
765
    // TODO(vicb): lazy compute
766
    if (typeof nLike === 'string') {
767
        nLike = parseInt(/** @type {?} */ (nLike), 10);
768
    }
769
    const /** @type {?} */ n = (nLike);
770
    const /** @type {?} */ nDecimal = n.toString().replace(/^[^.]*\.?/, '');
771
    const /** @type {?} */ i = Math.floor(Math.abs(n));
772
    const /** @type {?} */ v = nDecimal.length;
773
    const /** @type {?} */ f = parseInt(nDecimal, 10);
774
    const /** @type {?} */ t = parseInt(n.toString().replace(/^[^.]*\.?|0+$/g, ''), 10) || 0;
775
    const /** @type {?} */ lang = locale.split('-')[0].toLowerCase();
776
    switch (lang) {
777
        case 'af':
778
        case 'asa':
779
        case 'az':
780
        case 'bem':
781
        case 'bez':
782
        case 'bg':
783
        case 'brx':
784
        case 'ce':
785
        case 'cgg':
786
        case 'chr':
787
        case 'ckb':
788
        case 'ee':
789
        case 'el':
790
        case 'eo':
791
        case 'es':
792
        case 'eu':
793
        case 'fo':
794
        case 'fur':
795
        case 'gsw':
796
        case 'ha':
797
        case 'haw':
798
        case 'hu':
799
        case 'jgo':
800
        case 'jmc':
801
        case 'ka':
802
        case 'kk':
803
        case 'kkj':
804
        case 'kl':
805
        case 'ks':
806
        case 'ksb':
807
        case 'ky':
808
        case 'lb':
809
        case 'lg':
810
        case 'mas':
811
        case 'mgo':
812
        case 'ml':
813
        case 'mn':
814
        case 'nb':
815
        case 'nd':
816
        case 'ne':
817
        case 'nn':
818
        case 'nnh':
819
        case 'nyn':
820
        case 'om':
821
        case 'or':
822
        case 'os':
823
        case 'ps':
824
        case 'rm':
825
        case 'rof':
826
        case 'rwk':
827
        case 'saq':
828
        case 'seh':
829
        case 'sn':
830
        case 'so':
831
        case 'sq':
832
        case 'ta':
833
        case 'te':
834
        case 'teo':
835
        case 'tk':
836
        case 'tr':
837
        case 'ug':
838
        case 'uz':
839
        case 'vo':
840
        case 'vun':
841
        case 'wae':
842
        case 'xog':
843
            if (n === 1)
844
                return Plural.One;
845
            return Plural.Other;
846
        case 'ak':
847
        case 'ln':
848
        case 'mg':
849
        case 'pa':
850
        case 'ti':
851
            if (n === Math.floor(n) && n >= 0 && n <= 1)
852
                return Plural.One;
853
            return Plural.Other;
854
        case 'am':
855
        case 'as':
856
        case 'bn':
857
        case 'fa':
858
        case 'gu':
859
        case 'hi':
860
        case 'kn':
861
        case 'mr':
862
        case 'zu':
863
            if (i === 0 || n === 1)
864
                return Plural.One;
865
            return Plural.Other;
866
        case 'ar':
867
            if (n === 0)
868
                return Plural.Zero;
869
            if (n === 1)
870
                return Plural.One;
871
            if (n === 2)
872
                return Plural.Two;
873
            if (n % 100 === Math.floor(n % 100) && n % 100 >= 3 && n % 100 <= 10)
874
                return Plural.Few;
875
            if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 99)
876
                return Plural.Many;
877
            return Plural.Other;
878
        case 'ast':
879
        case 'ca':
880
        case 'de':
881
        case 'en':
882
        case 'et':
883
        case 'fi':
884
        case 'fy':
885
        case 'gl':
886
        case 'it':
887
        case 'nl':
888
        case 'sv':
889
        case 'sw':
890
        case 'ur':
891
        case 'yi':
892
            if (i === 1 && v === 0)
893
                return Plural.One;
894
            return Plural.Other;
895
        case 'be':
896
            if (n % 10 === 1 && !(n % 100 === 11))
897
                return Plural.One;
898
            if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 4 &&
899
                !(n % 100 >= 12 && n % 100 <= 14))
900
                return Plural.Few;
901
            if (n % 10 === 0 || n % 10 === Math.floor(n % 10) && n % 10 >= 5 && n % 10 <= 9 ||
902
                n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 14)
903
                return Plural.Many;
904
            return Plural.Other;
905
        case 'br':
906
            if (n % 10 === 1 && !(n % 100 === 11 || n % 100 === 71 || n % 100 === 91))
907
                return Plural.One;
908
            if (n % 10 === 2 && !(n % 100 === 12 || n % 100 === 72 || n % 100 === 92))
909
                return Plural.Two;
910
            if (n % 10 === Math.floor(n % 10) && (n % 10 >= 3 && n % 10 <= 4 || n % 10 === 9) &&
911
                !(n % 100 >= 10 && n % 100 <= 19 || n % 100 >= 70 && n % 100 <= 79 ||
912
                    n % 100 >= 90 && n % 100 <= 99))
913
                return Plural.Few;
914
            if (!(n === 0) && n % 1e6 === 0)
915
                return Plural.Many;
916
            return Plural.Other;
917
        case 'bs':
918
        case 'hr':
919
        case 'sr':
920
            if (v === 0 && i % 10 === 1 && !(i % 100 === 11) || f % 10 === 1 && !(f % 100 === 11))
921
                return Plural.One;
922
            if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
923
                !(i % 100 >= 12 && i % 100 <= 14) ||
924
                f % 10 === Math.floor(f % 10) && f % 10 >= 2 && f % 10 <= 4 &&
925
                    !(f % 100 >= 12 && f % 100 <= 14))
926
                return Plural.Few;
927
            return Plural.Other;
928
        case 'cs':
929
        case 'sk':
930
            if (i === 1 && v === 0)
931
                return Plural.One;
932
            if (i === Math.floor(i) && i >= 2 && i <= 4 && v === 0)
933
                return Plural.Few;
934
            if (!(v === 0))
935
                return Plural.Many;
936
            return Plural.Other;
937
        case 'cy':
938
            if (n === 0)
939
                return Plural.Zero;
940
            if (n === 1)
941
                return Plural.One;
942
            if (n === 2)
943
                return Plural.Two;
944
            if (n === 3)
945
                return Plural.Few;
946
            if (n === 6)
947
                return Plural.Many;
948
            return Plural.Other;
949
        case 'da':
950
            if (n === 1 || !(t === 0) && (i === 0 || i === 1))
951
                return Plural.One;
952
            return Plural.Other;
953
        case 'dsb':
954
        case 'hsb':
955
            if (v === 0 && i % 100 === 1 || f % 100 === 1)
956
                return Plural.One;
957
            if (v === 0 && i % 100 === 2 || f % 100 === 2)
958
                return Plural.Two;
959
            if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 ||
960
                f % 100 === Math.floor(f % 100) && f % 100 >= 3 && f % 100 <= 4)
961
                return Plural.Few;
962
            return Plural.Other;
963
        case 'ff':
964
        case 'fr':
965
        case 'hy':
966
        case 'kab':
967
            if (i === 0 || i === 1)
968
                return Plural.One;
969
            return Plural.Other;
970
        case 'fil':
971
            if (v === 0 && (i === 1 || i === 2 || i === 3) ||
972
                v === 0 && !(i % 10 === 4 || i % 10 === 6 || i % 10 === 9) ||
973
                !(v === 0) && !(f % 10 === 4 || f % 10 === 6 || f % 10 === 9))
974
                return Plural.One;
975
            return Plural.Other;
976
        case 'ga':
977
            if (n === 1)
978
                return Plural.One;
979
            if (n === 2)
980
                return Plural.Two;
981
            if (n === Math.floor(n) && n >= 3 && n <= 6)
982
                return Plural.Few;
983
            if (n === Math.floor(n) && n >= 7 && n <= 10)
984
                return Plural.Many;
985
            return Plural.Other;
986
        case 'gd':
987
            if (n === 1 || n === 11)
988
                return Plural.One;
989
            if (n === 2 || n === 12)
990
                return Plural.Two;
991
            if (n === Math.floor(n) && (n >= 3 && n <= 10 || n >= 13 && n <= 19))
992
                return Plural.Few;
993
            return Plural.Other;
994
        case 'gv':
995
            if (v === 0 && i % 10 === 1)
996
                return Plural.One;
997
            if (v === 0 && i % 10 === 2)
998
                return Plural.Two;
999
            if (v === 0 &&
1000
                (i % 100 === 0 || i % 100 === 20 || i % 100 === 40 || i % 100 === 60 || i % 100 === 80))
1001
                return Plural.Few;
1002
            if (!(v === 0))
1003
                return Plural.Many;
1004
            return Plural.Other;
1005
        case 'he':
1006
            if (i === 1 && v === 0)
1007
                return Plural.One;
1008
            if (i === 2 && v === 0)
1009
                return Plural.Two;
1010
            if (v === 0 && !(n >= 0 && n <= 10) && n % 10 === 0)
1011
                return Plural.Many;
1012
            return Plural.Other;
1013
        case 'is':
1014
            if (t === 0 && i % 10 === 1 && !(i % 100 === 11) || !(t === 0))
1015
                return Plural.One;
1016
            return Plural.Other;
1017
        case 'ksh':
1018
            if (n === 0)
1019
                return Plural.Zero;
1020
            if (n === 1)
1021
                return Plural.One;
1022
            return Plural.Other;
1023
        case 'kw':
1024
        case 'naq':
1025
        case 'se':
1026
        case 'smn':
1027
            if (n === 1)
1028
                return Plural.One;
1029
            if (n === 2)
1030
                return Plural.Two;
1031
            return Plural.Other;
1032
        case 'lag':
1033
            if (n === 0)
1034
                return Plural.Zero;
1035
            if ((i === 0 || i === 1) && !(n === 0))
1036
                return Plural.One;
1037
            return Plural.Other;
1038
        case 'lt':
1039
            if (n % 10 === 1 && !(n % 100 >= 11 && n % 100 <= 19))
1040
                return Plural.One;
1041
            if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 9 &&
1042
                !(n % 100 >= 11 && n % 100 <= 19))
1043
                return Plural.Few;
1044
            if (!(f === 0))
1045
                return Plural.Many;
1046
            return Plural.Other;
1047
        case 'lv':
1048
        case 'prg':
1049
            if (n % 10 === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19 ||
1050
                v === 2 && f % 100 === Math.floor(f % 100) && f % 100 >= 11 && f % 100 <= 19)
1051
                return Plural.Zero;
1052
            if (n % 10 === 1 && !(n % 100 === 11) || v === 2 && f % 10 === 1 && !(f % 100 === 11) ||
1053
                !(v === 2) && f % 10 === 1)
1054
                return Plural.One;
1055
            return Plural.Other;
1056
        case 'mk':
1057
            if (v === 0 && i % 10 === 1 || f % 10 === 1)
1058
                return Plural.One;
1059
            return Plural.Other;
1060
        case 'mt':
1061
            if (n === 1)
1062
                return Plural.One;
1063
            if (n === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 2 && n % 100 <= 10)
1064
                return Plural.Few;
1065
            if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19)
1066
                return Plural.Many;
1067
            return Plural.Other;
1068
        case 'pl':
1069
            if (i === 1 && v === 0)
1070
                return Plural.One;
1071
            if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
1072
                !(i % 100 >= 12 && i % 100 <= 14))
1073
                return Plural.Few;
1074
            if (v === 0 && !(i === 1) && i % 10 === Math.floor(i % 10) && i % 10 >= 0 && i % 10 <= 1 ||
1075
                v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 ||
1076
                v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 12 && i % 100 <= 14)
1077
                return Plural.Many;
1078
            return Plural.Other;
1079
        case 'pt':
1080
            if (n === Math.floor(n) && n >= 0 && n <= 2 && !(n === 2))
1081
                return Plural.One;
1082
            return Plural.Other;
1083
        case 'ro':
1084
            if (i === 1 && v === 0)
1085
                return Plural.One;
1086
            if (!(v === 0) || n === 0 ||
1087
                !(n === 1) && n % 100 === Math.floor(n % 100) && n % 100 >= 1 && n % 100 <= 19)
1088
                return Plural.Few;
1089
            return Plural.Other;
1090
        case 'ru':
1091
        case 'uk':
1092
            if (v === 0 && i % 10 === 1 && !(i % 100 === 11))
1093
                return Plural.One;
1094
            if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
1095
                !(i % 100 >= 12 && i % 100 <= 14))
1096
                return Plural.Few;
1097
            if (v === 0 && i % 10 === 0 ||
1098
                v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 ||
1099
                v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 11 && i % 100 <= 14)
1100
                return Plural.Many;
1101
            return Plural.Other;
1102
        case 'shi':
1103
            if (i === 0 || n === 1)
1104
                return Plural.One;
1105
            if (n === Math.floor(n) && n >= 2 && n <= 10)
1106
                return Plural.Few;
1107
            return Plural.Other;
1108
        case 'si':
1109
            if (n === 0 || n === 1 || i === 0 && f === 1)
1110
                return Plural.One;
1111
            return Plural.Other;
1112
        case 'sl':
1113
            if (v === 0 && i % 100 === 1)
1114
                return Plural.One;
1115
            if (v === 0 && i % 100 === 2)
1116
                return Plural.Two;
1117
            if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 || !(v === 0))
1118
                return Plural.Few;
1119
            return Plural.Other;
1120
        case 'tzm':
1121
            if (n === Math.floor(n) && n >= 0 && n <= 1 || n === Math.floor(n) && n >= 11 && n <= 99)
1122
                return Plural.One;
1123
            return Plural.Other;
1124
        // When there is no specification, the default is always "other"
1125
        // Spec: http://cldr.unicode.org/index/cldr-spec/plural-rules
1126
        // > other (required—general plural form — also used if the language only has a single form)
1127
        default:
1128
            return Plural.Other;
1129
    }
1130
}
1131

    
1132
/**
1133
 * @license
1134
 * Copyright Google Inc. All Rights Reserved.
1135
 *
1136
 * Use of this source code is governed by an MIT-style license that can be
1137
 * found in the LICENSE file at https://angular.io/license
1138
 * @param {?} cookieStr
1139
 * @param {?} name
1140
 * @return {?}
1141
 */
1142
function parseCookieValue(cookieStr, name) {
1143
    name = encodeURIComponent(name);
1144
    for (const /** @type {?} */ cookie of cookieStr.split(';')) {
1145
        const /** @type {?} */ eqIndex = cookie.indexOf('=');
1146
        const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];
1147
        if (cookieName.trim() === name) {
1148
            return decodeURIComponent(cookieValue);
1149
        }
1150
    }
1151
    return null;
1152
}
1153

    
1154
/**
1155
 * @license
1156
 * Copyright Google Inc. All Rights Reserved.
1157
 *
1158
 * Use of this source code is governed by an MIT-style license that can be
1159
 * found in the LICENSE file at https://angular.io/license
1160
 */
1161
/**
1162
 * \@ngModule CommonModule
1163
 *
1164
 * \@whatItDoes Adds and removes CSS classes on an HTML element.
1165
 *
1166
 * \@howToUse
1167
 * ```
1168
 *     <some-element [ngClass]="'first second'">...</some-element>
1169
 *
1170
 *     <some-element [ngClass]="['first', 'second']">...</some-element>
1171
 *
1172
 *     <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
1173
 *
1174
 *     <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
1175
 *
1176
 *     <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
1177
 * ```
1178
 *
1179
 * \@description
1180
 *
1181
 * The CSS classes are updated as follows, depending on the type of the expression evaluation:
1182
 * - `string` - the CSS classes listed in the string (space delimited) are added,
1183
 * - `Array` - the CSS classes declared as Array elements are added,
1184
 * - `Object` - keys are CSS classes that get added when the expression given in the value
1185
 *              evaluates to a truthy value, otherwise they are removed.
1186
 *
1187
 * \@stable
1188
 */
1189
class NgClass {
1190
    /**
1191
     * @param {?} _iterableDiffers
1192
     * @param {?} _keyValueDiffers
1193
     * @param {?} _ngEl
1194
     * @param {?} _renderer
1195
     */
1196
    constructor(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) {
1197
        this._iterableDiffers = _iterableDiffers;
1198
        this._keyValueDiffers = _keyValueDiffers;
1199
        this._ngEl = _ngEl;
1200
        this._renderer = _renderer;
1201
        this._initialClasses = [];
1202
    }
1203
    /**
1204
     * @param {?} v
1205
     * @return {?}
1206
     */
1207
    set klass(v) {
1208
        this._applyInitialClasses(true);
1209
        this._initialClasses = typeof v === 'string' ? v.split(/\s+/) : [];
1210
        this._applyInitialClasses(false);
1211
        this._applyClasses(this._rawClass, false);
1212
    }
1213
    /**
1214
     * @param {?} v
1215
     * @return {?}
1216
     */
1217
    set ngClass(v) {
1218
        this._cleanupClasses(this._rawClass);
1219
        this._iterableDiffer = null;
1220
        this._keyValueDiffer = null;
1221
        this._rawClass = typeof v === 'string' ? v.split(/\s+/) : v;
1222
        if (this._rawClass) {
1223
            if (ɵisListLikeIterable(this._rawClass)) {
1224
                this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create();
1225
            }
1226
            else {
1227
                this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create();
1228
            }
1229
        }
1230
    }
1231
    /**
1232
     * @return {?}
1233
     */
1234
    ngDoCheck() {
1235
        if (this._iterableDiffer) {
1236
            const /** @type {?} */ iterableChanges = this._iterableDiffer.diff(/** @type {?} */ (this._rawClass));
1237
            if (iterableChanges) {
1238
                this._applyIterableChanges(iterableChanges);
1239
            }
1240
        }
1241
        else if (this._keyValueDiffer) {
1242
            const /** @type {?} */ keyValueChanges = this._keyValueDiffer.diff(/** @type {?} */ (this._rawClass));
1243
            if (keyValueChanges) {
1244
                this._applyKeyValueChanges(keyValueChanges);
1245
            }
1246
        }
1247
    }
1248
    /**
1249
     * @param {?} rawClassVal
1250
     * @return {?}
1251
     */
1252
    _cleanupClasses(rawClassVal) {
1253
        this._applyClasses(rawClassVal, true);
1254
        this._applyInitialClasses(false);
1255
    }
1256
    /**
1257
     * @param {?} changes
1258
     * @return {?}
1259
     */
1260
    _applyKeyValueChanges(changes) {
1261
        changes.forEachAddedItem((record) => this._toggleClass(record.key, record.currentValue));
1262
        changes.forEachChangedItem((record) => this._toggleClass(record.key, record.currentValue));
1263
        changes.forEachRemovedItem((record) => {
1264
            if (record.previousValue) {
1265
                this._toggleClass(record.key, false);
1266
            }
1267
        });
1268
    }
1269
    /**
1270
     * @param {?} changes
1271
     * @return {?}
1272
     */
1273
    _applyIterableChanges(changes) {
1274
        changes.forEachAddedItem((record) => {
1275
            if (typeof record.item === 'string') {
1276
                this._toggleClass(record.item, true);
1277
            }
1278
            else {
1279
                throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${ɵstringify(record.item)}`);
1280
            }
1281
        });
1282
        changes.forEachRemovedItem((record) => this._toggleClass(record.item, false));
1283
    }
1284
    /**
1285
     * @param {?} isCleanup
1286
     * @return {?}
1287
     */
1288
    _applyInitialClasses(isCleanup) {
1289
        this._initialClasses.forEach(klass => this._toggleClass(klass, !isCleanup));
1290
    }
1291
    /**
1292
     * @param {?} rawClassVal
1293
     * @param {?} isCleanup
1294
     * @return {?}
1295
     */
1296
    _applyClasses(rawClassVal, isCleanup) {
1297
        if (rawClassVal) {
1298
            if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
1299
                ((rawClassVal)).forEach((klass) => this._toggleClass(klass, !isCleanup));
1300
            }
1301
            else {
1302
                Object.keys(rawClassVal).forEach(klass => {
1303
                    if (rawClassVal[klass] != null)
1304
                        this._toggleClass(klass, !isCleanup);
1305
                });
1306
            }
1307
        }
1308
    }
1309
    /**
1310
     * @param {?} klass
1311
     * @param {?} enabled
1312
     * @return {?}
1313
     */
1314
    _toggleClass(klass, enabled) {
1315
        klass = klass.trim();
1316
        if (klass) {
1317
            klass.split(/\s+/g).forEach(klass => { this._renderer.setElementClass(this._ngEl.nativeElement, klass, !!enabled); });
1318
        }
1319
    }
1320
}
1321
NgClass.decorators = [
1322
    { type: Directive, args: [{ selector: '[ngClass]' },] },
1323
];
1324
/**
1325
 * @nocollapse
1326
 */
1327
NgClass.ctorParameters = () => [
1328
    { type: IterableDiffers, },
1329
    { type: KeyValueDiffers, },
1330
    { type: ElementRef, },
1331
    { type: Renderer, },
1332
];
1333
NgClass.propDecorators = {
1334
    'klass': [{ type: Input, args: ['class',] },],
1335
    'ngClass': [{ type: Input },],
1336
};
1337

    
1338
/**
1339
 * @license
1340
 * Copyright Google Inc. All Rights Reserved.
1341
 *
1342
 * Use of this source code is governed by an MIT-style license that can be
1343
 * found in the LICENSE file at https://angular.io/license
1344
 */
1345
/**
1346
 * Instantiates a single {\@link Component} type and inserts its Host View into current View.
1347
 * `NgComponentOutlet` provides a declarative approach for dynamic component creation.
1348
 *
1349
 * `NgComponentOutlet` requires a component type, if a falsy value is set the view will clear and
1350
 * any existing component will get destroyed.
1351
 *
1352
 * ### Fine tune control
1353
 *
1354
 * You can control the component creation process by using the following optional attributes:
1355
 *
1356
 * * `ngComponentOutletInjector`: Optional custom {\@link Injector} that will be used as parent for
1357
 * the Component. Defaults to the injector of the current view container.
1358
 *
1359
 * * `ngComponentOutletContent`: Optional list of projectable nodes to insert into the content
1360
 * section of the component, if exists.
1361
 *
1362
 * * `ngComponentOutletNgModuleFactory`: Optional module factory to allow dynamically loading other
1363
 * module, then load a component from that module.
1364
 *
1365
 * ### Syntax
1366
 *
1367
 * Simple
1368
 * ```
1369
 * <ng-container *ngComponentOutlet="componentTypeExpression"></ng-container>
1370
 * ```
1371
 *
1372
 * Customized injector/content
1373
 * ```
1374
 * <ng-container *ngComponentOutlet="componentTypeExpression;
1375
 *                                   injector: injectorExpression;
1376
 *                                   content: contentNodesExpression;">
1377
 * </ng-container>
1378
 * ```
1379
 *
1380
 * Customized ngModuleFactory
1381
 * ```
1382
 * <ng-container *ngComponentOutlet="componentTypeExpression;
1383
 *                                   ngModuleFactory: moduleFactory;">
1384
 * </ng-container>
1385
 * ```
1386
 * ## Example
1387
 *
1388
 * {\@example common/ngComponentOutlet/ts/module.ts region='SimpleExample'}
1389
 *
1390
 * A more complete example with additional options:
1391
 *
1392
 * {\@example common/ngComponentOutlet/ts/module.ts region='CompleteExample'}
1393
 * A more complete example with ngModuleFactory:
1394
 *
1395
 * {\@example common/ngComponentOutlet/ts/module.ts region='NgModuleFactoryExample'}
1396
 *
1397
 * \@experimental
1398
 */
1399
class NgComponentOutlet {
1400
    /**
1401
     * @param {?} _viewContainerRef
1402
     */
1403
    constructor(_viewContainerRef) {
1404
        this._viewContainerRef = _viewContainerRef;
1405
        this._componentRef = null;
1406
        this._moduleRef = null;
1407
    }
1408
    /**
1409
     * @param {?} changes
1410
     * @return {?}
1411
     */
1412
    ngOnChanges(changes) {
1413
        this._viewContainerRef.clear();
1414
        this._componentRef = null;
1415
        if (this.ngComponentOutlet) {
1416
            const /** @type {?} */ elInjector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
1417
            if (changes['ngComponentOutletNgModuleFactory']) {
1418
                if (this._moduleRef)
1419
                    this._moduleRef.destroy();
1420
                if (this.ngComponentOutletNgModuleFactory) {
1421
                    const /** @type {?} */ parentModule = elInjector.get(NgModuleRef);
1422
                    this._moduleRef = this.ngComponentOutletNgModuleFactory.create(parentModule.injector);
1423
                }
1424
                else {
1425
                    this._moduleRef = null;
1426
                }
1427
            }
1428
            const /** @type {?} */ componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver :
1429
                elInjector.get(ComponentFactoryResolver);
1430
            const /** @type {?} */ componentFactory = componentFactoryResolver.resolveComponentFactory(this.ngComponentOutlet);
1431
            this._componentRef = this._viewContainerRef.createComponent(componentFactory, this._viewContainerRef.length, elInjector, this.ngComponentOutletContent);
1432
        }
1433
    }
1434
    /**
1435
     * @return {?}
1436
     */
1437
    ngOnDestroy() {
1438
        if (this._moduleRef)
1439
            this._moduleRef.destroy();
1440
    }
1441
}
1442
NgComponentOutlet.decorators = [
1443
    { type: Directive, args: [{ selector: '[ngComponentOutlet]' },] },
1444
];
1445
/**
1446
 * @nocollapse
1447
 */
1448
NgComponentOutlet.ctorParameters = () => [
1449
    { type: ViewContainerRef, },
1450
];
1451
NgComponentOutlet.propDecorators = {
1452
    'ngComponentOutlet': [{ type: Input },],
1453
    'ngComponentOutletInjector': [{ type: Input },],
1454
    'ngComponentOutletContent': [{ type: Input },],
1455
    'ngComponentOutletNgModuleFactory': [{ type: Input },],
1456
};
1457

    
1458
/**
1459
 * @license
1460
 * Copyright Google Inc. All Rights Reserved.
1461
 *
1462
 * Use of this source code is governed by an MIT-style license that can be
1463
 * found in the LICENSE file at https://angular.io/license
1464
 */
1465
/**
1466
 * \@stable
1467
 */
1468
class NgForOfContext {
1469
    /**
1470
     * @param {?} $implicit
1471
     * @param {?} ngForOf
1472
     * @param {?} index
1473
     * @param {?} count
1474
     */
1475
    constructor($implicit, ngForOf, index, count) {
1476
        this.$implicit = $implicit;
1477
        this.ngForOf = ngForOf;
1478
        this.index = index;
1479
        this.count = count;
1480
    }
1481
    /**
1482
     * @return {?}
1483
     */
1484
    get first() { return this.index === 0; }
1485
    /**
1486
     * @return {?}
1487
     */
1488
    get last() { return this.index === this.count - 1; }
1489
    /**
1490
     * @return {?}
1491
     */
1492
    get even() { return this.index % 2 === 0; }
1493
    /**
1494
     * @return {?}
1495
     */
1496
    get odd() { return !this.even; }
1497
}
1498
/**
1499
 * The `NgForOf` directive instantiates a template once per item from an iterable. The context
1500
 * for each instantiated template inherits from the outer context with the given loop variable
1501
 * set to the current item from the iterable.
1502
 *
1503
 * ### Local Variables
1504
 *
1505
 * `NgForOf` provides several exported values that can be aliased to local variables:
1506
 *
1507
 * - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
1508
 * - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is
1509
 * more complex then a property access, for example when using the async pipe (`userStreams |
1510
 * async`).
1511
 * - `index: number`: The index of the current item in the iterable.
1512
 * - `first: boolean`: True when the item is the first item in the iterable.
1513
 * - `last: boolean`: True when the item is the last item in the iterable.
1514
 * - `even: boolean`: True when the item has an even index in the iterable.
1515
 * - `odd: boolean`: True when the item has an odd index in the iterable.
1516
 *
1517
 * ```
1518
 * <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
1519
 *    {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
1520
 * </li>
1521
 * ```
1522
 *
1523
 * ### Change Propagation
1524
 *
1525
 * When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
1526
 *
1527
 * * When an item is added, a new instance of the template is added to the DOM.
1528
 * * When an item is removed, its template instance is removed from the DOM.
1529
 * * When items are reordered, their respective templates are reordered in the DOM.
1530
 * * Otherwise, the DOM element for that item will remain the same.
1531
 *
1532
 * Angular uses object identity to track insertions and deletions within the iterator and reproduce
1533
 * those changes in the DOM. This has important implications for animations and any stateful
1534
 * controls (such as `<input>` elements which accept user input) that are present. Inserted rows can
1535
 * be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
1536
 * such as user input.
1537
 *
1538
 * It is possible for the identities of elements in the iterator to change while the data does not.
1539
 * This can happen, for example, if the iterator produced from an RPC to the server, and that
1540
 * RPC is re-run. Even if the data hasn't changed, the second response will produce objects with
1541
 * different identities, and Angular will tear down the entire DOM and rebuild it (as if all old
1542
 * elements were deleted and all new elements inserted). This is an expensive operation and should
1543
 * be avoided if possible.
1544
 *
1545
 * To customize the default tracking algorithm, `NgForOf` supports `trackBy` option.
1546
 * `trackBy` takes a function which has two arguments: `index` and `item`.
1547
 * If `trackBy` is given, Angular tracks changes by the return value of the function.
1548
 *
1549
 * ### Syntax
1550
 *
1551
 * - `<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>`
1552
 * - `<li template="ngFor let item of items; index as i; trackBy: trackByFn">...</li>`
1553
 *
1554
 * With `<ng-template>` element:
1555
 *
1556
 * ```
1557
 * <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
1558
 *   <li>...</li>
1559
 * </ng-template>
1560
 * ```
1561
 *
1562
 * ### Example
1563
 *
1564
 * See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
1565
 * example.
1566
 *
1567
 * \@stable
1568
 */
1569
class NgForOf {
1570
    /**
1571
     * @param {?} _viewContainer
1572
     * @param {?} _template
1573
     * @param {?} _differs
1574
     */
1575
    constructor(_viewContainer, _template, _differs) {
1576
        this._viewContainer = _viewContainer;
1577
        this._template = _template;
1578
        this._differs = _differs;
1579
        this._differ = null;
1580
    }
1581
    /**
1582
     * @param {?} fn
1583
     * @return {?}
1584
     */
1585
    set ngForTrackBy(fn) {
1586
        if (isDevMode() && fn != null && typeof fn !== 'function') {
1587
            // TODO(vicb): use a log service once there is a public one available
1588
            if ((console) && (console.warn)) {
1589
                console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
1590
                    `See https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#change-propagation for more information.`);
1591
            }
1592
        }
1593
        this._trackByFn = fn;
1594
    }
1595
    /**
1596
     * @return {?}
1597
     */
1598
    get ngForTrackBy() { return this._trackByFn; }
1599
    /**
1600
     * @param {?} value
1601
     * @return {?}
1602
     */
1603
    set ngForTemplate(value) {
1604
        // TODO(TS2.1): make TemplateRef<Partial<NgForRowOf<T>>> once we move to TS v2.1
1605
        // The current type is too restrictive; a template that just uses index, for example,
1606
        // should be acceptable.
1607
        if (value) {
1608
            this._template = value;
1609
        }
1610
    }
1611
    /**
1612
     * @param {?} changes
1613
     * @return {?}
1614
     */
1615
    ngOnChanges(changes) {
1616
        if ('ngForOf' in changes) {
1617
            // React on ngForOf changes only once all inputs have been initialized
1618
            const /** @type {?} */ value = changes['ngForOf'].currentValue;
1619
            if (!this._differ && value) {
1620
                try {
1621
                    this._differ = this._differs.find(value).create(this.ngForTrackBy);
1622
                }
1623
                catch (e) {
1624
                    throw new Error(`Cannot find a differ supporting object '${value}' of type '${getTypeNameForDebugging(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
1625
                }
1626
            }
1627
        }
1628
    }
1629
    /**
1630
     * @return {?}
1631
     */
1632
    ngDoCheck() {
1633
        if (this._differ) {
1634
            const /** @type {?} */ changes = this._differ.diff(this.ngForOf);
1635
            if (changes)
1636
                this._applyChanges(changes);
1637
        }
1638
    }
1639
    /**
1640
     * @param {?} changes
1641
     * @return {?}
1642
     */
1643
    _applyChanges(changes) {
1644
        const /** @type {?} */ insertTuples = [];
1645
        changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
1646
            if (item.previousIndex == null) {
1647
                const /** @type {?} */ view = this._viewContainer.createEmbeddedView(this._template, new NgForOfContext(/** @type {?} */ ((null)), this.ngForOf, -1, -1), currentIndex);
1648
                const /** @type {?} */ tuple = new RecordViewTuple(item, view);
1649
                insertTuples.push(tuple);
1650
            }
1651
            else if (currentIndex == null) {
1652
                this._viewContainer.remove(adjustedPreviousIndex);
1653
            }
1654
            else {
1655
                const /** @type {?} */ view = ((this._viewContainer.get(adjustedPreviousIndex)));
1656
                this._viewContainer.move(view, currentIndex);
1657
                const /** @type {?} */ tuple = new RecordViewTuple(item, /** @type {?} */ (view));
1658
                insertTuples.push(tuple);
1659
            }
1660
        });
1661
        for (let /** @type {?} */ i = 0; i < insertTuples.length; i++) {
1662
            this._perViewChange(insertTuples[i].view, insertTuples[i].record);
1663
        }
1664
        for (let /** @type {?} */ i = 0, /** @type {?} */ ilen = this._viewContainer.length; i < ilen; i++) {
1665
            const /** @type {?} */ viewRef = (this._viewContainer.get(i));
1666
            viewRef.context.index = i;
1667
            viewRef.context.count = ilen;
1668
        }
1669
        changes.forEachIdentityChange((record) => {
1670
            const /** @type {?} */ viewRef = (this._viewContainer.get(record.currentIndex));
1671
            viewRef.context.$implicit = record.item;
1672
        });
1673
    }
1674
    /**
1675
     * @param {?} view
1676
     * @param {?} record
1677
     * @return {?}
1678
     */
1679
    _perViewChange(view, record) {
1680
        view.context.$implicit = record.item;
1681
    }
1682
}
1683
NgForOf.decorators = [
1684
    { type: Directive, args: [{ selector: '[ngFor][ngForOf]' },] },
1685
];
1686
/**
1687
 * @nocollapse
1688
 */
1689
NgForOf.ctorParameters = () => [
1690
    { type: ViewContainerRef, },
1691
    { type: TemplateRef, },
1692
    { type: IterableDiffers, },
1693
];
1694
NgForOf.propDecorators = {
1695
    'ngForOf': [{ type: Input },],
1696
    'ngForTrackBy': [{ type: Input },],
1697
    'ngForTemplate': [{ type: Input },],
1698
};
1699
class RecordViewTuple {
1700
    /**
1701
     * @param {?} record
1702
     * @param {?} view
1703
     */
1704
    constructor(record, view) {
1705
        this.record = record;
1706
        this.view = view;
1707
    }
1708
}
1709
/**
1710
 * @deprecated from v4.0.0 - Use NgForOf instead.
1711
 */
1712
const NgFor = NgForOf;
1713
/**
1714
 * @param {?} type
1715
 * @return {?}
1716
 */
1717
function getTypeNameForDebugging(type) {
1718
    return type['name'] || typeof type;
1719
}
1720

    
1721
/**
1722
 * @license
1723
 * Copyright Google Inc. All Rights Reserved.
1724
 *
1725
 * Use of this source code is governed by an MIT-style license that can be
1726
 * found in the LICENSE file at https://angular.io/license
1727
 */
1728
/**
1729
 * Conditionally includes a template based on the value of an `expression`.
1730
 *
1731
 * `ngIf` evaluates the `expression` and then renders the `then` or `else` template in its place
1732
 * when expression is truthy or falsy respectively. Typically the:
1733
 *  - `then` template is the inline template of `ngIf` unless bound to a different value.
1734
 *  - `else` template is blank unless it is bound.
1735
 *
1736
 * ## Most common usage
1737
 *
1738
 * The most common usage of the `ngIf` directive is to conditionally show the inline template as
1739
 * seen in this example:
1740
 * {\@example common/ngIf/ts/module.ts region='NgIfSimple'}
1741
 *
1742
 * ## Showing an alternative template using `else`
1743
 *
1744
 * If it is necessary to display a template when the `expression` is falsy use the `else` template
1745
 * binding as shown. Note that the `else` binding points to a `<ng-template>` labeled `#elseBlock`.
1746
 * The template can be defined anywhere in the component view but is typically placed right after
1747
 * `ngIf` for readability.
1748
 *
1749
 * {\@example common/ngIf/ts/module.ts region='NgIfElse'}
1750
 *
1751
 * ## Using non-inlined `then` template
1752
 *
1753
 * Usually the `then` template is the inlined template of the `ngIf`, but it can be changed using
1754
 * a binding (just like `else`). Because `then` and `else` are bindings, the template references can
1755
 * change at runtime as shown in this example.
1756
 *
1757
 * {\@example common/ngIf/ts/module.ts region='NgIfThenElse'}
1758
 *
1759
 * ## Storing conditional result in a variable
1760
 *
1761
 * A common pattern is that we need to show a set of properties from the same object. If the
1762
 * object is undefined, then we have to use the safe-traversal-operator `?.` to guard against
1763
 * dereferencing a `null` value. This is especially the case when waiting on async data such as
1764
 * when using the `async` pipe as shown in following example:
1765
 *
1766
 * ```
1767
 * Hello {{ (userStream|async)?.last }}, {{ (userStream|async)?.first }}!
1768
 * ```
1769
 *
1770
 * There are several inefficiencies in the above example:
1771
 *  - We create multiple subscriptions on `userStream`. One for each `async` pipe, or two in the
1772
 *    example above.
1773
 *  - We cannot display an alternative screen while waiting for the data to arrive asynchronously.
1774
 *  - We have to use the safe-traversal-operator `?.` to access properties, which is cumbersome.
1775
 *  - We have to place the `async` pipe in parenthesis.
1776
 *
1777
 * A better way to do this is to use `ngIf` and store the result of the condition in a local
1778
 * variable as shown in the the example below:
1779
 *
1780
 * {\@example common/ngIf/ts/module.ts region='NgIfAs'}
1781
 *
1782
 * Notice that:
1783
 *  - We use only one `async` pipe and hence only one subscription gets created.
1784
 *  - `ngIf` stores the result of the `userStream|async` in the local variable `user`.
1785
 *  - The local `user` can then be bound repeatedly in a more efficient way.
1786
 *  - No need to use the safe-traversal-operator `?.` to access properties as `ngIf` will only
1787
 *    display the data if `userStream` returns a value.
1788
 *  - We can display an alternative template while waiting for the data.
1789
 *
1790
 * ### Syntax
1791
 *
1792
 * Simple form:
1793
 * - `<div *ngIf="condition">...</div>`
1794
 * - `<div template="ngIf condition">...</div>`
1795
 * - `<ng-template [ngIf]="condition"><div>...</div></ng-template>`
1796
 *
1797
 * Form with an else block:
1798
 * ```
1799
 * <div *ngIf="condition; else elseBlock">...</div>
1800
 * <ng-template #elseBlock>...</ng-template>
1801
 * ```
1802
 *
1803
 * Form with a `then` and `else` block:
1804
 * ```
1805
 * <div *ngIf="condition; then thenBlock else elseBlock"></div>
1806
 * <ng-template #thenBlock>...</ng-template>
1807
 * <ng-template #elseBlock>...</ng-template>
1808
 * ```
1809
 *
1810
 * Form with storing the value locally:
1811
 * ```
1812
 * <div *ngIf="condition as value; else elseBlock">{{value}}</div>
1813
 * <ng-template #elseBlock>...</ng-template>
1814
 * ```
1815
 *
1816
 * \@stable
1817
 */
1818
class NgIf {
1819
    /**
1820
     * @param {?} _viewContainer
1821
     * @param {?} templateRef
1822
     */
1823
    constructor(_viewContainer, templateRef) {
1824
        this._viewContainer = _viewContainer;
1825
        this._context = new NgIfContext();
1826
        this._thenTemplateRef = null;
1827
        this._elseTemplateRef = null;
1828
        this._thenViewRef = null;
1829
        this._elseViewRef = null;
1830
        this._thenTemplateRef = templateRef;
1831
    }
1832
    /**
1833
     * @param {?} condition
1834
     * @return {?}
1835
     */
1836
    set ngIf(condition) {
1837
        this._context.$implicit = this._context.ngIf = condition;
1838
        this._updateView();
1839
    }
1840
    /**
1841
     * @param {?} templateRef
1842
     * @return {?}
1843
     */
1844
    set ngIfThen(templateRef) {
1845
        this._thenTemplateRef = templateRef;
1846
        this._thenViewRef = null; // clear previous view if any.
1847
        this._updateView();
1848
    }
1849
    /**
1850
     * @param {?} templateRef
1851
     * @return {?}
1852
     */
1853
    set ngIfElse(templateRef) {
1854
        this._elseTemplateRef = templateRef;
1855
        this._elseViewRef = null; // clear previous view if any.
1856
        this._updateView();
1857
    }
1858
    /**
1859
     * @return {?}
1860
     */
1861
    _updateView() {
1862
        if (this._context.$implicit) {
1863
            if (!this._thenViewRef) {
1864
                this._viewContainer.clear();
1865
                this._elseViewRef = null;
1866
                if (this._thenTemplateRef) {
1867
                    this._thenViewRef =
1868
                        this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
1869
                }
1870
            }
1871
        }
1872
        else {
1873
            if (!this._elseViewRef) {
1874
                this._viewContainer.clear();
1875
                this._thenViewRef = null;
1876
                if (this._elseTemplateRef) {
1877
                    this._elseViewRef =
1878
                        this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
1879
                }
1880
            }
1881
        }
1882
    }
1883
}
1884
NgIf.decorators = [
1885
    { type: Directive, args: [{ selector: '[ngIf]' },] },
1886
];
1887
/**
1888
 * @nocollapse
1889
 */
1890
NgIf.ctorParameters = () => [
1891
    { type: ViewContainerRef, },
1892
    { type: TemplateRef, },
1893
];
1894
NgIf.propDecorators = {
1895
    'ngIf': [{ type: Input },],
1896
    'ngIfThen': [{ type: Input },],
1897
    'ngIfElse': [{ type: Input },],
1898
};
1899
/**
1900
 * \@stable
1901
 */
1902
class NgIfContext {
1903
    constructor() {
1904
        this.$implicit = null;
1905
        this.ngIf = null;
1906
    }
1907
}
1908

    
1909
/**
1910
 * @license
1911
 * Copyright Google Inc. All Rights Reserved.
1912
 *
1913
 * Use of this source code is governed by an MIT-style license that can be
1914
 * found in the LICENSE file at https://angular.io/license
1915
 */
1916
class SwitchView {
1917
    /**
1918
     * @param {?} _viewContainerRef
1919
     * @param {?} _templateRef
1920
     */
1921
    constructor(_viewContainerRef, _templateRef) {
1922
        this._viewContainerRef = _viewContainerRef;
1923
        this._templateRef = _templateRef;
1924
        this._created = false;
1925
    }
1926
    /**
1927
     * @return {?}
1928
     */
1929
    create() {
1930
        this._created = true;
1931
        this._viewContainerRef.createEmbeddedView(this._templateRef);
1932
    }
1933
    /**
1934
     * @return {?}
1935
     */
1936
    destroy() {
1937
        this._created = false;
1938
        this._viewContainerRef.clear();
1939
    }
1940
    /**
1941
     * @param {?} created
1942
     * @return {?}
1943
     */
1944
    enforceState(created) {
1945
        if (created && !this._created) {
1946
            this.create();
1947
        }
1948
        else if (!created && this._created) {
1949
            this.destroy();
1950
        }
1951
    }
1952
}
1953
/**
1954
 * \@ngModule CommonModule
1955
 *
1956
 * \@whatItDoes Adds / removes DOM sub-trees when the nest match expressions matches the switch
1957
 *             expression.
1958
 *
1959
 * \@howToUse
1960
 * ```
1961
 *     <container-element [ngSwitch]="switch_expression">
1962
 *       <some-element *ngSwitchCase="match_expression_1">...</some-element>
1963
 *       <some-element *ngSwitchCase="match_expression_2">...</some-element>
1964
 *       <some-other-element *ngSwitchCase="match_expression_3">...</some-other-element>
1965
 *       <ng-container *ngSwitchCase="match_expression_3">
1966
 *         <!-- use a ng-container to group multiple root nodes -->
1967
 *         <inner-element></inner-element>
1968
 *         <inner-other-element></inner-other-element>
1969
 *       </ng-container>
1970
 *       <some-element *ngSwitchDefault>...</some-element>
1971
 *     </container-element>
1972
 * ```
1973
 * \@description
1974
 *
1975
 * `NgSwitch` stamps out nested views when their match expression value matches the value of the
1976
 * switch expression.
1977
 *
1978
 * In other words:
1979
 * - you define a container element (where you place the directive with a switch expression on the
1980
 * `[ngSwitch]="..."` attribute)
1981
 * - you define inner views inside the `NgSwitch` and place a `*ngSwitchCase` attribute on the view
1982
 * root elements.
1983
 *
1984
 * Elements within `NgSwitch` but outside of a `NgSwitchCase` or `NgSwitchDefault` directives will
1985
 * be preserved at the location.
1986
 *
1987
 * The `ngSwitchCase` directive informs the parent `NgSwitch` of which view to display when the
1988
 * expression is evaluated.
1989
 * When no matching expression is found on a `ngSwitchCase` view, the `ngSwitchDefault` view is
1990
 * stamped out.
1991
 *
1992
 * \@stable
1993
 */
1994
class NgSwitch {
1995
    constructor() {
1996
        this._defaultUsed = false;
1997
        this._caseCount = 0;
1998
        this._lastCaseCheckIndex = 0;
1999
        this._lastCasesMatched = false;
2000
    }
2001
    /**
2002
     * @param {?} newValue
2003
     * @return {?}
2004
     */
2005
    set ngSwitch(newValue) {
2006
        this._ngSwitch = newValue;
2007
        if (this._caseCount === 0) {
2008
            this._updateDefaultCases(true);
2009
        }
2010
    }
2011
    /**
2012
     * \@internal
2013
     * @return {?}
2014
     */
2015
    _addCase() { return this._caseCount++; }
2016
    /**
2017
     * \@internal
2018
     * @param {?} view
2019
     * @return {?}
2020
     */
2021
    _addDefault(view) {
2022
        if (!this._defaultViews) {
2023
            this._defaultViews = [];
2024
        }
2025
        this._defaultViews.push(view);
2026
    }
2027
    /**
2028
     * \@internal
2029
     * @param {?} value
2030
     * @return {?}
2031
     */
2032
    _matchCase(value) {
2033
        const /** @type {?} */ matched = value == this._ngSwitch;
2034
        this._lastCasesMatched = this._lastCasesMatched || matched;
2035
        this._lastCaseCheckIndex++;
2036
        if (this._lastCaseCheckIndex === this._caseCount) {
2037
            this._updateDefaultCases(!this._lastCasesMatched);
2038
            this._lastCaseCheckIndex = 0;
2039
            this._lastCasesMatched = false;
2040
        }
2041
        return matched;
2042
    }
2043
    /**
2044
     * @param {?} useDefault
2045
     * @return {?}
2046
     */
2047
    _updateDefaultCases(useDefault) {
2048
        if (this._defaultViews && useDefault !== this._defaultUsed) {
2049
            this._defaultUsed = useDefault;
2050
            for (let /** @type {?} */ i = 0; i < this._defaultViews.length; i++) {
2051
                const /** @type {?} */ defaultView = this._defaultViews[i];
2052
                defaultView.enforceState(useDefault);
2053
            }
2054
        }
2055
    }
2056
}
2057
NgSwitch.decorators = [
2058
    { type: Directive, args: [{ selector: '[ngSwitch]' },] },
2059
];
2060
/**
2061
 * @nocollapse
2062
 */
2063
NgSwitch.ctorParameters = () => [];
2064
NgSwitch.propDecorators = {
2065
    'ngSwitch': [{ type: Input },],
2066
};
2067
/**
2068
 * \@ngModule CommonModule
2069
 *
2070
 * \@whatItDoes Creates a view that will be added/removed from the parent {\@link NgSwitch} when the
2071
 *             given expression evaluate to respectively the same/different value as the switch
2072
 *             expression.
2073
 *
2074
 * \@howToUse
2075
 * ```
2076
 * <container-element [ngSwitch]="switch_expression">
2077
 *   <some-element *ngSwitchCase="match_expression_1">...</some-element>
2078
 * </container-element>
2079
 * ```
2080
 * \@description
2081
 *
2082
 * Insert the sub-tree when the expression evaluates to the same value as the enclosing switch
2083
 * expression.
2084
 *
2085
 * If multiple match expressions match the switch expression value, all of them are displayed.
2086
 *
2087
 * See {\@link NgSwitch} for more details and example.
2088
 *
2089
 * \@stable
2090
 */
2091
class NgSwitchCase {
2092
    /**
2093
     * @param {?} viewContainer
2094
     * @param {?} templateRef
2095
     * @param {?} ngSwitch
2096
     */
2097
    constructor(viewContainer, templateRef, ngSwitch) {
2098
        this.ngSwitch = ngSwitch;
2099
        ngSwitch._addCase();
2100
        this._view = new SwitchView(viewContainer, templateRef);
2101
    }
2102
    /**
2103
     * @return {?}
2104
     */
2105
    ngDoCheck() { this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase)); }
2106
}
2107
NgSwitchCase.decorators = [
2108
    { type: Directive, args: [{ selector: '[ngSwitchCase]' },] },
2109
];
2110
/**
2111
 * @nocollapse
2112
 */
2113
NgSwitchCase.ctorParameters = () => [
2114
    { type: ViewContainerRef, },
2115
    { type: TemplateRef, },
2116
    { type: NgSwitch, decorators: [{ type: Host },] },
2117
];
2118
NgSwitchCase.propDecorators = {
2119
    'ngSwitchCase': [{ type: Input },],
2120
};
2121
/**
2122
 * \@ngModule CommonModule
2123
 * \@whatItDoes Creates a view that is added to the parent {\@link NgSwitch} when no case expressions
2124
 * match the
2125
 *             switch expression.
2126
 *
2127
 * \@howToUse
2128
 * ```
2129
 * <container-element [ngSwitch]="switch_expression">
2130
 *   <some-element *ngSwitchCase="match_expression_1">...</some-element>
2131
 *   <some-other-element *ngSwitchDefault>...</some-other-element>
2132
 * </container-element>
2133
 * ```
2134
 *
2135
 * \@description
2136
 *
2137
 * Insert the sub-tree when no case expressions evaluate to the same value as the enclosing switch
2138
 * expression.
2139
 *
2140
 * See {\@link NgSwitch} for more details and example.
2141
 *
2142
 * \@stable
2143
 */
2144
class NgSwitchDefault {
2145
    /**
2146
     * @param {?} viewContainer
2147
     * @param {?} templateRef
2148
     * @param {?} ngSwitch
2149
     */
2150
    constructor(viewContainer, templateRef, ngSwitch) {
2151
        ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
2152
    }
2153
}
2154
NgSwitchDefault.decorators = [
2155
    { type: Directive, args: [{ selector: '[ngSwitchDefault]' },] },
2156
];
2157
/**
2158
 * @nocollapse
2159
 */
2160
NgSwitchDefault.ctorParameters = () => [
2161
    { type: ViewContainerRef, },
2162
    { type: TemplateRef, },
2163
    { type: NgSwitch, decorators: [{ type: Host },] },
2164
];
2165

    
2166
/**
2167
 * @license
2168
 * Copyright Google Inc. All Rights Reserved.
2169
 *
2170
 * Use of this source code is governed by an MIT-style license that can be
2171
 * found in the LICENSE file at https://angular.io/license
2172
 */
2173
/**
2174
 * \@ngModule CommonModule
2175
 *
2176
 * \@whatItDoes Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization.
2177
 *
2178
 * \@howToUse
2179
 * ```
2180
 * <some-element [ngPlural]="value">
2181
 *   <ng-template ngPluralCase="=0">there is nothing</ng-template>
2182
 *   <ng-template ngPluralCase="=1">there is one</ng-template>
2183
 *   <ng-template ngPluralCase="few">there are a few</ng-template>
2184
 * </some-element>
2185
 * ```
2186
 *
2187
 * \@description
2188
 *
2189
 * Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees
2190
 * that match the switch expression's pluralization category.
2191
 *
2192
 * To use this directive you must provide a container element that sets the `[ngPlural]` attribute
2193
 * to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their
2194
 * expression:
2195
 * - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value
2196
 *   matches the switch expression exactly,
2197
 * - otherwise, the view will be treated as a "category match", and will only display if exact
2198
 *   value matches aren't found and the value maps to its category for the defined locale.
2199
 *
2200
 * See http://cldr.unicode.org/index/cldr-spec/plural-rules
2201
 *
2202
 * \@experimental
2203
 */
2204
class NgPlural {
2205
    /**
2206
     * @param {?} _localization
2207
     */
2208
    constructor(_localization) {
2209
        this._localization = _localization;
2210
        this._caseViews = {};
2211
    }
2212
    /**
2213
     * @param {?} value
2214
     * @return {?}
2215
     */
2216
    set ngPlural(value) {
2217
        this._switchValue = value;
2218
        this._updateView();
2219
    }
2220
    /**
2221
     * @param {?} value
2222
     * @param {?} switchView
2223
     * @return {?}
2224
     */
2225
    addCase(value, switchView) { this._caseViews[value] = switchView; }
2226
    /**
2227
     * @return {?}
2228
     */
2229
    _updateView() {
2230
        this._clearViews();
2231
        const /** @type {?} */ cases = Object.keys(this._caseViews);
2232
        const /** @type {?} */ key = getPluralCategory(this._switchValue, cases, this._localization);
2233
        this._activateView(this._caseViews[key]);
2234
    }
2235
    /**
2236
     * @return {?}
2237
     */
2238
    _clearViews() {
2239
        if (this._activeView)
2240
            this._activeView.destroy();
2241
    }
2242
    /**
2243
     * @param {?} view
2244
     * @return {?}
2245
     */
2246
    _activateView(view) {
2247
        if (view) {
2248
            this._activeView = view;
2249
            this._activeView.create();
2250
        }
2251
    }
2252
}
2253
NgPlural.decorators = [
2254
    { type: Directive, args: [{ selector: '[ngPlural]' },] },
2255
];
2256
/**
2257
 * @nocollapse
2258
 */
2259
NgPlural.ctorParameters = () => [
2260
    { type: NgLocalization, },
2261
];
2262
NgPlural.propDecorators = {
2263
    'ngPlural': [{ type: Input },],
2264
};
2265
/**
2266
 * \@ngModule CommonModule
2267
 *
2268
 * \@whatItDoes Creates a view that will be added/removed from the parent {\@link NgPlural} when the
2269
 *             given expression matches the plural expression according to CLDR rules.
2270
 *
2271
 * \@howToUse
2272
 * ```
2273
 * <some-element [ngPlural]="value">
2274
 *   <ng-template ngPluralCase="=0">...</ng-template>
2275
 *   <ng-template ngPluralCase="other">...</ng-template>
2276
 * </some-element>
2277
 * ```
2278
 *
2279
 * See {\@link NgPlural} for more details and example.
2280
 *
2281
 * \@experimental
2282
 */
2283
class NgPluralCase {
2284
    /**
2285
     * @param {?} value
2286
     * @param {?} template
2287
     * @param {?} viewContainer
2288
     * @param {?} ngPlural
2289
     */
2290
    constructor(value, template, viewContainer, ngPlural) {
2291
        this.value = value;
2292
        const isANumber = !isNaN(Number(value));
2293
        ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));
2294
    }
2295
}
2296
NgPluralCase.decorators = [
2297
    { type: Directive, args: [{ selector: '[ngPluralCase]' },] },
2298
];
2299
/**
2300
 * @nocollapse
2301
 */
2302
NgPluralCase.ctorParameters = () => [
2303
    { type: undefined, decorators: [{ type: Attribute, args: ['ngPluralCase',] },] },
2304
    { type: TemplateRef, },
2305
    { type: ViewContainerRef, },
2306
    { type: NgPlural, decorators: [{ type: Host },] },
2307
];
2308

    
2309
/**
2310
 * @license
2311
 * Copyright Google Inc. All Rights Reserved.
2312
 *
2313
 * Use of this source code is governed by an MIT-style license that can be
2314
 * found in the LICENSE file at https://angular.io/license
2315
 */
2316
/**
2317
 * \@ngModule CommonModule
2318
 *
2319
 * \@whatItDoes Update an HTML element styles.
2320
 *
2321
 * \@howToUse
2322
 * ```
2323
 * <some-element [ngStyle]="{'font-style': styleExp}">...</some-element>
2324
 *
2325
 * <some-element [ngStyle]="{'max-width.px': widthExp}">...</some-element>
2326
 *
2327
 * <some-element [ngStyle]="objExp">...</some-element>
2328
 * ```
2329
 *
2330
 * \@description
2331
 *
2332
 * The styles are updated according to the value of the expression evaluation:
2333
 * - keys are style names with an optional `.<unit>` suffix (ie 'top.px', 'font-style.em'),
2334
 * - values are the values assigned to those properties (expressed in the given unit).
2335
 *
2336
 * \@stable
2337
 */
2338
class NgStyle {
2339
    /**
2340
     * @param {?} _differs
2341
     * @param {?} _ngEl
2342
     * @param {?} _renderer
2343
     */
2344
    constructor(_differs, _ngEl, _renderer) {
2345
        this._differs = _differs;
2346
        this._ngEl = _ngEl;
2347
        this._renderer = _renderer;
2348
    }
2349
    /**
2350
     * @param {?} v
2351
     * @return {?}
2352
     */
2353
    set ngStyle(v) {
2354
        this._ngStyle = v;
2355
        if (!this._differ && v) {
2356
            this._differ = this._differs.find(v).create();
2357
        }
2358
    }
2359
    /**
2360
     * @return {?}
2361
     */
2362
    ngDoCheck() {
2363
        if (this._differ) {
2364
            const /** @type {?} */ changes = this._differ.diff(this._ngStyle);
2365
            if (changes) {
2366
                this._applyChanges(changes);
2367
            }
2368
        }
2369
    }
2370
    /**
2371
     * @param {?} changes
2372
     * @return {?}
2373
     */
2374
    _applyChanges(changes) {
2375
        changes.forEachRemovedItem((record) => this._setStyle(record.key, null));
2376
        changes.forEachAddedItem((record) => this._setStyle(record.key, record.currentValue));
2377
        changes.forEachChangedItem((record) => this._setStyle(record.key, record.currentValue));
2378
    }
2379
    /**
2380
     * @param {?} nameAndUnit
2381
     * @param {?} value
2382
     * @return {?}
2383
     */
2384
    _setStyle(nameAndUnit, value) {
2385
        const [name, unit] = nameAndUnit.split('.');
2386
        value = value != null && unit ? `${value}${unit}` : value;
2387
        this._renderer.setElementStyle(this._ngEl.nativeElement, name, /** @type {?} */ (value));
2388
    }
2389
}
2390
NgStyle.decorators = [
2391
    { type: Directive, args: [{ selector: '[ngStyle]' },] },
2392
];
2393
/**
2394
 * @nocollapse
2395
 */
2396
NgStyle.ctorParameters = () => [
2397
    { type: KeyValueDiffers, },
2398
    { type: ElementRef, },
2399
    { type: Renderer, },
2400
];
2401
NgStyle.propDecorators = {
2402
    'ngStyle': [{ type: Input },],
2403
};
2404

    
2405
/**
2406
 * @license
2407
 * Copyright Google Inc. All Rights Reserved.
2408
 *
2409
 * Use of this source code is governed by an MIT-style license that can be
2410
 * found in the LICENSE file at https://angular.io/license
2411
 */
2412
/**
2413
 * \@ngModule CommonModule
2414
 *
2415
 * \@whatItDoes Inserts an embedded view from a prepared `TemplateRef`
2416
 *
2417
 * \@howToUse
2418
 * ```
2419
 * <ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>
2420
 * ```
2421
 *
2422
 * \@description
2423
 *
2424
 * You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.
2425
 * `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding
2426
 * by the local template `let` declarations.
2427
 *
2428
 * Note: using the key `$implicit` in the context object will set it's value as default.
2429
 *
2430
 * ## Example
2431
 *
2432
 * {\@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'}
2433
 *
2434
 * \@experimental
2435
 */
2436
class NgTemplateOutlet {
2437
    /**
2438
     * @param {?} _viewContainerRef
2439
     */
2440
    constructor(_viewContainerRef) {
2441
        this._viewContainerRef = _viewContainerRef;
2442
    }
2443
    /**
2444
     * @deprecated v4.0.0 - Renamed to ngTemplateOutletContext.
2445
     * @param {?} context
2446
     * @return {?}
2447
     */
2448
    set ngOutletContext(context) { this.ngTemplateOutletContext = context; }
2449
    /**
2450
     * @param {?} changes
2451
     * @return {?}
2452
     */
2453
    ngOnChanges(changes) {
2454
        if (this._viewRef) {
2455
            this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
2456
        }
2457
        if (this.ngTemplateOutlet) {
2458
            this._viewRef = this._viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, this.ngTemplateOutletContext);
2459
        }
2460
    }
2461
}
2462
NgTemplateOutlet.decorators = [
2463
    { type: Directive, args: [{ selector: '[ngTemplateOutlet]' },] },
2464
];
2465
/**
2466
 * @nocollapse
2467
 */
2468
NgTemplateOutlet.ctorParameters = () => [
2469
    { type: ViewContainerRef, },
2470
];
2471
NgTemplateOutlet.propDecorators = {
2472
    'ngTemplateOutletContext': [{ type: Input },],
2473
    'ngTemplateOutlet': [{ type: Input },],
2474
    'ngOutletContext': [{ type: Input },],
2475
};
2476

    
2477
/**
2478
 * @license
2479
 * Copyright Google Inc. All Rights Reserved.
2480
 *
2481
 * Use of this source code is governed by an MIT-style license that can be
2482
 * found in the LICENSE file at https://angular.io/license
2483
 */
2484
/**
2485
 * A collection of Angular directives that are likely to be used in each and every Angular
2486
 * application.
2487
 */
2488
const COMMON_DIRECTIVES = [
2489
    NgClass,
2490
    NgComponentOutlet,
2491
    NgForOf,
2492
    NgIf,
2493
    NgTemplateOutlet,
2494
    NgStyle,
2495
    NgSwitch,
2496
    NgSwitchCase,
2497
    NgSwitchDefault,
2498
    NgPlural,
2499
    NgPluralCase,
2500
];
2501
/**
2502
 * A collection of deprecated directives that are no longer part of the core module.
2503
 */
2504

    
2505
/**
2506
 * @license
2507
 * Copyright Google Inc. All Rights Reserved.
2508
 *
2509
 * Use of this source code is governed by an MIT-style license that can be
2510
 * found in the LICENSE file at https://angular.io/license
2511
 */
2512
/**
2513
 * @param {?} type
2514
 * @param {?} value
2515
 * @return {?}
2516
 */
2517
function invalidPipeArgumentError(type, value) {
2518
    return Error(`InvalidPipeArgument: '${value}' for pipe '${ɵstringify(type)}'`);
2519
}
2520

    
2521
/**
2522
 * @license
2523
 * Copyright Google Inc. All Rights Reserved.
2524
 *
2525
 * Use of this source code is governed by an MIT-style license that can be
2526
 * found in the LICENSE file at https://angular.io/license
2527
 */
2528
class ObservableStrategy {
2529
    /**
2530
     * @param {?} async
2531
     * @param {?} updateLatestValue
2532
     * @return {?}
2533
     */
2534
    createSubscription(async, updateLatestValue) {
2535
        return async.subscribe({ next: updateLatestValue, error: (e) => { throw e; } });
2536
    }
2537
    /**
2538
     * @param {?} subscription
2539
     * @return {?}
2540
     */
2541
    dispose(subscription) { subscription.unsubscribe(); }
2542
    /**
2543
     * @param {?} subscription
2544
     * @return {?}
2545
     */
2546
    onDestroy(subscription) { subscription.unsubscribe(); }
2547
}
2548
class PromiseStrategy {
2549
    /**
2550
     * @param {?} async
2551
     * @param {?} updateLatestValue
2552
     * @return {?}
2553
     */
2554
    createSubscription(async, updateLatestValue) {
2555
        return async.then(updateLatestValue, e => { throw e; });
2556
    }
2557
    /**
2558
     * @param {?} subscription
2559
     * @return {?}
2560
     */
2561
    dispose(subscription) { }
2562
    /**
2563
     * @param {?} subscription
2564
     * @return {?}
2565
     */
2566
    onDestroy(subscription) { }
2567
}
2568
const _promiseStrategy = new PromiseStrategy();
2569
const _observableStrategy = new ObservableStrategy();
2570
/**
2571
 * \@ngModule CommonModule
2572
 * \@whatItDoes Unwraps a value from an asynchronous primitive.
2573
 * \@howToUse `observable_or_promise_expression | async`
2574
 * \@description
2575
 * The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has
2576
 * emitted. When a new value is emitted, the `async` pipe marks the component to be checked for
2577
 * changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid
2578
 * potential memory leaks.
2579
 *
2580
 *
2581
 * ## Examples
2582
 *
2583
 * This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the
2584
 * promise.
2585
 *
2586
 * {\@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'}
2587
 *
2588
 * It's also possible to use `async` with Observables. The example below binds the `time` Observable
2589
 * to the view. The Observable continuously updates the view with the current time.
2590
 *
2591
 * {\@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'}
2592
 *
2593
 * \@stable
2594
 */
2595
class AsyncPipe {
2596
    /**
2597
     * @param {?} _ref
2598
     */
2599
    constructor(_ref) {
2600
        this._ref = _ref;
2601
        this._latestValue = null;
2602
        this._latestReturnedValue = null;
2603
        this._subscription = null;
2604
        this._obj = null;
2605
        this._strategy = ((null));
2606
    }
2607
    /**
2608
     * @return {?}
2609
     */
2610
    ngOnDestroy() {
2611
        if (this._subscription) {
2612
            this._dispose();
2613
        }
2614
    }
2615
    /**
2616
     * @param {?} obj
2617
     * @return {?}
2618
     */
2619
    transform(obj) {
2620
        if (!this._obj) {
2621
            if (obj) {
2622
                this._subscribe(obj);
2623
            }
2624
            this._latestReturnedValue = this._latestValue;
2625
            return this._latestValue;
2626
        }
2627
        if (obj !== this._obj) {
2628
            this._dispose();
2629
            return this.transform(/** @type {?} */ (obj));
2630
        }
2631
        if (this._latestValue === this._latestReturnedValue) {
2632
            return this._latestReturnedValue;
2633
        }
2634
        this._latestReturnedValue = this._latestValue;
2635
        return WrappedValue.wrap(this._latestValue);
2636
    }
2637
    /**
2638
     * @param {?} obj
2639
     * @return {?}
2640
     */
2641
    _subscribe(obj) {
2642
        this._obj = obj;
2643
        this._strategy = this._selectStrategy(obj);
2644
        this._subscription = this._strategy.createSubscription(obj, (value) => this._updateLatestValue(obj, value));
2645
    }
2646
    /**
2647
     * @param {?} obj
2648
     * @return {?}
2649
     */
2650
    _selectStrategy(obj) {
2651
        if (ɵisPromise(obj)) {
2652
            return _promiseStrategy;
2653
        }
2654
        if (ɵisObservable(obj)) {
2655
            return _observableStrategy;
2656
        }
2657
        throw invalidPipeArgumentError(AsyncPipe, obj);
2658
    }
2659
    /**
2660
     * @return {?}
2661
     */
2662
    _dispose() {
2663
        this._strategy.dispose(/** @type {?} */ ((this._subscription)));
2664
        this._latestValue = null;
2665
        this._latestReturnedValue = null;
2666
        this._subscription = null;
2667
        this._obj = null;
2668
    }
2669
    /**
2670
     * @param {?} async
2671
     * @param {?} value
2672
     * @return {?}
2673
     */
2674
    _updateLatestValue(async, value) {
2675
        if (async === this._obj) {
2676
            this._latestValue = value;
2677
            this._ref.markForCheck();
2678
        }
2679
    }
2680
}
2681
AsyncPipe.decorators = [
2682
    { type: Pipe, args: [{ name: 'async', pure: false },] },
2683
];
2684
/**
2685
 * @nocollapse
2686
 */
2687
AsyncPipe.ctorParameters = () => [
2688
    { type: ChangeDetectorRef, },
2689
];
2690

    
2691
/**
2692
 * @license
2693
 * Copyright Google Inc. All Rights Reserved.
2694
 *
2695
 * Use of this source code is governed by an MIT-style license that can be
2696
 * found in the LICENSE file at https://angular.io/license
2697
 */
2698
/**
2699
 * Transforms text to lowercase.
2700
 *
2701
 * {\@example  common/pipes/ts/lowerupper_pipe.ts region='LowerUpperPipe' }
2702
 *
2703
 * \@stable
2704
 */
2705
class LowerCasePipe {
2706
    /**
2707
     * @param {?} value
2708
     * @return {?}
2709
     */
2710
    transform(value) {
2711
        if (!value)
2712
            return value;
2713
        if (typeof value !== 'string') {
2714
            throw invalidPipeArgumentError(LowerCasePipe, value);
2715
        }
2716
        return value.toLowerCase();
2717
    }
2718
}
2719
LowerCasePipe.decorators = [
2720
    { type: Pipe, args: [{ name: 'lowercase' },] },
2721
];
2722
/**
2723
 * @nocollapse
2724
 */
2725
LowerCasePipe.ctorParameters = () => [];
2726
/**
2727
 * Helper method to transform a single word to titlecase.
2728
 *
2729
 * \@stable
2730
 * @param {?} word
2731
 * @return {?}
2732
 */
2733
function titleCaseWord(word) {
2734
    if (!word)
2735
        return word;
2736
    return word[0].toUpperCase() + word.substr(1).toLowerCase();
2737
}
2738
/**
2739
 * Transforms text to titlecase.
2740
 *
2741
 * \@stable
2742
 */
2743
class TitleCasePipe {
2744
    /**
2745
     * @param {?} value
2746
     * @return {?}
2747
     */
2748
    transform(value) {
2749
        if (!value)
2750
            return value;
2751
        if (typeof value !== 'string') {
2752
            throw invalidPipeArgumentError(TitleCasePipe, value);
2753
        }
2754
        return value.split(/\b/g).map(word => titleCaseWord(word)).join('');
2755
    }
2756
}
2757
TitleCasePipe.decorators = [
2758
    { type: Pipe, args: [{ name: 'titlecase' },] },
2759
];
2760
/**
2761
 * @nocollapse
2762
 */
2763
TitleCasePipe.ctorParameters = () => [];
2764
/**
2765
 * Transforms text to uppercase.
2766
 *
2767
 * \@stable
2768
 */
2769
class UpperCasePipe {
2770
    /**
2771
     * @param {?} value
2772
     * @return {?}
2773
     */
2774
    transform(value) {
2775
        if (!value)
2776
            return value;
2777
        if (typeof value !== 'string') {
2778
            throw invalidPipeArgumentError(UpperCasePipe, value);
2779
        }
2780
        return value.toUpperCase();
2781
    }
2782
}
2783
UpperCasePipe.decorators = [
2784
    { type: Pipe, args: [{ name: 'uppercase' },] },
2785
];
2786
/**
2787
 * @nocollapse
2788
 */
2789
UpperCasePipe.ctorParameters = () => [];
2790

    
2791
let NumberFormatStyle = {};
2792
NumberFormatStyle.Decimal = 0;
2793
NumberFormatStyle.Percent = 1;
2794
NumberFormatStyle.Currency = 2;
2795
NumberFormatStyle[NumberFormatStyle.Decimal] = "Decimal";
2796
NumberFormatStyle[NumberFormatStyle.Percent] = "Percent";
2797
NumberFormatStyle[NumberFormatStyle.Currency] = "Currency";
2798
class NumberFormatter {
2799
    /**
2800
     * @param {?} num
2801
     * @param {?} locale
2802
     * @param {?} style
2803
     * @param {?=} opts
2804
     * @return {?}
2805
     */
2806
    static format(num, locale, style, opts = {}) {
2807
        const { minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, currency, currencyAsSymbol = false } = opts;
2808
        const /** @type {?} */ options = {
2809
            minimumIntegerDigits,
2810
            minimumFractionDigits,
2811
            maximumFractionDigits,
2812
            style: NumberFormatStyle[style].toLowerCase()
2813
        };
2814
        if (style == NumberFormatStyle.Currency) {
2815
            options.currency = typeof currency == 'string' ? currency : undefined;
2816
            options.currencyDisplay = currencyAsSymbol ? 'symbol' : 'code';
2817
        }
2818
        return new Intl.NumberFormat(locale, options).format(num);
2819
    }
2820
}
2821
const DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsazZEwGjJ']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|J+|j+|m+|s+|a|z|Z|G+|w+))(.*)/;
2822
const PATTERN_ALIASES = {
2823
    // Keys are quoted so they do not get renamed during closure compilation.
2824
    'yMMMdjms': datePartGetterFactory(combine([
2825
        digitCondition('year', 1),
2826
        nameCondition('month', 3),
2827
        digitCondition('day', 1),
2828
        digitCondition('hour', 1),
2829
        digitCondition('minute', 1),
2830
        digitCondition('second', 1),
2831
    ])),
2832
    'yMdjm': datePartGetterFactory(combine([
2833
        digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1),
2834
        digitCondition('hour', 1), digitCondition('minute', 1)
2835
    ])),
2836
    'yMMMMEEEEd': datePartGetterFactory(combine([
2837
        digitCondition('year', 1), nameCondition('month', 4), nameCondition('weekday', 4),
2838
        digitCondition('day', 1)
2839
    ])),
2840
    'yMMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 4), digitCondition('day', 1)])),
2841
    'yMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 3), digitCondition('day', 1)])),
2842
    'yMd': datePartGetterFactory(combine([digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1)])),
2843
    'jms': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('second', 1), digitCondition('minute', 1)])),
2844
    'jm': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('minute', 1)]))
2845
};
2846
const DATE_FORMATS = {
2847
    // Keys are quoted so they do not get renamed.
2848
    'yyyy': datePartGetterFactory(digitCondition('year', 4)),
2849
    'yy': datePartGetterFactory(digitCondition('year', 2)),
2850
    'y': datePartGetterFactory(digitCondition('year', 1)),
2851
    'MMMM': datePartGetterFactory(nameCondition('month', 4)),
2852
    'MMM': datePartGetterFactory(nameCondition('month', 3)),
2853
    'MM': datePartGetterFactory(digitCondition('month', 2)),
2854
    'M': datePartGetterFactory(digitCondition('month', 1)),
2855
    'LLLL': datePartGetterFactory(nameCondition('month', 4)),
2856
    'L': datePartGetterFactory(nameCondition('month', 1)),
2857
    'dd': datePartGetterFactory(digitCondition('day', 2)),
2858
    'd': datePartGetterFactory(digitCondition('day', 1)),
2859
    'HH': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), false)))),
2860
    'H': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), false))),
2861
    'hh': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), true)))),
2862
    'h': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
2863
    'jj': datePartGetterFactory(digitCondition('hour', 2)),
2864
    'j': datePartGetterFactory(digitCondition('hour', 1)),
2865
    'mm': digitModifier(datePartGetterFactory(digitCondition('minute', 2))),
2866
    'm': datePartGetterFactory(digitCondition('minute', 1)),
2867
    'ss': digitModifier(datePartGetterFactory(digitCondition('second', 2))),
2868
    's': datePartGetterFactory(digitCondition('second', 1)),
2869
    // while ISO 8601 requires fractions to be prefixed with `.` or `,`
2870
    // we can be just safely rely on using `sss` since we currently don't support single or two digit
2871
    // fractions
2872
    'sss': datePartGetterFactory(digitCondition('second', 3)),
2873
    'EEEE': datePartGetterFactory(nameCondition('weekday', 4)),
2874
    'EEE': datePartGetterFactory(nameCondition('weekday', 3)),
2875
    'EE': datePartGetterFactory(nameCondition('weekday', 2)),
2876
    'E': datePartGetterFactory(nameCondition('weekday', 1)),
2877
    'a': hourClockExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
2878
    'Z': timeZoneGetter('short'),
2879
    'z': timeZoneGetter('long'),
2880
    'ww': datePartGetterFactory({}),
2881
    // first Thursday of the year. not support ?
2882
    'w': datePartGetterFactory({}),
2883
    // of the year not support ?
2884
    'G': datePartGetterFactory(nameCondition('era', 1)),
2885
    'GG': datePartGetterFactory(nameCondition('era', 2)),
2886
    'GGG': datePartGetterFactory(nameCondition('era', 3)),
2887
    'GGGG': datePartGetterFactory(nameCondition('era', 4))
2888
};
2889
/**
2890
 * @param {?} inner
2891
 * @return {?}
2892
 */
2893
function digitModifier(inner) {
2894
    return function (date, locale) {
2895
        const /** @type {?} */ result = inner(date, locale);
2896
        return result.length == 1 ? '0' + result : result;
2897
    };
2898
}
2899
/**
2900
 * @param {?} inner
2901
 * @return {?}
2902
 */
2903
function hourClockExtractor(inner) {
2904
    return function (date, locale) { return inner(date, locale).split(' ')[1]; };
2905
}
2906
/**
2907
 * @param {?} inner
2908
 * @return {?}
2909
 */
2910
function hourExtractor(inner) {
2911
    return function (date, locale) { return inner(date, locale).split(' ')[0]; };
2912
}
2913
/**
2914
 * @param {?} date
2915
 * @param {?} locale
2916
 * @param {?} options
2917
 * @return {?}
2918
 */
2919
function intlDateFormat(date, locale, options) {
2920
    return new Intl.DateTimeFormat(locale, options).format(date).replace(/[\u200e\u200f]/g, '');
2921
}
2922
/**
2923
 * @param {?} timezone
2924
 * @return {?}
2925
 */
2926
function timeZoneGetter(timezone) {
2927
    // To workaround `Intl` API restriction for single timezone let format with 24 hours
2928
    const /** @type {?} */ options = { hour: '2-digit', hour12: false, timeZoneName: timezone };
2929
    return function (date, locale) {
2930
        const /** @type {?} */ result = intlDateFormat(date, locale, options);
2931
        // Then extract first 3 letters that related to hours
2932
        return result ? result.substring(3) : '';
2933
    };
2934
}
2935
/**
2936
 * @param {?} options
2937
 * @param {?} value
2938
 * @return {?}
2939
 */
2940
function hour12Modify(options, value) {
2941
    options.hour12 = value;
2942
    return options;
2943
}
2944
/**
2945
 * @param {?} prop
2946
 * @param {?} len
2947
 * @return {?}
2948
 */
2949
function digitCondition(prop, len) {
2950
    const /** @type {?} */ result = {};
2951
    result[prop] = len === 2 ? '2-digit' : 'numeric';
2952
    return result;
2953
}
2954
/**
2955
 * @param {?} prop
2956
 * @param {?} len
2957
 * @return {?}
2958
 */
2959
function nameCondition(prop, len) {
2960
    const /** @type {?} */ result = {};
2961
    if (len < 4) {
2962
        result[prop] = len > 1 ? 'short' : 'narrow';
2963
    }
2964
    else {
2965
        result[prop] = 'long';
2966
    }
2967
    return result;
2968
}
2969
/**
2970
 * @param {?} options
2971
 * @return {?}
2972
 */
2973
function combine(options) {
2974
    return options.reduce((merged, opt) => (Object.assign({}, merged, opt)), {});
2975
}
2976
/**
2977
 * @param {?} ret
2978
 * @return {?}
2979
 */
2980
function datePartGetterFactory(ret) {
2981
    return (date, locale) => intlDateFormat(date, locale, ret);
2982
}
2983
const DATE_FORMATTER_CACHE = new Map();
2984
/**
2985
 * @param {?} format
2986
 * @param {?} date
2987
 * @param {?} locale
2988
 * @return {?}
2989
 */
2990
function dateFormatter(format, date, locale) {
2991
    const /** @type {?} */ fn = PATTERN_ALIASES[format];
2992
    if (fn)
2993
        return fn(date, locale);
2994
    const /** @type {?} */ cacheKey = format;
2995
    let /** @type {?} */ parts = DATE_FORMATTER_CACHE.get(cacheKey);
2996
    if (!parts) {
2997
        parts = [];
2998
        let /** @type {?} */ match;
2999
        DATE_FORMATS_SPLIT.exec(format);
3000
        let /** @type {?} */ _format = format;
3001
        while (_format) {
3002
            match = DATE_FORMATS_SPLIT.exec(_format);
3003
            if (match) {
3004
                parts = parts.concat(match.slice(1));
3005
                _format = ((parts.pop()));
3006
            }
3007
            else {
3008
                parts.push(_format);
3009
                _format = null;
3010
            }
3011
        }
3012
        DATE_FORMATTER_CACHE.set(cacheKey, parts);
3013
    }
3014
    return parts.reduce((text, part) => {
3015
        const /** @type {?} */ fn = DATE_FORMATS[part];
3016
        return text + (fn ? fn(date, locale) : partToTime(part));
3017
    }, '');
3018
}
3019
/**
3020
 * @param {?} part
3021
 * @return {?}
3022
 */
3023
function partToTime(part) {
3024
    return part === '\'\'' ? '\'' : part.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
3025
}
3026
class DateFormatter {
3027
    /**
3028
     * @param {?} date
3029
     * @param {?} locale
3030
     * @param {?} pattern
3031
     * @return {?}
3032
     */
3033
    static format(date, locale, pattern) {
3034
        return dateFormatter(pattern, date, locale);
3035
    }
3036
}
3037

    
3038
/**
3039
 * @license
3040
 * Copyright Google Inc. All Rights Reserved.
3041
 *
3042
 * Use of this source code is governed by an MIT-style license that can be
3043
 * found in the LICENSE file at https://angular.io/license
3044
 */
3045
const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
3046
/**
3047
 * @param {?} pipe
3048
 * @param {?} locale
3049
 * @param {?} value
3050
 * @param {?} style
3051
 * @param {?=} digits
3052
 * @param {?=} currency
3053
 * @param {?=} currencyAsSymbol
3054
 * @return {?}
3055
 */
3056
function formatNumber(pipe, locale, value, style, digits, currency = null, currencyAsSymbol = false) {
3057
    if (value == null)
3058
        return null;
3059
    // Convert strings to numbers
3060
    value = typeof value === 'string' && isNumeric(value) ? +value : value;
3061
    if (typeof value !== 'number') {
3062
        throw invalidPipeArgumentError(pipe, value);
3063
    }
3064
    let /** @type {?} */ minInt = undefined;
3065
    let /** @type {?} */ minFraction = undefined;
3066
    let /** @type {?} */ maxFraction = undefined;
3067
    if (style !== NumberFormatStyle.Currency) {
3068
        // rely on Intl default for currency
3069
        minInt = 1;
3070
        minFraction = 0;
3071
        maxFraction = 3;
3072
    }
3073
    if (digits) {
3074
        const /** @type {?} */ parts = digits.match(_NUMBER_FORMAT_REGEXP);
3075
        if (parts === null) {
3076
            throw new Error(`${digits} is not a valid digit info for number pipes`);
3077
        }
3078
        if (parts[1] != null) {
3079
            minInt = parseIntAutoRadix(parts[1]);
3080
        }
3081
        if (parts[3] != null) {
3082
            minFraction = parseIntAutoRadix(parts[3]);
3083
        }
3084
        if (parts[5] != null) {
3085
            maxFraction = parseIntAutoRadix(parts[5]);
3086
        }
3087
    }
3088
    return NumberFormatter.format(/** @type {?} */ (value), locale, style, {
3089
        minimumIntegerDigits: minInt,
3090
        minimumFractionDigits: minFraction,
3091
        maximumFractionDigits: maxFraction,
3092
        currency: currency,
3093
        currencyAsSymbol: currencyAsSymbol,
3094
    });
3095
}
3096
/**
3097
 * \@ngModule CommonModule
3098
 * \@whatItDoes Formats a number according to locale rules.
3099
 * \@howToUse `number_expression | number[:digitInfo]`
3100
 *
3101
 * Formats a number as text. Group sizing and separator and other locale-specific
3102
 * configurations are based on the active locale.
3103
 *
3104
 * where `expression` is a number:
3105
 *  - `digitInfo` is a `string` which has a following format: <br>
3106
 *     <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>
3107
 *   - `minIntegerDigits` is the minimum number of integer digits to use. Defaults to `1`.
3108
 *   - `minFractionDigits` is the minimum number of digits after fraction. Defaults to `0`.
3109
 *   - `maxFractionDigits` is the maximum number of digits after fraction. Defaults to `3`.
3110
 *
3111
 * For more information on the acceptable range for each of these numbers and other
3112
 * details see your native internationalization library.
3113
 *
3114
 * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
3115
 * and may require a polyfill. See [Browser Support](guide/browser-support) for details.
3116
 *
3117
 * ### Example
3118
 *
3119
 * {\@example common/pipes/ts/number_pipe.ts region='NumberPipe'}
3120
 *
3121
 * \@stable
3122
 */
3123
class DecimalPipe {
3124
    /**
3125
     * @param {?} _locale
3126
     */
3127
    constructor(_locale) {
3128
        this._locale = _locale;
3129
    }
3130
    /**
3131
     * @param {?} value
3132
     * @param {?=} digits
3133
     * @return {?}
3134
     */
3135
    transform(value, digits) {
3136
        return formatNumber(DecimalPipe, this._locale, value, NumberFormatStyle.Decimal, digits);
3137
    }
3138
}
3139
DecimalPipe.decorators = [
3140
    { type: Pipe, args: [{ name: 'number' },] },
3141
];
3142
/**
3143
 * @nocollapse
3144
 */
3145
DecimalPipe.ctorParameters = () => [
3146
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
3147
];
3148
/**
3149
 * \@ngModule CommonModule
3150
 * \@whatItDoes Formats a number as a percentage according to locale rules.
3151
 * \@howToUse `number_expression | percent[:digitInfo]`
3152
 *
3153
 * \@description
3154
 *
3155
 * Formats a number as percentage.
3156
 *
3157
 * - `digitInfo` See {\@link DecimalPipe} for detailed description.
3158
 *
3159
 * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
3160
 * and may require a polyfill. See [Browser Support](guide/browser-support) for details.
3161
 *
3162
 * ### Example
3163
 *
3164
 * {\@example common/pipes/ts/number_pipe.ts region='PercentPipe'}
3165
 *
3166
 * \@stable
3167
 */
3168
class PercentPipe {
3169
    /**
3170
     * @param {?} _locale
3171
     */
3172
    constructor(_locale) {
3173
        this._locale = _locale;
3174
    }
3175
    /**
3176
     * @param {?} value
3177
     * @param {?=} digits
3178
     * @return {?}
3179
     */
3180
    transform(value, digits) {
3181
        return formatNumber(PercentPipe, this._locale, value, NumberFormatStyle.Percent, digits);
3182
    }
3183
}
3184
PercentPipe.decorators = [
3185
    { type: Pipe, args: [{ name: 'percent' },] },
3186
];
3187
/**
3188
 * @nocollapse
3189
 */
3190
PercentPipe.ctorParameters = () => [
3191
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
3192
];
3193
/**
3194
 * \@ngModule CommonModule
3195
 * \@whatItDoes Formats a number as currency using locale rules.
3196
 * \@howToUse `number_expression | currency[:currencyCode[:symbolDisplay[:digitInfo]]]`
3197
 * \@description
3198
 *
3199
 * Use `currency` to format a number as currency.
3200
 *
3201
 * - `currencyCode` is the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, such
3202
 *    as `USD` for the US dollar and `EUR` for the euro.
3203
 * - `symbolDisplay` is a boolean indicating whether to use the currency symbol or code.
3204
 *   - `true`: use symbol (e.g. `$`).
3205
 *   - `false`(default): use code (e.g. `USD`).
3206
 * - `digitInfo` See {\@link DecimalPipe} for detailed description.
3207
 *
3208
 * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
3209
 * and may require a polyfill. See [Browser Support](guide/browser-support) for details.
3210
 *
3211
 * ### Example
3212
 *
3213
 * {\@example common/pipes/ts/number_pipe.ts region='CurrencyPipe'}
3214
 *
3215
 * \@stable
3216
 */
3217
class CurrencyPipe {
3218
    /**
3219
     * @param {?} _locale
3220
     */
3221
    constructor(_locale) {
3222
        this._locale = _locale;
3223
    }
3224
    /**
3225
     * @param {?} value
3226
     * @param {?=} currencyCode
3227
     * @param {?=} symbolDisplay
3228
     * @param {?=} digits
3229
     * @return {?}
3230
     */
3231
    transform(value, currencyCode = 'USD', symbolDisplay = false, digits) {
3232
        return formatNumber(CurrencyPipe, this._locale, value, NumberFormatStyle.Currency, digits, currencyCode, symbolDisplay);
3233
    }
3234
}
3235
CurrencyPipe.decorators = [
3236
    { type: Pipe, args: [{ name: 'currency' },] },
3237
];
3238
/**
3239
 * @nocollapse
3240
 */
3241
CurrencyPipe.ctorParameters = () => [
3242
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
3243
];
3244
/**
3245
 * @param {?} text
3246
 * @return {?}
3247
 */
3248
function parseIntAutoRadix(text) {
3249
    const /** @type {?} */ result = parseInt(text);
3250
    if (isNaN(result)) {
3251
        throw new Error('Invalid integer literal when parsing ' + text);
3252
    }
3253
    return result;
3254
}
3255
/**
3256
 * @param {?} value
3257
 * @return {?}
3258
 */
3259
function isNumeric(value) {
3260
    return !isNaN(value - parseFloat(value));
3261
}
3262

    
3263
/**
3264
 * @license
3265
 * Copyright Google Inc. All Rights Reserved.
3266
 *
3267
 * Use of this source code is governed by an MIT-style license that can be
3268
 * found in the LICENSE file at https://angular.io/license
3269
 */
3270
const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
3271
/**
3272
 * \@ngModule CommonModule
3273
 * \@whatItDoes Formats a date according to locale rules.
3274
 * \@howToUse `date_expression | date[:format]`
3275
 * \@description
3276
 *
3277
 * Where:
3278
 * - `expression` is a date object or a number (milliseconds since UTC epoch) or an ISO string
3279
 * (https://www.w3.org/TR/NOTE-datetime).
3280
 * - `format` indicates which date/time components to include. The format can be predefined as
3281
 *   shown below or custom as shown in the table.
3282
 *   - `'medium'`: equivalent to `'yMMMdjms'` (e.g. `Sep 3, 2010, 12:05:08 PM` for `en-US`)
3283
 *   - `'short'`: equivalent to `'yMdjm'` (e.g. `9/3/2010, 12:05 PM` for `en-US`)
3284
 *   - `'fullDate'`: equivalent to `'yMMMMEEEEd'` (e.g. `Friday, September 3, 2010` for `en-US`)
3285
 *   - `'longDate'`: equivalent to `'yMMMMd'` (e.g. `September 3, 2010` for `en-US`)
3286
 *   - `'mediumDate'`: equivalent to `'yMMMd'` (e.g. `Sep 3, 2010` for `en-US`)
3287
 *   - `'shortDate'`: equivalent to `'yMd'` (e.g. `9/3/2010` for `en-US`)
3288
 *   - `'mediumTime'`: equivalent to `'jms'` (e.g. `12:05:08 PM` for `en-US`)
3289
 *   - `'shortTime'`: equivalent to `'jm'` (e.g. `12:05 PM` for `en-US`)
3290
 *
3291
 *
3292
 *  | Component | Symbol | Narrow | Short Form   | Long Form         | Numeric   | 2-digit   |
3293
 *  |-----------|:------:|--------|--------------|-------------------|-----------|-----------|
3294
 *  | era       |   G    | G (A)  | GGG (AD)     | GGGG (Anno Domini)| -         | -         |
3295
 *  | year      |   y    | -      | -            | -                 | y (2015)  | yy (15)   |
3296
 *  | month     |   M    | L (S)  | MMM (Sep)    | MMMM (September)  | M (9)     | MM (09)   |
3297
 *  | day       |   d    | -      | -            | -                 | d (3)     | dd (03)   |
3298
 *  | weekday   |   E    | E (S)  | EEE (Sun)    | EEEE (Sunday)     | -         | -         |
3299
 *  | hour      |   j    | -      | -            | -                 | j (1 PM)  | jj (1 PM) |
3300
 *  | hour12    |   h    | -      | -            | -                 | h (1)     | hh (01)   |
3301
 *  | hour24    |   H    | -      | -            | -                 | H (13)    | HH (13)   |
3302
 *  | minute    |   m    | -      | -            | -                 | m (5)     | mm (05)   |
3303
 *  | second    |   s    | -      | -            | -                 | s (9)     | ss (09)   |
3304
 *  | timezone  |   z    | -      | -            | z (Pacific Standard Time)| -  | -         |
3305
 *  | timezone  |   Z    | -      | Z (GMT-8:00) | -                 | -         | -         |
3306
 *  | timezone  |   a    | -      | a (PM)       | -                 | -         | -         |
3307
 *
3308
 * In javascript, only the components specified will be respected (not the ordering,
3309
 * punctuations, ...) and details of the formatting will be dependent on the locale.
3310
 *
3311
 * Timezone of the formatted text will be the local system timezone of the end-user's machine.
3312
 *
3313
 * When the expression is a ISO string without time (e.g. 2016-09-19) the time zone offset is not
3314
 * applied and the formatted text will have the same day, month and year of the expression.
3315
 *
3316
 * WARNINGS:
3317
 * - this pipe is marked as pure hence it will not be re-evaluated when the input is mutated.
3318
 *   Instead users should treat the date as an immutable object and change the reference when the
3319
 *   pipe needs to re-run (this is to avoid reformatting the date on every change detection run
3320
 *   which would be an expensive operation).
3321
 * - this pipe uses the Internationalization API. Therefore it is only reliable in Chrome and Opera
3322
 *   browsers.
3323
 *
3324
 * ### Examples
3325
 *
3326
 * Assuming `dateObj` is (year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11)
3327
 * in the _local_ time and locale is 'en-US':
3328
 *
3329
 * ```
3330
 *     {{ dateObj | date }}               // output is 'Jun 15, 2015'
3331
 *     {{ dateObj | date:'medium' }}      // output is 'Jun 15, 2015, 9:43:11 PM'
3332
 *     {{ dateObj | date:'shortTime' }}   // output is '9:43 PM'
3333
 *     {{ dateObj | date:'mmss' }}        // output is '43:11'
3334
 * ```
3335
 *
3336
 * {\@example common/pipes/ts/date_pipe.ts region='DatePipe'}
3337
 *
3338
 * \@stable
3339
 */
3340
class DatePipe {
3341
    /**
3342
     * @param {?} _locale
3343
     */
3344
    constructor(_locale) {
3345
        this._locale = _locale;
3346
    }
3347
    /**
3348
     * @param {?} value
3349
     * @param {?=} pattern
3350
     * @return {?}
3351
     */
3352
    transform(value, pattern = 'mediumDate') {
3353
        let /** @type {?} */ date;
3354
        if (isBlank(value) || value !== value)
3355
            return null;
3356
        if (typeof value === 'string') {
3357
            value = value.trim();
3358
        }
3359
        if (isDate(value)) {
3360
            date = value;
3361
        }
3362
        else if (isNumeric(value)) {
3363
            date = new Date(parseFloat(value));
3364
        }
3365
        else if (typeof value === 'string' && /^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
3366
            /**
3367
             * For ISO Strings without time the day, month and year must be extracted from the ISO String
3368
             * before Date creation to avoid time offset and errors in the new Date.
3369
             * If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new
3370
             * date, some browsers (e.g. IE 9) will throw an invalid Date error
3371
             * If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset
3372
             * is applied
3373
             * Note: ISO months are 0 for January, 1 for February, ...
3374
             */
3375
            const [y, m, d] = value.split('-').map((val) => parseInt(val, 10));
3376
            date = new Date(y, m - 1, d);
3377
        }
3378
        else {
3379
            date = new Date(value);
3380
        }
3381
        if (!isDate(date)) {
3382
            let /** @type {?} */ match;
3383
            if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
3384
                date = isoStringToDate(match);
3385
            }
3386
            else {
3387
                throw invalidPipeArgumentError(DatePipe, value);
3388
            }
3389
        }
3390
        return DateFormatter.format(date, this._locale, DatePipe._ALIASES[pattern] || pattern);
3391
    }
3392
}
3393
/**
3394
 * \@internal
3395
 */
3396
DatePipe._ALIASES = {
3397
    'medium': 'yMMMdjms',
3398
    'short': 'yMdjm',
3399
    'fullDate': 'yMMMMEEEEd',
3400
    'longDate': 'yMMMMd',
3401
    'mediumDate': 'yMMMd',
3402
    'shortDate': 'yMd',
3403
    'mediumTime': 'jms',
3404
    'shortTime': 'jm'
3405
};
3406
DatePipe.decorators = [
3407
    { type: Pipe, args: [{ name: 'date', pure: true },] },
3408
];
3409
/**
3410
 * @nocollapse
3411
 */
3412
DatePipe.ctorParameters = () => [
3413
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
3414
];
3415
/**
3416
 * @param {?} obj
3417
 * @return {?}
3418
 */
3419
function isBlank(obj) {
3420
    return obj == null || obj === '';
3421
}
3422
/**
3423
 * @param {?} obj
3424
 * @return {?}
3425
 */
3426
function isDate(obj) {
3427
    return obj instanceof Date && !isNaN(obj.valueOf());
3428
}
3429
/**
3430
 * @param {?} match
3431
 * @return {?}
3432
 */
3433
function isoStringToDate(match) {
3434
    const /** @type {?} */ date = new Date(0);
3435
    let /** @type {?} */ tzHour = 0;
3436
    let /** @type {?} */ tzMin = 0;
3437
    const /** @type {?} */ dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
3438
    const /** @type {?} */ timeSetter = match[8] ? date.setUTCHours : date.setHours;
3439
    if (match[9]) {
3440
        tzHour = toInt(match[9] + match[10]);
3441
        tzMin = toInt(match[9] + match[11]);
3442
    }
3443
    dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
3444
    const /** @type {?} */ h = toInt(match[4] || '0') - tzHour;
3445
    const /** @type {?} */ m = toInt(match[5] || '0') - tzMin;
3446
    const /** @type {?} */ s = toInt(match[6] || '0');
3447
    const /** @type {?} */ ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
3448
    timeSetter.call(date, h, m, s, ms);
3449
    return date;
3450
}
3451
/**
3452
 * @param {?} str
3453
 * @return {?}
3454
 */
3455
function toInt(str) {
3456
    return parseInt(str, 10);
3457
}
3458

    
3459
/**
3460
 * @license
3461
 * Copyright Google Inc. All Rights Reserved.
3462
 *
3463
 * Use of this source code is governed by an MIT-style license that can be
3464
 * found in the LICENSE file at https://angular.io/license
3465
 */
3466
const _INTERPOLATION_REGEXP = /#/g;
3467
/**
3468
 * \@ngModule CommonModule
3469
 * \@whatItDoes Maps a value to a string that pluralizes the value according to locale rules.
3470
 * \@howToUse `expression | i18nPlural:mapping`
3471
 * \@description
3472
 *
3473
 *  Where:
3474
 *  - `expression` is a number.
3475
 *  - `mapping` is an object that mimics the ICU format, see
3476
 *    http://userguide.icu-project.org/formatparse/messages
3477
 *
3478
 *  ## Example
3479
 *
3480
 * {\@example common/pipes/ts/i18n_pipe.ts region='I18nPluralPipeComponent'}
3481
 *
3482
 * \@experimental
3483
 */
3484
class I18nPluralPipe {
3485
    /**
3486
     * @param {?} _localization
3487
     */
3488
    constructor(_localization) {
3489
        this._localization = _localization;
3490
    }
3491
    /**
3492
     * @param {?} value
3493
     * @param {?} pluralMap
3494
     * @return {?}
3495
     */
3496
    transform(value, pluralMap) {
3497
        if (value == null)
3498
            return '';
3499
        if (typeof pluralMap !== 'object' || pluralMap === null) {
3500
            throw invalidPipeArgumentError(I18nPluralPipe, pluralMap);
3501
        }
3502
        const /** @type {?} */ key = getPluralCategory(value, Object.keys(pluralMap), this._localization);
3503
        return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString());
3504
    }
3505
}
3506
I18nPluralPipe.decorators = [
3507
    { type: Pipe, args: [{ name: 'i18nPlural', pure: true },] },
3508
];
3509
/**
3510
 * @nocollapse
3511
 */
3512
I18nPluralPipe.ctorParameters = () => [
3513
    { type: NgLocalization, },
3514
];
3515

    
3516
/**
3517
 * @license
3518
 * Copyright Google Inc. All Rights Reserved.
3519
 *
3520
 * Use of this source code is governed by an MIT-style license that can be
3521
 * found in the LICENSE file at https://angular.io/license
3522
 */
3523
/**
3524
 * \@ngModule CommonModule
3525
 * \@whatItDoes Generic selector that displays the string that matches the current value.
3526
 * \@howToUse `expression | i18nSelect:mapping`
3527
 * \@description
3528
 *
3529
 *  Where `mapping` is an object that indicates the text that should be displayed
3530
 *  for different values of the provided `expression`.
3531
 *  If none of the keys of the mapping match the value of the `expression`, then the content
3532
 *  of the `other` key is returned when present, otherwise an empty string is returned.
3533
 *
3534
 *  ## Example
3535
 *
3536
 * {\@example common/pipes/ts/i18n_pipe.ts region='I18nSelectPipeComponent'}
3537
 *
3538
 *  \@experimental
3539
 */
3540
class I18nSelectPipe {
3541
    /**
3542
     * @param {?} value
3543
     * @param {?} mapping
3544
     * @return {?}
3545
     */
3546
    transform(value, mapping) {
3547
        if (value == null)
3548
            return '';
3549
        if (typeof mapping !== 'object' || typeof value !== 'string') {
3550
            throw invalidPipeArgumentError(I18nSelectPipe, mapping);
3551
        }
3552
        if (mapping.hasOwnProperty(value)) {
3553
            return mapping[value];
3554
        }
3555
        if (mapping.hasOwnProperty('other')) {
3556
            return mapping['other'];
3557
        }
3558
        return '';
3559
    }
3560
}
3561
I18nSelectPipe.decorators = [
3562
    { type: Pipe, args: [{ name: 'i18nSelect', pure: true },] },
3563
];
3564
/**
3565
 * @nocollapse
3566
 */
3567
I18nSelectPipe.ctorParameters = () => [];
3568

    
3569
/**
3570
 * @license
3571
 * Copyright Google Inc. All Rights Reserved.
3572
 *
3573
 * Use of this source code is governed by an MIT-style license that can be
3574
 * found in the LICENSE file at https://angular.io/license
3575
 */
3576
/**
3577
 * \@ngModule CommonModule
3578
 * \@whatItDoes Converts value into JSON string.
3579
 * \@howToUse `expression | json`
3580
 * \@description
3581
 *
3582
 * Converts value into string using `JSON.stringify`. Useful for debugging.
3583
 *
3584
 * ### Example
3585
 * {\@example common/pipes/ts/json_pipe.ts region='JsonPipe'}
3586
 *
3587
 * \@stable
3588
 */
3589
class JsonPipe {
3590
    /**
3591
     * @param {?} value
3592
     * @return {?}
3593
     */
3594
    transform(value) { return JSON.stringify(value, null, 2); }
3595
}
3596
JsonPipe.decorators = [
3597
    { type: Pipe, args: [{ name: 'json', pure: false },] },
3598
];
3599
/**
3600
 * @nocollapse
3601
 */
3602
JsonPipe.ctorParameters = () => [];
3603

    
3604
/**
3605
 * @license
3606
 * Copyright Google Inc. All Rights Reserved.
3607
 *
3608
 * Use of this source code is governed by an MIT-style license that can be
3609
 * found in the LICENSE file at https://angular.io/license
3610
 */
3611
/**
3612
 * \@ngModule CommonModule
3613
 * \@whatItDoes Creates a new List or String containing a subset (slice) of the elements.
3614
 * \@howToUse `array_or_string_expression | slice:start[:end]`
3615
 * \@description
3616
 *
3617
 * Where the input expression is a `List` or `String`, and:
3618
 * - `start`: The starting index of the subset to return.
3619
 *   - **a positive integer**: return the item at `start` index and all items after
3620
 *     in the list or string expression.
3621
 *   - **a negative integer**: return the item at `start` index from the end and all items after
3622
 *     in the list or string expression.
3623
 *   - **if positive and greater than the size of the expression**: return an empty list or string.
3624
 *   - **if negative and greater than the size of the expression**: return entire list or string.
3625
 * - `end`: The ending index of the subset to return.
3626
 *   - **omitted**: return all items until the end.
3627
 *   - **if positive**: return all items before `end` index of the list or string.
3628
 *   - **if negative**: return all items before `end` index from the end of the list or string.
3629
 *
3630
 * All behavior is based on the expected behavior of the JavaScript API `Array.prototype.slice()`
3631
 * and `String.prototype.slice()`.
3632
 *
3633
 * When operating on a [List], the returned list is always a copy even when all
3634
 * the elements are being returned.
3635
 *
3636
 * When operating on a blank value, the pipe returns the blank value.
3637
 *
3638
 * ## List Example
3639
 *
3640
 * This `ngFor` example:
3641
 *
3642
 * {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_list'}
3643
 *
3644
 * produces the following:
3645
 *
3646
 *     <li>b</li>
3647
 *     <li>c</li>
3648
 *
3649
 * ## String Examples
3650
 *
3651
 * {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'}
3652
 *
3653
 * \@stable
3654
 */
3655
class SlicePipe {
3656
    /**
3657
     * @param {?} value
3658
     * @param {?} start
3659
     * @param {?=} end
3660
     * @return {?}
3661
     */
3662
    transform(value, start, end) {
3663
        if (value == null)
3664
            return value;
3665
        if (!this.supports(value)) {
3666
            throw invalidPipeArgumentError(SlicePipe, value);
3667
        }
3668
        return value.slice(start, end);
3669
    }
3670
    /**
3671
     * @param {?} obj
3672
     * @return {?}
3673
     */
3674
    supports(obj) { return typeof obj === 'string' || Array.isArray(obj); }
3675
}
3676
SlicePipe.decorators = [
3677
    { type: Pipe, args: [{ name: 'slice', pure: false },] },
3678
];
3679
/**
3680
 * @nocollapse
3681
 */
3682
SlicePipe.ctorParameters = () => [];
3683

    
3684
/**
3685
 * @license
3686
 * Copyright Google Inc. All Rights Reserved.
3687
 *
3688
 * Use of this source code is governed by an MIT-style license that can be
3689
 * found in the LICENSE file at https://angular.io/license
3690
 */
3691
/**
3692
 * @module
3693
 * @description
3694
 * This module provides a set of common Pipes.
3695
 */
3696
/**
3697
 * A collection of Angular pipes that are likely to be used in each and every application.
3698
 */
3699
const COMMON_PIPES = [
3700
    AsyncPipe,
3701
    UpperCasePipe,
3702
    LowerCasePipe,
3703
    JsonPipe,
3704
    SlicePipe,
3705
    DecimalPipe,
3706
    PercentPipe,
3707
    TitleCasePipe,
3708
    CurrencyPipe,
3709
    DatePipe,
3710
    I18nPluralPipe,
3711
    I18nSelectPipe,
3712
];
3713

    
3714
/**
3715
 * @license
3716
 * Copyright Google Inc. All Rights Reserved.
3717
 *
3718
 * Use of this source code is governed by an MIT-style license that can be
3719
 * found in the LICENSE file at https://angular.io/license
3720
 */
3721
/**
3722
 * The module that includes all the basic Angular directives like {\@link NgIf}, {\@link NgForOf}, ...
3723
 *
3724
 * \@stable
3725
 */
3726
class CommonModule {
3727
}
3728
CommonModule.decorators = [
3729
    { type: NgModule, args: [{
3730
                declarations: [COMMON_DIRECTIVES, COMMON_PIPES],
3731
                exports: [COMMON_DIRECTIVES, COMMON_PIPES],
3732
                providers: [
3733
                    { provide: NgLocalization, useClass: NgLocaleLocalization },
3734
                ],
3735
            },] },
3736
];
3737
/**
3738
 * @nocollapse
3739
 */
3740
CommonModule.ctorParameters = () => [];
3741
/**
3742
 * I18N pipes are being changed to move away from using the JS Intl API.
3743
 *
3744
 * The former pipes relying on the Intl API will be moved to this module while the `CommonModule`
3745
 * will contain the new pipes that do not rely on Intl.
3746
 *
3747
 * As a first step this module is created empty to ease the migration.
3748
 *
3749
 * see https://github.com/angular/angular/pull/18284
3750
 *
3751
 * @deprecated from v5
3752
 */
3753
class DeprecatedI18NPipesModule {
3754
}
3755
DeprecatedI18NPipesModule.decorators = [
3756
    { type: NgModule, args: [{ declarations: [], exports: [] },] },
3757
];
3758
/**
3759
 * @nocollapse
3760
 */
3761
DeprecatedI18NPipesModule.ctorParameters = () => [];
3762

    
3763
/**
3764
 * @license
3765
 * Copyright Google Inc. All Rights Reserved.
3766
 *
3767
 * Use of this source code is governed by an MIT-style license that can be
3768
 * found in the LICENSE file at https://angular.io/license
3769
 */
3770
/**
3771
 * A DI Token representing the main rendering context. In a browser this is the DOM Document.
3772
 *
3773
 * Note: Document might not be available in the Application Context when Application and Rendering
3774
 * Contexts are not the same (e.g. when running the application into a Web Worker).
3775
 *
3776
 * \@stable
3777
 */
3778
const DOCUMENT = new InjectionToken('DocumentToken');
3779

    
3780
/**
3781
 * @license
3782
 * Copyright Google Inc. All Rights Reserved.
3783
 *
3784
 * Use of this source code is governed by an MIT-style license that can be
3785
 * found in the LICENSE file at https://angular.io/license
3786
 */
3787
const PLATFORM_BROWSER_ID = 'browser';
3788
const PLATFORM_SERVER_ID = 'server';
3789
const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
3790
const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
3791
/**
3792
 * Returns whether a platform id represents a browser platform.
3793
 * \@experimental
3794
 * @param {?} platformId
3795
 * @return {?}
3796
 */
3797
function isPlatformBrowser(platformId) {
3798
    return platformId === PLATFORM_BROWSER_ID;
3799
}
3800
/**
3801
 * Returns whether a platform id represents a server platform.
3802
 * \@experimental
3803
 * @param {?} platformId
3804
 * @return {?}
3805
 */
3806
function isPlatformServer(platformId) {
3807
    return platformId === PLATFORM_SERVER_ID;
3808
}
3809
/**
3810
 * Returns whether a platform id represents a web worker app platform.
3811
 * \@experimental
3812
 * @param {?} platformId
3813
 * @return {?}
3814
 */
3815
function isPlatformWorkerApp(platformId) {
3816
    return platformId === PLATFORM_WORKER_APP_ID;
3817
}
3818
/**
3819
 * Returns whether a platform id represents a web worker UI platform.
3820
 * \@experimental
3821
 * @param {?} platformId
3822
 * @return {?}
3823
 */
3824
function isPlatformWorkerUi(platformId) {
3825
    return platformId === PLATFORM_WORKER_UI_ID;
3826
}
3827

    
3828
/**
3829
 * @license
3830
 * Copyright Google Inc. All Rights Reserved.
3831
 *
3832
 * Use of this source code is governed by an MIT-style license that can be
3833
 * found in the LICENSE file at https://angular.io/license
3834
 */
3835
/**
3836
 * @module
3837
 * @description
3838
 * Entry point for all public APIs of the common package.
3839
 */
3840
/**
3841
 * \@stable
3842
 */
3843
const VERSION = new Version('4.4.6');
3844

    
3845
/**
3846
 * @license
3847
 * Copyright Google Inc. All Rights Reserved.
3848
 *
3849
 * Use of this source code is governed by an MIT-style license that can be
3850
 * found in the LICENSE file at https://angular.io/license
3851
 */
3852
/**
3853
 * @module
3854
 * @description
3855
 * Entry point for all public APIs of the common package.
3856
 */
3857

    
3858
/**
3859
 * @license
3860
 * Copyright Google Inc. All Rights Reserved.
3861
 *
3862
 * Use of this source code is governed by an MIT-style license that can be
3863
 * found in the LICENSE file at https://angular.io/license
3864
 */
3865
/**
3866
 * @module
3867
 * @description
3868
 * Entry point for all public APIs of the common package.
3869
 */
3870

    
3871
// This file only reexports content of the `src` folder. Keep it that way.
3872

    
3873
/**
3874
 * Generated bundle index. Do not edit.
3875
 */
3876

    
3877
export { NgLocaleLocalization, NgLocalization, parseCookieValue as ɵparseCookieValue, CommonModule, DeprecatedI18NPipesModule, NgClass, NgFor, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe, PLATFORM_BROWSER_ID as ɵPLATFORM_BROWSER_ID, PLATFORM_SERVER_ID as ɵPLATFORM_SERVER_ID, PLATFORM_WORKER_APP_ID as ɵPLATFORM_WORKER_APP_ID, PLATFORM_WORKER_UI_ID as ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi, VERSION, PlatformLocation, LOCATION_INITIALIZED, LocationStrategy, APP_BASE_HREF, HashLocationStrategy, PathLocationStrategy, Location, COMMON_DIRECTIVES as ɵa, COMMON_PIPES as ɵb };
3878
//# sourceMappingURL=common.js.map
(3-3/4)