fix(parse5): support comment nodes with getText and setText

In the browser, calling element.textContent causes child comment
nodes to be ignored, while getting textContent directly on a
comment node will return the comment. This change makes
parse5Adapter consistent with this behavior by adding a 2nd
argument to getText telling if it's being called recursively.

Closes #5805
This commit is contained in:
Jeff Cross 2015-12-10 10:11:39 -08:00 committed by Victor Savkin
parent 194dc7da78
commit 693d9dce5d
4 changed files with 11 additions and 14 deletions

View File

@ -1,7 +1,5 @@
import {Inject, Injectable, OpaqueToken} from 'angular2/src/core/di'; import {Inject, Injectable, OpaqueToken} from 'angular2/src/core/di';
import {AnimationBuilder} from 'angular2/src/animate/animation_builder'; import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import { import {
isPresent, isPresent,
isBlank, isBlank,
@ -42,9 +40,8 @@ import {
DefaultProtoViewRef DefaultProtoViewRef
} from 'angular2/src/core/render/view'; } from 'angular2/src/core/render/view';
import {ViewEncapsulation} from 'angular2/src/core/metadata'; import {ViewEncapsulation} from 'angular2/src/core/metadata';
// TODO move it once DdomAdapter is moved
import {DOM} from 'angular2/src/platform/dom/dom_adapter'; import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {camelCaseToDashCase} from './util';
const NAMESPACE_URIS = const NAMESPACE_URIS =
CONST_EXPR({'xlink': 'http://www.w3.org/1999/xlink', 'svg': 'http://www.w3.org/2000/svg'}); CONST_EXPR({'xlink': 'http://www.w3.org/1999/xlink', 'svg': 'http://www.w3.org/2000/svg'});
@ -162,11 +159,7 @@ export abstract class DomRenderer extends Renderer implements NodeFactory<Node>
var existingBindings = RegExpWrapper.firstMatch( var existingBindings = RegExpWrapper.firstMatch(
TEMPLATE_BINDINGS_EXP, StringWrapper.replaceAll(DOM.getText(element), /\n/g, '')); TEMPLATE_BINDINGS_EXP, StringWrapper.replaceAll(DOM.getText(element), /\n/g, ''));
var parsedBindings = Json.parse(existingBindings[1]); var parsedBindings = Json.parse(existingBindings[1]);
if (isPresent(propertyValue)) { parsedBindings[dashCasedPropertyName] = propertyValue;
parsedBindings[dashCasedPropertyName] = propertyValue;
} else {
StringMapWrapper.delete(parsedBindings, dashCasedPropertyName);
}
DOM.setText(element, StringWrapper.replace(TEMPLATE_COMMENT_TEXT, '{}', DOM.setText(element, StringWrapper.replace(TEMPLATE_COMMENT_TEXT, '{}',
Json.stringify(parsedBindings))); Json.stringify(parsedBindings)));
} else { } else {

View File

@ -239,21 +239,25 @@ export class Parse5DomAdapter extends DomAdapter {
treeAdapter.appendChild(el, content.childNodes[i]); treeAdapter.appendChild(el, content.childNodes[i]);
} }
} }
getText(el): string { getText(el, isRecursive?: boolean): string {
if (this.isTextNode(el)) { if (this.isTextNode(el)) {
return el.data; return el.data;
} else if (this.isCommentNode(el)) {
// In the DOM, comments within an element return an empty string for textContent
// However, comment node instances return the comment content for textContent getter
return isRecursive ? '' : el.data;
} else if (isBlank(el.childNodes) || el.childNodes.length == 0) { } else if (isBlank(el.childNodes) || el.childNodes.length == 0) {
return ""; return "";
} else { } else {
var textContent = ""; var textContent = "";
for (var i = 0; i < el.childNodes.length; i++) { for (var i = 0; i < el.childNodes.length; i++) {
textContent += this.getText(el.childNodes[i]); textContent += this.getText(el.childNodes[i], true);
} }
return textContent; return textContent;
} }
} }
setText(el, value: string) { setText(el, value: string) {
if (this.isTextNode(el)) { if (this.isTextNode(el) || this.isCommentNode(el)) {
el.data = value; el.data = value;
} else { } else {
this.clearNodes(el); this.clearNodes(el);

View File

@ -1613,7 +1613,7 @@ export function main() {
it('should reflect property values on template comments', it('should reflect property values on template comments',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var tpl = '<template [ng-if]="ctxBoolProp"></template>'; var tpl = '<template [ngIf]="ctxBoolProp"></template>';
tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [NgIf]})) tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [NgIf]}))
.createAsync(MyComp) .createAsync(MyComp)

View File

@ -189,7 +189,7 @@ export function main() {
it('should update any template comment property/attributes', it('should update any template comment property/attributes',
inject([TestComponentBuilder, Renderer, AsyncTestCompleter], inject([TestComponentBuilder, Renderer, AsyncTestCompleter],
(tcb: TestComponentBuilder, renderer: Renderer, async) => { (tcb: TestComponentBuilder, renderer: Renderer, async) => {
var tpl = '<template [ng-if]="ctxBoolProp"></template>'; var tpl = '<template [ngIf]="ctxBoolProp"></template>';
tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [NgIf]})) tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [NgIf]}))
.createAsync(MyComp) .createAsync(MyComp)