Merge pull request #1 from sjmiles/master

Initial Components
This commit is contained in:
Steve Orvell 2012-10-10 12:55:52 -07:00
commit ba5e8cd071
4 changed files with 181 additions and 17 deletions

View File

@ -1,20 +1,5 @@
# Toolkitchen:Toolkit
Cutting-edge code for web-application development utilizing the latest browser technologies, e.g. Shadow DOM, Custom DOM Elements, Model Driven Views.
Source files for Components that implement the Toolkitchen Toolkit.
Emphasis on modularity and encapsulation via a Component model.
Be declarative, Say What You Mean (SWYM).
## Dependencies
Code herein depends on the polyfills in toolkitchen/polyfills/Components. THe dependencies are satisfied by loading _components-polyfill.js_ from that checkout.
## Browser Support
tbd
## Documentation
tbd
See Toolkitchen:ToolkitchenSink for the complete package.

22
src/css/g-icon.css Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright 2012 The Toolkitchen Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@host {
display: inline-block;
opacity: 0.65;
}
@host:hover {
opacity: 0.8;
}
.icon {
width: 21px;
height: 21px;
cursor: pointer;
background-position: center;
background-repeat: no-repeat;
background-size: contain;
}

128
src/g-component.html Normal file
View File

@ -0,0 +1,128 @@
<!--
Copyright 2012 The Toolkitchen Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<element name="g-component">
<script>
this.lifecycle({
shadowRootCreated: function() {
}
});
</script>
<script>
(function(){
var bindAttrs = function(inAttrs) {
inAttrs.forEach(function(a) {
a = a.trim();
Object.defineProperty(this, a, {
get: function() {
return this.getAttribute(a);
},
set: function(v) {
return this.setAttribute(a, v);
}
})
}, this);
};
var deref = function(inNode) {
return inNode.baby || inNode;
};
var establishNodeReferences = function(inRoot) {
this.$ = this.$ || {};
var nodes = inRoot.querySelectorAll("[id]");
Array.prototype.forEach.call(nodes, function(n) {
this.$[n.id] = deref(n);
}, this);
};
var handleMutations = function(inMxns) {
inMxns.forEach(function(inMxn) {
var name = inMxn.attributeName, method = name + "AttributeChanged";
if (this[method]) {
this[method](inMxn.target.getAttribute(name), inMxn.oldValue);
}
}, this);
};
var AttrObserver = function(inNode) {
var observer = new WebKitMutationObserver(handleMutations.bind(inNode));
observer.observe(inNode, {
attributes: true,
attributeOldValue: true
});
return observer;
};
var $ = document.querySelector.bind(document);
var nodeIterator = function(inNodes, inFn) {
if (inNodes) {
for (var i=0, n; (n=inNodes[i]); i++) {
var v = inFn(n);
if (v !== undefined) {
return v;
}
}
}
};
var inPublicTree = function(inNodes, inNode) {
return nodeIterator(inNodes, function(n) {
if (inNode == n || inPublicTree(n.lightDom, inNode)) {
return true;
}
});
};
var findOwner = function(inNode) {
// find the root of the LOCAL tree that contains 'this'
//
// find a parent who is a component
// ask if we are in his LOCAL tree
// repeat
//
var t = inNode.parentNode;
while (t) {
if (t.__upgraded__) {
if (inPublicTree(t.childNodes, inNode)) {
return t;
};
}
t = t.parentNode;
}
};
// experimental event handler for mapping events to component instances
// publish handler globally, make name as small as possible since
// this is ideally an invisible helper API
x = function(inHandler) {
var owner = findOwner(event.currentTarget);
//console.log(inHandler, owner, event);
if (owner && owner[inHandler]) {
owner[inHandler](event);
}
};
HTMLElementElement.prototype.component = function(inUber) {
var attributes = this.element.getAttribute("attributes").split(",");
//var events = this.getAttribute("events");
this.lifecycle({
shadowRootCreated: function(inRoot) {
bindAttrs.call(this, attributes);
establishNodeReferences.call(this, inRoot);
if (inUber.shadowRootCreated) {
inUber.shadowRootCreated(inRoot);
}
this.attrObserver = new AttrObserver(this);
},
created: inUber.created
});
this.generatedConstructor.prototype = inUber.prototype;
};
})();
</script>
</element>

29
src/g-icon.html Normal file
View File

@ -0,0 +1,29 @@
<!--
Copyright 2012 The Toolkitchen Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<element name="g-icon" attributes="src" onclick="click" onselect="tabSelected">
<link rel="components" href="g-component.html">
<link rel="stylesheet" href="css/g-icon.css">
<template>
<div id="icon" class="icon" onclick="x('colorize')"></div>
</template>
<script>
this.component({
created: function(inSuper) {
this.srcAttributeChanged();
},
prototype: {
// note: this is called asyncronously. can we live with this?
srcAttributeChanged: function() {
this.$.icon.style.backgroundImage =
this.src ? 'url(' + this.src + ')' : null;
},
colorize: function() {
this.style.backgroundColor = "orange";
}
}
});
</script>
</element>