Skip to content

Instantly share code, notes, and snippets.

@rohmann
Last active December 7, 2016 04:11
Show Gist options
  • Save rohmann/80427e7c56cb2d66fe4125f4a18559bd to your computer and use it in GitHub Desktop.
Save rohmann/80427e7c56cb2d66fe4125f4a18559bd to your computer and use it in GitHub Desktop.
runtime markup
import Ember from 'ember';
export default Ember.Component.extend({
tagName: '',
markup: Ember.computed('state',function(){
return `<div><strong>${this.get('state')}</strong><div><!--morph:yield--></div></div>`;
}),
});
import Ember from 'ember';
export default Ember.Component.extend({
markup: null,
markupNormalized: Ember.computed('markup', function() {
return Ember.String.htmlSafe(this.get('markup'));
}),
yieldMorph: Ember.computed(function() {
return this.findMorph('yield');
}).readOnly(),
yieldedNodes: Ember.computed(function() {
let start = this.findMorph('start');
let end = this.findMorph('end');
let cursor = start.nextSibling;
let nodes = [];
while (cursor !== end) {
nodes.push(cursor);
cursor = cursor.nextSibling;
}
return [].concat(start, nodes, end);
}).readOnly(),
findMorph(name) {
let target = `morph:${name}`;
return (function recur(element) {
let cursor = element.firstChild;
while (cursor) {
if (cursor.nodeType === document.COMMENT_NODE && cursor.nodeValue === target) {
return cursor;
}
let found = recur(cursor);
if (found) {
return found;
}
cursor = cursor.nextSibling;
}
return null;
})(this.element);
},
swapNodes() {
let fragment = document.createDocumentFragment();
let morph = this.get('yieldMorph');
let nodes = this.get('yieldedNodes');
let swapper = document.createTextNode('');
let first = nodes[0];
first.parentNode.insertBefore(swapper, first);
nodes.forEach(node => {
fragment.appendChild(node);
});
Ember.$(morph).replaceWith(fragment);
Ember.$(swapper).replaceWith(morph);
},
didInsertElement() {
this._super(...arguments);
this.initialSwap = true;
},
didRender() {
this._super(...arguments);
this.swapNodes();
},
willRender() {
this._super(...arguments);
if ( this.initialSwap ) {
this.swapNodes();
}
},
willDestroyElement() {
this._super(...arguments);
this.swapNodes();
}
});
import Ember from 'ember';
export default Ember.Controller.extend({
state: 0,
actions: {
updateMarkup() {
this.incrementProperty('state')
}
}
});
<button {{action 'updateMarkup'}}>update</button>
{{invoking-component state=state}}
{{#runtime-markup markup=markup}}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
{{/runtime-markup}}
{{markupNormalized}}
<!--morph:start-->{{yield}}<!--morph:end-->
{
"version": "0.10.6",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.9.0",
"ember-data": "2.9.0",
"ember-template-compiler": "2.9.0",
"ember-testing": "2.9.0"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment