Skip to content

Instantly share code, notes, and snippets.

@christospappas
Created January 5, 2015 02:11
Show Gist options
  • Save christospappas/183781edbcf141ce8f20 to your computer and use it in GitHub Desktop.
Save christospappas/183781edbcf141ce8f20 to your computer and use it in GitHub Desktop.
Nucleus: Lightweight Web Components
var Nucleus = {};
Nucleus.components = {};
Nucleus.Component = (function() {
var _elementPrototype;
var _reservedPropertiesRegex = /created|attached|detached|attributeChanged|extends|template/;
function element(tagName, definition) {
_elementPrototype = Object.create(getExtendsPrototype(definition.extends));
attachCallbacks(definition);
attachProperties(definition);
Nucleus.components[tagName] = _elementPrototype;
var registerElementOptions = { prototype: _elementPrototype };
if (definition.extends) {
registerElementOptions.extends = definition.extends;
}
document.registerElement(tagName, registerElementOptions);
};
function getTagPrototype(tag) {
return tag ? HTMLElement.prototype : Object.getPrototypeOf(document.createElement(tag));
};
function getExtendsPrototype(name) {
if (Nucleus.components[name]) {
return Nucleus.components[name];
}
return getTagPrototype(name);
};
function loadTemplate(name) {
var root = this.createShadowRoot();
var link = document.querySelector('link[rel="import"]');
var content = link.import;
var template = content.querySelector('#' + name + 'Template');
var clone = document.importNode(template.content, true);
root.appendChild(clone);
};
function attachCallbacks(definition) {
if (definition.created) {
_elementPrototype.createdCallback = function() {
if (definition.template) {
loadTemplate.call(this, definition.template);
}
Object.observe(this, propertyChanged.bind(this));
definition.created.call(this);
};
}
if (definition.attached) {
_elementPrototype.attachedCallback = definition.attached;
}
if (definition.detached) {
_elementPrototype.detachedCallback = definition.detached;
}
if (definition.attributeChanged) {
_elementPrototype.attributeChangedCallback = definition.attributeChanged;
}
};
function attachProperties(definition) {
for (var key in definition) {
if (key.match(_reservedPropertiesRegex)) {
continue;
}
if (definition.hasOwnProperty(key)) {
_elementPrototype[key] = definition[key];
}
}
};
function propertyChanged(changes) {
changes.forEach((change) => {
var handler = this[change.name + 'Changed'];
if (handler) {
handler.call(this, change);
}
});
};
return element;
})();
export default Nucleus;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment