mirror of https://github.com/vuejs/vue.git
				
				
				
			separate storage in todos example, expose some utils methods
This commit is contained in:
		
							parent
							
								
									d0c96c5c25
								
							
						
					
					
						commit
						cfc27d89f1
					
				| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
        <link rel="stylesheet" type="text/css" href="common/base.css">
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <section id="todoapp" sd-controller="Todos">
 | 
			
		||||
        <section id="todoapp" sd-controller="todos">
 | 
			
		||||
            <header id="header">
 | 
			
		||||
                <h1>todos</h1>
 | 
			
		||||
                <input
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@
 | 
			
		|||
                                sd-checked="todo.completed"
 | 
			
		||||
                                sd-on="change:updateCount"
 | 
			
		||||
                            >
 | 
			
		||||
                            <label sd-text="todo.title" sd-on="dblclick:edit"></label>
 | 
			
		||||
                            <label sd-text="todo.title" sd-on="dblclick:editTodo"></label>
 | 
			
		||||
                            <button class="destroy" sd-on="click:removeTodo"></button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <input
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +71,7 @@
 | 
			
		|||
            <p>Created by <a href="http://evanyou.me">Evan You</a></p>
 | 
			
		||||
        </footer>
 | 
			
		||||
        <script src="../../dist/seed.js"></script>
 | 
			
		||||
        <script src="js/todoStorage.js"></script>
 | 
			
		||||
        <script src="js/app.js"></script>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,25 +1,7 @@
 | 
			
		|||
Seed.controller('Todos', function (scope) {
 | 
			
		||||
 | 
			
		||||
    // data persistence -------------------------------------------------------
 | 
			
		||||
    var STORAGE_KEY = 'todos-seedjs'
 | 
			
		||||
    function sync () {
 | 
			
		||||
        localStorage.setItem(STORAGE_KEY, scope.$serialize('todos'))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // filters ----------------------------------------------------------------
 | 
			
		||||
    var filters = {
 | 
			
		||||
        all: function () { return true },
 | 
			
		||||
        active: function (v) { return !v },
 | 
			
		||||
        completed: function (v) { return v }
 | 
			
		||||
    }
 | 
			
		||||
    updateFilter()
 | 
			
		||||
    window.addEventListener('hashchange', updateFilter)
 | 
			
		||||
    function updateFilter () {
 | 
			
		||||
        scope.filter = location.hash ? location.hash.slice(2) : 'all'
 | 
			
		||||
    }
 | 
			
		||||
Seed.controller('todos', function (scope) {
 | 
			
		||||
 | 
			
		||||
    // regular properties -----------------------------------------------------
 | 
			
		||||
    scope.todos = JSON.parse(localStorage.getItem(STORAGE_KEY)) || []
 | 
			
		||||
    scope.todos = todoStorage.fetch()
 | 
			
		||||
    scope.remaining = scope.todos.reduce(function (n, todo) {
 | 
			
		||||
        return n + (todo.completed ? 0 : 1)
 | 
			
		||||
    }, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -63,23 +45,23 @@ Seed.controller('Todos', function (scope) {
 | 
			
		|||
            scope.todos.unshift({ title: value, completed: false })
 | 
			
		||||
            scope.newTodo = ''
 | 
			
		||||
            scope.remaining++
 | 
			
		||||
            sync()
 | 
			
		||||
            todoStorage.save(scope.todos)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scope.removeTodo = function (e) {
 | 
			
		||||
        scope.todos.remove(e.scope)
 | 
			
		||||
        scope.remaining -= e.scope.completed ? 0 : 1
 | 
			
		||||
        sync()
 | 
			
		||||
        todoStorage.save(scope.todos)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scope.updateCount = function (e) {
 | 
			
		||||
        scope.remaining += e.scope.completed ? -1 : 1
 | 
			
		||||
        sync()
 | 
			
		||||
        todoStorage.save(scope.todos)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var beforeEditCache
 | 
			
		||||
    scope.edit = function (e) {
 | 
			
		||||
    scope.editTodo = function (e) {
 | 
			
		||||
        beforeEditCache = e.scope.title
 | 
			
		||||
        e.scope.editing = true
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +71,7 @@ Seed.controller('Todos', function (scope) {
 | 
			
		|||
        e.scope.editing = false
 | 
			
		||||
        e.scope.title = e.scope.title.trim()
 | 
			
		||||
        if (!e.scope.title) scope.removeTodo(e)
 | 
			
		||||
        sync()
 | 
			
		||||
        todoStorage.save(scope.todos)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scope.cancelEdit = function (e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -103,11 +85,23 @@ Seed.controller('Todos', function (scope) {
 | 
			
		|||
        scope.todos = scope.todos.filter(function (todo) {
 | 
			
		||||
            return !todo.completed
 | 
			
		||||
        })
 | 
			
		||||
        sync()
 | 
			
		||||
        todoStorage.save(scope.todos)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // filters ----------------------------------------------------------------
 | 
			
		||||
    var filters = {
 | 
			
		||||
        all: function () { return true },
 | 
			
		||||
        active: function (v) { return !v },
 | 
			
		||||
        completed: function (v) { return v }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateFilter () {
 | 
			
		||||
        scope.filter = location.hash ? location.hash.slice(2) : 'all'
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    updateFilter()
 | 
			
		||||
    window.addEventListener('hashchange', updateFilter)
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
var s = Date.now()
 | 
			
		||||
Seed.bootstrap({ debug: false })
 | 
			
		||||
console.log(Date.now() - s)
 | 
			
		||||
Seed.bootstrap()
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
var todoStorage = (function () {
 | 
			
		||||
    var STORAGE_KEY = 'todos-seedjs'
 | 
			
		||||
    return {
 | 
			
		||||
        fetch: function () {
 | 
			
		||||
            return JSON.parse(localStorage.getItem(this.STORAGE_KEY) || '[]')
 | 
			
		||||
        },
 | 
			
		||||
        save: function (todos) {
 | 
			
		||||
            localStorage.setItem(this.STORAGE_KEY, Seed.utils.serialize(todos))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}())
 | 
			
		||||
							
								
								
									
										38
									
								
								src/main.js
								
								
								
								
							
							
						
						
									
										38
									
								
								src/main.js
								
								
								
								
							| 
						 | 
				
			
			@ -2,7 +2,8 @@ var config      = require('./config'),
 | 
			
		|||
    Seed        = require('./seed'),
 | 
			
		||||
    directives  = require('./directives'),
 | 
			
		||||
    filters     = require('./filters'),
 | 
			
		||||
    textParser  = require('./text-parser')
 | 
			
		||||
    textParser  = require('./text-parser'),
 | 
			
		||||
    utils       = require('./utils')
 | 
			
		||||
 | 
			
		||||
var controllers = config.controllers,
 | 
			
		||||
    datum       = config.datum,
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +11,11 @@ var controllers = config.controllers,
 | 
			
		|||
    reserved    = ['datum', 'controllers'],
 | 
			
		||||
    booted      = false
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  expose utils
 | 
			
		||||
 */
 | 
			
		||||
api.utils = utils
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  Store a piece of plain data in config.datum
 | 
			
		||||
 *  so it can be consumed by sd-data
 | 
			
		||||
| 
						 | 
				
			
			@ -45,12 +51,9 @@ api.filter = function (name, fn) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  Bootstrap the whole thing
 | 
			
		||||
 *  by creating a Seed instance for top level nodes
 | 
			
		||||
 *  that has either sd-controller or sd-data
 | 
			
		||||
 *  Set config options
 | 
			
		||||
 */
 | 
			
		||||
api.bootstrap = function (opts) {
 | 
			
		||||
    if (booted) return
 | 
			
		||||
api.config = function (opts) {
 | 
			
		||||
    if (opts) {
 | 
			
		||||
        for (var key in opts) {
 | 
			
		||||
            if (reserved.indexOf(key) === -1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -59,16 +62,31 @@ api.bootstrap = function (opts) {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    textParser.buildRegex()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  Compile a single element
 | 
			
		||||
 */
 | 
			
		||||
api.compile = function (el) {
 | 
			
		||||
    new Seed(el)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  Bootstrap the whole thing
 | 
			
		||||
 *  by creating a Seed instance for top level nodes
 | 
			
		||||
 *  that has either sd-controller or sd-data
 | 
			
		||||
 */
 | 
			
		||||
api.bootstrap = function (opts) {
 | 
			
		||||
    if (booted) return
 | 
			
		||||
    api.config(opts)
 | 
			
		||||
    var el,
 | 
			
		||||
        ctrlSlt = '[' + config.prefix + '-controller]',
 | 
			
		||||
        dataSlt = '[' + config.prefix + '-data]',
 | 
			
		||||
        seeds   = []
 | 
			
		||||
        dataSlt = '[' + config.prefix + '-data]'
 | 
			
		||||
    /* jshint boss: true */
 | 
			
		||||
    while (el = document.querySelector(ctrlSlt) || document.querySelector(dataSlt)) {
 | 
			
		||||
        seeds.push((new Seed(el)).scope)
 | 
			
		||||
        new Seed(el)
 | 
			
		||||
    }
 | 
			
		||||
    booted = true
 | 
			
		||||
    return seeds.length > 1 ? seeds : seeds[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = api
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ ScopeProto.$unwatch = function (key) {
 | 
			
		|||
 */
 | 
			
		||||
ScopeProto.$dump = function (key) {
 | 
			
		||||
    var bindings = this.$seed._bindings
 | 
			
		||||
    return utils.dumpValue(key ? bindings[key].value : this)
 | 
			
		||||
    return utils.dump(key ? bindings[key].value : this)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,9 +64,10 @@ function Seed (el, options) {
 | 
			
		|||
    var ctrlID = el.getAttribute(ctrlAttr)
 | 
			
		||||
    if (ctrlID) {
 | 
			
		||||
        el.removeAttribute(ctrlAttr)
 | 
			
		||||
        var factory = config.controllers[ctrlID]
 | 
			
		||||
        if (factory) {
 | 
			
		||||
            factory(this.scope)
 | 
			
		||||
        var controller = config.controllers[ctrlID]
 | 
			
		||||
        if (controller) {
 | 
			
		||||
            this._controller = controller
 | 
			
		||||
            controller(this.scope)
 | 
			
		||||
        } else {
 | 
			
		||||
            config.warn('controller "' + ctrlID + '" is not defined.')
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +87,7 @@ function Seed (el, options) {
 | 
			
		|||
    if (this._computed.length) depsParser.parse(this._computed)
 | 
			
		||||
    delete this._computed
 | 
			
		||||
    
 | 
			
		||||
    // extract dependencies for computed properties with dynamic context
 | 
			
		||||
    if (this._contextBindings.length) this._bindContexts(this._contextBindings)
 | 
			
		||||
    delete this._contextBindings
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ module.exports = {
 | 
			
		|||
     *  Parse a piece of text, return an array of tokens
 | 
			
		||||
     */
 | 
			
		||||
    parse: function (node) {
 | 
			
		||||
        if (!BINDING_RE) module.exports.buildRegex()
 | 
			
		||||
        var text = node.nodeValue
 | 
			
		||||
        if (!BINDING_RE.test(text)) return null
 | 
			
		||||
        var m, i, tokens = []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								src/utils.js
								
								
								
								
							
							
						
						
									
										22
									
								
								src/utils.js
								
								
								
								
							| 
						 | 
				
			
			@ -24,21 +24,22 @@ function typeOf (obj) {
 | 
			
		|||
/*
 | 
			
		||||
 *  Recursively dump stuff...
 | 
			
		||||
 */
 | 
			
		||||
function dumpValue (val) {
 | 
			
		||||
function dump (val) {
 | 
			
		||||
    var type = typeOf(val)
 | 
			
		||||
    if (type === 'Array') {
 | 
			
		||||
        return val.map(dumpValue)
 | 
			
		||||
        return val.map(dump)
 | 
			
		||||
    } else if (type === 'Object') {
 | 
			
		||||
        if (val.get) { // computed property
 | 
			
		||||
            return val.get()
 | 
			
		||||
        } else { // object / child scope
 | 
			
		||||
            var ret = {}
 | 
			
		||||
            var ret = {}, prop
 | 
			
		||||
            for (var key in val) {
 | 
			
		||||
                if (val.hasOwnProperty(key) &&
 | 
			
		||||
                    typeof val[key] !== 'function' &&
 | 
			
		||||
                prop = val[key]
 | 
			
		||||
                if (typeof prop !== 'function' &&
 | 
			
		||||
                    val.hasOwnProperty(key) &&
 | 
			
		||||
                    key.charAt(0) !== '$')
 | 
			
		||||
                {
 | 
			
		||||
                    ret[key] = dumpValue(val[key])
 | 
			
		||||
                    ret[key] = dump(prop)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return ret
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +52,14 @@ function dumpValue (val) {
 | 
			
		|||
module.exports = {
 | 
			
		||||
 | 
			
		||||
    typeOf: typeOf,
 | 
			
		||||
    dumpValue: dumpValue,
 | 
			
		||||
    dump: dump,
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     *  shortcut for JSON.stringify-ing a dumped value
 | 
			
		||||
     */
 | 
			
		||||
    serialize: function (val) {
 | 
			
		||||
        return JSON.stringify(dump(val))
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     *  Get a value from an object based on a path array
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue