|
enyo.kind({ |
|
name: "enyo.TextNode", |
|
kind: "enyo.Control", |
|
tag: null, |
|
setAttribute: enyo.nop, |
|
getAttribute: enyo.nop, |
|
renderContent: function() { |
|
if(this.node) { |
|
this.node.nodeValue = this.content || ""; |
|
} |
|
} |
|
}); |
|
|
|
(function(enyo) { |
|
|
|
var attributeImportMap = { |
|
"class": "classes", |
|
|
|
// name and id are explicitly imported |
|
"name": false, |
|
"id": false |
|
}; |
|
|
|
// special kinds that don't match their element name |
|
var elementToKind = { |
|
"a": "enyo.Anchor", |
|
"img": "enyo.Image", |
|
"textarea": "enyo.TextArea" |
|
}; |
|
|
|
function parseKinds(root) { |
|
var children = []; |
|
for(var i=0, l=root.childNodes.length; i<l; i++) { |
|
var config = parseNode(root.childNodes.item(i)); |
|
config && children.push(config); |
|
} |
|
|
|
return children; |
|
} |
|
|
|
function parseNode(k) { |
|
var config; |
|
// ignore whitespace text nodes |
|
if(k.nodeType === 3) { |
|
if(/\S/.test(k.nodeValue)) { |
|
config = { |
|
kind: "enyo.TextNode", |
|
content: k.nodeValue, |
|
node: k, |
|
generated: true |
|
}; |
|
} |
|
} else if(k.nodeType === 1) { |
|
var comps = parseKinds(k); |
|
var content; |
|
if(comps.length === 1 && comps[0].kind == "enyo.TextNode") { |
|
content = comps[0].content; |
|
comps = null; |
|
} |
|
|
|
config = { |
|
id: k.id, |
|
name: k.getAttribute("name") || k.id, |
|
kind: determineKind(k), |
|
node: k, |
|
generated: true, |
|
components: comps, |
|
content: content, |
|
}; |
|
|
|
importAttributes(k, config) |
|
} |
|
|
|
return config; |
|
} |
|
|
|
function importAttributes(node, config) { |
|
var attr = node.attributes; |
|
for(var i=0, l=attr.length; i<l; i++) { |
|
var a = attr.item(i); |
|
var isData = a.name.substring(0, 5) == "data-"; |
|
|
|
var map = attributeImportMap[a.name]; |
|
if(!(isData || map === false)) { |
|
// if the attr is not in the map or is true, |
|
// use the attr name as the property |
|
var name = (!map || map === true)? a.name : map; |
|
|
|
// hyphen to camelCase |
|
name = name.replace(/-([a-z])/gi, function(s, group1) { |
|
return group1.toUpperCase(); |
|
}); |
|
|
|
var value = a.value; |
|
if(value === "") { |
|
value = true; |
|
} |
|
|
|
config[name] = a.value; |
|
} |
|
} |
|
} |
|
|
|
function determineKind(k) { |
|
var kind = k.getAttribute("data-kind"); |
|
|
|
if(!kind) { |
|
var nodeName = k.nodeName.toLowerCase(); |
|
kind = enyo.cap(nodeName); |
|
if(nodeName === "input") { |
|
if(k.getAttribute("type") === "checkbox") { |
|
kind = "enyo.Checkbox"; |
|
} else { |
|
kind = "enyo.Input"; |
|
} |
|
} else if(enyo[kind]) { |
|
kind = "enyo." + kind; |
|
} else { |
|
kind = elementToKind[nodeName]; |
|
} |
|
} |
|
|
|
return kind || "enyo.Control"; |
|
} |
|
|
|
var attached = []; |
|
enyo.ready(function() { |
|
enyo.forEach(attached, function(a) { |
|
a.attachToNode(); |
|
}); |
|
}); |
|
|
|
enyo.Attachable = { |
|
constructed: enyo.inherit(function(sup) { |
|
return function() { |
|
sup.apply(this, arguments); |
|
attached.push(this); |
|
}; |
|
}), |
|
attached: enyo.inherit(function(sup) { |
|
return function() { |
|
sup.apply(this, arguments); |
|
this.rendered(); |
|
}; |
|
}), |
|
attachToNode: function(node) { |
|
if(!node && this.attachTo) { |
|
node = this.attachTo; |
|
} |
|
|
|
if(enyo.isString(node)) { |
|
// special case: if the code is loaded in HEAD, |
|
// document.body isn't defined yet so let's provide |
|
// a way to specify it without assigning it an ID |
|
if(node === "document.body") { |
|
node = document.body; |
|
} else { |
|
node = document.getElementById(node); |
|
} |
|
} |
|
|
|
if(!node) { |
|
console.error("Node does not exist"); |
|
return; |
|
} |
|
|
|
var config = parseNode(node); |
|
var keys = enyo.keys(config); |
|
enyo.forEach(keys, function(prop) { |
|
if(prop === "components") { |
|
this.createComponents(config.components, {owner: this}); |
|
} else { |
|
this.set(prop, config[prop]); |
|
} |
|
}, this); |
|
|
|
node.enyoInstance = this; |
|
this.attached(); |
|
}, |
|
configureComponents: function(config) { |
|
enyo.forEach(config, function(c) { |
|
var name = c.name; |
|
var control = name && this.$[name]; |
|
|
|
if(control) { |
|
enyo.forEach(enyo.keys(c), function(prop) { |
|
control.set(prop, c[prop]); |
|
}); |
|
} |
|
}, this); |
|
} |
|
}; |
|
|
|
enyo.attach = function(kind, node) { |
|
if(!enyo.isFunction(kind)) { |
|
if(enyo.isString(kind)) { |
|
kind = enyo.constructorForKind(kind); |
|
} else { |
|
// allow node to override attachTo but honor |
|
// attachTo if node is undefined |
|
if(!node && kind.attachTo) { |
|
node = kind.attachTo; |
|
delete kind.attachTo; |
|
} |
|
|
|
// the kind will be an anonymous singleton |
|
// accessible from the return value of enyo.attach |
|
// or via node.enyoInstance |
|
delete kind.name; |
|
kind = enyo.kind(kind); |
|
} |
|
} |
|
|
|
config = { |
|
mixins: [enyo.Attachable], |
|
attachTo: node |
|
} |
|
|
|
return new kind(config); |
|
} |
|
|
|
})(enyo); |
|
|
|
var App = enyo.attach({ |
|
attached: enyo.inherit(function(sup) { |
|
return function() { |
|
sup.apply(this, arguments); |
|
|
|
this.configureComponents([ |
|
{name: "panels", arrangerKind: "enyo.CarouselArranger", narrowFit: false}, |
|
{name: "button", ontap: "buttonTapped"} |
|
]); |
|
|
|
// Panels doesn't like this approach but a flow |
|
// seems to coax it into compliance. More specifically, |
|
// Arranger sets up a cache of the panels in this.c$ during |
|
// flow() which is required for arranger animations |
|
this.$.panels.flow(); |
|
}; |
|
}), |
|
buttonTapped: function(inSender, inEvent) { |
|
alert("email = " + this.$.email.getValue()); |
|
this.$.panels.set("index", 2); |
|
} |
|
}, "document.body"); |