Skip to content

Commit

Permalink
partials done.
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Oct 8, 2013
1 parent b0dcfd5 commit 3cbf498
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 41 deletions.
50 changes: 31 additions & 19 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,19 @@ CompilerProto.compile = function (node, root) {
var compiler = this
if (node.nodeType === 1) {
// a normal node
var opts = compiler.options,
eachExp = node.getAttribute(eachAttr),
vmExp = node.getAttribute(vmAttr),
partialExp = node.getAttribute(partialAttr)
var eachExp = node.getAttribute(eachAttr),
vmId = node.getAttribute(vmAttr),
partialId = node.getAttribute(partialAttr)
// we need to check for any possbile special directives
// e.g. sd-each, sd-viewmodel & sd-partial
if (eachExp) { // each block
var directive = Directive.parse(eachAttr, eachExp, compiler, node)
if (directive) {
compiler.bindDirective(directive)
}
} else if (vmExp && !root) { // nested ViewModels
} else if (vmId && !root) { // nested ViewModels
node.removeAttribute(vmAttr)
var ChildVM =
(opts.vms && opts.vms[vmExp]) ||
utils.vms[vmExp]
var ChildVM = compiler.getOption('vms', vmId)
if (ChildVM) {
new ChildVM({
el: node,
Expand All @@ -199,11 +196,9 @@ CompilerProto.compile = function (node, root) {
})
}
} else {
if (partialExp) { // replace innerHTML with partial
if (partialId) { // replace innerHTML with partial
node.removeAttribute(partialAttr)
var partial =
(opts.partials && opts.partials[partialExp]) ||
utils.partials[partialExp]
var partial = compiler.getOption('partials', partialId)
if (partial) {
node.innerHTML = ''
node.appendChild(partial.cloneNode(true))
Expand Down Expand Up @@ -265,14 +260,23 @@ CompilerProto.compileTextNode = function (node) {
el, token, directive
for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i]
el = document.createTextNode('')
if (token.key) {
directive = Directive.parse(dirname, token.key, this, el)
if (directive) {
this.bindDirective(directive)
if (token.key) { // a binding
if (token.key.charAt(0) === '>') { // a partial
var partialId = token.key.slice(1),
partial = this.getOption('partials', partialId)
if (partial) {
el = partial.cloneNode(true)
this.compileNode(el)
}
} else { // a binding
el = document.createTextNode('')
directive = Directive.parse(dirname, token.key, this, el)
if (directive) {
this.bindDirective(directive)
}
}
} else {
el.nodeValue = token
} else { // a plain string
el = document.createTextNode(token)
}
node.parentNode.insertBefore(el, node)
}
Expand Down Expand Up @@ -505,6 +509,14 @@ CompilerProto.bindContexts = function (bindings) {
}
}

/*
* Retrive an option from the compiler
*/
CompilerProto.getOption = function (type, id) {
var opts = this.options
return (opts[type] && opts[type][id]) || (utils[type] && utils[type][id])
}

/*
* Unbind and remove element
*/
Expand Down
9 changes: 4 additions & 5 deletions src/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function Directive (definition, directiveName, expression, rawKey, compiler, nod
this.filters = []
var i = 0, l = filterExps.length, filter
for (; i < l; i++) {
filter = parseFilter(filterExps[i], this.compiler.options)
filter = parseFilter(filterExps[i], this.compiler)
if (filter) this.filters.push(filter)
}
if (!this.filters.length) this.filters = null
Expand Down Expand Up @@ -91,7 +91,7 @@ function parseKey (dir, rawKey) {
/*
* parse a filter expression
*/
function parseFilter (filter, options) {
function parseFilter (filter, compiler) {

var tokens = filter.slice(1).match(FILTER_TOKEN_RE)
if (!tokens) return
Expand All @@ -100,7 +100,7 @@ function parseFilter (filter, options) {
})

var name = tokens[0],
apply = (options.filters && options.filters[name]) || filters[name]
apply = compiler.getOption('filters', name) || filters[name]
if (!apply) {
utils.warn('Unknown filter: ' + name)
return
Expand Down Expand Up @@ -190,8 +190,7 @@ Directive.parse = function (dirname, expression, compiler, node) {
if (dirname.indexOf(prefix) === -1) return null
dirname = dirname.slice(prefix.length + 1)

var opts = compiler.options,
dir = (opts.directives && opts.directives[dirname]) || directives[dirname],
var dir = compiler.getOption('directives', dirname) || directives[dirname],
keyMatch = expression.match(KEY_RE),
rawKey = keyMatch && keyMatch[0].trim()

Expand Down
7 changes: 1 addition & 6 deletions src/directives/each.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var config = require('../config'),
utils = require('../utils'),
Observer = require('../observer'),
Emitter = require('../emitter'),
ViewModel // lazy def to avoid circular dependency
Expand Down Expand Up @@ -139,11 +138,7 @@ module.exports = {
var node = this.el.cloneNode(true),
ctn = this.container,
vmID = node.getAttribute(config.prefix + '-viewmodel'),
opts = this.compiler.options,
ChildVM =
(opts.vms && opts.vms[vmID]) ||
utils.vms[vmID] ||
ViewModel,
ChildVM = this.compiler.getOption('vms', vmID) || ViewModel,
wrappedData = {}
wrappedData[this.arg] = data || {}
var item = new ChildVM({
Expand Down
13 changes: 13 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function extend (options) {
*/
function inheritOptions (child, parent, topLevel) {
child = child || {}
convertPartials(child.partials)
if (!parent) return child
for (var key in parent) {
if (key === 'el' || key === 'props') continue
Expand All @@ -121,6 +122,18 @@ function inheritOptions (child, parent, topLevel) {
return child
}

/*
* Convert an object of partials to dom fragments
*/
function convertPartials (partials) {
if (!partials) return
for (var key in partials) {
if (typeof partials[key] === 'string') {
partials[key] = templateToFragment(partials[key])
}
}
}

/*
* Convert a string template to a dom fragment
*/
Expand Down
64 changes: 55 additions & 9 deletions test/unit/specs/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,28 @@ describe('UNIT: API', function () {
assert.strictEqual(utils.partials[testId], seed.partial(testId))
})

it('should work with sd-partial', function () {
mock(testId, 'hello', {
'sd-partial': testId
it('should work with sd-partial as a directive', function () {
var testId = 'api-partial-direcitve'
seed.partial(testId, partial)
mock(testId, '<div class="directive" sd-partial="' + testId + '">hello</div>')
var t = new seed.ViewModel({
el: '#' + testId,
data: { hi: 'hohoho' }
})
assert.strictEqual(t.$el.querySelector('.directive .partial-test a').textContent, 'hohoho')
assert.strictEqual(t.$el.querySelector('.directive span').innerHTML, 'hahaha')
})

it('should work with sd-partial as an inline interpolation', function () {
var testId = 'api-partial-inline'
seed.partial(testId, partial)
mock(testId, '<div class="inline">{{>' + testId + '}}</div>')
var t = new seed.ViewModel({
el: '#' + testId,
data: { hi: 'hohoho' }
})
assert.strictEqual(t.$el.querySelector('.partial-test a').textContent, 'hohoho')
assert.strictEqual(t.$el.querySelector('span').innerHTML, 'hahaha')
assert.strictEqual(t.$el.querySelector('.inline .partial-test a').textContent, 'hohoho')
assert.strictEqual(t.$el.querySelector('.inline span').innerHTML, 'hahaha')
})
})

Expand Down Expand Up @@ -441,15 +453,49 @@ describe('UNIT: API', function () {
})

describe('vms', function () {
it('should be tested', function () {
assert.ok(false)

it('should allow the VM to use private child VMs', function () {
var Child = seed.ViewModel.extend({
data: {
name: 'child'
}
})
var Parent = seed.ViewModel.extend({
template: '<p>{{name}}</p><div sd-viewmodel="child">{{name}}</div>',
data: {
name: 'dad'
},
vms: {
child: Child
}
})
var p = new Parent()
assert.strictEqual(p.$el.querySelector('p').textContent, 'dad')
assert.strictEqual(p.$el.querySelector('div').textContent, 'child')
})

})

describe('partials', function () {
it('should be tested', function () {
assert.ok(false)

it('should allow the VM to use private partials', function () {
var Test = seed.ViewModel.extend({
attributes: {
'sd-partial': 'test'
},
partials: {
test: '<a>{{a}}</a><p>{{b}}</p>'
},
data: {
a: 'hi',
b: 'ho'
}
})
var t = new Test()
assert.strictEqual(t.$el.querySelector('a').textContent, 'hi')
assert.strictEqual(t.$el.querySelector('p').textContent, 'ho')
})

})

describe('transitions', function () {
Expand Down
1 change: 1 addition & 0 deletions test/unit/specs/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ describe('UNIT: Directive', function () {

var compiler = {
options: {},
getOption: function () {},
vm: {
constructor: {}
}
Expand Down
9 changes: 7 additions & 2 deletions test/unit/specs/text-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ describe('UNIT: TextNode Parser', function () {
assert.strictEqual(result[2], ' &#123;&#123;hello&#125;&#125;')
})

var tokens = TextParser.parse('hello {{a}}! {{ bcd }}{{d.e.f}} {{a + (b || c) ? d : e}}')
var tokens = TextParser.parse('hello {{a}}! {{ bcd }}{{d.e.f}} {{a + (b || c) ? d : e}} {{>test}}')

it('should extract correct amount of tokens', function () {
assert.strictEqual(tokens.length, 7)
assert.strictEqual(tokens.length, 9)
})

it('should extract plain strings', function () {
assert.strictEqual(typeof tokens[0], 'string')
assert.strictEqual(typeof tokens[2], 'string')
assert.strictEqual(typeof tokens[5], 'string')
assert.strictEqual(typeof tokens[7], 'string')
})

it('should extract basic keys', function () {
Expand All @@ -44,6 +45,10 @@ describe('UNIT: TextNode Parser', function () {
assert.strictEqual(tokens[6].key, 'a + (b || c) ? d : e')
})

it('should extract partials', function () {
assert.strictEqual(tokens[8].key, '>test')
})

})

describe('.buildRegex()', function () {
Expand Down

0 comments on commit 3cbf498

Please sign in to comment.