Evan You 13 年 前
コミット
ad1cc3be98
6 ファイル変更68 行追加33 行削除
  1. 2 2
      examples/todos/app.js
  2. 2 2
      src/binding.js
  3. 1 0
      src/config.js
  4. 4 2
      src/directive-parser.js
  5. 6 9
      src/main.js
  6. 53 18
      src/seed.js

+ 2 - 2
examples/todos/app.js

@@ -43,7 +43,7 @@ Seed.controller('Todos', function (scope) {
     // event handlers ---------------------------------------------------------
     scope.addTodo = function (e) {
         if (e.el.value) {
-            scope.todos.unshift({ text: e.el.value })
+            scope.todos.unshift({ text: e.el.value, done: false })
             e.el.value = ''
             scope.remaining++
         }
@@ -79,4 +79,4 @@ Seed.controller('Todos', function (scope) {
 
 })
 
-Seed.bootstrap()
+Seed.bootstrap({ debug: true })

+ 2 - 2
src/binding.js

@@ -13,7 +13,7 @@ function Binding (seed, key) {
     this.seed = seed
     this.key  = key
     var path = key.split('.')
-    this.set(getValue(seed.scope, path))
+    this.set(getNestedValue(seed.scope, path))
     this.def(seed.scope, path)
     this.instances    = []
     this.subs   = []
@@ -124,7 +124,7 @@ Binding.prototype.pub = function () {
 /*
  *  Get a value from an object based on a path array
  */
-function getValue (scope, path) {
+function getNestedValue (scope, path) {
     if (path.length === 1) return scope[path[0]]
     var i = 0
     /* jshint boss: true */

+ 1 - 0
src/config.js

@@ -1,6 +1,7 @@
 module.exports = {
 
     prefix      : 'sd',
+    debug       : false,
     datum       : {},
     controllers : {},
 

+ 4 - 2
src/directive-parser.js

@@ -168,8 +168,10 @@ module.exports = {
         var dir   = directives[dirname],
             valid = KEY_RE.test(expression)
 
-        if (!dir) console.warn('unknown directive: ' + dirname)
-        if (!valid) console.warn('invalid directive expression: ' + expression)
+        if (config.debug) {
+            if (!dir) console.warn('unknown directive: ' + dirname)
+            if (!valid) console.warn('invalid directive expression: ' + expression)
+        }
 
         return dir && valid
             ? new Directive(dirname, expression, oneway)

+ 6 - 9
src/main.js

@@ -7,7 +7,8 @@ var config      = require('./config'),
 var controllers = config.controllers,
     datum       = config.datum,
     api         = {},
-    reserved    = ['datum', 'controllers']
+    reserved    = ['datum', 'controllers'],
+    booted      = false
 
 /*
  *  Store a piece of plain data in config.datum
@@ -15,9 +16,6 @@ var controllers = config.controllers,
  */
 api.data = function (id, data) {
     if (!data) return datum[id]
-    if (datum[id]) {
-        console.warn('data object "' + id + '"" already exists and has been overwritten.')
-    }
     datum[id] = data
 }
 
@@ -27,9 +25,6 @@ api.data = function (id, data) {
  */
 api.controller = function (id, extensions) {
     if (!extensions) return controllers[id]
-    if (controllers[id]) {
-        console.warn('controller "' + id + '" already exists and has been overwritten.')
-    }
     controllers[id] = extensions
 }
 
@@ -55,6 +50,7 @@ api.filter = function (name, fn) {
  *  that has either sd-controller or sd-data
  */
 api.bootstrap = function (opts) {
+    if (booted) return
     if (opts) {
         for (var key in opts) {
             if (reserved.indexOf(key) === -1) {
@@ -66,11 +62,12 @@ api.bootstrap = function (opts) {
     var el,
         ctrlSlt = '[' + config.prefix + '-controller]',
         dataSlt = '[' + config.prefix + '-data]',
-        seeds = []
+        seeds   = []
     /* jshint boss: true */
     while (el = document.querySelector(ctrlSlt) || document.querySelector(dataSlt)) {
-        seeds.push(new Seed(el))
+        seeds.push((new Seed(el)).scope)
     }
+    booted = true
     return seeds.length > 1 ? seeds : seeds[0]
 }
 

+ 53 - 18
src/seed.js

@@ -32,7 +32,11 @@ function Seed (el, options) {
     // check if there's passed in data
     var dataAttr = config.prefix + '-data',
         dataId = el.getAttribute(dataAttr),
-        data = (options && options.data) || config.datum[dataId] || {}
+        data = (options && options.data) || config.datum[dataId]
+    if (config.debug && dataId && !data) {
+        console.warn('data "' + dataId + '" is not defined.')
+    }
+    data = data || {}
     el.removeAttribute(dataAttr)
 
     // if the passed in data is the scope of a Seed instance,
@@ -63,8 +67,8 @@ function Seed (el, options) {
         var factory = config.controllers[ctrlID]
         if (factory) {
             factory(this.scope)
-        } else {
-            console.warn('controller ' + ctrlID + ' is not defined.')
+        } else if (config.debug) {
+            console.warn('controller "' + ctrlID + '" is not defined.')
         }
     }
 
@@ -231,22 +235,18 @@ Seed.prototype._destroy = function () {
 
 /*
  *  Dump a copy of current scope data, excluding seed-exposed properties.
+ *  @param key (optional): key for the value to dump
  */
-Seed.prototype._dump = function () {
-    var dump = {}, binding, val,
-        subDump = function (scope) {
-            return scope.$dump()
-        }
-    for (var key in this._bindings) {
-        binding = this._bindings[key]
-        val = binding.value
-        if (!val) continue
-        if (Array.isArray(val)) {
-            dump[key] = val.map(subDump)
-        } else if (typeof val !== 'function') {
-            dump[key] = val
-        } else if (binding.isComputed) {
-            dump[key] = val.get()
+Seed.prototype._dump = function (key) {
+    if (key) {
+        return dumpValue(this._bindings[key])
+    } else {
+        var path, val, dump = {}
+        for (key in this._bindings) {
+            val = dumpValue(this._bindings[key])
+            if (val === undefined) continue
+            path = key.split('.')
+            setNestedValue(dump, path, val)
         }
     }
     return dump
@@ -271,4 +271,39 @@ function trace (key, seed) {
     return seed
 }
 
+/*
+ *  Determine value type before setting it on dump object
+ */
+function dumpValue (binding) {
+    var val = binding.value
+    if (Array.isArray(val)) {
+        return val.map(dumpScope)
+    } else if (binding.isComputed) {
+        return val.get()
+    } else if (typeof val !== 'function') {
+        return val
+    }
+}
+
+/*
+ *  recursively set a nested value on object based on keypath
+ *  used in $dump()
+ */
+function setNestedValue (obj, path, val) {
+    var key = path[0]
+    if (path.length === 1) {
+        obj[key] = val
+    } else {
+        if (!obj[key]) obj[key] = {}
+        setValue(obj[key], path.slice(1), val)
+    }
+}
+
+/*
+ *  dump sub-scope iterator
+ */
+function dumpScope (scope) {
+    return scope.$dump()
+}
+
 module.exports = Seed