2015-03-23 14:10:55 -07:00
|
|
|
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
|
|
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
2015-05-18 11:57:20 -07:00
|
|
|
import {
|
|
|
|
int,
|
|
|
|
isBlank,
|
|
|
|
isPresent,
|
|
|
|
Type,
|
|
|
|
StringJoiner,
|
|
|
|
assertionsEnabled
|
|
|
|
} from 'angular2/src/facade/lang';
|
2015-03-23 14:10:55 -07:00
|
|
|
|
|
|
|
import {ProtoViewBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collects all data that is needed to process an element
|
|
|
|
* in the compile process. Fields are filled
|
|
|
|
* by the CompileSteps starting out with the pure HTMLElement.
|
|
|
|
*/
|
|
|
|
export class CompileElement {
|
|
|
|
element;
|
2015-05-18 11:57:20 -07:00
|
|
|
_attrs: Map<string, string>;
|
|
|
|
_classList: List<string>;
|
|
|
|
isViewRoot: boolean;
|
|
|
|
inheritedProtoView: ProtoViewBuilder;
|
|
|
|
distanceToInheritedBinder: number;
|
|
|
|
inheritedElementBinder: ElementBinderBuilder;
|
2015-03-23 14:10:55 -07:00
|
|
|
compileChildren: boolean;
|
2015-05-18 11:57:20 -07:00
|
|
|
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of
|
|
|
|
// error
|
2015-03-23 14:10:55 -07:00
|
|
|
|
|
|
|
constructor(element, compilationUnit = '') {
|
|
|
|
this.element = element;
|
|
|
|
this._attrs = null;
|
|
|
|
this._classList = null;
|
|
|
|
this.isViewRoot = false;
|
|
|
|
// inherited down to children if they don't have
|
|
|
|
// an own protoView
|
|
|
|
this.inheritedProtoView = null;
|
|
|
|
// inherited down to children if they don't have
|
|
|
|
// an own elementBinder
|
|
|
|
this.inheritedElementBinder = null;
|
|
|
|
this.distanceToInheritedBinder = 0;
|
|
|
|
this.compileChildren = true;
|
|
|
|
// description is calculated here as compilation steps may change the element
|
2015-05-18 11:57:20 -07:00
|
|
|
var tplDesc = assertionsEnabled() ? getElementDescription(element) : null;
|
2015-03-23 14:10:55 -07:00
|
|
|
if (compilationUnit !== '') {
|
|
|
|
this.elementDescription = compilationUnit;
|
|
|
|
if (isPresent(tplDesc)) this.elementDescription += ": " + tplDesc;
|
|
|
|
} else {
|
|
|
|
this.elementDescription = tplDesc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isBound() {
|
|
|
|
return isPresent(this.inheritedElementBinder) && this.distanceToInheritedBinder === 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bindElement() {
|
|
|
|
if (!this.isBound()) {
|
|
|
|
var parentBinder = this.inheritedElementBinder;
|
2015-05-18 11:57:20 -07:00
|
|
|
this.inheritedElementBinder =
|
|
|
|
this.inheritedProtoView.bindElement(this.element, this.elementDescription);
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isPresent(parentBinder)) {
|
|
|
|
this.inheritedElementBinder.setParent(parentBinder, this.distanceToInheritedBinder);
|
|
|
|
}
|
|
|
|
this.distanceToInheritedBinder = 0;
|
|
|
|
}
|
|
|
|
return this.inheritedElementBinder;
|
|
|
|
}
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
refreshAttrs() { this._attrs = null; }
|
2015-03-23 14:10:55 -07:00
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
attrs(): Map<string, string> {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isBlank(this._attrs)) {
|
|
|
|
this._attrs = DOM.attributeMap(this.element);
|
|
|
|
}
|
|
|
|
return this._attrs;
|
|
|
|
}
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
refreshClassList() { this._classList = null; }
|
2015-03-23 14:10:55 -07:00
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
classList(): List<string> {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isBlank(this._classList)) {
|
|
|
|
this._classList = ListWrapper.create();
|
|
|
|
var elClassList = DOM.classList(this.element);
|
|
|
|
for (var i = 0; i < elClassList.length; i++) {
|
|
|
|
ListWrapper.push(this._classList, elClassList[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this._classList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// return an HTML representation of an element start tag - without its content
|
|
|
|
// this is used to give contextual information in case of errors
|
2015-05-18 11:57:20 -07:00
|
|
|
function getElementDescription(domElement): string {
|
2015-03-23 14:10:55 -07:00
|
|
|
var buf = new StringJoiner();
|
|
|
|
var atts = DOM.attributeMap(domElement);
|
|
|
|
|
|
|
|
buf.add("<");
|
|
|
|
buf.add(DOM.tagName(domElement).toLowerCase());
|
|
|
|
|
|
|
|
// show id and class first to ease element identification
|
|
|
|
addDescriptionAttribute(buf, "id", MapWrapper.get(atts, "id"));
|
|
|
|
addDescriptionAttribute(buf, "class", MapWrapper.get(atts, "class"));
|
|
|
|
MapWrapper.forEach(atts, (attValue, attName) => {
|
2015-05-18 11:57:20 -07:00
|
|
|
if (attName !== "id" && attName !== "class") {
|
|
|
|
addDescriptionAttribute(buf, attName, attValue);
|
|
|
|
}
|
2015-03-23 14:10:55 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
buf.add(">");
|
|
|
|
return buf.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
function addDescriptionAttribute(buffer: StringJoiner, attName: string, attValue) {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isPresent(attValue)) {
|
2015-05-18 11:57:20 -07:00
|
|
|
if (attValue.length === 0) {
|
|
|
|
buffer.add(' ' + attName);
|
|
|
|
} else {
|
|
|
|
buffer.add(' ' + attName + '="' + attValue + '"');
|
|
|
|
}
|
2015-03-23 14:10:55 -07:00
|
|
|
}
|
|
|
|
}
|