Commit c3cb6430 authored by Arthur Verschaeve's avatar Arthur Verschaeve

Migrate `spine` example to `todomvc-app-css`

Ref gh-1110
parent 2e8ef0cf
node_modules/todomvc-app-css/*
!node_modules/todomvc-app-css/index.css
node_modules/todomvc-common/*
!node_modules/todomvc-common/base.js
!node_modules/todomvc-common/base.css
node_modules/jquery/**
!node_modules/jquery/dist/jquery.js
node_modules/handlebars/**
!node_modules/handlebars/dist/handlebars.js
node_modules/spine/**
!node_modules/spine/lib/spine.js
!node_modules/spine/lib/route.js
!node_modules/spine/lib/local.js
{
"name": "todomvc-spine",
"version": "0.0.0",
"dependencies": {
"spine": "~1.0.9",
"todomvc-common": "~0.3.0",
"handlebars": "~1.0.0-rc.3",
"jquery": "~1.8.3"
}
}
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Spine.js • TodoMVC</title> <title>Spine.js • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
...@@ -50,12 +51,12 @@ ...@@ -50,12 +51,12 @@
</li> </li>
{{/this}} {{/this}}
</script> </script>
<script src="bower_components/todomvc-common/base.js"></script> <script src="node_modules/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script> <script src="node_modules/jquery/dist/jquery.js"></script>
<script src="bower_components/handlebars/handlebars.js"></script> <script src="node_modules/handlebars/dist/handlebars.js"></script>
<script src="bower_components/spine/lib/spine.js"></script> <script src="node_modules/spine/lib/spine.js"></script>
<script src="bower_components/spine/lib/route.js"></script> <script src="node_modules/spine/lib/route.js"></script>
<script src="bower_components/spine/lib/local.js"></script> <script src="node_modules/spine/lib/local.js"></script>
<script src="js/controllers/todos.js"></script> <script src="js/controllers/todos.js"></script>
<script src="js/models/todo.js"></script> <script src="js/models/todo.js"></script>
......
// Generated by CoffeeScript 1.4.0 // Generated by CoffeeScript 1.8.0
(function() { (function() {
var Spine; var Spine;
...@@ -14,12 +14,16 @@ ...@@ -14,12 +14,16 @@
result = JSON.stringify(this); result = JSON.stringify(this);
return localStorage[this.className] = result; return localStorage[this.className] = result;
}, },
loadLocal: function() { loadLocal: function(options) {
var result; var result;
if (options == null) {
options = {};
}
if (!options.hasOwnProperty('clear')) {
options.clear = true;
}
result = localStorage[this.className]; result = localStorage[this.className];
return this.refresh(result || [], { return this.refresh(result || [], options);
clear: true
});
} }
}; };
...@@ -28,3 +32,5 @@ ...@@ -28,3 +32,5 @@
} }
}).call(this); }).call(this);
//# sourceMappingURL=local.js.map
// Generated by CoffeeScript 1.4.0 // Generated by CoffeeScript 1.8.0
(function() { (function() {
var $, Spine, escapeRegExp, hashStrip, namedParam, splatParam, var $, Path, Route, Spine, escapeRegExp, hashStrip, namedParam, splatParam,
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice; __slice = [].slice;
...@@ -17,7 +17,55 @@ ...@@ -17,7 +17,55 @@
escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g; escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
Spine.Route = (function(_super) { Path = (function(_super) {
__extends(Path, _super);
function Path(path, callback) {
var match;
this.path = path;
this.callback = callback;
this.names = [];
if (typeof path === 'string') {
namedParam.lastIndex = 0;
while ((match = namedParam.exec(path)) !== null) {
this.names.push(match[1]);
}
splatParam.lastIndex = 0;
while ((match = splatParam.exec(path)) !== null) {
this.names.push(match[1]);
}
path = path.replace(escapeRegExp, '\\$&').replace(namedParam, '([^\/]*)').replace(splatParam, '(.*?)');
this.route = new RegExp("^" + path + "$");
} else {
this.route = path;
}
}
Path.prototype.match = function(path, options) {
var i, match, param, params, _i, _len;
if (options == null) {
options = {};
}
if (!(match = this.route.exec(path))) {
return false;
}
options.match = match;
params = match.slice(1);
if (this.names.length) {
for (i = _i = 0, _len = params.length; _i < _len; i = ++_i) {
param = params[i];
options[this.names[i]] = param;
}
}
Route.trigger('before', this);
return this.callback.call(null, options) !== false;
};
return Path;
})(Spine.Module);
Route = (function(_super) {
var _ref; var _ref;
__extends(Route, _super); __extends(Route, _super);
...@@ -26,28 +74,15 @@ ...@@ -26,28 +74,15 @@
Route.historySupport = ((_ref = window.history) != null ? _ref.pushState : void 0) != null; Route.historySupport = ((_ref = window.history) != null ? _ref.pushState : void 0) != null;
Route.routes = [];
Route.options = { Route.options = {
trigger: true, trigger: true,
history: false, history: false,
shim: false, shim: false,
replace: false replace: false,
redirect: false
}; };
Route.add = function(path, callback) { Route.routers = [];
var key, value, _results;
if (typeof path === 'object' && !(path instanceof RegExp)) {
_results = [];
for (key in path) {
value = path[key];
_results.push(this.add(key, value));
}
return _results;
} else {
return this.routes.push(new this(path, callback));
}
};
Route.setup = function(options) { Route.setup = function(options) {
if (options == null) { if (options == null) {
...@@ -69,6 +104,11 @@ ...@@ -69,6 +104,11 @@
}; };
Route.unbind = function() { Route.unbind = function() {
var unbindResult;
unbindResult = Spine.Events.unbind.apply(this, arguments);
if (arguments.length > 0) {
return unbindResult;
}
if (this.options.shim) { if (this.options.shim) {
return; return;
} }
...@@ -80,7 +120,7 @@ ...@@ -80,7 +120,7 @@
}; };
Route.navigate = function() { Route.navigate = function() {
var args, lastArg, options, path; var args, lastArg, options, path, routes;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
options = {}; options = {};
lastArg = args[args.length - 1]; lastArg = args[args.length - 1];
...@@ -95,14 +135,22 @@ ...@@ -95,14 +135,22 @@
return; return;
} }
this.path = path; this.path = path;
this.trigger('navigate', this.path);
if (options.trigger) { if (options.trigger) {
this.matchRoute(this.path, options); this.trigger('navigate', this.path);
routes = this.matchRoutes(this.path, options);
if (!routes.length) {
if (typeof options.redirect === 'function') {
return options.redirect.apply(this, [this.path, options]);
} else {
if (options.redirect === true) {
this.redirect(this.path);
}
}
}
} }
if (options.shim) { if (options.shim) {
return; return true;
} } else if (this.history && options.replace) {
if (this.history && options.replace) {
return history.replaceState({}, document.title, this.path); return history.replaceState({}, document.title, this.path);
} else if (this.history) { } else if (this.history) {
return history.pushState({}, document.title, this.path); return history.pushState({}, document.title, this.path);
...@@ -111,6 +159,48 @@ ...@@ -111,6 +159,48 @@
} }
}; };
Route.create = function() {
var router;
router = new this;
this.routers.push(router);
return router;
};
Route.add = function(path, callback) {
return this.router.add(path, callback);
};
Route.prototype.add = function(path, callback) {
var key, value, _results;
if (typeof path === 'object' && !(path instanceof RegExp)) {
_results = [];
for (key in path) {
value = path[key];
_results.push(this.add(key, value));
}
return _results;
} else {
return this.routes.push(new Path(path, callback));
}
};
Route.prototype.destroy = function() {
var r;
this.routes.length = 0;
return this.constructor.routers = (function() {
var _i, _len, _ref1, _results;
_ref1 = this.constructor.routers;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
r = _ref1[_i];
if (r !== this) {
_results.push(r);
}
}
return _results;
}).call(this);
};
Route.getPath = function() { Route.getPath = function() {
var path; var path;
if (this.history) { if (this.history) {
...@@ -131,77 +221,70 @@ ...@@ -131,77 +221,70 @@
Route.change = function() { Route.change = function() {
var path; var path;
path = this.getPath(); path = Route.getPath();
if (path === this.path) { if (path === Route.path) {
return; return;
} }
this.path = path; Route.path = path;
return this.matchRoute(this.path); return Route.matchRoutes(Route.path);
}; };
Route.matchRoute = function(path, options) { Route.matchRoutes = function(path, options) {
var route, _i, _len, _ref1; var match, matches, router, _i, _len, _ref1;
_ref1 = this.routes; matches = [];
_ref1 = this.routers.concat([this.router]);
for (_i = 0, _len = _ref1.length; _i < _len; _i++) { for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
route = _ref1[_i]; router = _ref1[_i];
if (!(route.match(path, options))) { match = router.matchRoute(path, options);
continue; if (match) {
matches.push(match);
} }
this.trigger('change', route, path);
return route;
} }
if (matches.length) {
this.trigger('change', matches, path);
}
return matches;
}; };
function Route(path, callback) { Route.redirect = function(path) {
var match; return window.location = path;
this.path = path; };
this.callback = callback;
this.names = []; function Route() {
if (typeof path === 'string') { this.routes = [];
namedParam.lastIndex = 0;
while ((match = namedParam.exec(path)) !== null) {
this.names.push(match[1]);
}
splatParam.lastIndex = 0;
while ((match = splatParam.exec(path)) !== null) {
this.names.push(match[1]);
}
path = path.replace(escapeRegExp, '\\$&').replace(namedParam, '([^\/]*)').replace(splatParam, '(.*?)');
this.route = new RegExp("^" + path + "$");
} else {
this.route = path;
}
} }
Route.prototype.match = function(path, options) { Route.prototype.matchRoute = function(path, options) {
var i, match, param, params, _i, _len; var route, _i, _len, _ref1;
if (options == null) { _ref1 = this.routes;
options = {}; for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
} route = _ref1[_i];
match = this.route.exec(path); if (route.match(path, options)) {
if (!match) { return route;
return false;
}
options.match = match;
params = match.slice(1);
if (this.names.length) {
for (i = _i = 0, _len = params.length; _i < _len; i = ++_i) {
param = params[i];
options[this.names[i]] = param;
} }
} }
return this.callback.call(null, options) !== false; };
Route.prototype.trigger = function() {
var args, _ref1;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
args.splice(1, 0, this);
return (_ref1 = this.constructor).trigger.apply(_ref1, args);
}; };
return Route; return Route;
})(Spine.Module); })(Spine.Module);
Spine.Route.change = Spine.Route.proxy(Spine.Route.change); Route.router = new Route;
Spine.Controller.include({ Spine.Controller.include({
route: function(path, callback) { route: function(path, callback) {
return Spine.Route.add(path, this.proxy(callback)); if (this.router instanceof Spine.Route) {
return this.router.add(path, this.proxy(callback));
} else {
return Spine.Route.add(path, this.proxy(callback));
}
}, },
routes: function(routes) { routes: function(routes) {
var key, value, _results; var key, value, _results;
...@@ -217,8 +300,14 @@ ...@@ -217,8 +300,14 @@
} }
}); });
Route.Path = Path;
Spine.Route = Route;
if (typeof module !== "undefined" && module !== null) { if (typeof module !== "undefined" && module !== null) {
module.exports = Spine.Route; module.exports = Route;
} }
}).call(this); }).call(this);
//# sourceMappingURL=route.js.map
// Generated by CoffeeScript 1.4.0 // Generated by CoffeeScript 1.8.0
/*
Spine.js MVC library
Released under the MIT License
*/
(function() { (function() {
var $, Controller, Events, Log, Model, Module, Spine, createObject, isArray, isBlank, makeArray, moduleKeywords, var $, Controller, Events, Log, Model, Module, Spine, createObject, isArray, isBlank, makeArray, moduleKeywords,
__slice = [].slice, __slice = [].slice,
...@@ -9,19 +15,22 @@ ...@@ -9,19 +15,22 @@
Events = { Events = {
bind: function(ev, callback) { bind: function(ev, callback) {
var calls, evs, name, _i, _len; var evs, name, _base, _i, _len;
evs = ev.split(' '); evs = ev.split(' ');
calls = this.hasOwnProperty('_callbacks') && this._callbacks || (this._callbacks = {}); if (!this.hasOwnProperty('_callbacks')) {
this._callbacks || (this._callbacks = {});
}
for (_i = 0, _len = evs.length; _i < _len; _i++) { for (_i = 0, _len = evs.length; _i < _len; _i++) {
name = evs[_i]; name = evs[_i];
calls[name] || (calls[name] = []); (_base = this._callbacks)[name] || (_base[name] = []);
calls[name].push(callback); this._callbacks[name].push(callback);
} }
return this; return this;
}, },
one: function(ev, callback) { one: function(ev, callback) {
return this.bind(ev, function() { var handler;
this.unbind(ev, arguments.callee); return this.bind(ev, handler = function() {
this.unbind(ev, handler);
return callback.apply(this, arguments); return callback.apply(this, arguments);
}); });
}, },
...@@ -29,7 +38,7 @@ ...@@ -29,7 +38,7 @@
var args, callback, ev, list, _i, _len, _ref; var args, callback, ev, list, _i, _len, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
ev = args.shift(); ev = args.shift();
list = this.hasOwnProperty('_callbacks') && ((_ref = this._callbacks) != null ? _ref[ev] : void 0); list = (_ref = this._callbacks) != null ? _ref[ev] : void 0;
if (!list) { if (!list) {
return; return;
} }
...@@ -41,12 +50,115 @@ ...@@ -41,12 +50,115 @@
} }
return true; return true;
}, },
listenTo: function(obj, ev, callback) {
obj.bind(ev, callback);
this.listeningTo || (this.listeningTo = []);
this.listeningTo.push({
obj: obj,
ev: ev,
callback: callback
});
return this;
},
listenToOnce: function(obj, ev, callback) {
var handler, listeningToOnce;
listeningToOnce = this.listeningToOnce || (this.listeningToOnce = []);
obj.bind(ev, handler = function() {
var i, idx, lt, _i, _len;
idx = -1;
for (i = _i = 0, _len = listeningToOnce.length; _i < _len; i = ++_i) {
lt = listeningToOnce[i];
if (lt.obj === obj) {
if (lt.ev === ev && lt.callback === handler) {
idx = i;
}
}
}
obj.unbind(ev, handler);
if (idx !== -1) {
listeningToOnce.splice(idx, 1);
}
return callback.apply(this, arguments);
});
listeningToOnce.push({
obj: obj,
ev: ev,
callback: handler
});
return this;
},
stopListening: function(obj, events, callback) {
var e, ev, evts, idx, listeningTo, lt, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2;
if (arguments.length === 0) {
_ref = [this.listeningTo, this.listeningToOnce];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
listeningTo = _ref[_i];
if (!listeningTo) {
continue;
}
for (_j = 0, _len1 = listeningTo.length; _j < _len1; _j++) {
lt = listeningTo[_j];
lt.obj.unbind(lt.ev, lt.callback);
}
}
this.listeningTo = void 0;
this.listeningToOnce = void 0;
} else if (obj) {
_ref1 = [this.listeningTo, this.listeningToOnce];
for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
listeningTo = _ref1[_k];
if (!listeningTo) {
continue;
}
events = events ? events.split(' ') : [void 0];
for (_l = 0, _len3 = events.length; _l < _len3; _l++) {
ev = events[_l];
for (idx = _m = _ref2 = listeningTo.length - 1; _ref2 <= 0 ? _m <= 0 : _m >= 0; idx = _ref2 <= 0 ? ++_m : --_m) {
lt = listeningTo[idx];
if (lt.obj !== obj) {
continue;
}
if (callback && lt.callback !== callback) {
continue;
}
if ((!ev) || (ev === lt.ev)) {
lt.obj.unbind(lt.ev, lt.callback);
if (idx !== -1) {
listeningTo.splice(idx, 1);
}
} else if (ev) {
evts = lt.ev.split(' ');
if (__indexOf.call(evts, ev) >= 0) {
evts = (function() {
var _len4, _n, _results;
_results = [];
for (_n = 0, _len4 = evts.length; _n < _len4; _n++) {
e = evts[_n];
if (e !== ev) {
_results.push(e);
}
}
return _results;
})();
lt.ev = $.trim(evts.join(' '));
lt.obj.unbind(ev, lt.callback);
}
}
}
}
}
}
return this;
},
unbind: function(ev, callback) { unbind: function(ev, callback) {
var cb, evs, i, list, name, _i, _j, _len, _len1, _ref; var cb, evs, i, list, name, _i, _j, _len, _len1, _ref;
if (!ev) { if (arguments.length === 0) {
this._callbacks = {}; this._callbacks = {};
return this; return this;
} }
if (!ev) {
return this;
}
evs = ev.split(' '); evs = ev.split(' ');
for (_i = 0, _len = evs.length; _i < _len; _i++) { for (_i = 0, _len = evs.length; _i < _len; _i++) {
name = evs[_i]; name = evs[_i];
...@@ -101,7 +213,6 @@ ...@@ -101,7 +213,6 @@
moduleKeywords = ['included', 'extended']; moduleKeywords = ['included', 'extended'];
Module = (function() { Module = (function() {
Module.include = function(obj) { Module.include = function(obj) {
var key, value, _ref; var key, value, _ref;
if (!obj) { if (!obj) {
...@@ -137,17 +248,19 @@ ...@@ -137,17 +248,19 @@
}; };
Module.proxy = function(func) { Module.proxy = function(func) {
var _this = this; return (function(_this) {
return function() { return function() {
return func.apply(_this, arguments); return func.apply(_this, arguments);
}; };
})(this);
}; };
Module.prototype.proxy = function(func) { Module.prototype.proxy = function(func) {
var _this = this; return (function(_this) {
return function() { return function() {
return func.apply(_this, arguments); return func.apply(_this, arguments);
}; };
})(this);
}; };
function Module() { function Module() {
...@@ -161,14 +274,15 @@ ...@@ -161,14 +274,15 @@
})(); })();
Model = (function(_super) { Model = (function(_super) {
__extends(Model, _super); __extends(Model, _super);
Model.extend(Events); Model.extend(Events);
Model.records = {}; Model.include(Events);
Model.records = [];
Model.crecords = {}; Model.irecords = {};
Model.attributes = []; Model.attributes = [];
...@@ -176,8 +290,7 @@ ...@@ -176,8 +290,7 @@
var attributes, name; var attributes, name;
name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : []; name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
this.className = name; this.className = name;
this.records = {}; this.deleteAll();
this.crecords = {};
if (attributes.length) { if (attributes.length) {
this.attributes = attributes; this.attributes = attributes;
} }
...@@ -191,43 +304,53 @@ ...@@ -191,43 +304,53 @@
return "" + this.className + "(" + (this.attributes.join(", ")) + ")"; return "" + this.className + "(" + (this.attributes.join(", ")) + ")";
}; };
Model.find = function(id) { Model.find = function(id, notFound) {
var record; var _ref;
record = this.records[id]; if (notFound == null) {
if (!record && ("" + id).match(/c-\d+/)) { notFound = this.notFound;
return this.findCID(id);
}
if (!record) {
throw new Error("\"" + this.className + "\" model could not find a record for the ID \"" + id + "\"");
} }
return record.clone(); return ((_ref = this.irecords[id]) != null ? _ref.clone() : void 0) || (typeof notFound === "function" ? notFound(id) : void 0);
}; };
Model.findCID = function(cid) { Model.findAll = function(ids, notFound) {
var record; var id, _i, _len, _results;
record = this.crecords[cid]; _results = [];
if (!record) { for (_i = 0, _len = ids.length; _i < _len; _i++) {
throw new Error("\"" + this.className + "\" model could not find a record for the ID \"" + id + "\""); id = ids[_i];
if (this.find(id, notFound)) {
_results.push(this.find(id));
}
} }
return record.clone(); return _results;
};
Model.notFound = function(id) {
return null;
}; };
Model.exists = function(id) { Model.exists = function(id) {
try { return Boolean(this.irecords[id]);
return this.find(id); };
} catch (e) {
return false; Model.addRecord = function(record) {
var root;
if (root = this.irecords[record.id || record.cid]) {
root.refresh(record);
} else {
record.id || (record.id = record.cid);
this.irecords[record.id] = this.irecords[record.cid] = record;
this.records.push(record);
} }
return record;
}; };
Model.refresh = function(values, options) { Model.refresh = function(values, options) {
var record, records, _i, _len; var record, records, result, _i, _len;
if (options == null) { if (options == null) {
options = {}; options = {};
} }
if (options.clear) { if (options.clear) {
this.records = {}; this.deleteAll();
this.crecords = {};
} }
records = this.fromJSON(values); records = this.fromJSON(values);
if (!isArray(records)) { if (!isArray(records)) {
...@@ -235,36 +358,32 @@ ...@@ -235,36 +358,32 @@
} }
for (_i = 0, _len = records.length; _i < _len; _i++) { for (_i = 0, _len = records.length; _i < _len; _i++) {
record = records[_i]; record = records[_i];
record.id || (record.id = record.cid); this.addRecord(record);
this.records[record.id] = record;
this.crecords[record.cid] = record;
} }
this.trigger('refresh', this.cloneArray(records)); this.sort();
return this; result = this.cloneArray(records);
this.trigger('refresh', result, options);
return result;
}; };
Model.select = function(callback) { Model.select = function(callback) {
var id, record, result; var record, _i, _len, _ref, _results;
result = (function() { _ref = this.records;
var _ref, _results; _results = [];
_ref = this.records; for (_i = 0, _len = _ref.length; _i < _len; _i++) {
_results = []; record = _ref[_i];
for (id in _ref) { if (callback(record)) {
record = _ref[id]; _results.push(record.clone());
if (callback(record)) {
_results.push(record);
}
} }
return _results; }
}).call(this); return _results;
return this.cloneArray(result);
}; };
Model.findByAttribute = function(name, value) { Model.findByAttribute = function(name, value) {
var id, record, _ref; var record, _i, _len, _ref;
_ref = this.records; _ref = this.records;
for (id in _ref) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
record = _ref[id]; record = _ref[_i];
if (record[name] === value) { if (record[name] === value) {
return record.clone(); return record.clone();
} }
...@@ -279,55 +398,64 @@ ...@@ -279,55 +398,64 @@
}; };
Model.each = function(callback) { Model.each = function(callback) {
var key, value, _ref, _results; var record, _i, _len, _ref, _results;
_ref = this.records; _ref = this.records;
_results = []; _results = [];
for (key in _ref) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
value = _ref[key]; record = _ref[_i];
_results.push(callback(value.clone())); _results.push(callback(record.clone()));
} }
return _results; return _results;
}; };
Model.all = function() { Model.all = function() {
return this.cloneArray(this.recordsValues()); return this.cloneArray(this.records);
}; };
Model.first = function() { Model.slice = function(begin, end) {
var record; if (begin == null) {
record = this.recordsValues()[0]; begin = 0;
return record != null ? record.clone() : void 0; }
return this.cloneArray(this.records.slice(begin, end));
}; };
Model.last = function() { Model.first = function(end) {
var record, values; var _ref;
values = this.recordsValues(); if (end == null) {
record = values[values.length - 1]; end = 1;
return record != null ? record.clone() : void 0; }
if (end > 1) {
return this.cloneArray(this.records.slice(0, end));
} else {
return (_ref = this.records[0]) != null ? _ref.clone() : void 0;
}
};
Model.last = function(begin) {
var _ref;
if (typeof begin === 'number') {
return this.cloneArray(this.records.slice(-begin));
} else {
return (_ref = this.records[this.records.length - 1]) != null ? _ref.clone() : void 0;
}
}; };
Model.count = function() { Model.count = function() {
return this.recordsValues().length; return this.records.length;
}; };
Model.deleteAll = function() { Model.deleteAll = function() {
var key, value, _ref, _results; this.records = [];
_ref = this.records; return this.irecords = {};
_results = [];
for (key in _ref) {
value = _ref[key];
_results.push(delete this.records[key]);
}
return _results;
}; };
Model.destroyAll = function(options) { Model.destroyAll = function(options) {
var key, value, _ref, _results; var record, _i, _len, _ref, _results;
_ref = this.records; _ref = this.records;
_results = []; _results = [];
for (key in _ref) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
value = _ref[key]; record = _ref[_i];
_results.push(this.records[key].destroy(options)); _results.push(record.destroy(options));
} }
return _results; return _results;
}; };
...@@ -350,7 +478,7 @@ ...@@ -350,7 +478,7 @@
if (typeof callbackOrParams === 'function') { if (typeof callbackOrParams === 'function') {
return this.bind('change', callbackOrParams); return this.bind('change', callbackOrParams);
} else { } else {
return this.trigger('change', callbackOrParams); return this.trigger.apply(this, ['change'].concat(__slice.call(arguments)));
} }
}; };
...@@ -358,12 +486,16 @@ ...@@ -358,12 +486,16 @@
if (typeof callbackOrParams === 'function') { if (typeof callbackOrParams === 'function') {
return this.bind('fetch', callbackOrParams); return this.bind('fetch', callbackOrParams);
} else { } else {
return this.trigger('fetch', callbackOrParams); return this.trigger.apply(this, ['fetch'].concat(__slice.call(arguments)));
} }
}; };
Model.toJSON = function() { Model.toJSON = function() {
return this.recordsValues(); return this.records;
};
Model.beforeFromJSON = function(objects) {
return objects;
}; };
Model.fromJSON = function(objects) { Model.fromJSON = function(objects) {
...@@ -374,14 +506,22 @@ ...@@ -374,14 +506,22 @@
if (typeof objects === 'string') { if (typeof objects === 'string') {
objects = JSON.parse(objects); objects = JSON.parse(objects);
} }
objects = this.beforeFromJSON(objects);
if (isArray(objects)) { if (isArray(objects)) {
_results = []; _results = [];
for (_i = 0, _len = objects.length; _i < _len; _i++) { for (_i = 0, _len = objects.length; _i < _len; _i++) {
value = objects[_i]; value = objects[_i];
_results.push(new this(value)); if (value instanceof this) {
_results.push(value);
} else {
_results.push(new this(value));
}
} }
return _results; return _results;
} else { } else {
if (objects instanceof this) {
return objects;
}
return new this(objects); return new this(objects);
} }
}; };
...@@ -391,15 +531,11 @@ ...@@ -391,15 +531,11 @@
return (_ref = new this).fromForm.apply(_ref, arguments); return (_ref = new this).fromForm.apply(_ref, arguments);
}; };
Model.recordsValues = function() { Model.sort = function() {
var key, result, value, _ref; if (this.comparator) {
result = []; this.records.sort(this.comparator);
_ref = this.records;
for (key in _ref) {
value = _ref[key];
result.push(value);
} }
return result; return this;
}; };
Model.cloneArray = function(array) { Model.cloneArray = function(array) {
...@@ -428,10 +564,17 @@ ...@@ -428,10 +564,17 @@
function Model(atts) { function Model(atts) {
Model.__super__.constructor.apply(this, arguments); Model.__super__.constructor.apply(this, arguments);
if ((this.constructor.uuid != null) && typeof this.constructor.uuid === 'function') {
this.cid = this.constructor.uuid();
if (!this.id) {
this.id = this.cid;
}
} else {
this.cid = (atts != null ? atts.cid : void 0) || this.constructor.uid('c-');
}
if (atts) { if (atts) {
this.load(atts); this.load(atts);
} }
this.cid = this.constructor.uid('c-');
} }
Model.prototype.isNew = function() { Model.prototype.isNew = function() {
...@@ -446,9 +589,15 @@ ...@@ -446,9 +589,15 @@
Model.prototype.load = function(atts) { Model.prototype.load = function(atts) {
var key, value; var key, value;
if (atts.id) {
this.id = atts.id;
}
for (key in atts) { for (key in atts) {
value = atts[key]; value = atts[key];
if (typeof this[key] === 'function') { if (typeof this[key] === 'function') {
if (typeof value === 'function') {
continue;
}
this[key](value); this[key](value);
} else { } else {
this[key] = value; this[key] = value;
...@@ -478,7 +627,7 @@ ...@@ -478,7 +627,7 @@
}; };
Model.prototype.eql = function(rec) { Model.prototype.eql = function(rec) {
return !!(rec && rec.constructor === this.constructor && (rec.cid === this.cid) || (rec.id && rec.id === this.id)); return rec && rec.constructor === this.constructor && ((rec.cid === this.cid) || (rec.id && rec.id === this.id));
}; };
Model.prototype.save = function(options) { Model.prototype.save = function(options) {
...@@ -489,14 +638,14 @@ ...@@ -489,14 +638,14 @@
if (options.validate !== false) { if (options.validate !== false) {
error = this.validate(); error = this.validate();
if (error) { if (error) {
this.trigger('error', error); this.trigger('error', this, error);
return false; return false;
} }
} }
this.trigger('beforeSave', options); this.trigger('beforeSave', this, options);
record = this.isNew() ? this.create(options) : this.update(options); record = this.isNew() ? this.create(options) : this.update(options);
this.stripCloneAttrs(); this.stripCloneAttrs();
this.trigger('save', options); this.trigger('save', record, options);
return record; return record;
}; };
...@@ -508,7 +657,7 @@ ...@@ -508,7 +657,7 @@
for (key in this) { for (key in this) {
if (!__hasProp.call(this, key)) continue; if (!__hasProp.call(this, key)) continue;
value = this[key]; value = this[key];
if (this.constructor.attributes.indexOf(key) > -1) { if (__indexOf.call(this.constructor.attributes, key) >= 0) {
delete this[key]; delete this[key];
} }
} }
...@@ -529,36 +678,74 @@ ...@@ -529,36 +678,74 @@
Model.prototype.changeID = function(id) { Model.prototype.changeID = function(id) {
var records; var records;
records = this.constructor.records; if (id === this.id) {
return;
}
records = this.constructor.irecords;
records[id] = records[this.id]; records[id] = records[this.id];
delete records[this.id]; if (this.cid !== this.id) {
delete records[this.id];
}
this.id = id; this.id = id;
return this.save(); return this.save();
}; };
Model.prototype.remove = function(options) {
var i, record, records, _i, _len;
if (options == null) {
options = {};
}
records = this.constructor.records.slice(0);
for (i = _i = 0, _len = records.length; _i < _len; i = ++_i) {
record = records[i];
if (!(this.eql(record))) {
continue;
}
records.splice(i, 1);
break;
}
this.constructor.records = records;
if (options.clear) {
delete this.constructor.irecords[this.id];
return delete this.constructor.irecords[this.cid];
}
};
Model.prototype.destroy = function(options) { Model.prototype.destroy = function(options) {
if (options == null) { if (options == null) {
options = {}; options = {};
} }
this.trigger('beforeDestroy', options); if (options.clear == null) {
delete this.constructor.records[this.id]; options.clear = true;
delete this.constructor.crecords[this.cid]; }
this.trigger('beforeDestroy', this, options);
this.remove(options);
this.destroyed = true; this.destroyed = true;
this.trigger('destroy', options); this.trigger('destroy', this, options);
this.trigger('change', 'destroy', options); this.trigger('change', this, 'destroy', options);
if (this.listeningTo) {
this.stopListening();
}
this.unbind(); this.unbind();
return this; return this;
}; };
Model.prototype.dup = function(newRecord) { Model.prototype.dup = function(newRecord) {
var result; var atts, record;
result = new this.constructor(this.attributes()); if (newRecord == null) {
if (newRecord === false) { newRecord = true;
result.cid = this.cid; }
atts = this.attributes();
if (newRecord) {
delete atts.id;
} else { } else {
delete result.id; atts.cid = this.cid;
} }
return result; record = new this.constructor(atts);
if (!newRecord) {
this._callbacks && (record._callbacks = this._callbacks);
}
return record;
}; };
Model.prototype.clone = function() { Model.prototype.clone = function() {
...@@ -575,6 +762,17 @@ ...@@ -575,6 +762,17 @@
return original; return original;
}; };
Model.prototype.refresh = function(atts) {
atts = this.constructor.fromJSON(atts);
if (atts.id && this.id !== atts.id) {
this.changeID(atts.id);
}
this.constructor.irecords[this.id].load(atts);
this.trigger('refresh', this);
this.trigger('change', this, 'refresh');
return this;
};
Model.prototype.toJSON = function() { Model.prototype.toJSON = function() {
return this.attributes(); return this.attributes();
}; };
...@@ -584,89 +782,95 @@ ...@@ -584,89 +782,95 @@
}; };
Model.prototype.fromForm = function(form) { Model.prototype.fromForm = function(form) {
var key, result, _i, _len, _ref; var checkbox, key, name, result, _i, _j, _k, _len, _len1, _len2, _name, _ref, _ref1, _ref2;
result = {}; result = {};
_ref = $(form).serializeArray(); _ref = $(form).find('[type=checkbox]:not([value])');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
key = _ref[_i]; checkbox = _ref[_i];
result[key.name] = key.value; result[checkbox.name] = $(checkbox).prop('checked');
}
_ref1 = $(form).find('[type=checkbox][name$="[]"]');
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
checkbox = _ref1[_j];
name = checkbox.name.replace(/\[\]$/, '');
result[name] || (result[name] = []);
if ($(checkbox).prop('checked')) {
result[name].push(checkbox.value);
}
}
_ref2 = $(form).serializeArray();
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
key = _ref2[_k];
result[_name = key.name] || (result[_name] = key.value);
} }
return this.load(result); return this.load(result);
}; };
Model.prototype.exists = function() { Model.prototype.exists = function() {
return this.id && this.id in this.constructor.records; return this.constructor.exists(this.id);
}; };
Model.prototype.update = function(options) { Model.prototype.update = function(options) {
var clone, records; var clone, records;
this.trigger('beforeUpdate', options); this.trigger('beforeUpdate', this, options);
records = this.constructor.records; records = this.constructor.irecords;
records[this.id].load(this.attributes()); records[this.id].load(this.attributes());
this.constructor.sort();
clone = records[this.id].clone(); clone = records[this.id].clone();
clone.trigger('update', options); clone.trigger('update', clone, options);
clone.trigger('change', 'update', options); clone.trigger('change', clone, 'update', options);
return clone; return clone;
}; };
Model.prototype.create = function(options) { Model.prototype.create = function(options) {
var clone, record; var clone, record;
this.trigger('beforeCreate', options); this.trigger('beforeCreate', this, options);
if (!this.id) { this.id || (this.id = this.cid);
this.id = this.cid;
}
record = this.dup(false); record = this.dup(false);
this.constructor.records[this.id] = record; this.constructor.addRecord(record);
this.constructor.crecords[this.cid] = record; this.constructor.sort();
clone = record.clone(); clone = record.clone();
clone.trigger('create', options); clone.trigger('create', clone, options);
clone.trigger('change', 'create', options); clone.trigger('change', clone, 'create', options);
return clone; return clone;
}; };
Model.prototype.bind = function(events, callback) { Model.prototype.bind = function() {
var binder, unbinder, var record;
_this = this; record = this.constructor.irecords[this.id] || this;
this.constructor.bind(events, binder = function(record) { return Events.bind.apply(record, arguments);
if (record && _this.eql(record)) {
return callback.apply(_this, arguments);
}
});
this.constructor.bind('unbind', unbinder = function(record) {
if (record && _this.eql(record)) {
_this.constructor.unbind(events, binder);
return _this.constructor.unbind('unbind', unbinder);
}
});
return binder;
}; };
Model.prototype.one = function(events, callback) { Model.prototype.one = function() {
var binder, var record;
_this = this; record = this.constructor.irecords[this.id] || this;
return binder = this.bind(events, function() { return Events.one.apply(record, arguments);
_this.constructor.unbind(events, binder);
return callback.apply(_this, arguments);
});
}; };
Model.prototype.trigger = function() { Model.prototype.unbind = function() {
var args, _ref; var record;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; record = this.constructor.irecords[this.id] || this;
args.splice(1, 0, this); return Events.unbind.apply(record, arguments);
return (_ref = this.constructor).trigger.apply(_ref, args);
}; };
Model.prototype.unbind = function() { Model.prototype.trigger = function() {
return this.trigger('unbind'); var _ref;
Events.trigger.apply(this, arguments);
if (arguments[0] === 'refresh') {
return true;
}
return (_ref = this.constructor).trigger.apply(_ref, arguments);
}; };
return Model; return Model;
})(Module); })(Module);
Controller = (function(_super) { Model.prototype.on = Model.prototype.bind;
Model.prototype.off = Model.prototype.unbind;
Controller = (function(_super) {
__extends(Controller, _super); __extends(Controller, _super);
Controller.include(Events); Controller.include(Events);
...@@ -679,8 +883,7 @@ ...@@ -679,8 +883,7 @@
function Controller(options) { function Controller(options) {
this.release = __bind(this.release, this); this.release = __bind(this.release, this);
var context, key, parent_prototype, value, _ref;
var key, value, _ref;
this.options = options; this.options = options;
_ref = this.options; _ref = this.options;
for (key in _ref) { for (key in _ref) {
...@@ -691,7 +894,6 @@ ...@@ -691,7 +894,6 @@
this.el = document.createElement(this.tag); this.el = document.createElement(this.tag);
} }
this.el = $(this.el); this.el = $(this.el);
this.$el = this.el;
if (this.className) { if (this.className) {
this.el.addClass(this.className); this.el.addClass(this.className);
} }
...@@ -704,6 +906,16 @@ ...@@ -704,6 +906,16 @@
if (!this.elements) { if (!this.elements) {
this.elements = this.constructor.elements; this.elements = this.constructor.elements;
} }
context = this;
while (parent_prototype = context.constructor.__super__) {
if (parent_prototype.events) {
this.events = $.extend({}, parent_prototype.events, this.events);
}
if (parent_prototype.elements) {
this.elements = $.extend({}, parent_prototype.elements, this.elements);
}
context = parent_prototype;
}
if (this.events) { if (this.events) {
this.delegateEvents(this.events); this.delegateEvents(this.events);
} }
...@@ -714,38 +926,42 @@ ...@@ -714,38 +926,42 @@
} }
Controller.prototype.release = function() { Controller.prototype.release = function() {
this.trigger('release'); this.trigger('release', this);
this.el.remove(); this.el.remove();
return this.unbind(); this.unbind();
return this.stopListening();
}; };
Controller.prototype.$ = function(selector) { Controller.prototype.$ = function(selector) {
return $(selector, this.el); return this.el.find(selector);
}; };
Controller.prototype.delegateEvents = function(events) { Controller.prototype.delegateEvents = function(events) {
var eventName, key, match, method, selector, _results, var eventName, key, match, method, selector, _results;
_this = this;
_results = []; _results = [];
for (key in events) { for (key in events) {
method = events[key]; method = events[key];
if (typeof method === 'function') { if (typeof method === 'function') {
method = (function(method) { method = (function(_this) {
return function() { return function(method) {
method.apply(_this, arguments); return function() {
return true; method.apply(_this, arguments);
return true;
};
}; };
})(method); })(this)(method);
} else { } else {
if (!this[method]) { if (!this[method]) {
throw new Error("" + method + " doesn't exist"); throw new Error("" + method + " doesn't exist");
} }
method = (function(method) { method = (function(_this) {
return function() { return function(method) {
_this[method].apply(_this, arguments); return function() {
return true; _this[method].apply(_this, arguments);
return true;
};
}; };
})(method); })(this)(method);
} }
match = key.match(this.eventSplitter); match = key.match(this.eventSplitter);
eventName = match[1]; eventName = match[1];
...@@ -753,7 +969,7 @@ ...@@ -753,7 +969,7 @@
if (selector === '') { if (selector === '') {
_results.push(this.el.bind(eventName, method)); _results.push(this.el.bind(eventName, method));
} else { } else {
_results.push(this.el.delegate(selector, eventName, method)); _results.push(this.el.on(eventName, selector, method));
} }
} }
return _results; return _results;
...@@ -821,8 +1037,12 @@ ...@@ -821,8 +1037,12 @@
}; };
Controller.prototype.replace = function(element) { Controller.prototype.replace = function(element) {
var previous, _ref; var previous, _ref, _ref1;
_ref = [this.el, $(element.el || element)], previous = _ref[0], this.el = _ref[1]; element = element.el || element;
if (typeof element === "string") {
element = $.trim(element);
}
_ref1 = [this.el, $(((_ref = $.parseHTML(element)) != null ? _ref[0] : void 0) || element)], previous = _ref1[0], this.el = _ref1[1];
previous.replaceWith(this.el); previous.replaceWith(this.el);
this.delegateEvents(this.events); this.delegateEvents(this.events);
this.refreshElements(); this.refreshElements();
...@@ -869,7 +1089,7 @@ ...@@ -869,7 +1089,7 @@
module.exports = Spine; module.exports = Spine;
} }
Spine.version = '1.0.9'; Spine.version = '1.4.1';
Spine.isArray = isArray; Spine.isArray = isArray;
...@@ -892,7 +1112,6 @@ ...@@ -892,7 +1112,6 @@
Module.create = Module.sub = Controller.create = Controller.sub = Model.sub = function(instances, statics) { Module.create = Module.sub = Controller.create = Controller.sub = Model.sub = function(instances, statics) {
var Result; var Result;
Result = (function(_super) { Result = (function(_super) {
__extends(Result, _super); __extends(Result, _super);
function Result() { function Result() {
...@@ -920,7 +1139,6 @@ ...@@ -920,7 +1139,6 @@
attributes = []; attributes = [];
} }
Instance = (function(_super) { Instance = (function(_super) {
__extends(Instance, _super); __extends(Instance, _super);
function Instance() { function Instance() {
...@@ -937,3 +1155,5 @@ ...@@ -937,3 +1155,5 @@
Spine.Class = Module; Spine.Class = Module;
}).call(this); }).call(this);
//# sourceMappingURL=spine.js.map
...@@ -12,104 +12,77 @@ button { ...@@ -12,104 +12,77 @@ button {
font-size: 100%; font-size: 100%;
vertical-align: baseline; vertical-align: baseline;
font-family: inherit; font-family: inherit;
font-weight: inherit;
color: inherit; color: inherit;
-webkit-appearance: none; -webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none; appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
} }
body { body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em; line-height: 1.4em;
background: #eaeaea url('bg.png'); background: #f5f5f5;
color: #4d4d4d; color: #4d4d4d;
width: 550px; min-width: 230px;
max-width: 550px;
margin: 0 auto; margin: 0 auto;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased; -moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased; font-smoothing: antialiased;
font-weight: 300;
} }
button, button,
input[type="checkbox"] { input[type="checkbox"] {
outline: none; outline: none;
}
.hidden {
display: none;
} }
#todoapp { #todoapp {
background: #fff; background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0; margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative; position: relative;
border-top-left-radius: 2px; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
border-top-right-radius: 2px; 0 25px 50px 0 rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
} }
#todoapp input::-webkit-input-placeholder { #todoapp input::-webkit-input-placeholder {
font-style: italic; font-style: italic;
font-weight: 300;
color: #e6e6e6;
} }
#todoapp input::-moz-placeholder { #todoapp input::-moz-placeholder {
font-style: italic; font-style: italic;
color: #a9a9a9; font-weight: 300;
color: #e6e6e6;
}
#todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
} }
#todoapp h1 { #todoapp h1 {
position: absolute; position: absolute;
top: -120px; top: -155px;
width: 100%; width: 100%;
font-size: 70px; font-size: 100px;
font-weight: bold; font-weight: 100;
text-align: center; text-align: center;
color: #b3b3b3; color: rgba(175, 47, 47, 0.15);
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
} }
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo, #new-todo,
.edit { .edit {
position: relative; position: relative;
...@@ -117,6 +90,7 @@ input[type="checkbox"] { ...@@ -117,6 +90,7 @@ input[type="checkbox"] {
width: 100%; width: 100%;
font-size: 24px; font-size: 24px;
font-family: inherit; font-family: inherit;
font-weight: inherit;
line-height: 1.4em; line-height: 1.4em;
border: 0; border: 0;
outline: none; outline: none;
...@@ -124,29 +98,23 @@ input[type="checkbox"] { ...@@ -124,29 +98,23 @@ input[type="checkbox"] {
padding: 6px; padding: 6px;
border: 1px solid #999; border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased; -moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased; font-smoothing: antialiased;
} }
#new-todo { #new-todo {
padding: 16px 16px 16px 60px; padding: 16px 16px 16px 60px;
border: none; border: none;
background: rgba(0, 0, 0, 0.02); background: rgba(0, 0, 0, 0.003);
z-index: 2; box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
box-shadow: none;
} }
#main { #main {
position: relative; position: relative;
z-index: 2; z-index: 2;
border-top: 1px dotted #adadad; border-top: 1px solid #e6e6e6;
} }
label[for='toggle-all'] { label[for='toggle-all'] {
...@@ -155,19 +123,19 @@ label[for='toggle-all'] { ...@@ -155,19 +123,19 @@ label[for='toggle-all'] {
#toggle-all { #toggle-all {
position: absolute; position: absolute;
top: -42px; top: -55px;
left: -4px; left: -12px;
width: 40px; width: 60px;
height: 34px;
text-align: center; text-align: center;
/* Mobile Safari */ border: none; /* Mobile Safari */
border: none;
} }
#toggle-all:before { #toggle-all:before {
content: '»'; content: '';
font-size: 28px; font-size: 22px;
color: #d9d9d9; color: #e6e6e6;
padding: 0 25px 7px; padding: 10px 27px 10px 27px;
} }
#toggle-all:checked:before { #toggle-all:checked:before {
...@@ -183,7 +151,7 @@ label[for='toggle-all'] { ...@@ -183,7 +151,7 @@ label[for='toggle-all'] {
#todo-list li { #todo-list li {
position: relative; position: relative;
font-size: 24px; font-size: 24px;
border-bottom: 1px dotted #ccc; border-bottom: 1px solid #ededed;
} }
#todo-list li:last-child { #todo-list li:last-child {
...@@ -215,28 +183,17 @@ label[for='toggle-all'] { ...@@ -215,28 +183,17 @@ label[for='toggle-all'] {
top: 0; top: 0;
bottom: 0; bottom: 0;
margin: auto 0; margin: auto 0;
/* Mobile Safari */ border: none; /* Mobile Safari */
border: none;
-webkit-appearance: none; -webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none; appearance: none;
} }
#todo-list li .toggle:after { #todo-list li .toggle:after {
content: '✔'; content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
/* 40 + a couple of pixels visual adjustment */
line-height: 43px;
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
} }
#todo-list li .toggle:checked:after { #todo-list li .toggle:checked:after {
color: #85ada7; content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
} }
#todo-list li label { #todo-list li label {
...@@ -246,12 +203,11 @@ label[for='toggle-all'] { ...@@ -246,12 +203,11 @@ label[for='toggle-all'] {
margin-left: 45px; margin-left: 45px;
display: block; display: block;
line-height: 1.2; line-height: 1.2;
-webkit-transition: color 0.4s;
transition: color 0.4s; transition: color 0.4s;
} }
#todo-list li.completed label { #todo-list li.completed label {
color: #a9a9a9; color: #d9d9d9;
text-decoration: line-through; text-decoration: line-through;
} }
...@@ -264,21 +220,18 @@ label[for='toggle-all'] { ...@@ -264,21 +220,18 @@ label[for='toggle-all'] {
width: 40px; width: 40px;
height: 40px; height: 40px;
margin: auto 0; margin: auto 0;
font-size: 22px; font-size: 30px;
color: #a88a8a; color: #cc9a9a;
-webkit-transition: all 0.2s; margin-bottom: 11px;
transition: all 0.2s; transition: color 0.2s ease-out;
} }
#todo-list li .destroy:hover { #todo-list li .destroy:hover {
text-shadow: 0 0 1px #000, color: #af5b5e;
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
transform: scale(1.3);
} }
#todo-list li .destroy:after { #todo-list li .destroy:after {
content: ''; content: '×';
} }
#todo-list li:hover .destroy { #todo-list li:hover .destroy {
...@@ -295,29 +248,25 @@ label[for='toggle-all'] { ...@@ -295,29 +248,25 @@ label[for='toggle-all'] {
#footer { #footer {
color: #777; color: #777;
padding: 0 15px; padding: 10px 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px; height: 20px;
z-index: 1;
text-align: center; text-align: center;
border-top: 1px solid #e6e6e6;
} }
#footer:before { #footer:before {
content: ''; content: '';
position: absolute; position: absolute;
right: 0; right: 0;
bottom: 31px; bottom: 0;
left: 0; left: 0;
height: 50px; height: 50px;
z-index: -1; overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 6px 0 -3px rgba(255, 255, 255, 0.8), 0 8px 0 -3px #f6f6f6,
0 7px 1px -3px rgba(0, 0, 0, 0.3), 0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 43px 0 -6px rgba(255, 255, 255, 0.8), 0 16px 0 -6px #f6f6f6,
0 44px 2px -6px rgba(0, 0, 0, 0.2); 0 17px 2px -6px rgba(0, 0, 0, 0.2);
} }
#todo-count { #todo-count {
...@@ -325,6 +274,10 @@ label[for='toggle-all'] { ...@@ -325,6 +274,10 @@ label[for='toggle-all'] {
text-align: left; text-align: left;
} }
#todo-count strong {
font-weight: 300;
}
#filters { #filters {
margin: 0; margin: 0;
padding: 0; padding: 0;
...@@ -339,49 +292,73 @@ label[for='toggle-all'] { ...@@ -339,49 +292,73 @@ label[for='toggle-all'] {
} }
#filters li a { #filters li a {
color: #83756f; color: inherit;
margin: 2px; margin: 3px;
padding: 3px 7px;
text-decoration: none; text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
#filters li a.selected,
#filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
} }
#filters li a.selected { #filters li a.selected {
font-weight: bold; border-color: rgba(175, 47, 47, 0.2);
} }
#clear-completed { #clear-completed,
html #clear-completed:active {
float: right; float: right;
position: relative; position: relative;
line-height: 20px; line-height: 20px;
text-decoration: none; text-decoration: none;
background: rgba(0, 0, 0, 0.1); cursor: pointer;
font-size: 11px; visibility: hidden;
padding: 0 10px; position: relative;
border-radius: 3px; }
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
#clear-completed::after {
visibility: visible;
content: 'Clear completed';
position: absolute;
top: 0;
right: 0;
white-space: nowrap;
} }
#clear-completed:hover { #clear-completed:hover::after {
background: rgba(0, 0, 0, 0.15); text-decoration: underline;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
} }
#info { #info {
margin: 65px auto 0; margin: 65px auto 0;
color: #a6a6a6; color: #bfbfbf;
font-size: 12px; font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center; text-align: center;
} }
#info p {
line-height: 1;
}
#info a { #info a {
color: inherit; color: inherit;
text-decoration: none;
font-weight: 400;
}
#info a:hover {
text-decoration: underline;
} }
/* /*
Hack to remove background from Mobile Safari. Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera Can't use it globally since it destroys checkboxes in Firefox
*/ */
@media screen and (-webkit-min-device-pixel-ratio:0) { @media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all, #toggle-all,
#todo-list li .toggle { #todo-list li .toggle {
...@@ -393,10 +370,6 @@ label[for='toggle-all'] { ...@@ -393,10 +370,6 @@ label[for='toggle-all'] {
} }
#toggle-all { #toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg); -webkit-transform: rotate(90deg);
transform: rotate(90deg); transform: rotate(90deg);
-webkit-appearance: none; -webkit-appearance: none;
...@@ -404,151 +377,12 @@ label[for='toggle-all'] { ...@@ -404,151 +377,12 @@ label[for='toggle-all'] {
} }
} }
.hidden { @media (max-width: 430px) {
display: none; #footer {
} height: 50px;
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
-webkit-transition-property: left;
transition-property: left;
-webkit-transition-duration: 500ms;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
.learn-bar > .learn {
left: 8px;
} }
.learn-bar #todoapp { #filters {
width: 550px; bottom: 10px;
margin: 130px auto 40px auto;
} }
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #c5c5c5;
border-bottom: 1px dashed #f7f7f7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
#issue-count {
display: none;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
padding-left: 300px;
}
.learn-bar > .learn {
left: 8px;
}
}
/* global _ */
(function () { (function () {
'use strict'; 'use strict';
/* jshint ignore:start */
// Underscore's Template Module // Underscore's Template Module
// Courtesy of underscorejs.org // Courtesy of underscorejs.org
var _ = (function (_) { var _ = (function (_) {
...@@ -114,6 +116,7 @@ ...@@ -114,6 +116,7 @@
if (location.hostname === 'todomvc.com') { if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
} }
/* jshint ignore:end */
function redirect() { function redirect() {
if (location.hostname === 'tastejs.github.io') { if (location.hostname === 'tastejs.github.io') {
...@@ -175,13 +178,17 @@ ...@@ -175,13 +178,17 @@
if (learnJSON.backend) { if (learnJSON.backend) {
this.frameworkJSON = learnJSON.backend; this.frameworkJSON = learnJSON.backend;
this.frameworkJSON.issueLabel = framework;
this.append({ this.append({
backend: true backend: true
}); });
} else if (learnJSON[framework]) { } else if (learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework]; this.frameworkJSON = learnJSON[framework];
this.frameworkJSON.issueLabel = framework;
this.append(); this.append();
} }
this.fetchIssueCount();
} }
Learn.prototype.append = function (opts) { Learn.prototype.append = function (opts) {
...@@ -212,6 +219,26 @@ ...@@ -212,6 +219,26 @@
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML); document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
}; };
Learn.prototype.fetchIssueCount = function () {
var issueLink = document.getElementById('issue-count-link');
if (issueLink) {
var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
var parsedResponse = JSON.parse(e.target.responseText);
if (parsedResponse instanceof Array) {
var count = parsedResponse.length
if (count !== 0) {
issueLink.innerHTML = 'This app has ' + count + ' open issues';
document.getElementById('issue-count').style.display = 'inline';
}
}
};
xhr.send();
}
};
redirect(); redirect();
getFile('learn.json', Learn); getFile('learn.json', Learn);
})(); })();
{
"private": true,
"dependencies": {
"spine": "^1.0.9",
"todomvc-common": "^1.0.1",
"todomvc-app-css": "^1.0.1",
"handlebars": "^1.0.0",
"jquery": "^1.8.3"
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment