Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
design a polymer-element via x-design-host
Browse files Browse the repository at this point in the history
  • Loading branch information
sorvell committed Apr 7, 2014
1 parent 5bbc698 commit 30ed1c6
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 70 deletions.
169 changes: 169 additions & 0 deletions elements/x-design-host/x-design-host.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<polymer-element name="x-design-host">
<script>
(function() {

Polymer('x-design-host', {

name: 'my-element',

ready: function() {
this.model = {};
this.treeInfo = {name: this.name, id: ''};
},

dumpTag: function(serializer, indent, tab) {
var indented = indent + tab, attrs = '';
var attrs = this.dumpAttributes();
return indent + '<polymer-element' + attrs + '>\n\n' +
indented + '<template>\n' +
serializer.dumpChildren(this,indented + tab) +
indented + '</template>\n\n' +
indented + '<sc' + 'ript>\n\n' +
indented + tab + this.dumpScript(indented + tab, tab) +
indented + '</sc' + 'ript>\n\n' +
indent + '</polymer-element>';
},

dumpAttributes: function() {
var attrs = '';
var a$ = this.polymerElement ? this.polymerElement.attributes :
[{name: 'name', value: this.name}];
for (var i=0, a; (a=a$[i]); i++) {
attrs += ' ' + a.name + '="' + a.value + '"';
}
return attrs;
},

dumpScript: function(indent, tab) {
var s = 'Polymer(\'' + this.name + '\', {\n' + indent + tab;
var props = [];
Object.keys(this.model).forEach(function(k) {
if (serializeScriptBlacklist.indexOf(k) < 0) {
props.push(serializePropertyValue(k, this.model));
}
}, this);
s += props.join(',\n' + indent + tab);
s += '\n' + indent + '});' + '\n\n';
return s;
},

loadHtml: function(html, callback) {
var raw = document.createElement('div');
raw.innerHTML = html;
// remove imports
var imports = raw.querySelectorAll('link[rel=import]').array();
imports.forEach(function(i) {
i.remove();
});
// absorb polymer-element
this.polymerElement = raw.querySelector('polymer-element');
// absorb script
this.scriptElement = this.polymerElement.querySelector('script');
this.model = this.modelFromScript(this.scriptElement);
// absorb template
var template = this.polymerElement.querySelector('template');
if (template) {
template.bindingDelegate = this.syntax;
// make imports go...
this.loadElementImports(template.content, function() {
this.appendChild(template.createInstance(this.model));
this.meta.ensureMeta(this);
this.marshalNodeReferences(this);
this.model.$ = this.$;
callback && callback();
}.bind(this));
} else if (callback) {
callback();
}
},

loadElementImports: function(element, callback) {
var pending = 1;
var receive = function() {
pending--;
checkDone();
}
var checkDone = function() {
if (pending == 0 && callback) {
callback();
}
};
var n$ = element.querySelectorAll('*');
for (var i=0, l=n$.length, n, m; (i<l) && (n=n$[i]); i++) {
m = this.meta.byId(n.localName);
if (m && !m.importsLoaded) {
pending++;
m.loadImports(receive);
}
}
receive();
},

modelFromScript: function(script) {
var p = executePolymerScript(script);
return p || {};
},

_getInspectorProps: function() {
return this.model;
}

});

var serializeScriptBlacklist = ['$'];

function serializePropertyValue(name, obj) {
var value = obj[name], type = typeof value;
switch(type) {
case 'function':
value = value.toString();
break;
case 'string':
value = '\'' + value + '\'';
break;
}
return name + ': ' + value;
}

// this is not secure, it's just intended to make it harder to accidentally
// mess up the main document.
var frame = document.createElement('iframe');
frame.style.display = 'none';
document.body.appendChild(frame);
frame.src = '';

function executePolymerScript(script) {
if (!frame.contentWindow.Polymer) {
frame.contentWindow.Polymer = function(name, model) {
var model = typeof name === 'object' ? name : model;
frame.contentWindow.model = model;
}
}
try {
var code = script.textContent.trim();
frame.contentWindow.eval(code);
} catch(e) {
console.log(e);
}
var r = frame.contentWindow.model;
frame.contentWindow.model = null;
return r;
}

function executeScriptsInScope(scope) {
// make scripts go....
var s$ = scope.querySelectorAll('script:not([src])');
for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
replaceAndExecuteScript(s);
}
}

function replaceAndExecuteScript(script) {
var newScript = document.createElement('script');
script.parentNode.replaceChild(newScript, script);
newScript.textContent = script.textContent;
}

})();
</script>
</polymer-element>
84 changes: 23 additions & 61 deletions elements/x-designable/x-designable.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<link rel="import" href="../../components/polymer/polymer.html">
<link rel="import" href="../x-design-host/x-design-host.html">

<polymer-element name="x-designable" designer attributes="selected" on-keydown="{{keydown}}" on-pointerdown="{{pointerDown}}" on-pointerup="{{pointerUp}}" on-trackstart="{{trackStart}}" on-track="{{track}}" on-trackend="{{trackEnd}}">

Expand Down Expand Up @@ -29,6 +30,8 @@

ready: function() {
this.meta = document.createElement('x-meta');
this.makeDesignHost();
this.appendChild(this.designHost);
},

// communication
Expand All @@ -46,6 +49,11 @@
},

// commands
addElement: function(element) {
this.designHost.appendChild(element);
this.decorateElement(element);
},

deleteElement: function() {
var e = this.selected;
if (e && e !== this) {
Expand Down Expand Up @@ -91,7 +99,6 @@
},

update: function() {
this.marshalNodeReferences(this);
},

//
Expand Down Expand Up @@ -166,7 +173,7 @@
s.webkitTransition = null;
// designer is absolutely positioned, ad-hoc
s.position = 'absolute';
if (element.parentNode !== this) {
if (element.parentNode !== this.designHost) {
s.left = s.top = s.position = '';
}
var self = this;
Expand Down Expand Up @@ -211,7 +218,7 @@
target.removeAttribute(name);
}
if (path) {
target.bind(name, new PathObserver(this, path));
target.bind(name, new PathObserver(this.designHost.model, path));
}
},

Expand Down Expand Up @@ -311,8 +318,11 @@
},

findContainer: function(element, container) {
if (container === this) {
container = this.designHost;
}
while (container) {
if (container === this || element !== container && container.meta && container.meta.isContainer) {
if (container === this.designHost || element !== container && container.meta && container.meta.isContainer) {
return container;
}
container = container.parentNode;
Expand All @@ -338,7 +348,7 @@
// nominal target
elt = target;
// find top level parent
while (elt && elt.parentNode !== this) {
while (elt && elt.parentNode !== this.designHost) {
elt = elt.parentNode;
}
}
Expand Down Expand Up @@ -372,59 +382,25 @@
editorElements: {input: 1, select: 1, textarea: 1},

loadHtml: function(html) {
// TODO(sorvell): what should we bind to? for right now, we bind
// to 'this', but we should bind to some element that we're designing...
var template = document.createElement('template');
template.bindingDelegate = this.syntax;
template.innerHTML = html;
this.sanitizeContent(template.content);
this.innerHTML = '';
// make imports go...
this.loadElementImports(template.content, function() {
this.appendChild(template.createInstance(this));
executeScriptsInScope(this);
this.meta.ensureMeta(this);
this.update();
this.makeDesignHost();
this.designHost.loadHtml(html, function() {
this.appendChild(this.designHost);
this.notify();
}.bind(this));
},

sanitizeContent: function(element) {
// remove imports so that we don't have to keep track of them
var imports = element.querySelectorAll('link[rel=import]').array();
imports.forEach(function(i) {
i.remove();
});
},

loadElementImports: function(element, callback) {
var pending = 1;
var receive = function() {
pending--;
checkDone();
}
var checkDone = function() {
if (pending == 0 && callback) {
callback();
}
};
var n$ = element.querySelectorAll('*');
for (var i=0, l=n$.length, n, m; (i<l) && (n=n$[i]); i++) {
m = this.meta.byId(n.localName);
if (m && !m.importsLoaded) {
pending++;
m.loadImports(receive);
}
}
receive();
makeDesignHost: function() {
this.designHost = document.createElement('x-design-host');
this.designHost.meta = this.meta;
},

setupStyleElement: function() {
var s = this.querySelector('style');
if (!s) {
s = document.createElement('style');
s.textContent = ' ';
this.insertBefore(s, this.firstElementChild);
this.designHost.insertBefore(s, this.designHost.firstElementChild);
}
this.styleElement = s;
},
Expand All @@ -451,8 +427,8 @@
if (!rules[i]) {
sheet.insertRule('#' + element.id + '{' + element.style.cssText + '}',
i);
element.style.cssText = '';
}
element.style.cssText = '';
return rules[i];
},

Expand All @@ -475,20 +451,6 @@

});

function executeScriptsInScope(scope) {
// make scripts go....
var s$ = scope.querySelectorAll('script:not([src])');
for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
replaceAndExecuteScript(s);
}
}

function replaceAndExecuteScript(script) {
var newScript = document.createElement('script');
script.parentNode.replaceChild(newScript, script);
newScript.textContent = script.textContent;
}

function cssTextFromStyle(style) {
var sheet = style && style.sheet;
if (sheet) {
Expand Down
3 changes: 1 addition & 2 deletions elements/x-designer/x-designer.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@
createElement: function(tag) {
var meta = this.$.meta.byId(tag);
var element = meta.createElement();
this.$.canvas.appendChild(element);
this.$.canvas.decorateElement(element);
this.$.canvas.addElement(element);
return element;
},

Expand Down
6 changes: 3 additions & 3 deletions elements/x-dom-serializer/x-dom-serializer.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
attributesBlacklist: ['style', 'tabindex', 'role'],
dumpTag: function(node, indent) {
if (node.dumpTag) {
return node.dumpTag(this.dumpTab, indent, this.tab);
return node.dumpTag(this, indent, this.tab);
}
if (node.nodeType == Node.TEXT_NODE) {
return this.dumpTextNode(node, indent);
Expand Down Expand Up @@ -110,7 +110,7 @@
dumpElement: function(node, indent) {
var html = '', indent = indent || '';
if (!node.querySelector('link[rel=import]')) {
html+= this.dumpImports(node, indent);
html+= this.dumpImports(node, indent) + '\n';
}
html += this.dumpChildren(node, indent);
//var name = ''; //node.elementAttributes.name || '';
Expand Down Expand Up @@ -229,7 +229,7 @@
}
}
css.push('');
return css.join('\n');
return css.join('\n') + indent;
}
return '';
},
Expand Down
Loading

0 comments on commit 30ed1c6

Please sign in to comment.