parent
b2e6ad85ea
commit
d599fd3434
@ -1,6 +1,6 @@
|
|||||||
import * as ldModule from './light_dom';
|
import * as ldModule from './light_dom';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {isPresent} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
class ContentStrategy {
|
class ContentStrategy {
|
||||||
@ -20,7 +20,6 @@ class RenderedContent extends ContentStrategy {
|
|||||||
constructor(contentEl) {
|
constructor(contentEl) {
|
||||||
super();
|
super();
|
||||||
this.beginScript = contentEl;
|
this.beginScript = contentEl;
|
||||||
this.endScript = DOM.nextSibling(this.beginScript);
|
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,15 +27,23 @@ class RenderedContent extends ContentStrategy {
|
|||||||
// Previous content is removed.
|
// Previous content is removed.
|
||||||
insert(nodes: List</*node*/ any>) {
|
insert(nodes: List</*node*/ any>) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
|
|
||||||
|
if (isBlank(this.endScript)) {
|
||||||
|
// On first invocation, we need to create the end marker
|
||||||
|
this.endScript = DOM.createScriptTag('type', 'ng/contentEnd');
|
||||||
|
DOM.insertAfter(this.beginScript, this.endScript);
|
||||||
|
} else {
|
||||||
|
// On subsequent invocations, only remove all the nodes between the start end end markers
|
||||||
|
this._removeNodes();
|
||||||
|
}
|
||||||
|
|
||||||
DOM.insertAllBefore(this.endScript, nodes);
|
DOM.insertAllBefore(this.endScript, nodes);
|
||||||
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeNodesUntil(node) {
|
_removeNodes() {
|
||||||
var p = DOM.parentElement(this.beginScript);
|
for (var node = DOM.nextSibling(this.beginScript); node !== this.endScript;
|
||||||
for (var next = DOM.nextSibling(this.beginScript); next !== node;
|
node = DOM.nextSibling(this.beginScript)) {
|
||||||
next = DOM.nextSibling(this.beginScript)) {
|
DOM.remove(node);
|
||||||
DOM.removeChild(p, next);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,15 @@ export class ShadowDomCompileStep implements CompileStep {
|
|||||||
var selector = MapWrapper.get(attrs, 'select');
|
var selector = MapWrapper.get(attrs, 'select');
|
||||||
selector = isPresent(selector) ? selector : '';
|
selector = isPresent(selector) ? selector : '';
|
||||||
|
|
||||||
|
// The content tag should be replaced by a pair of marker tags (start & end).
|
||||||
|
// The end marker creation is delayed to keep the number of elements constant.
|
||||||
|
// Creating the end marker here would invalidate the parent's textNodeIndices for the subsequent
|
||||||
|
// text nodes
|
||||||
var contentStart = DOM.createScriptTag('type', 'ng/contentStart');
|
var contentStart = DOM.createScriptTag('type', 'ng/contentStart');
|
||||||
if (assertionsEnabled()) {
|
if (assertionsEnabled()) {
|
||||||
DOM.setAttribute(contentStart, 'select', selector);
|
DOM.setAttribute(contentStart, 'select', selector);
|
||||||
}
|
}
|
||||||
var contentEnd = DOM.createScriptTag('type', 'ng/contentEnd');
|
|
||||||
DOM.insertBefore(current.element, contentStart);
|
DOM.insertBefore(current.element, contentStart);
|
||||||
DOM.insertBefore(current.element, contentEnd);
|
|
||||||
DOM.remove(current.element);
|
DOM.remove(current.element);
|
||||||
|
|
||||||
current.element = contentStart;
|
current.element = contentStart;
|
||||||
|
@ -13,7 +13,6 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
|||||||
import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag';
|
import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag';
|
||||||
|
|
||||||
var _scriptStart = `<script start=""></script>`;
|
var _scriptStart = `<script start=""></script>`;
|
||||||
var _scriptEnd = `<script end=""></script>`;
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('Content', function() {
|
describe('Content', function() {
|
||||||
@ -21,35 +20,32 @@ export function main() {
|
|||||||
var content;
|
var content;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
parent = el(`<div>${_scriptStart}${_scriptEnd}`);
|
parent = el(`<div>${_scriptStart}</div>`);
|
||||||
content = DOM.firstChild(parent);
|
let contentStartMarker = DOM.firstChild(parent);
|
||||||
|
content = new Content(contentStartMarker, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should insert the nodes", () => {
|
it("should insert the nodes", () => {
|
||||||
var c = new Content(content, '');
|
content.init(null);
|
||||||
c.init(null);
|
content.insert([el("<a>A</a>"), el("<b>B</b>")]);
|
||||||
c.insert([el("<a></a>"), el("<b></b>")])
|
|
||||||
|
|
||||||
expect(DOM.getInnerHTML(parent))
|
expect(parent).toHaveText('AB');
|
||||||
.toEqual(`${_scriptStart}<a></a><b></b>${_scriptEnd}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove the nodes from the previous insertion", () => {
|
it("should remove the nodes from the previous insertion", () => {
|
||||||
var c = new Content(content, '');
|
content.init(null);
|
||||||
c.init(null);
|
content.insert([el("<a>A</a>")]);
|
||||||
c.insert([el("<a></a>")]);
|
content.insert([el("<b>B</b>")]);
|
||||||
c.insert([el("<b></b>")]);
|
|
||||||
|
|
||||||
expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}<b></b>${_scriptEnd}`);
|
expect(parent).toHaveText('B');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should insert empty list", () => {
|
it("should clear nodes on inserting an empty list", () => {
|
||||||
var c = new Content(content, '');
|
content.init(null);
|
||||||
c.init(null);
|
content.insert([el("<a>A</a>")]);
|
||||||
c.insert([el("<a></a>")]);
|
content.insert([]);
|
||||||
c.insert([]);
|
|
||||||
|
|
||||||
expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`);
|
expect(parent).toHaveText('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
it,
|
it,
|
||||||
xit,
|
xit,
|
||||||
beforeEachBindings,
|
beforeEachBindings,
|
||||||
SpyObject,
|
SpyObject
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {bind} from 'angular2/di';
|
import {bind} from 'angular2/di';
|
||||||
@ -34,6 +34,10 @@ import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
|||||||
|
|
||||||
import {DomTestbed} from './dom_testbed';
|
import {DomTestbed} from './dom_testbed';
|
||||||
|
|
||||||
|
import {Injectable} from 'angular2/di';
|
||||||
|
|
||||||
|
import {Component, View} from 'angular2/annotations';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('ShadowDom integration tests', function() {
|
describe('ShadowDom integration tests', function() {
|
||||||
var strategies = {
|
var strategies = {
|
||||||
@ -60,6 +64,26 @@ export function main() {
|
|||||||
beforeEachBindings(() => { return [strategyBinding, DomTestbed]; });
|
beforeEachBindings(() => { return [strategyBinding, DomTestbed]; });
|
||||||
|
|
||||||
describe(`${name} shadow dom strategy`, () => {
|
describe(`${name} shadow dom strategy`, () => {
|
||||||
|
// GH-2095 - https://github.com/angular/angular/issues/2095
|
||||||
|
it('should support text nodes after content tags',
|
||||||
|
inject([DomTestbed, AsyncTestCompleter], (tb, async) => {
|
||||||
|
tb.compileAll([
|
||||||
|
simple,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'simple',
|
||||||
|
template: '<content></content><p>P,</p>{{a}}',
|
||||||
|
directives: []
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
|
||||||
|
tb.renderer.setText(cmpView.viewRef, 0, 'text');
|
||||||
|
expect(tb.rootEl).toHaveText('P,text');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
it('should support simple components',
|
it('should support simple components',
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user