Commit 2f9b33e5 authored by TasteBot's avatar TasteBot

update the build files for gh-pages [ci skip]

parent 02db8fca
......@@ -5,6 +5,7 @@
"todomvc-common": "~0.3.0",
"lumbar-loader": "~1.1.0",
"script.js": "latest",
"thorax": "~2.0.0"
"thorax": "~2.0.0",
"Backbone.localStorage": "~1.1.16"
}
}
/**
* Backbone localStorage Adapter
* Version 1.1.16
*
* https://github.com/jeromegn/Backbone.localStorage
*/
(function(_, Backbone) {
(function (root, factory) {
if (typeof exports === 'object' && typeof require === 'function') {
module.exports = factory(require("backbone"));
} else if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["backbone"], function(Backbone) {
// Use global variables if the locals are undefined.
return factory(Backbone || root.Backbone);
});
} else {
factory(Backbone);
}
}(this, function(Backbone) {
// A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that.
// Hold reference to Underscore.js and Backbone.js in the closure in order
// to make things work even if they are removed from the global namespace
// Generate four random hex digits.
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
......@@ -21,16 +31,49 @@ function guid() {
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
};
function isObject(item) {
return item === Object(item);
}
function contains(array, item) {
var i = array.length;
while (i--) if (array[i] === item) return true;
return false;
}
function extend(obj, props) {
for (var key in props) obj[key] = props[key]
return obj;
}
function result(object, property) {
if (object == null) return void 0;
var value = object[property];
return (typeof value === 'function') ? object[property]() : value;
}
// Our Store is represented by a single JS object in *localStorage*. Create it
// with a meaningful name, like the name you'd give a table.
// window.Store is deprectated, use Backbone.LocalStorage instead
Backbone.LocalStorage = window.Store = function(name) {
Backbone.LocalStorage = window.Store = function(name, serializer) {
if( !this.localStorage ) {
throw "Backbone.localStorage: Environment does not support localStorage."
}
this.name = name;
this.serializer = serializer || {
serialize: function(item) {
return isObject(item) ? JSON.stringify(item) : item;
},
// fix for "illegal access" error on Android when JSON.parse is passed null
deserialize: function (data) {
return data && JSON.parse(data);
}
};
var store = this.localStorage().getItem(this.name);
this.records = (store && store.split(",")) || [];
};
_.extend(Backbone.LocalStorage.prototype, {
extend(Backbone.LocalStorage.prototype, {
// Save the current state of the **Store** to *localStorage*.
save: function() {
......@@ -40,81 +83,165 @@ _.extend(Backbone.LocalStorage.prototype, {
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create: function(model) {
if (!model.id) {
model.id = guid();
model.set(model.idAttribute, model.id);
if (!model.id && model.id !== 0) {
model.id = guid();
model.set(model.idAttribute, model.id);
}
this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
this.localStorage().setItem(this._itemName(model.id), this.serializer.serialize(model));
this.records.push(model.id.toString());
this.save();
return model.toJSON();
return this.find(model);
},
// Update a model by replacing its copy in `this.data`.
update: function(model) {
this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
if (!_.include(this.records, model.id.toString())) this.records.push(model.id.toString()); this.save();
return model.toJSON();
this.localStorage().setItem(this._itemName(model.id), this.serializer.serialize(model));
var modelId = model.id.toString();
if (!contains(this.records, modelId)) {
this.records.push(modelId);
this.save();
}
return this.find(model);
},
// Retrieve a model from `this.data` by id.
find: function(model) {
return JSON.parse(this.localStorage().getItem(this.name+"-"+model.id));
return this.serializer.deserialize(this.localStorage().getItem(this._itemName(model.id)));
},
// Return the array of all models currently in storage.
findAll: function() {
return _(this.records).chain()
.map(function(id){return JSON.parse(this.localStorage().getItem(this.name+"-"+id));}, this)
.compact()
.value();
var result = [];
for (var i = 0, id, data; i < this.records.length; i++) {
id = this.records[i];
data = this.serializer.deserialize(this.localStorage().getItem(this._itemName(id)));
if (data != null) result.push(data);
}
return result;
},
// Delete a model from `this.data`, returning it.
destroy: function(model) {
this.localStorage().removeItem(this.name+"-"+model.id);
this.records = _.reject(this.records, function(record_id){return record_id == model.id.toString();});
this.localStorage().removeItem(this._itemName(model.id));
var modelId = model.id.toString();
for (var i = 0, id; i < this.records.length; i++) {
if (this.records[i] === modelId) {
this.records.splice(i, 1);
}
}
this.save();
return model;
},
localStorage: function() {
return localStorage;
return localStorage;
},
// Clear localStorage for specific collection.
_clear: function() {
var local = this.localStorage(),
itemRe = new RegExp("^" + this.name + "-");
// Remove id-tracking item (e.g., "foo").
local.removeItem(this.name);
// Match all data items (e.g., "foo-ID") and remove.
for (var k in local) {
if (itemRe.test(k)) {
local.removeItem(k);
}
}
this.records.length = 0;
},
// Size of localStorage.
_storageSize: function() {
return this.localStorage().length;
},
_itemName: function(id) {
return this.name+"-"+id;
}
});
// localSync delegate to the model or collection's
// *localStorage* property, which should be an instance of `Store`.
// window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead
// window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead
Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) {
var store = model.localStorage || model.collection.localStorage;
var store = result(model, 'localStorage') || result(model.collection, 'localStorage');
var resp, errorMessage;
//If $ is having Deferred - use it.
var syncDfd = Backbone.$ ?
(Backbone.$.Deferred && Backbone.$.Deferred()) :
(Backbone.Deferred && Backbone.Deferred());
try {
var resp, syncDfd = $.Deferred && $.Deferred(); //If $ is having Deferred - use it.
switch (method) {
case "read":
resp = model.id != undefined ? store.find(model) : store.findAll();
break;
case "create":
resp = store.create(model);
break;
case "update":
resp = store.update(model);
break;
case "delete":
resp = store.destroy(model);
break;
}
switch (method) {
case "read": resp = model.id != undefined ? store.find(model) : store.findAll(); break;
case "create": resp = store.create(model); break;
case "update": resp = store.update(model); break;
case "delete": resp = store.destroy(model); break;
} catch(error) {
if (error.code === 22 && store._storageSize() === 0)
errorMessage = "Private browsing is unsupported";
else
errorMessage = error.message;
}
if (resp) {
if (options && options.success) options.success(resp);
if (syncDfd) syncDfd.resolve();
if (options && options.success) {
if (Backbone.VERSION === "0.9.10") {
options.success(model, resp, options);
} else {
options.success(resp);
}
}
if (syncDfd) {
syncDfd.resolve(resp);
}
} else {
if (options && options.error) options.error("Record not found");
if (syncDfd) syncDfd.reject();
errorMessage = errorMessage ? errorMessage
: "Record Not Found";
if (options && options.error)
if (Backbone.VERSION === "0.9.10") {
options.error(model, errorMessage, options);
} else {
options.error(errorMessage);
}
if (syncDfd)
syncDfd.reject(errorMessage);
}
// add compatibility with $.ajax
// always execute callback for success and error
if (options && options.complete) options.complete(resp);
return syncDfd && syncDfd.promise();
};
Backbone.ajaxSync = Backbone.sync;
Backbone.getSyncMethod = function(model) {
if(model.localStorage || (model.collection && model.collection.localStorage))
{
Backbone.getSyncMethod = function(model, options) {
var forceAjaxSync = options && options.ajaxSync;
if(!forceAjaxSync && (result(model, 'localStorage') || result(model.collection, 'localStorage'))) {
return Backbone.localSync;
}
......@@ -124,7 +251,8 @@ Backbone.getSyncMethod = function(model) {
// Override 'Backbone.sync' to default to localSync,
// the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
Backbone.sync = function(method, model, options) {
return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
return Backbone.getSyncMethod(model, options).apply(this, [method, model, options]);
};
})(_, Backbone);
\ No newline at end of file
return Backbone.LocalStorage;
}));
......@@ -31,7 +31,7 @@
"global": true
},
{
"src": "src/js/lib/backbone-localstorage.js",
"src": "bower_components/Backbone.localStorage/backbone.localStorage.js",
"global": true
},
{
......
This diff is collapsed.
This diff is collapsed.
var ENTER_KEY = 13;
$(function() {
// Kick things off by creating the **App**.
var view = new Thorax.Views['app']({
collection: window.app.Todos
});
view.appendTo('body');
$(function () {
// Kick things off by creating the **App**.
var view = new Thorax.Views.app({
collection: window.app.Todos
});
view.appendTo('body');
});
(function() {
(function () {
'use strict';
// Todo Collection
......@@ -37,7 +37,7 @@
// Create our global collection of **Todos**.
window.app.Todos = new TodoList();
// Ensure that we always have data available
window.app.Todos.fetch();
// Ensure that we always have data available
window.app.Todos.fetch();
}());
......@@ -3,7 +3,7 @@ Thorax.templatePathPrefix = 'src/templates/';
var app = window.app = module.exports;
$(function() {
app.initBackboneLoader();
Backbone.history.start();
$(function () {
app.initBackboneLoader();
Backbone.history.start();
});
(function() {
(function () {
'use strict';
// Todo Model
......@@ -15,7 +15,7 @@
},
// Toggle the `completed` state of this todo item.
toggle: function() {
toggle: function () {
this.save({
completed: !this.get('completed')
});
......
(function() {
(function () {
'use strict';
// Todo Router
......@@ -10,7 +10,7 @@
name: module.name,
routes: module.routes,
setFilter: function( param ) {
setFilter: function (param) {
// Set the current filter to be used
window.app.TodoFilter = param ? param.trim().replace(/^\//, '') : '';
// Thorax listens for a `filter` event which will
......
$(function( $ ) {
$(function ($) {
'use strict';
// The Application
......@@ -23,7 +23,7 @@ $(function( $ ) {
rendered: 'toggleToggleAllButton'
},
toggleToggleAllButton: function() {
toggleToggleAllButton: function () {
var toggleInput = this.$('#toggle-all')[0];
if (toggleInput) {
toggleInput.checked = !this.collection.remaining().length;
......@@ -32,12 +32,12 @@ $(function( $ ) {
// When this function is specified, items will only be shown
// when this function returns true
itemFilter: function(model) {
itemFilter: function (model) {
return model.isVisible();
},
// Generate the attributes for a new Todo item.
newAttributes: function() {
newAttributes: function () {
return {
title: this.$('#new-todo').val().trim(),
order: this.collection.nextOrder(),
......@@ -47,18 +47,18 @@ $(function( $ ) {
// If you hit return in the main input field, create new **Todo** model,
// persisting it to *localStorage*.
createOnEnter: function( e ) {
if ( e.which !== ENTER_KEY || !this.$('#new-todo').val().trim() ) {
createOnEnter: function (e) {
if (e.which !== ENTER_KEY || !this.$('#new-todo').val().trim()) {
return;
}
this.collection.create( this.newAttributes() );
this.collection.create(this.newAttributes());
this.$('#new-todo').val('');
},
toggleAllComplete: function() {
toggleAllComplete: function () {
var completed = this.$('#toggle-all')[0].checked;
this.collection.each(function( todo ) {
this.collection.each(function (todo) {
todo.save({
completed: completed
});
......
Thorax.View.extend({
name: 'stats',
name: 'stats',
events: {
'click #clear-completed': 'clearCompleted',
// The "rendered" event is triggered by Thorax each time render()
// is called and the result of the template has been appended
// to the View's $el
rendered: 'highlightFilter'
},
events: {
'click #clear-completed': 'clearCompleted',
// The "rendered" event is triggered by Thorax each time render()
// is called and the result of the template has been appended
// to the View's $el
rendered: 'highlightFilter'
},
initialize: function() {
// Whenever the Todos collection changes re-render the stats
// render() needs to be called with no arguments, otherwise calling
// it with arguments will insert the arguments as content
this.listenTo(window.app.Todos, 'all', _.debounce(function() {
this.render();
}));
},
initialize: function () {
// Whenever the Todos collection changes re-render the stats
// render() needs to be called with no arguments, otherwise calling
// it with arguments will insert the arguments as content
this.listenTo(window.app.Todos, 'all', _.debounce(function () {
this.render();
}));
},
// Clear all completed todo items, destroying their models.
clearCompleted: function() {
_.each( window.app.Todos.completed(), function( todo ) {
todo.destroy();
});
// Clear all completed todo items, destroying their models.
clearCompleted: function () {
_.each(window.app.Todos.completed(), function (todo) {
todo.destroy();
});
return false;
},
return false;
},
// Each time the stats view is rendered this function will
// be called to generate the context / scope that the template
// will be called with. "context" defaults to "return this"
context: function() {
var remaining = window.app.Todos.remaining().length;
return {
itemText: remaining === 1 ? 'item' : 'items',
completed: window.app.Todos.completed().length,
remaining: remaining
};
},
// Each time the stats view is rendered this function will
// be called to generate the context / scope that the template
// will be called with. "context" defaults to "return this"
context: function () {
var remaining = window.app.Todos.remaining().length;
return {
itemText: remaining === 1 ? 'item' : 'items',
completed: window.app.Todos.completed().length,
remaining: remaining
};
},
// Highlight which filter will appear to be active
highlightFilter: function() {
this.$('#filters li a')
.removeClass('selected')
.filter('[href="#/' + ( window.app.TodoFilter || '' ) + '"]')
.addClass('selected');
}
// Highlight which filter will appear to be active
highlightFilter: function () {
this.$('#filters li a')
.removeClass('selected')
.filter('[href="#/' + (window.app.TodoFilter || '') + '"]')
.addClass('selected');
}
});
$(function() {
$(function () {
'use strict';
// Todo Item View
......@@ -23,27 +23,27 @@ $(function() {
// The "rendered" event is triggered by Thorax each time render()
// is called and the result of the template has been appended
// to the View's $el
rendered: function() {
this.$el.toggleClass( 'completed', this.model.get('completed') );
rendered: function () {
this.$el.toggleClass('completed', this.model.get('completed'));
}
},
// Toggle the `"completed"` state of the model.
toggleCompleted: function() {
toggleCompleted: function () {
this.model.toggle();
},
// Switch this view into `"editing"` mode, displaying the input field.
edit: function() {
edit: function () {
this.$el.addClass('editing');
this.$('.edit').focus();
},
// Close the `"editing"` mode, saving changes to the todo.
close: function() {
close: function () {
var value = this.$('.edit').val().trim();
if ( value ) {
if (value) {
this.model.save({ title: value });
} else {
this.clear();
......@@ -53,14 +53,14 @@ $(function() {
},
// If you hit `enter`, we're through editing the item.
updateOnEnter: function( e ) {
if ( e.which === ENTER_KEY ) {
updateOnEnter: function (e) {
if (e.which === ENTER_KEY) {
this.close();
}
},
// Remove the item, destroy the model from *localStorage* and delete its view.
clear: function() {
clear: function () {
this.model.destroy();
}
});
......
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