parent
5a59e44765
commit
6402d61f69
|
@ -1,14 +1,16 @@
|
|||
import {isPresent, isString, StringWrapper, isBlank, isArray} from 'angular2/src/facade/lang';
|
||||
import {isPresent, isString, isArray} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
DoCheck,
|
||||
OnDestroy,
|
||||
Directive,
|
||||
ElementRef,
|
||||
IterableDiffer,
|
||||
IterableDiffers,
|
||||
KeyValueDiffer,
|
||||
KeyValueDiffers,
|
||||
Renderer
|
||||
Renderer,
|
||||
IterableDiffer,
|
||||
KeyValueDiffer,
|
||||
CollectionChangeRecord,
|
||||
KeyValueChangeRecord
|
||||
} from 'angular2/core';
|
||||
import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collection';
|
||||
|
||||
|
@ -73,66 +75,68 @@ import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collecti
|
|||
*/
|
||||
@Directive({selector: '[ngClass]', inputs: ['rawClass: ngClass', 'initialClasses: class']})
|
||||
export class NgClass implements DoCheck, OnDestroy {
|
||||
private _differ: any;
|
||||
private _mode: string;
|
||||
private _initialClasses = [];
|
||||
private _rawClass;
|
||||
private _iterableDiffer: IterableDiffer;
|
||||
private _keyValueDiffer: KeyValueDiffer;
|
||||
private _initialClasses: string[] = [];
|
||||
private _rawClass: string[] | Set<string>;
|
||||
|
||||
constructor(private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
|
||||
private _ngEl: ElementRef, private _renderer: Renderer) {}
|
||||
|
||||
set initialClasses(v) {
|
||||
set initialClasses(v: string) {
|
||||
this._applyInitialClasses(true);
|
||||
this._initialClasses = isPresent(v) && isString(v) ? v.split(' ') : [];
|
||||
this._applyInitialClasses(false);
|
||||
this._applyClasses(this._rawClass, false);
|
||||
}
|
||||
|
||||
set rawClass(v) {
|
||||
set rawClass(v: string | string[] | Set<string>| {[key: string]: any}) {
|
||||
this._cleanupClasses(this._rawClass);
|
||||
|
||||
if (isString(v)) {
|
||||
v = v.split(' ');
|
||||
v = (<string>v).split(' ');
|
||||
}
|
||||
|
||||
this._rawClass = v;
|
||||
this._rawClass = <string[] | Set<string>>v;
|
||||
this._iterableDiffer = null;
|
||||
this._keyValueDiffer = null;
|
||||
if (isPresent(v)) {
|
||||
if (isListLikeIterable(v)) {
|
||||
this._differ = this._iterableDiffers.find(v).create(null);
|
||||
this._mode = 'iterable';
|
||||
this._iterableDiffer = this._iterableDiffers.find(v).create(null);
|
||||
} else {
|
||||
this._differ = this._keyValueDiffers.find(v).create(null);
|
||||
this._mode = 'keyValue';
|
||||
this._keyValueDiffer = this._keyValueDiffers.find(v).create(null);
|
||||
}
|
||||
} else {
|
||||
this._differ = null;
|
||||
}
|
||||
}
|
||||
|
||||
ngDoCheck(): void {
|
||||
if (isPresent(this._differ)) {
|
||||
var changes = this._differ.diff(this._rawClass);
|
||||
if (isPresent(this._iterableDiffer)) {
|
||||
var changes = this._iterableDiffer.diff(this._rawClass);
|
||||
if (isPresent(changes)) {
|
||||
if (this._mode == 'iterable') {
|
||||
this._applyIterableChanges(changes);
|
||||
} else {
|
||||
this._applyKeyValueChanges(changes);
|
||||
}
|
||||
}
|
||||
if (isPresent(this._keyValueDiffer)) {
|
||||
var changes = this._keyValueDiffer.diff(this._rawClass);
|
||||
if (isPresent(changes)) {
|
||||
this._applyKeyValueChanges(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void { this._cleanupClasses(this._rawClass); }
|
||||
|
||||
private _cleanupClasses(rawClassVal): void {
|
||||
private _cleanupClasses(rawClassVal: string[] | Set<string>| {[key: string]: any}): void {
|
||||
this._applyClasses(rawClassVal, true);
|
||||
this._applyInitialClasses(false);
|
||||
}
|
||||
|
||||
private _applyKeyValueChanges(changes: any): void {
|
||||
changes.forEachAddedItem((record) => { this._toggleClass(record.key, record.currentValue); });
|
||||
changes.forEachChangedItem((record) => { this._toggleClass(record.key, record.currentValue); });
|
||||
changes.forEachRemovedItem((record) => {
|
||||
changes.forEachAddedItem(
|
||||
(record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
|
||||
changes.forEachChangedItem(
|
||||
(record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
|
||||
changes.forEachRemovedItem((record: KeyValueChangeRecord) => {
|
||||
if (record.previousValue) {
|
||||
this._toggleClass(record.key, false);
|
||||
}
|
||||
|
@ -140,15 +144,17 @@ export class NgClass implements DoCheck, OnDestroy {
|
|||
}
|
||||
|
||||
private _applyIterableChanges(changes: any): void {
|
||||
changes.forEachAddedItem((record) => { this._toggleClass(record.item, true); });
|
||||
changes.forEachRemovedItem((record) => { this._toggleClass(record.item, false); });
|
||||
changes.forEachAddedItem(
|
||||
(record: CollectionChangeRecord) => { this._toggleClass(record.item, true); });
|
||||
changes.forEachRemovedItem(
|
||||
(record: CollectionChangeRecord) => { this._toggleClass(record.item, false); });
|
||||
}
|
||||
|
||||
private _applyInitialClasses(isCleanup: boolean) {
|
||||
this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup));
|
||||
}
|
||||
|
||||
private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: string},
|
||||
private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: any},
|
||||
isCleanup: boolean) {
|
||||
if (isPresent(rawClassVal)) {
|
||||
if (isArray(rawClassVal)) {
|
||||
|
@ -156,14 +162,15 @@ export class NgClass implements DoCheck, OnDestroy {
|
|||
} else if (rawClassVal instanceof Set) {
|
||||
(<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
|
||||
} else {
|
||||
StringMapWrapper.forEach(<{[k: string]: string}>rawClassVal, (expVal, className) => {
|
||||
if (expVal) this._toggleClass(className, !isCleanup);
|
||||
StringMapWrapper.forEach(<{[k: string]: any}>rawClassVal,
|
||||
(expVal: any, className: string) => {
|
||||
if (isPresent(expVal)) this._toggleClass(className, !isCleanup);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _toggleClass(className: string, enabled): void {
|
||||
private _toggleClass(className: string, enabled: boolean): void {
|
||||
className = className.trim();
|
||||
if (className.length > 0) {
|
||||
if (className.indexOf(' ') > -1) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
Renderer
|
||||
} from 'angular2/core';
|
||||
import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
|
||||
import {KVChangeRecord} from "../../core/change_detection/differs/default_keyvalue_differ";
|
||||
import {KeyValueChangeRecord} from "../../core/change_detection/differs/default_keyvalue_differ";
|
||||
|
||||
/**
|
||||
* The `NgStyle` directive changes styles based on a result of expression evaluation.
|
||||
|
@ -88,10 +88,11 @@ export class NgStyle implements DoCheck {
|
|||
|
||||
private _applyChanges(changes: any): void {
|
||||
changes.forEachAddedItem(
|
||||
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
||||
(record: KeyValueChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
||||
changes.forEachChangedItem(
|
||||
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
||||
changes.forEachRemovedItem((record: KVChangeRecord) => { this._setStyle(record.key, null); });
|
||||
(record: KeyValueChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
||||
changes.forEachRemovedItem(
|
||||
(record: KeyValueChangeRecord) => { this._setStyle(record.key, null); });
|
||||
}
|
||||
|
||||
private _setStyle(name: string, val: string): void {
|
||||
|
|
|
@ -21,5 +21,7 @@ export {
|
|||
KeyValueDiffers,
|
||||
KeyValueDiffer,
|
||||
KeyValueDifferFactory,
|
||||
CollectionChangeRecord,
|
||||
KeyValueChangeRecord,
|
||||
TrackByFn
|
||||
} from './change_detection/change_detection';
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
import {IterableDiffers, IterableDifferFactory, TrackByFn} from './differs/iterable_differs';
|
||||
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
|
||||
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
||||
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
||||
import {CONST, CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
DefaultKeyValueDifferFactory,
|
||||
KeyValueChangeRecord
|
||||
} from './differs/default_keyvalue_differ';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
export {
|
||||
DefaultKeyValueDifferFactory,
|
||||
KeyValueChangeRecord
|
||||
} from './differs/default_keyvalue_differ';
|
||||
export {
|
||||
DefaultIterableDifferFactory,
|
||||
CollectionChangeRecord
|
||||
} from './differs/default_iterable_differ';
|
||||
export {
|
||||
ASTWithSource,
|
||||
AST,
|
||||
|
|
|
@ -13,14 +13,14 @@ export class DefaultKeyValueDifferFactory implements KeyValueDifferFactory {
|
|||
|
||||
export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
||||
private _records: Map<any, any> = new Map();
|
||||
private _mapHead: KVChangeRecord = null;
|
||||
private _previousMapHead: KVChangeRecord = null;
|
||||
private _changesHead: KVChangeRecord = null;
|
||||
private _changesTail: KVChangeRecord = null;
|
||||
private _additionsHead: KVChangeRecord = null;
|
||||
private _additionsTail: KVChangeRecord = null;
|
||||
private _removalsHead: KVChangeRecord = null;
|
||||
private _removalsTail: KVChangeRecord = null;
|
||||
private _mapHead: KeyValueChangeRecord = null;
|
||||
private _previousMapHead: KeyValueChangeRecord = null;
|
||||
private _changesHead: KeyValueChangeRecord = null;
|
||||
private _changesTail: KeyValueChangeRecord = null;
|
||||
private _additionsHead: KeyValueChangeRecord = null;
|
||||
private _additionsTail: KeyValueChangeRecord = null;
|
||||
private _removalsHead: KeyValueChangeRecord = null;
|
||||
private _removalsTail: KeyValueChangeRecord = null;
|
||||
|
||||
get isDirty(): boolean {
|
||||
return this._additionsHead !== null || this._changesHead !== null ||
|
||||
|
@ -28,35 +28,35 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
forEachItem(fn: Function) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
for (record = this._mapHead; record !== null; record = record._next) {
|
||||
fn(record);
|
||||
}
|
||||
}
|
||||
|
||||
forEachPreviousItem(fn: Function) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
|
||||
fn(record);
|
||||
}
|
||||
}
|
||||
|
||||
forEachChangedItem(fn: Function) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
for (record = this._changesHead; record !== null; record = record._nextChanged) {
|
||||
fn(record);
|
||||
}
|
||||
}
|
||||
|
||||
forEachAddedItem(fn: Function) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
for (record = this._additionsHead; record !== null; record = record._nextAdded) {
|
||||
fn(record);
|
||||
}
|
||||
}
|
||||
|
||||
forEachRemovedItem(fn: Function) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
|
||||
fn(record);
|
||||
}
|
||||
|
@ -80,9 +80,9 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
check(map: Map<any, any>): boolean {
|
||||
this._reset();
|
||||
var records = this._records;
|
||||
var oldSeqRecord: KVChangeRecord = this._mapHead;
|
||||
var lastOldSeqRecord: KVChangeRecord = null;
|
||||
var lastNewSeqRecord: KVChangeRecord = null;
|
||||
var oldSeqRecord: KeyValueChangeRecord = this._mapHead;
|
||||
var lastOldSeqRecord: KeyValueChangeRecord = null;
|
||||
var lastNewSeqRecord: KeyValueChangeRecord = null;
|
||||
var seqChanged: boolean = false;
|
||||
|
||||
this._forEach(map, (value, key) => {
|
||||
|
@ -104,7 +104,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
if (records.has(key)) {
|
||||
newSeqRecord = records.get(key);
|
||||
} else {
|
||||
newSeqRecord = new KVChangeRecord(key);
|
||||
newSeqRecord = new KeyValueChangeRecord(key);
|
||||
records.set(key, newSeqRecord);
|
||||
newSeqRecord.currentValue = value;
|
||||
this._addToAdditions(newSeqRecord);
|
||||
|
@ -132,7 +132,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
/** @internal */
|
||||
_reset() {
|
||||
if (this.isDirty) {
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
// Record the state of the mapping
|
||||
for (record = this._previousMapHead = this._mapHead; record !== null; record = record._next) {
|
||||
record._nextPrevious = record._next;
|
||||
|
@ -178,7 +178,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_truncate(lastRecord: KVChangeRecord, record: KVChangeRecord) {
|
||||
_truncate(lastRecord: KeyValueChangeRecord, record: KeyValueChangeRecord) {
|
||||
while (record !== null) {
|
||||
if (lastRecord === null) {
|
||||
this._mapHead = null;
|
||||
|
@ -196,7 +196,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
record = nextRecord;
|
||||
}
|
||||
|
||||
for (var rec: KVChangeRecord = this._removalsHead; rec !== null; rec = rec._nextRemoved) {
|
||||
for (var rec: KeyValueChangeRecord = this._removalsHead; rec !== null; rec = rec._nextRemoved) {
|
||||
rec.previousValue = rec.currentValue;
|
||||
rec.currentValue = null;
|
||||
this._records.delete(rec.key);
|
||||
|
@ -204,13 +204,13 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_isInRemovals(record: KVChangeRecord) {
|
||||
_isInRemovals(record: KeyValueChangeRecord) {
|
||||
return record === this._removalsHead || record._nextRemoved !== null ||
|
||||
record._prevRemoved !== null;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_addToRemovals(record: KVChangeRecord) {
|
||||
_addToRemovals(record: KeyValueChangeRecord) {
|
||||
// todo(vicb) assert
|
||||
// assert(record._next == null);
|
||||
// assert(record._nextAdded == null);
|
||||
|
@ -227,7 +227,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_removeFromSeq(prev: KVChangeRecord, record: KVChangeRecord) {
|
||||
_removeFromSeq(prev: KeyValueChangeRecord, record: KeyValueChangeRecord) {
|
||||
var next = record._next;
|
||||
if (prev === null) {
|
||||
this._mapHead = next;
|
||||
|
@ -242,7 +242,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_removeFromRemovals(record: KVChangeRecord) {
|
||||
_removeFromRemovals(record: KeyValueChangeRecord) {
|
||||
// todo(vicb) assert
|
||||
// assert(record._next == null);
|
||||
// assert(record._nextAdded == null);
|
||||
|
@ -264,7 +264,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_addToAdditions(record: KVChangeRecord) {
|
||||
_addToAdditions(record: KeyValueChangeRecord) {
|
||||
// todo(vicb): assert
|
||||
// assert(record._next == null);
|
||||
// assert(record._nextAdded == null);
|
||||
|
@ -280,7 +280,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
_addToChanges(record: KVChangeRecord) {
|
||||
_addToChanges(record: KeyValueChangeRecord) {
|
||||
// todo(vicb) assert
|
||||
// assert(record._nextAdded == null);
|
||||
// assert(record._nextChanged == null);
|
||||
|
@ -300,7 +300,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
var changes = [];
|
||||
var additions = [];
|
||||
var removals = [];
|
||||
var record: KVChangeRecord;
|
||||
var record: KeyValueChangeRecord;
|
||||
|
||||
for (record = this._mapHead; record !== null; record = record._next) {
|
||||
items.push(stringify(record));
|
||||
|
@ -334,22 +334,22 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
|
|||
}
|
||||
|
||||
|
||||
export class KVChangeRecord {
|
||||
export class KeyValueChangeRecord {
|
||||
previousValue: any = null;
|
||||
currentValue: any = null;
|
||||
|
||||
/** @internal */
|
||||
_nextPrevious: KVChangeRecord = null;
|
||||
_nextPrevious: KeyValueChangeRecord = null;
|
||||
/** @internal */
|
||||
_next: KVChangeRecord = null;
|
||||
_next: KeyValueChangeRecord = null;
|
||||
/** @internal */
|
||||
_nextAdded: KVChangeRecord = null;
|
||||
_nextAdded: KeyValueChangeRecord = null;
|
||||
/** @internal */
|
||||
_nextRemoved: KVChangeRecord = null;
|
||||
_nextRemoved: KeyValueChangeRecord = null;
|
||||
/** @internal */
|
||||
_prevRemoved: KVChangeRecord = null;
|
||||
_prevRemoved: KeyValueChangeRecord = null;
|
||||
/** @internal */
|
||||
_nextChanged: KVChangeRecord = null;
|
||||
_nextChanged: KeyValueChangeRecord = null;
|
||||
|
||||
constructor(public key: any) {}
|
||||
|
||||
|
|
|
@ -789,6 +789,7 @@ var NG_CORE = [
|
|||
'ProviderBuilder.token',
|
||||
'ProviderBuilder.token=',
|
||||
'PLATFORM_DIRECTIVES:js',
|
||||
"CollectionChangeRecord",
|
||||
'ChangeDetectionError',
|
||||
'ChangeDetectionError.context',
|
||||
'ChangeDetectionError.location',
|
||||
|
@ -1152,6 +1153,13 @@ var NG_CORE = [
|
|||
'Key.id=',
|
||||
'Key.token',
|
||||
'Key.token=',
|
||||
'KeyValueChangeRecord',
|
||||
'KeyValueChangeRecord.currentValue',
|
||||
'KeyValueChangeRecord.currentValue=',
|
||||
'KeyValueChangeRecord.key',
|
||||
'KeyValueChangeRecord.key=',
|
||||
'KeyValueChangeRecord.previousValue',
|
||||
'KeyValueChangeRecord.previousValue=',
|
||||
'KeyValueDiffers#create()',
|
||||
'KeyValueDiffers#extend()',
|
||||
'KeyValueDiffers',
|
||||
|
|
|
@ -80,6 +80,11 @@ const CORE = [
|
|||
'ClassDefinition',
|
||||
'ClassDefinition.constructor:Function|any[]',
|
||||
'ClassDefinition.extends:Type',
|
||||
'CollectionChangeRecord',
|
||||
'CollectionChangeRecord.constructor(item:any, trackById:any)',
|
||||
'CollectionChangeRecord.currentIndex:number',
|
||||
'CollectionChangeRecord.previousIndex:number',
|
||||
'CollectionChangeRecord.toString():string',
|
||||
'Compiler',
|
||||
'Compiler.clearCache():any',
|
||||
'Compiler.compileInHost(componentType:Type):Promise<HostViewFactoryRef>',
|
||||
|
@ -260,6 +265,11 @@ const CORE = [
|
|||
'Key.displayName:string',
|
||||
'Key.get(token:Object):Key',
|
||||
'Key.numberOfKeys:number',
|
||||
'KeyValueChangeRecord',
|
||||
'KeyValueChangeRecord.constructor(key:any)',
|
||||
'KeyValueChangeRecord.currentValue:any',
|
||||
'KeyValueChangeRecord.previousValue:any',
|
||||
'KeyValueChangeRecord.toString():string',
|
||||
'KeyValueDiffer',
|
||||
'KeyValueDiffer.diff(object:any):any',
|
||||
'KeyValueDiffer.onDestroy():any',
|
||||
|
@ -656,10 +666,10 @@ const COMMON = [
|
|||
'MinLengthValidator.validate(c:Control):{[key:string]:any}',
|
||||
'NgClass',
|
||||
'NgClass.constructor(_iterableDiffers:IterableDiffers, _keyValueDiffers:KeyValueDiffers, _ngEl:ElementRef, _renderer:Renderer)',
|
||||
'NgClass.initialClasses=(v:any)',
|
||||
'NgClass.initialClasses=(v:string)',
|
||||
'NgClass.ngDoCheck():void',
|
||||
'NgClass.ngOnDestroy():void',
|
||||
'NgClass.rawClass=(v:any)',
|
||||
'NgClass.rawClass=(v:string|string[]|Set<string>|{[key:string]:any})',
|
||||
'NgControl',
|
||||
'NgControl.asyncValidator:Function',
|
||||
'NgControl.name:string',
|
||||
|
|
Loading…
Reference in New Issue