Jelajahi Sumber

private directives and filters

Evan You 12 tahun lalu
induk
melakukan
eef0dc6ad1
5 mengubah file dengan 126 tambahan dan 40 penghapusan
  1. 32 0
      examples/encapsulation.html
  2. 5 4
      src/directive.js
  3. 1 0
      src/main.js
  4. 46 0
      test/unit/specs/api.js
  5. 42 36
      test/unit/specs/directive.js

+ 32 - 0
examples/encapsulation.html

@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title></title>
+        <meta charset="utf-8">
+    </head>
+    <body>
+        <div id="test" sd-hola="hi | nodigits"></div>
+        <script src="../dist/seed.js"></script>
+        <script>
+            var T = seed.ViewModel.extend({
+                directives: {
+                    hola: function (value) {
+                        this.el.innerHTML = value + '<span style="color:#f00"> this part is added by the directive</span>'
+                    }
+                },
+                filters: {
+                    nodigits: function (value) {
+                        return value.replace(/\d/g, '')
+                    }
+                }
+            })
+            new T({
+                el: '#test',
+                data: {
+                    hi: 'ho43h132oh5o12345'
+                }
+            })
+            // expected ouput: hohoho this part is added by the directive
+        </script>
+    </body>
+</html>

+ 5 - 4
src/directive.js

@@ -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])
+            filter = parseFilter(filterExps[i], this.vm.constructor.options)
             if (filter) this.filters.push(filter)
         }
         if (!this.filters.length) this.filters = null
@@ -91,7 +91,7 @@ function parseKey (dir, rawKey) {
 /*
  *  parse a filter expression
  */
-function parseFilter (filter) {
+function parseFilter (filter, options) {
 
     var tokens = filter.slice(1).match(FILTER_TOKEN_RE)
     if (!tokens) return
@@ -100,7 +100,7 @@ function parseFilter (filter) {
     })
 
     var name = tokens[0],
-        apply = filters[name]
+        apply = (options && options.filters && options.filters[name]) || filters[name]
     if (!apply) {
         utils.warn('Unknown filter: ' + name)
         return
@@ -190,7 +190,8 @@ Directive.parse = function (dirname, expression, compiler, node) {
     if (dirname.indexOf(prefix) === -1) return null
     dirname = dirname.slice(prefix.length + 1)
 
-    var dir = directives[dirname],
+    var opts = compiler.vm.constructor.options,
+        dir = (opts && opts.directives && opts.directives[dirname]) || directives[dirname],
         keyMatch = expression.match(KEY_RE),
         rawKey = keyMatch && keyMatch[0].trim()
 

+ 1 - 0
src/main.js

@@ -76,6 +76,7 @@ function extend (options) {
     // allow extended VM to be further extended
     ExtendedVM.extend = extend
     ExtendedVM.super = ParentVM
+    ExtendedVM.options = options
     return ExtendedVM
 }
 

+ 46 - 0
test/unit/specs/api.js

@@ -259,6 +259,52 @@ describe('UNIT: API', function () {
 
             })
 
+            describe('directives', function () {
+                
+                it('should allow the VM to use private directives', function () {
+                    var Test = seed.ViewModel.extend({
+                        directives: {
+                            test: function (value) {
+                                this.el.innerHTML = value ? 'YES' : 'NO'
+                            }
+                        }
+                    })
+                    var t = new Test({
+                        attributes: {
+                            'sd-test': 'ok'
+                        },
+                        data: {
+                            ok: true
+                        }
+                    })
+                    assert.strictEqual(t.$el.innerHTML, 'YES')
+                    t.ok = false
+                    assert.strictEqual(t.$el.innerHTML, 'NO')
+                })
+
+            })
+
+            describe('filters', function () {
+                
+                it('should allow the VM to use private filters', function () {
+                    var Test = seed.ViewModel.extend({
+                        filters: {
+                            test: function (value) {
+                                return value + '12345'
+                            }
+                        }
+                    })
+                    var t = new Test({
+                        template: '{{hi | test}}',
+                        data: {
+                            hi: 'hohoho'
+                        }
+                    })
+                    assert.strictEqual(t.$el.textContent, 'hohoho12345')
+                })
+
+            })
+
         })
 
     })

+ 42 - 36
test/unit/specs/directive.js

@@ -3,23 +3,29 @@ var Directive = require('seed/src/directive'),
 
 describe('UNIT: Directive', function () {
 
+    var compiler = {
+        vm: {
+            constructor: {}
+        }
+    }
+
     describe('.parse()', function () {
         
         it('should return null if directive name does not have correct prefix', function () {
-            var d = Directive.parse('ds-test', 'abc', {})
+            var d = Directive.parse('ds-test', 'abc', compiler)
             assert.strictEqual(d, null)
         })
 
         it('should return null if directive is unknown', function () {
-            var d = Directive.parse('sd-directive-that-does-not-exist', 'abc')
+            var d = Directive.parse('sd-directive-that-does-not-exist', 'abc', compiler)
             assert.ok(d === null)
         })
 
         it('should return null if the expression is invalid', function () {
-            var d = Directive.parse('sd-text', '', {}),
-                e = Directive.parse('sd-text', '  ', {}),
-                f = Directive.parse('sd-text', '|', {}),
-                g = Directive.parse('sd-text', '  |  ', {})
+            var d = Directive.parse('sd-text', '', compiler),
+                e = Directive.parse('sd-text', '  ', compiler),
+                f = Directive.parse('sd-text', '|', compiler),
+                g = Directive.parse('sd-text', '  |  ', compiler)
             assert.strictEqual(d, null, 'empty')
             assert.strictEqual(e, null, 'spaces')
             assert.strictEqual(f, null, 'single pipe')
@@ -27,7 +33,7 @@ describe('UNIT: Directive', function () {
         })
 
         it('should return an instance of Directive if args are good', function () {
-            var d = Directive.parse('sd-text', 'abc', {})
+            var d = Directive.parse('sd-text', 'abc', compiler)
             assert.ok(d instanceof Directive)
         })
 
@@ -47,12 +53,12 @@ describe('UNIT: Directive', function () {
         directives.obj = obj
         
         it('should copy the definition as _update if the def is a function', function () {
-            var d = Directive.parse('sd-test', 'abc', {})
+            var d = Directive.parse('sd-test', 'abc', compiler)
             assert.strictEqual(d._update, test)                
         })
 
         it('should copy methods if the def is an object', function () {
-            var d = Directive.parse('sd-obj', 'abc', {})
+            var d = Directive.parse('sd-obj', 'abc', compiler)
             assert.strictEqual(d._update, obj.update, 'update should be copied as _update')
             assert.strictEqual(d._unbind, obj.unbind, 'unbind should be copied as _unbind')
             assert.strictEqual(d.bind, obj.bind)
@@ -61,24 +67,24 @@ describe('UNIT: Directive', function () {
 
         it('should trim the expression', function () {
             var exp = ' fsfsef   | fsef a  ',
-                d = Directive.parse('sd-text', exp, {})
+                d = Directive.parse('sd-text', exp, compiler)
             assert.strictEqual(d.expression, exp.trim())
         })
 
         it('should extract correct argument', function () {
-            var d = Directive.parse('sd-text', 'todo:todos', {}),
-                e = Directive.parse('sd-text', 'todo:todos + abc', {}),
-                f = Directive.parse('sd-text', 'todo:todos | fsf fsef', {})
+            var d = Directive.parse('sd-text', 'todo:todos', compiler),
+                e = Directive.parse('sd-text', 'todo:todos + abc', compiler),
+                f = Directive.parse('sd-text', 'todo:todos | fsf fsef', compiler)
             assert.strictEqual(d.arg, 'todo', 'simple')
             assert.strictEqual(e.arg, 'todo', 'expression')
             assert.strictEqual(f.arg, 'todo', 'with filters')
         })
 
         it('should extract correct nesting info', function () {
-            var d = Directive.parse('sd-text', 'abc', {}),
-                e = Directive.parse('sd-text', '^abc', {}),
-                f = Directive.parse('sd-text', '^^^abc', {}),
-                g = Directive.parse('sd-text', '$abc', {})
+            var d = Directive.parse('sd-text', 'abc', compiler),
+                e = Directive.parse('sd-text', '^abc', compiler),
+                f = Directive.parse('sd-text', '^^^abc', compiler),
+                g = Directive.parse('sd-text', '$abc', compiler)
             assert.ok(d.nesting === false && d.root === false && d.key === 'abc', 'no nesting')
             assert.ok(e.nesting === 1 && e.root === false && e.key === 'abc', '1 level')
             assert.ok(f.nesting === 3 && f.root === false && f.key === 'abc', '3 levels')
@@ -86,11 +92,11 @@ describe('UNIT: Directive', function () {
         })
 
         it('should be able to determine whether the key is an expression', function () {
-            var d = Directive.parse('sd-text', 'abc', {}),
-                e = Directive.parse('sd-text', '!abc', {}),
-                f = Directive.parse('sd-text', 'abc + bcd * 5 / 2', {}),
-                g = Directive.parse('sd-text', 'abc && (bcd || eee)', {}),
-                h = Directive.parse('sd-text', 'test(abc)', {})
+            var d = Directive.parse('sd-text', 'abc', compiler),
+                e = Directive.parse('sd-text', '!abc', compiler),
+                f = Directive.parse('sd-text', 'abc + bcd * 5 / 2', compiler),
+                g = Directive.parse('sd-text', 'abc && (bcd || eee)', compiler),
+                h = Directive.parse('sd-text', 'test(abc)', compiler)
             assert.ok(!d.isExp, 'non-expression')
             assert.ok(e.isExp, 'negation')
             assert.ok(f.isExp, 'math')
@@ -99,11 +105,11 @@ describe('UNIT: Directive', function () {
         })
 
         it('should have a filter prop of null if no filters are present', function () {
-            var d = Directive.parse('sd-text', 'abc', {}),
-                e = Directive.parse('sd-text', 'abc |', {}),
-                f = Directive.parse('sd-text', 'abc ||', {}),
-                g = Directive.parse('sd-text', 'abc | | ', {}),
-                h = Directive.parse('sd-text', 'abc | unknown | nothing at all | whaaat', {})
+            var d = Directive.parse('sd-text', 'abc', compiler),
+                e = Directive.parse('sd-text', 'abc |', compiler),
+                f = Directive.parse('sd-text', 'abc ||', compiler),
+                g = Directive.parse('sd-text', 'abc | | ', compiler),
+                h = Directive.parse('sd-text', 'abc | unknown | nothing at all | whaaat', compiler)
             assert.strictEqual(d.filters, null)
             assert.strictEqual(e.filters, null, 'single')
             assert.strictEqual(f.filters, null, 'double')
@@ -112,7 +118,7 @@ describe('UNIT: Directive', function () {
         })
 
         it('should extract correct filters (single filter)', function () {
-            var d = Directive.parse('sd-text', 'abc | uppercase', {}),
+            var d = Directive.parse('sd-text', 'abc | uppercase', compiler),
                 f = d.filters[0]
             assert.strictEqual(f.name, 'uppercase')
             assert.strictEqual(f.args, null)
@@ -120,7 +126,7 @@ describe('UNIT: Directive', function () {
         })
 
         it('should extract correct filters (single filter with args)', function () {
-            var d = Directive.parse('sd-text', 'abc | pluralize item \'arg with spaces\'', {}),
+            var d = Directive.parse('sd-text', 'abc | pluralize item \'arg with spaces\'', compiler),
                 f = d.filters[0]
             assert.strictEqual(f.name, 'pluralize', 'name')
             assert.strictEqual(f.args.length, 2, 'args length')
@@ -130,7 +136,7 @@ describe('UNIT: Directive', function () {
 
         it('should extract correct filters (multiple filters)', function () {
             // intentional double pipe
-            var d = Directive.parse('sd-text', 'abc | uppercase | pluralize item || lowercase', {}),
+            var d = Directive.parse('sd-text', 'abc | uppercase | pluralize item || lowercase', compiler),
                 f1 = d.filters[0],
                 f2 = d.filters[1],
                 f3 = d.filters[2]
@@ -146,7 +152,7 @@ describe('UNIT: Directive', function () {
     describe('.applyFilters()', function () {
         
         it('should work', function () {
-            var d = Directive.parse('sd-text', 'abc | pluralize item | capitalize', {}),
+            var d = Directive.parse('sd-text', 'abc | pluralize item | capitalize', compiler),
                 v = d.applyFilters(2)
             assert.strictEqual(v, 'Items')
         })
@@ -160,13 +166,13 @@ describe('UNIT: Directive', function () {
         directives.applyTest = applyTest
 
         it('should invole the _update function', function () {
-            var d = Directive.parse('sd-applyTest', 'abc', {})
+            var d = Directive.parse('sd-applyTest', 'abc', compiler)
             d.apply(12345)
             assert.strictEqual(test, 12345)
         })
         
         it('should apply the filter if there is any', function () {
-            var d = Directive.parse('sd-applyTest', 'abc | currency £', {})
+            var d = Directive.parse('sd-applyTest', 'abc | currency £', compiler)
             d.apply(12345)
             assert.strictEqual(test, '£12,345.00')
         })
@@ -175,7 +181,7 @@ describe('UNIT: Directive', function () {
 
     describe('.update()', function () {
         
-        var d = Directive.parse('sd-text', 'abc', {}),
+        var d = Directive.parse('sd-text', 'abc', compiler),
             applied = false
         d.apply = function () {
             applied = true
@@ -203,7 +209,7 @@ describe('UNIT: Directive', function () {
 
     describe('.refresh()', function () {
         
-        var d = Directive.parse('sd-text', 'abc', {}),
+        var d = Directive.parse('sd-text', 'abc', compiler),
             applied = false,
             el = 1, vm = 2,
             value = {
@@ -241,7 +247,7 @@ describe('UNIT: Directive', function () {
 
     describe('.unbind()', function () {
         
-        var d = Directive.parse('sd-text', 'abc', {}),
+        var d = Directive.parse('sd-text', 'abc', compiler),
             unbound = false,
             val
         d._unbind = function (v) {