I am digging messing about with Polymer.dart and Shadow DOM. That's some good clean fun.
Without much difficulty, I have used Polymer to create an
<ice-code-editor> tag that embeds nicely into a regular web page:
It seems that it was easy, in part, because I cheated. The actual code editor is not part of the shadow DOM that contains the title of the element:

In some respects, this might qualify as no-harm, no-foul. After all, it works and no harm is being caused by the ICE Code Editor being part of the main DOM tree. On the other hand, encapsulating all of a Polymer element inside the shadow DOM can keep the contents secure. More relevant to this particular case, it will prevent conflicts between elements. ICE has been developed primarily for a one-instance-per-page use case. It might work with multiple instances, but why risk conflicts if I don't have to?
Anyhow, tonight, I am going to attempt to drive the editor into the shadow DOM using tests (that's a pretty cool sentence, eh?). After last night, I already have some tests that are probing the shadow DOM:
test("can set line number", (){
expect(
query('ice-code-editor').shadowRoot.query('h1').text,
contains('(42)')
);
});Using that test as a basis, I can describe my expectations as: test("creates an editor and preview", (){
expect(
query('ice-code-editor').shadowRoot.query('.ice-code-editor-editor'),
isNotNull
);
expect(
query('ice-code-editor').shadowRoot.query('.ice-code-editor-preview'),
isNotNull
);
});And, just like that, I have a failing test:PASS: [polymer] can embed code
PASS: [polymer] can set line number
FAIL: [polymer] creates an editor and preview
Expected: not null
Actual: <null>A quick look at my Polymer code shows where I need to address the situation:@CustomTag('ice-code-editor')
class IceCodeEditorElement extends PolymerElement with ObservableMixin {
@published String src;
@published int line_number;
void created() {
super.created();
var container = new DivElement();
host.append(container);
var editor = new ICE.Editor(container);
// Other setup...
}
}Instead of adding the container element to the document, I need only add it to the Polymer element's shadow root:@CustomTag('ice-code-editor')
class IceCodeEditorElement extends PolymerElement with ObservableMixin {
@published String src;
@published int line_number;
void created() {
super.created();
var container = new DivElement();
shadowRoot.append(container);
var editor = new ICE.Editor(container);
// Other setup...
}
}Easy peasy. Except, of course, it does not work at all.It turns out that the JavaScript code editor (ACE code editor) that is being used via js-interop does a lot of mucking with the DOM. The real DOM. The DOM that needs to have access to
document and various top-level methods.So I am pretty much out of luck in trying to add the editor to the shadow DOM. At least until the underlying JavaScript code supports the shadow DOM. That said, I am not at a complete dead end. Even though the editor part of ICE cannot be added to the shadow DOM, the preview layer can be:
test("creates a shadow preview", (){
expect(
query('ice-code-editor').shadowRoot.query('.ice-code-editor-preview'),
isNotNull
);
});I make that test pass by adding a <div> to the shadow DOM and then passing it to the ICE Editor constructor:@CustomTag('ice-code-editor')
class IceCodeEditorElement extends PolymerElement with ObservableMixin {
// ...
void created() {
super.created();
var container = new DivElement();
host.append(container);
var preview_el = new DivElement();
shadowRoot.append(preview_el);
var editor = new ICE.Editor(container, preview_el: preview_el);
// Other setup...
}
}Now that I think about it, it will not hurt to test that the editor is added to the main DOM tree as well: test("creates an editor", (){
expect(
query('ice-code-editor').query('.ice-code-editor-editor'),
isNotNull
);
});With that, I have four passing tests:PASS: [polymer] can embed code PASS: [polymer] can set line number PASS: [polymer] creates a shadow preview PASS: [polymer] creates an editor All 4 tests passed.Best of all, I drove new behavior—element encapsulation—with tests. At some point I will need to verify that multiple instances of
<ice-code-editor> on the same page will not cause trouble, but I will leave that for another day. This first pass at TDDing Polymer.dart features seems a fine stopping point for tonight.Day #892
No comments:
Post a Comment