Skip to content

Commit

Permalink
simplify template API
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan You committed Sep 26, 2013
1 parent e77edee commit c94ff6b
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 60 deletions.
25 changes: 10 additions & 15 deletions examples/template.html
Expand Up @@ -6,31 +6,26 @@
</head>
<body>

<div id="hawaii" sd-template="test"></div>

<script type="text/sd-template" sd-template-id="test">
<script type="text/sd-template" id="test">
<p>{{hi}}!</p>
</script>

<script src="../dist/seed.js"></script>
<script>
// compile an existing node with sd-template directive
// will replace its innerHTML with the template's content
var hawaii = new seed.ViewModel({
el: '#hawaii'
})
var template = document.getElementById('test').innerHTML.trim()

// if using template without an existing node
// the VM's $el will be a clone of the template's content
// and you will have to manually append it into DOM.
// this is mostly to allow users to create VMs dynamically.
var china = new seed.ViewModel({
template: 'test'
template: template
})
document.body.appendChild(china.$el)

hawaii.hi = 'Aloha'
china.hi = '你好'

var Child = seed.ViewModel.extend({
template: template
})
var hawaii = new Child()
document.body.appendChild(hawaii.$el)
hawaii.hi = 'Aloha!'
</script>
</body>
</html>
31 changes: 11 additions & 20 deletions src/compiler.js
Expand Up @@ -30,26 +30,17 @@ function Compiler (vm, options) {
if (data) utils.extend(vm, data)

// determine el
var tpl = options.template,
el = options.el
el = typeof el === 'string'
? document.querySelector(el)
: el
if (el) {
var tplExp = tpl || el.getAttribute(config.prefix + '-template')
if (tplExp) {
el.innerHTML = utils.getTemplate(tplExp) || ''
el.removeAttribute(config.prefix + '-template')
}
} else if (tpl) {
var template = utils.getTemplate(tpl)
if (template) {
var tplHolder = document.createElement('div')
tplHolder.innerHTML = template
el = tplHolder.childNodes[0]
}
}

var el = typeof options.el === 'string'
? document.querySelector(options.el)
: options.el
? options.el
: options.template
? utils.makeTemplateNode(options)
: vm.templateNode
? vm.templateNode.cloneNode(true)
: null

if (!el) return utils.warn('invalid VM options.')
utils.log('\nnew VM instance: ', el, '\n')

// set stuff on the ViewModel
Expand Down
19 changes: 14 additions & 5 deletions src/main.js
Expand Up @@ -56,8 +56,8 @@ api.compile = function (el, opts) {
* and add extend method
*/
api.ViewModel = ViewModel

ViewModel.extend = function (options) {
// create child constructor
var ExtendedVM = function (opts) {
opts = opts || {}
if (options.init) {
Expand All @@ -69,16 +69,25 @@ ViewModel.extend = function (options) {
}
ViewModel.call(this, opts)
}
// inherit from ViewModel
var proto = ExtendedVM.prototype = Object.create(ViewModel.prototype)
proto.constructor = ExtendedVM
if (options.props) utils.extend(proto, options.props)
// copy props
if (options.props) {
utils.extend(proto, options.props, function (key) {
return !(key in ViewModel.prototype)
})
}
// register vm id so it can be found by sd-viewmodel
if (options.id) {
utils.registerVM(options.id, ExtendedVM)
}
// convert string template into a node
// because cloneNode is faster than innerHTML
if (options.template) {
proto.templateNode = utils.makeTemplateNode(options)
}
return ExtendedVM
}

// collect templates on load
utils.collectTemplates()

module.exports = api
26 changes: 6 additions & 20 deletions src/utils.js
Expand Up @@ -9,31 +9,17 @@ module.exports = {
return toString.call(obj).slice(8, -1)
},

extend: function (obj, ext) {
extend: function (obj, ext, qualifier) {
for (var key in ext) {
if (qualifier && !qualifier(key)) continue
obj[key] = ext[key]
}
},

collectTemplates: function () {
var selector = 'script[type="text/' + config.prefix + '-template"]',
templates = document.querySelectorAll(selector),
i = templates.length
while (i--) {
this.storeTemplate(templates[i])
}
},

storeTemplate: function (template) {
var id = template.getAttribute(config.prefix + '-template-id')
if (id) {
templates[id] = template.innerHTML.trim()
}
template.parentNode.removeChild(template)
},

getTemplate: function (id) {
return templates[id]
makeTemplateNode: function (options) {
var node = document.createElement(options.tagName || 'div')
node.innerHTML = options.template
return node
},

registerVM: function (id, VM) {
Expand Down
17 changes: 17 additions & 0 deletions test/unit/specs/api.js
Expand Up @@ -37,6 +37,23 @@ describe('UNIT: API', function () {
assert.strictEqual(utils.getVM('test'), Test)
})

it('should take options.template and work', function () {
var Test = seed.ViewModel.extend({
tagName: 'p',
template: '<span>{{hello}}</span><a>haha</a>',
data: {
hello: 'Ahaha'
}
}),
vm = new Test(),
text1 = vm.$el.querySelector('span').textContent,
text2 = vm.$el.querySelector('a').textContent
assert.ok(Test.prototype.templateNode instanceof HTMLElement)
assert.strictEqual(vm.$el.nodeName, 'P')
assert.strictEqual(text1, 'Ahaha')
assert.strictEqual(text2, 'haha')
})

it('should call options.init when instantiating', function () {
var called = false,
Test = seed.ViewModel.extend({ init: function () {
Expand Down

0 comments on commit c94ff6b

Please sign in to comment.