Browse Source

update todomvc example to be same as lended version

Evan You 12 years ago
parent
commit
cb1d69c66c

+ 7 - 2
dist/vue.js

@@ -1,3 +1,8 @@
+/*
+ Vue.js v0.8.3
+ (c) 2014 Evan You
+ License: MIT
+*/
 ;(function(){
 'use strict';
 
@@ -3538,8 +3543,8 @@ module.exports = {
         var prop = this.prop
         this.el.style[prop] = value
         if (this.prefixed) {
-            var i = prefixes.length,
-                prop = prop.charAt(0).toUpperCase() + prop.slice(1)
+            prop = prop.charAt(0).toUpperCase() + prop.slice(1)
+            var i = prefixes.length
             while (i--) {
                 this.el.style[prefixes[i] + prop] = value
             }

File diff suppressed because it is too large
+ 0 - 0
dist/vue.min.js


+ 36 - 0
examples/commits/app.js

@@ -0,0 +1,36 @@
+var demo = new Vue({
+
+    el: '#demo',
+
+    data: {
+        branch: 'master'
+    },
+
+    created: function () {
+        this.$watch('branch', function () {
+            this.fetchData()
+        })
+    },
+
+    filters: {
+        truncate: function (v) {
+            var newline = v.indexOf('\n')
+            return newline > 0 ? v.slice(0, newline) : v
+        },
+        formatDate: function (v) {
+            return v.replace(/T|Z/g, ' ')
+        }
+    },
+
+    methods: {
+        fetchData: function () {
+            var xhr = new XMLHttpRequest(),
+                self = this
+            xhr.open('GET', 'https://api.github.com/repos/yyx990803/vue/commits?per_page=3&sha=' + self.branch)
+            xhr.onload = function () {
+                self.commits = JSON.parse(xhr.responseText)
+            }
+            xhr.send()
+        }
+    }
+})

+ 1 - 38
examples/commits/index.html

@@ -35,41 +35,4 @@
 </div>
 
 <script src="../../dist/vue.js"></script>
-<script>
-    var demo = new Vue({
-
-        el: '#demo',
-
-        data: {
-            branch: 'master'
-        },
-
-        created: function () {
-            this.$watch('branch', function () {
-                this.fetchData()
-            })
-        },
-
-        filters: {
-            truncate: function (v) {
-                var newline = v.indexOf('\n')
-                return newline > 0 ? v.slice(0, newline) : v
-            },
-            formatDate: function (v) {
-                return v.replace(/T|Z/g, ' ')
-            }
-        },
-
-        methods: {
-            fetchData: function () {
-                var xhr = new XMLHttpRequest(),
-                    self = this
-                xhr.open('GET', 'https://api.github.com/repos/yyx990803/vue/commits?per_page=3&sha=' + self.branch)
-                xhr.onload = function () {
-                    self.commits = JSON.parse(xhr.responseText)
-                }
-                xhr.send()
-            }
-        }
-    })
-</script>
+<script src="app.js"></script>

+ 719 - 0
examples/todomvc/bower_components/director/director.js

@@ -0,0 +1,719 @@
+
+
+//
+// Generated on Fri Dec 27 2013 12:02:11 GMT-0500 (EST) by Nodejitsu, Inc (Using Codesurgeon).
+// Version 1.2.2
+//
+
+(function (exports) {
+
+/*
+ * browser.js: Browser specific functionality for director.
+ *
+ * (C) 2011, Nodejitsu Inc.
+ * MIT LICENSE
+ *
+ */
+
+if (!Array.prototype.filter) {
+  Array.prototype.filter = function(filter, that) {
+    var other = [], v;
+    for (var i = 0, n = this.length; i < n; i++) {
+      if (i in this && filter.call(that, v = this[i], i, this)) {
+        other.push(v);
+      }
+    }
+    return other;
+  };
+}
+
+if (!Array.isArray){
+  Array.isArray = function(obj) {
+    return Object.prototype.toString.call(obj) === '[object Array]';
+  };
+}
+
+var dloc = document.location;
+
+function dlocHashEmpty() {
+  // Non-IE browsers return '' when the address bar shows '#'; Director's logic
+  // assumes both mean empty.
+  return dloc.hash === '' || dloc.hash === '#';
+}
+
+var listener = {
+  mode: 'modern',
+  hash: dloc.hash,
+  history: false,
+
+  check: function () {
+    var h = dloc.hash;
+    if (h != this.hash) {
+      this.hash = h;
+      this.onHashChanged();
+    }
+  },
+
+  fire: function () {
+    if (this.mode === 'modern') {
+      this.history === true ? window.onpopstate() : window.onhashchange();
+    }
+    else {
+      this.onHashChanged();
+    }
+  },
+
+  init: function (fn, history) {
+    var self = this;
+    this.history = history;
+
+    if (!Router.listeners) {
+      Router.listeners = [];
+    }
+
+    function onchange(onChangeEvent) {
+      for (var i = 0, l = Router.listeners.length; i < l; i++) {
+        Router.listeners[i](onChangeEvent);
+      }
+    }
+
+    //note IE8 is being counted as 'modern' because it has the hashchange event
+    if ('onhashchange' in window && (document.documentMode === undefined
+      || document.documentMode > 7)) {
+      // At least for now HTML5 history is available for 'modern' browsers only
+      if (this.history === true) {
+        // There is an old bug in Chrome that causes onpopstate to fire even
+        // upon initial page load. Since the handler is run manually in init(),
+        // this would cause Chrome to run it twise. Currently the only
+        // workaround seems to be to set the handler after the initial page load
+        // http://code.google.com/p/chromium/issues/detail?id=63040
+        setTimeout(function() {
+          window.onpopstate = onchange;
+        }, 500);
+      }
+      else {
+        window.onhashchange = onchange;
+      }
+      this.mode = 'modern';
+    }
+    else {
+      //
+      // IE support, based on a concept by Erik Arvidson ...
+      //
+      var frame = document.createElement('iframe');
+      frame.id = 'state-frame';
+      frame.style.display = 'none';
+      document.body.appendChild(frame);
+      this.writeFrame('');
+
+      if ('onpropertychange' in document && 'attachEvent' in document) {
+        document.attachEvent('onpropertychange', function () {
+          if (event.propertyName === 'location') {
+            self.check();
+          }
+        });
+      }
+
+      window.setInterval(function () { self.check(); }, 50);
+
+      this.onHashChanged = onchange;
+      this.mode = 'legacy';
+    }
+
+    Router.listeners.push(fn);
+
+    return this.mode;
+  },
+
+  destroy: function (fn) {
+    if (!Router || !Router.listeners) {
+      return;
+    }
+
+    var listeners = Router.listeners;
+
+    for (var i = listeners.length - 1; i >= 0; i--) {
+      if (listeners[i] === fn) {
+        listeners.splice(i, 1);
+      }
+    }
+  },
+
+  setHash: function (s) {
+    // Mozilla always adds an entry to the history
+    if (this.mode === 'legacy') {
+      this.writeFrame(s);
+    }
+
+    if (this.history === true) {
+      window.history.pushState({}, document.title, s);
+      // Fire an onpopstate event manually since pushing does not obviously
+      // trigger the pop event.
+      this.fire();
+    } else {
+      dloc.hash = (s[0] === '/') ? s : '/' + s;
+    }
+    return this;
+  },
+
+  writeFrame: function (s) {
+    // IE support...
+    var f = document.getElementById('state-frame');
+    var d = f.contentDocument || f.contentWindow.document;
+    d.open();
+    d.write("<script>_hash = '" + s + "'; onload = parent.listener.syncHash;<script>");
+    d.close();
+  },
+
+  syncHash: function () {
+    // IE support...
+    var s = this._hash;
+    if (s != dloc.hash) {
+      dloc.hash = s;
+    }
+    return this;
+  },
+
+  onHashChanged: function () {}
+};
+
+var Router = exports.Router = function (routes) {
+  if (!(this instanceof Router)) return new Router(routes);
+
+  this.params   = {};
+  this.routes   = {};
+  this.methods  = ['on', 'once', 'after', 'before'];
+  this.scope    = [];
+  this._methods = {};
+
+  this._insert = this.insert;
+  this.insert = this.insertEx;
+
+  this.historySupport = (window.history != null ? window.history.pushState : null) != null
+
+  this.configure();
+  this.mount(routes || {});
+};
+
+Router.prototype.init = function (r) {
+  var self = this;
+  this.handler = function(onChangeEvent) {
+    var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;
+    var url = self.history === true ? self.getPath() : newURL.replace(/.*#/, '');
+    self.dispatch('on', url.charAt(0) === '/' ? url : '/' + url);
+  };
+
+  listener.init(this.handler, this.history);
+
+  if (this.history === false) {
+    if (dlocHashEmpty() && r) {
+      dloc.hash = r;
+    } else if (!dlocHashEmpty()) {
+      self.dispatch('on', '/' + dloc.hash.replace(/^(#\/|#|\/)/, ''));
+    }
+  }
+  else {
+    var routeTo = dlocHashEmpty() && r ? r : !dlocHashEmpty() ? dloc.hash.replace(/^#/, '') : null;
+    if (routeTo) {
+      window.history.replaceState({}, document.title, routeTo);
+    }
+
+    // Router has been initialized, but due to the chrome bug it will not
+    // yet actually route HTML5 history state changes. Thus, decide if should route.
+    if (routeTo || this.run_in_init === true) {
+      this.handler();
+    }
+  }
+
+  return this;
+};
+
+Router.prototype.explode = function () {
+  var v = this.history === true ? this.getPath() : dloc.hash;
+  if (v.charAt(1) === '/') { v=v.slice(1) }
+  return v.slice(1, v.length).split("/");
+};
+
+Router.prototype.setRoute = function (i, v, val) {
+  var url = this.explode();
+
+  if (typeof i === 'number' && typeof v === 'string') {
+    url[i] = v;
+  }
+  else if (typeof val === 'string') {
+    url.splice(i, v, s);
+  }
+  else {
+    url = [i];
+  }
+
+  listener.setHash(url.join('/'));
+  return url;
+};
+
+//
+// ### function insertEx(method, path, route, parent)
+// #### @method {string} Method to insert the specific `route`.
+// #### @path {Array} Parsed path to insert the `route` at.
+// #### @route {Array|function} Route handlers to insert.
+// #### @parent {Object} **Optional** Parent "routes" to insert into.
+// insert a callback that will only occur once per the matched route.
+//
+Router.prototype.insertEx = function(method, path, route, parent) {
+  if (method === "once") {
+    method = "on";
+    route = function(route) {
+      var once = false;
+      return function() {
+        if (once) return;
+        once = true;
+        return route.apply(this, arguments);
+      };
+    }(route);
+  }
+  return this._insert(method, path, route, parent);
+};
+
+Router.prototype.getRoute = function (v) {
+  var ret = v;
+
+  if (typeof v === "number") {
+    ret = this.explode()[v];
+  }
+  else if (typeof v === "string"){
+    var h = this.explode();
+    ret = h.indexOf(v);
+  }
+  else {
+    ret = this.explode();
+  }
+
+  return ret;
+};
+
+Router.prototype.destroy = function () {
+  listener.destroy(this.handler);
+  return this;
+};
+
+Router.prototype.getPath = function () {
+  var path = window.location.pathname;
+  if (path.substr(0, 1) !== '/') {
+    path = '/' + path;
+  }
+  return path;
+};
+function _every(arr, iterator) {
+  for (var i = 0; i < arr.length; i += 1) {
+    if (iterator(arr[i], i, arr) === false) {
+      return;
+    }
+  }
+}
+
+function _flatten(arr) {
+  var flat = [];
+  for (var i = 0, n = arr.length; i < n; i++) {
+    flat = flat.concat(arr[i]);
+  }
+  return flat;
+}
+
+function _asyncEverySeries(arr, iterator, callback) {
+  if (!arr.length) {
+    return callback();
+  }
+  var completed = 0;
+  (function iterate() {
+    iterator(arr[completed], function(err) {
+      if (err || err === false) {
+        callback(err);
+        callback = function() {};
+      } else {
+        completed += 1;
+        if (completed === arr.length) {
+          callback();
+        } else {
+          iterate();
+        }
+      }
+    });
+  })();
+}
+
+function paramifyString(str, params, mod) {
+  mod = str;
+  for (var param in params) {
+    if (params.hasOwnProperty(param)) {
+      mod = params[param](str);
+      if (mod !== str) {
+        break;
+      }
+    }
+  }
+  return mod === str ? "([._a-zA-Z0-9-]+)" : mod;
+}
+
+function regifyString(str, params) {
+  var matches, last = 0, out = "";
+  while (matches = str.substr(last).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/)) {
+    last = matches.index + matches[0].length;
+    matches[0] = matches[0].replace(/^\*/, "([_.()!\\ %@&a-zA-Z0-9-]+)");
+    out += str.substr(0, matches.index) + matches[0];
+  }
+  str = out += str.substr(last);
+  var captures = str.match(/:([^\/]+)/ig), capture, length;
+  if (captures) {
+    length = captures.length;
+    for (var i = 0; i < length; i++) {
+      capture = captures[i];
+      if (capture.slice(0, 2) === "::") {
+        str = capture.slice(1);
+      } else {
+        str = str.replace(capture, paramifyString(capture, params));
+      }
+    }
+  }
+  return str;
+}
+
+function terminator(routes, delimiter, start, stop) {
+  var last = 0, left = 0, right = 0, start = (start || "(").toString(), stop = (stop || ")").toString(), i;
+  for (i = 0; i < routes.length; i++) {
+    var chunk = routes[i];
+    if (chunk.indexOf(start, last) > chunk.indexOf(stop, last) || ~chunk.indexOf(start, last) && !~chunk.indexOf(stop, last) || !~chunk.indexOf(start, last) && ~chunk.indexOf(stop, last)) {
+      left = chunk.indexOf(start, last);
+      right = chunk.indexOf(stop, last);
+      if (~left && !~right || !~left && ~right) {
+        var tmp = routes.slice(0, (i || 1) + 1).join(delimiter);
+        routes = [ tmp ].concat(routes.slice((i || 1) + 1));
+      }
+      last = (right > left ? right : left) + 1;
+      i = 0;
+    } else {
+      last = 0;
+    }
+  }
+  return routes;
+}
+
+Router.prototype.configure = function(options) {
+  options = options || {};
+  for (var i = 0; i < this.methods.length; i++) {
+    this._methods[this.methods[i]] = true;
+  }
+  this.recurse = options.recurse || this.recurse || false;
+  this.async = options.async || false;
+  this.delimiter = options.delimiter || "/";
+  this.strict = typeof options.strict === "undefined" ? true : options.strict;
+  this.notfound = options.notfound;
+  this.resource = options.resource;
+  this.history = options.html5history && this.historySupport || false;
+  this.run_in_init = this.history === true && options.run_handler_in_init !== false;
+  this.every = {
+    after: options.after || null,
+    before: options.before || null,
+    on: options.on || null
+  };
+  return this;
+};
+
+Router.prototype.param = function(token, matcher) {
+  if (token[0] !== ":") {
+    token = ":" + token;
+  }
+  var compiled = new RegExp(token, "g");
+  this.params[token] = function(str) {
+    return str.replace(compiled, matcher.source || matcher);
+  };
+};
+
+Router.prototype.on = Router.prototype.route = function(method, path, route) {
+  var self = this;
+  if (!route && typeof path == "function") {
+    route = path;
+    path = method;
+    method = "on";
+  }
+  if (Array.isArray(path)) {
+    return path.forEach(function(p) {
+      self.on(method, p, route);
+    });
+  }
+  if (path.source) {
+    path = path.source.replace(/\\\//ig, "/");
+  }
+  if (Array.isArray(method)) {
+    return method.forEach(function(m) {
+      self.on(m.toLowerCase(), path, route);
+    });
+  }
+  path = path.split(new RegExp(this.delimiter));
+  path = terminator(path, this.delimiter);
+  this.insert(method, this.scope.concat(path), route);
+};
+
+Router.prototype.dispatch = function(method, path, callback) {
+  var self = this, fns = this.traverse(method, path, this.routes, ""), invoked = this._invoked, after;
+  this._invoked = true;
+  if (!fns || fns.length === 0) {
+    this.last = [];
+    if (typeof this.notfound === "function") {
+      this.invoke([ this.notfound ], {
+        method: method,
+        path: path
+      }, callback);
+    }
+    return false;
+  }
+  if (this.recurse === "forward") {
+    fns = fns.reverse();
+  }
+  function updateAndInvoke() {
+    self.last = fns.after;
+    self.invoke(self.runlist(fns), self, callback);
+  }
+  after = this.every && this.every.after ? [ this.every.after ].concat(this.last) : [ this.last ];
+  if (after && after.length > 0 && invoked) {
+    if (this.async) {
+      this.invoke(after, this, updateAndInvoke);
+    } else {
+      this.invoke(after, this);
+      updateAndInvoke();
+    }
+    return true;
+  }
+  updateAndInvoke();
+  return true;
+};
+
+Router.prototype.invoke = function(fns, thisArg, callback) {
+  var self = this;
+  var apply;
+  if (this.async) {
+    apply = function(fn, next) {
+      if (Array.isArray(fn)) {
+        return _asyncEverySeries(fn, apply, next);
+      } else if (typeof fn == "function") {
+        fn.apply(thisArg, fns.captures.concat(next));
+      }
+    };
+    _asyncEverySeries(fns, apply, function() {
+      if (callback) {
+        callback.apply(thisArg, arguments);
+      }
+    });
+  } else {
+    apply = function(fn) {
+      if (Array.isArray(fn)) {
+        return _every(fn, apply);
+      } else if (typeof fn === "function") {
+        return fn.apply(thisArg, fns.captures || []);
+      } else if (typeof fn === "string" && self.resource) {
+        self.resource[fn].apply(thisArg, fns.captures || []);
+      }
+    };
+    _every(fns, apply);
+  }
+};
+
+Router.prototype.traverse = function(method, path, routes, regexp, filter) {
+  var fns = [], current, exact, match, next, that;
+  function filterRoutes(routes) {
+    if (!filter) {
+      return routes;
+    }
+    function deepCopy(source) {
+      var result = [];
+      for (var i = 0; i < source.length; i++) {
+        result[i] = Array.isArray(source[i]) ? deepCopy(source[i]) : source[i];
+      }
+      return result;
+    }
+    function applyFilter(fns) {
+      for (var i = fns.length - 1; i >= 0; i--) {
+        if (Array.isArray(fns[i])) {
+          applyFilter(fns[i]);
+          if (fns[i].length === 0) {
+            fns.splice(i, 1);
+          }
+        } else {
+          if (!filter(fns[i])) {
+            fns.splice(i, 1);
+          }
+        }
+      }
+    }
+    var newRoutes = deepCopy(routes);
+    newRoutes.matched = routes.matched;
+    newRoutes.captures = routes.captures;
+    newRoutes.after = routes.after.filter(filter);
+    applyFilter(newRoutes);
+    return newRoutes;
+  }
+  if (path === this.delimiter && routes[method]) {
+    next = [ [ routes.before, routes[method] ].filter(Boolean) ];
+    next.after = [ routes.after ].filter(Boolean);
+    next.matched = true;
+    next.captures = [];
+    return filterRoutes(next);
+  }
+  for (var r in routes) {
+    if (routes.hasOwnProperty(r) && (!this._methods[r] || this._methods[r] && typeof routes[r] === "object" && !Array.isArray(routes[r]))) {
+      current = exact = regexp + this.delimiter + r;
+      if (!this.strict) {
+        exact += "[" + this.delimiter + "]?";
+      }
+      match = path.match(new RegExp("^" + exact));
+      if (!match) {
+        continue;
+      }
+      if (match[0] && match[0] == path && routes[r][method]) {
+        next = [ [ routes[r].before, routes[r][method] ].filter(Boolean) ];
+        next.after = [ routes[r].after ].filter(Boolean);
+        next.matched = true;
+        next.captures = match.slice(1);
+        if (this.recurse && routes === this.routes) {
+          next.push([ routes.before, routes.on ].filter(Boolean));
+          next.after = next.after.concat([ routes.after ].filter(Boolean));
+        }
+        return filterRoutes(next);
+      }
+      next = this.traverse(method, path, routes[r], current);
+      if (next.matched) {
+        if (next.length > 0) {
+          fns = fns.concat(next);
+        }
+        if (this.recurse) {
+          fns.push([ routes[r].before, routes[r].on ].filter(Boolean));
+          next.after = next.after.concat([ routes[r].after ].filter(Boolean));
+          if (routes === this.routes) {
+            fns.push([ routes["before"], routes["on"] ].filter(Boolean));
+            next.after = next.after.concat([ routes["after"] ].filter(Boolean));
+          }
+        }
+        fns.matched = true;
+        fns.captures = next.captures;
+        fns.after = next.after;
+        return filterRoutes(fns);
+      }
+    }
+  }
+  return false;
+};
+
+Router.prototype.insert = function(method, path, route, parent) {
+  var methodType, parentType, isArray, nested, part;
+  path = path.filter(function(p) {
+    return p && p.length > 0;
+  });
+  parent = parent || this.routes;
+  part = path.shift();
+  if (/\:|\*/.test(part) && !/\\d|\\w/.test(part)) {
+    part = regifyString(part, this.params);
+  }
+  if (path.length > 0) {
+    parent[part] = parent[part] || {};
+    return this.insert(method, path, route, parent[part]);
+  }
+  if (!part && !path.length && parent === this.routes) {
+    methodType = typeof parent[method];
+    switch (methodType) {
+     case "function":
+      parent[method] = [ parent[method], route ];
+      return;
+     case "object":
+      parent[method].push(route);
+      return;
+     case "undefined":
+      parent[method] = route;
+      return;
+    }
+    return;
+  }
+  parentType = typeof parent[part];
+  isArray = Array.isArray(parent[part]);
+  if (parent[part] && !isArray && parentType == "object") {
+    methodType = typeof parent[part][method];
+    switch (methodType) {
+     case "function":
+      parent[part][method] = [ parent[part][method], route ];
+      return;
+     case "object":
+      parent[part][method].push(route);
+      return;
+     case "undefined":
+      parent[part][method] = route;
+      return;
+    }
+  } else if (parentType == "undefined") {
+    nested = {};
+    nested[method] = route;
+    parent[part] = nested;
+    return;
+  }
+  throw new Error("Invalid route context: " + parentType);
+};
+
+
+
+Router.prototype.extend = function(methods) {
+  var self = this, len = methods.length, i;
+  function extend(method) {
+    self._methods[method] = true;
+    self[method] = function() {
+      var extra = arguments.length === 1 ? [ method, "" ] : [ method ];
+      self.on.apply(self, extra.concat(Array.prototype.slice.call(arguments)));
+    };
+  }
+  for (i = 0; i < len; i++) {
+    extend(methods[i]);
+  }
+};
+
+Router.prototype.runlist = function(fns) {
+  var runlist = this.every && this.every.before ? [ this.every.before ].concat(_flatten(fns)) : _flatten(fns);
+  if (this.every && this.every.on) {
+    runlist.push(this.every.on);
+  }
+  runlist.captures = fns.captures;
+  runlist.source = fns.source;
+  return runlist;
+};
+
+Router.prototype.mount = function(routes, path) {
+  if (!routes || typeof routes !== "object" || Array.isArray(routes)) {
+    return;
+  }
+  var self = this;
+  path = path || [];
+  if (!Array.isArray(path)) {
+    path = path.split(self.delimiter);
+  }
+  function insertOrMount(route, local) {
+    var rename = route, parts = route.split(self.delimiter), routeType = typeof routes[route], isRoute = parts[0] === "" || !self._methods[parts[0]], event = isRoute ? "on" : rename;
+    if (isRoute) {
+      rename = rename.slice((rename.match(new RegExp("^" + self.delimiter)) || [ "" ])[0].length);
+      parts.shift();
+    }
+    if (isRoute && routeType === "object" && !Array.isArray(routes[route])) {
+      local = local.concat(parts);
+      self.mount(routes[route], local);
+      return;
+    }
+    if (isRoute) {
+      local = local.concat(rename.split(self.delimiter));
+      local = terminator(local, self.delimiter);
+    }
+    self.insert(event, local, routes[route]);
+  }
+  for (var route in routes) {
+    if (routes.hasOwnProperty(route)) {
+      insertOrMount(route, path.slice(0));
+    }
+  }
+};
+
+
+
+}(typeof exports === "object" ? exports : window));

+ 0 - 15
examples/todomvc/bower_components/todomvc-common/.bower.json

@@ -1,15 +0,0 @@
-{
-  "name": "todomvc-common",
-  "version": "0.1.9",
-  "homepage": "https://github.com/tastejs/todomvc-common",
-  "_release": "0.1.9",
-  "_resolution": {
-    "type": "version",
-    "tag": "v0.1.9",
-    "commit": "7dd61b0ebf56c020e719a69444442cc7ae7242ff"
-  },
-  "_source": "git://github.com/tastejs/todomvc-common.git",
-  "_target": "~0.1.9",
-  "_originalSource": "todomvc-common",
-  "_direct": true
-}

+ 0 - 4
examples/todomvc/bower_components/todomvc-common/bower.json

@@ -1,4 +0,0 @@
-{
-  "name": "todomvc-common",
-  "version": "0.1.9"
-}

+ 0 - 8
examples/todomvc/bower_components/todomvc-common/readme.md

@@ -1,8 +0,0 @@
-# todomvc-common
-
-> Bower component for some common utilities we use in every app
-
-
-## License
-
-MIT

+ 2 - 0
examples/todomvc/index.html

@@ -87,8 +87,10 @@
         <!-- end testing -->
 
         <script src="../../dist/vue.js"></script>
+        <script src="bower_components/director/director.js"></script>
         <script src="js/store.js"></script>
         <script src="js/app.js"></script>
+        <script src="js/routes.js"></script>
         <script src="js/benchmark.js"></script>
     </body>
 </html>

+ 119 - 98
examples/todomvc/js/app.js

@@ -1,115 +1,136 @@
-'use strict'
+/*global Vue, todoStorage */
 
-var app = new Vue({
+(function (exports) {
 
-    // the root element that will be compiled
-    el: '#todoapp',
+    'use strict';
 
-    // a custom directive to wait for the DOM to be updated
-    // before focusing on the input field.
-    directives: {
-        'todo-focus': function (value) {
-            if (value) {
-                var el = this.el
-                setTimeout(function () { el.focus() }, 0)
-            }
-        }
-    },
-
-    // the `created` lifecycle hook, which will be called
-    // when the ViewModel instance is created but not yet compiled.
-    created: function () {
-        // setup filters
-        this.filters = {
-            all: function (todo) { todo.completed; return true },
-            active: function (todo) { return !todo.completed },
-            completed: function (todo) { return todo.completed }
-        }
-        this.updateFilter()
-        window.addEventListener('hashchange', function () {
-            app.updateFilter()
-        })
-        // initialize some state
-        this.newTodo = ''
-        this.editedTodo = null
-        this.remaining = this.todos.filter(this.filters.active).length
-    },
-
-    // data
-    data: {
-        todos: todoStorage.fetch(),
-    },
-
-    // computed property
-    computed: {
-        allDone: {
-            $get: function () {
-                return this.remaining === 0
-            },
-            $set: function (value) {
-                this.todos.forEach(function (todo) {
-                    todo.completed = value
-                })
-                this.remaining = value ? 0 : this.todos.length
-                todoStorage.save()
-            }
-        }
-    },
+    exports.app = new Vue({
 
-    // methods that implement data logic.
-    // note there's no DOM manipulation here at all!
-    methods: {
+        // the root element that will be compiled
+        el: '#todoapp',
 
-        updateFilter: function () {
-            var filter = location.hash.slice(2)
-            this.filter = (filter in this.filters) ? filter : 'all'
-            this.filterTodo = this.filters[this.filter]
+        // data
+        data: {
+            todos: todoStorage.fetch(),
+            newTodo: '',
+            editedTodo: null
         },
 
-        addTodo: function () {
-            var value = this.newTodo && this.newTodo.trim()
-            if (value) {
-                this.todos.push({ title: value, completed: false })
-                this.newTodo = ''
-                this.remaining++
-                todoStorage.save()
+        // a custom directive to wait for the DOM to be updated
+        // before focusing on the input field.
+        // http://vuejs.org/guide/directives.html#Writing_a_Custom_Directive
+        directives: {
+            'todo-focus': function (value) {
+                if (!value) {
+                    return;
+                }
+                var el = this.el;
+                setTimeout(function () {
+                    el.focus();
+                }, 0);
             }
         },
 
-        removeTodo: function (todo) {
-            this.todos.remove(todo.$data)
-            this.remaining -= todo.completed ? 0 : 1
-            todoStorage.save()
+        // the `created` lifecycle hook.
+        // this is where we do the initialization work.
+        // http://vuejs.org/api/instantiation-options.html#created
+        created: function () {
+            // setup filters
+            this.filters = {
+                all: function (todo) {
+                    // collect dependency.
+                    // http://vuejs.org/guide/computed.html#Dependency_Collection_Gotcha
+                    /* jshint expr:true */
+                    todo.completed;
+                    return true;
+                },
+                active: function (todo) {
+                    return !todo.completed;
+                },
+                completed: function (todo) {
+                    return todo.completed;
+                }
+            };
+            // default filter
+            this.setFilter('all');
         },
 
-        toggleTodo: function (todo) {
-            this.remaining += todo.completed ? -1 : 1
-            todoStorage.save()
+        // computed property
+        // http://vuejs.org/guide/computed.html
+        computed: {
+            remaining: function () {
+                return this.todos.filter(this.filters.active).length
+            },
+            allDone: {
+                $get: function () {
+                    return this.remaining === 0;
+                },
+                $set: function (value) {
+                    this.todos.forEach(function (todo) {
+                        todo.completed = value;
+                    });
+                    todoStorage.save();
+                }
+            }
         },
 
-        editTodo: function (todo) {
-            this.beforeEditCache = todo.title
-            this.editedTodo = todo
-        },
+        // methods that implement data logic.
+        // note there's no DOM manipulation here at all.
+        methods: {
 
-        doneEdit: function (todo) {
-            if (!this.editedTodo) return
-            this.editedTodo = null
-            todo.title = todo.title.trim()
-            if (!todo.title) this.removeTodo(todo)
-            todoStorage.save()
-        },
+            setFilter: function (filter) {
+                this.filter = filter;
+                this.filterTodo = this.filters[filter];
+            },
 
-        cancelEdit: function (todo) {
-            this.editedTodo = null
-            todo.title = this.beforeEditCache
-        },
-        
-        removeCompleted: function () {
-            this.todos.remove(function (todo) {
-                return todo.completed
-            })
-            todoStorage.save()
+            addTodo: function () {
+                var value = this.newTodo && this.newTodo.trim();
+                if (!value) {
+                    return;
+                }
+                this.todos.push({ title: value, completed: false });
+                this.newTodo = '';
+                todoStorage.save();
+            },
+
+            removeTodo: function (todo) {
+                this.todos.remove(todo.$data);
+                todoStorage.save();
+            },
+
+            toggleTodo: function (todo) {
+                todoStorage.save();
+            },
+
+            editTodo: function (todo) {
+                this.beforeEditCache = todo.title;
+                this.editedTodo = todo;
+            },
+
+            doneEdit: function (todo) {
+                if (!this.editedTodo) {
+                    return;
+                }
+                this.editedTodo = null;
+                todo.title = todo.title.trim();
+                if (!todo.title) {
+                    this.removeTodo(todo);
+                }
+                todoStorage.save();
+            },
+
+            cancelEdit: function (todo) {
+                this.editedTodo = null;
+                todo.title = this.beforeEditCache;
+            },
+            
+            removeCompleted: function () {
+                this.todos.remove(function (todo) {
+                    return todo.completed;
+                });
+                todoStorage.save();
+            }
         }
-    }
-})
+    });
+
+})(window);

+ 17 - 0
examples/todomvc/js/routes.js

@@ -0,0 +1,17 @@
+/*global app, Router */
+
+(function (app, Router) {
+
+    'use strict'
+
+    var router = new Router()
+
+    Object.keys(app.filters).forEach(function (filter) {
+        router.on(filter, function () {
+            app.setFilter(filter)
+        })
+    })
+
+    router.init()
+    
+})(app, Router)

+ 11 - 6
examples/todomvc/js/store.js

@@ -1,9 +1,13 @@
-var todoStorage = (function () {
+/*jshint unused:false */
 
-    var STORAGE_KEY = 'todos-vuejs',
-        todos = null
-        
-    return {
+(function (exports) {
+
+    'use strict'
+
+    var STORAGE_KEY = 'todos-vuejs'
+    var todos = null
+
+    exports.todoStorage = {
         fetch: function () {
             if (!todos) {
                 todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
@@ -14,4 +18,5 @@ var todoStorage = (function () {
             localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
         }
     }
-}())
+
+})(window)

+ 2 - 2
src/directives/style.js

@@ -25,8 +25,8 @@ module.exports = {
         var prop = this.prop
         this.el.style[prop] = value
         if (this.prefixed) {
-            var i = prefixes.length,
-                prop = prop.charAt(0).toUpperCase() + prop.slice(1)
+            prop = prop.charAt(0).toUpperCase() + prop.slice(1)
+            var i = prefixes.length
             while (i--) {
                 this.el.style[prefixes[i] + prop] = value
             }

Some files were not shown because too many files changed in this diff