Skip to content

Commit

Permalink
add support for interpolation in html attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan You committed Jan 6, 2014
1 parent 354f559 commit a2e287f
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 86 deletions.
53 changes: 34 additions & 19 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,15 @@ CompilerProto.compile = function (node, root) {
if (repeatExp = utils.attr(node, 'repeat')) {

// repeat block cannot have v-id at the same time.
directive = Directive.parse(config.attrs.repeat, repeatExp, compiler, node)
directive = Directive.parse('repeat', repeatExp, compiler, node)
if (directive) {
compiler.bindDirective(directive)
}

// v-component has 2nd highest priority
} else if (!root && (componentExp = utils.attr(node, 'component'))) {

directive = Directive.parse(config.attrs.component, componentExp, compiler, node)
directive = Directive.parse('component', componentExp, compiler, node)
if (directive) {
// component directive is a bit different from the others.
// when it has no argument, it should be treated as a
Expand Down Expand Up @@ -293,28 +293,44 @@ CompilerProto.compile = function (node, root) {
* Compile a normal node
*/
CompilerProto.compileNode = function (node) {
var i, j, attrs = node.attributes
var i, j,
attrs = node.attributes,
prefix = config.prefix + '-'
// parse if has attributes
if (attrs && attrs.length) {
var attr, valid, exps, exp
var attr, isDirective, exps, exp, directive
// loop through all attributes
i = attrs.length
while (i--) {
attr = attrs[i]
valid = false
exps = Directive.split(attr.value)
// loop through clauses (separated by ",")
// inside each attribute
j = exps.length
while (j--) {
exp = exps[j]
var directive = Directive.parse(attr.name, exp, this, node)
if (directive) {
valid = true
this.bindDirective(directive)
isDirective = false

if (attr.name.indexOf(prefix) === 0) {
// a directive - split, parse and bind it.
isDirective = true
exps = Directive.split(attr.value)
// loop through clauses (separated by ",")
// inside each attribute
j = exps.length
while (j--) {
exp = exps[j]
directive = Directive.parse(attr.name.slice(prefix.length), exp, this, node)
if (directive) {
this.bindDirective(directive)
}
}
} else {
// non directive attribute, check interpolation tags
exp = TextParser.parseAttr(attr.value)
if (exp) {
directive = Directive.parse('attr', attr.name + ':' + exp, this, node)
if (directive) {
this.bindDirective(directive)
}
}
}
if (valid) node.removeAttribute(attr.name)

if (isDirective) node.removeAttribute(attr.name)
}
}
// recursively compile childNodes
Expand All @@ -332,8 +348,7 @@ CompilerProto.compileNode = function (node) {
CompilerProto.compileTextNode = function (node) {
var tokens = TextParser.parse(node.nodeValue)
if (!tokens) return
var dirname = config.attrs.text,
el, token, directive
var el, token, directive
for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i]
if (token.key) { // a binding
Expand All @@ -346,7 +361,7 @@ CompilerProto.compileTextNode = function (node) {
}
} else { // a binding
el = document.createTextNode('')
directive = Directive.parse(dirname, token.key, this, el)
directive = Directive.parse('text', token.key, this, el)
if (directive) {
this.bindDirective(directive)
}
Expand Down
7 changes: 1 addition & 6 deletions src/directive.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var config = require('./config'),
utils = require('./utils'),
var utils = require('./utils'),
directives = require('./directives'),
filters = require('./filters'),

Expand Down Expand Up @@ -201,10 +200,6 @@ Directive.split = function (exp) {
*/
Directive.parse = function (dirname, expression, compiler, node) {

var prefix = config.prefix + '-'
if (dirname.indexOf(prefix) !== 0) return
dirname = dirname.slice(prefix.length)

var dir = compiler.getOption('directives', dirname) || directives[dirname]
if (!dir) return utils.warn('unknown directive: ' + dirname)

Expand Down
50 changes: 32 additions & 18 deletions src/text-parser.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
var BINDING_RE = /\{\{(.+?)\}\}/

module.exports = {
/**
* Parse a piece of text, return an array of tokens
*/
function parse (text) {
if (!BINDING_RE.test(text)) return null
var m, i, tokens = []
/* jshint boss: true */
while (m = text.match(BINDING_RE)) {
i = m.index
if (i > 0) tokens.push(text.slice(0, i))
tokens.push({ key: m[1].trim() })
text = text.slice(i + m[0].length)
}
if (text.length) tokens.push(text)
return tokens
}

/**
* Parse a piece of text, return an array of tokens
*/
parse: function (text) {
if (!BINDING_RE.test(text)) return null
var m, i, tokens = []
/* jshint boss: true */
while (m = text.match(BINDING_RE)) {
i = m.index
if (i > 0) tokens.push(text.slice(0, i))
tokens.push({ key: m[1].trim() })
text = text.slice(i + m[0].length)
}
if (text.length) tokens.push(text)
return tokens
/**
* Parse an attribute value with possible interpolation tags
* return a Directive-friendly expression
*/
function parseAttr (attr) {
var tokens = parse(attr)
if (!tokens) return null
var res = [], token
for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i]
res.push(token.key || ('"' + token + '"'))
}

}
return res.join('+')
}

exports.parse = parse
exports.parseAttr = parseAttr
11 changes: 10 additions & 1 deletion test/functional/fixtures/expression.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
<button v-on="click: ok = !ok" class="toggle">toggle</button>
<button v-on="click: noMsg = 'Nah'" class="change">change</button>
</div>
<div id="attrs" data-test="hi {{msg}} ha"></div>
<script>
Vue.config({debug:true})
Vue.config({debug:true})

var normal = new Vue({
el: '#normal',
data: {
Expand Down Expand Up @@ -54,6 +56,13 @@
noMsg: 'NO'
}
})

var attrs = new Vue({
el: '#attrs',
data: {
msg: 'ho'
}
})
</script>
</body>
</html>
16 changes: 14 additions & 2 deletions test/functional/specs/expression.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global normal */
/* global normal, attrs */

casper.test.begin('Expression', 19, function (test) {
casper.test.begin('Expression', 21, function (test) {

casper
.start('./fixtures/expression.html')
Expand All @@ -11,6 +11,10 @@ casper.test.begin('Expression', 19, function (test) {
test.assertField('two', 'World')
test.assertField('three', 'Hi')
test.assertField('four', 'Ho')
// attrs
test.assertEval(function () {
return document.getElementById('attrs').dataset.test === 'hi ho ha'
})
})
.thenEvaluate(function () {
// setting value
Expand Down Expand Up @@ -67,6 +71,14 @@ casper.test.begin('Expression', 19, function (test) {
.thenClick('#conditional .change', function () {
test.assertSelectorHasText('#conditional p', 'Nah')
})
.thenEvaluate(function () {
attrs.msg = 'hoho'
})
.then(function () {
test.assertEval(function () {
return document.getElementById('attrs').dataset.test === 'hi hoho ha'
})
})
.run(function () {
test.done()
})
Expand Down

0 comments on commit a2e287f

Please sign in to comment.