Commit d2245d57 authored by Kostantinos  Margaritis's avatar Kostantinos Margaritis Committed by Sindre Sorhus

Close #1144 PR: React-backbone: New ui & upgrade to NPM. Fixes #1110

parent 1de82da0
node_modules/backbone/*
!node_modules/backbone/backbone.js
node_modules/backbone.localstorage/*
!node_modules/backbone.localstorage/backbone.localStorage.js
node_modules/jquery/*
!node_modules/jquery/dist
node_modules/jquery/dist/*
!node_modules/jquery/dist/jquery.js
node_modules/react/*
!node_modules/react/dist
node_modules/react/dist/*
!node_modules/react/dist/react-with-addons.js
!node_modules/react/dist/JSXTransformer.js
node_modules/todomvc-app-css/*
!node_modules/todomvc-app-css/index.css
node_modules/todomvc-common/*
!node_modules/todomvc-common/base.css
!node_modules/todomvc-common/base.js
node_modules/underscore/*
!node_modules/underscore/underscore.js
{
"name": "todomvc-react-backbone",
"version": "0.0.0",
"dependencies": {
"react": "~0.10.0",
"backbone": "~1.1.2",
"backbone.localstorage": "~1.1.7",
"jquery": "~2.1.0",
"todomvc-common": "~0.3.0",
"underscore": "~1.6.0"
}
}
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>React + Backbone • TodoMVC</title> <title>React _ Backbone • 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> <section id="todoapp"></section>
...@@ -14,13 +15,13 @@ ...@@ -14,13 +15,13 @@
<p>Part of<a href="http://todomvc.com">TodoMVC</a></p> <p>Part of<a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="bower_components/todomvc-common/base.js"></script> <script src="node_modules/todomvc-common/base.js"></script>
<script src="bower_components/react/react-with-addons.js"></script> <script src="node_modules/react/dist/react-with-addons.js"></script>
<script src="bower_components/react/JSXTransformer.js"></script> <script src="node_modules/react/dist/JSXTransformer.js"></script>
<script src="bower_components/jquery/dist/jquery.js"></script> <script src="node_modules/jquery/dist/jquery.js"></script>
<script src="bower_components/underscore/underscore.js"></script> <script src="node_modules/underscore/underscore.js"></script>
<script src="bower_components/backbone/backbone.js"></script> <script src="node_modules/backbone/backbone.js"></script>
<script src="bower_components/backbone.localstorage/backbone.localStorage.js"></script> <script src="node_modules/backbone.localstorage/backbone.localStorage.js"></script>
<script src="js/todo.js"></script> <script src="js/todo.js"></script>
<script src="js/todos.js"></script> <script src="js/todos.js"></script>
......
/** /**
* Backbone localStorage Adapter * Backbone localStorage Adapter
* Version 1.1.7 * Version 1.1.16
* *
* https://github.com/jeromegn/Backbone.localStorage * https://github.com/jeromegn/Backbone.localStorage
*/ */
(function (root, factory) { (function (root, factory) {
if (typeof exports === 'object' && typeof require === 'function') { if (typeof exports === 'object' && typeof require === 'function') {
module.exports = factory(require("underscore"), require("backbone")); module.exports = factory(require("backbone"));
} else if (typeof define === "function" && define.amd) { } else if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module. // AMD. Register as an anonymous module.
define(["underscore","backbone"], function(_, Backbone) { define(["backbone"], function(Backbone) {
// Use global variables if the locals are undefined. // Use global variables if the locals are undefined.
return factory(_ || root._, Backbone || root.Backbone); return factory(Backbone || root.Backbone);
}); });
} else { } else {
// RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags factory(Backbone);
factory(_, Backbone); }
} }(this, function(Backbone) {
}(this, function(_, Backbone) {
// A simple module to replace `Backbone.sync` with *localStorage*-based // A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple // persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that. // 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. // Generate four random hex digits.
function S4() { function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1); return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
...@@ -35,19 +31,49 @@ function guid() { ...@@ -35,19 +31,49 @@ function guid() {
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); 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 // 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. // with a meaningful name, like the name you'd give a table.
// window.Store is deprectated, use Backbone.LocalStorage instead // window.Store is deprectated, use Backbone.LocalStorage instead
Backbone.LocalStorage = window.Store = function(name) { Backbone.LocalStorage = window.Store = function(name, serializer) {
if( !this.localStorage ) { if( !this.localStorage ) {
throw "Backbone.localStorage: Environment does not support localStorage." throw "Backbone.localStorage: Environment does not support localStorage."
} }
this.name = name; 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); var store = this.localStorage().getItem(this.name);
this.records = (store && store.split(",")) || []; this.records = (store && store.split(",")) || [];
}; };
_.extend(Backbone.LocalStorage.prototype, { extend(Backbone.LocalStorage.prototype, {
// Save the current state of the **Store** to *localStorage*. // Save the current state of the **Store** to *localStorage*.
save: function() { save: function() {
...@@ -57,11 +83,11 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -57,11 +83,11 @@ _.extend(Backbone.LocalStorage.prototype, {
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own. // have an id of it's own.
create: function(model) { create: function(model) {
if (!model.id) { if (!model.id && model.id !== 0) {
model.id = guid(); model.id = guid();
model.set(model.idAttribute, model.id); 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.records.push(model.id.toString());
this.save(); this.save();
return this.find(model); return this.find(model);
...@@ -69,36 +95,40 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -69,36 +95,40 @@ _.extend(Backbone.LocalStorage.prototype, {
// Update a model by replacing its copy in `this.data`. // Update a model by replacing its copy in `this.data`.
update: function(model) { update: function(model) {
this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model)); this.localStorage().setItem(this._itemName(model.id), this.serializer.serialize(model));
if (!_.include(this.records, model.id.toString())) var modelId = model.id.toString();
this.records.push(model.id.toString()); this.save(); if (!contains(this.records, modelId)) {
this.records.push(modelId);
this.save();
}
return this.find(model); return this.find(model);
}, },
// Retrieve a model from `this.data` by id. // Retrieve a model from `this.data` by id.
find: function(model) { find: function(model) {
return this.jsonData(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. // Return the array of all models currently in storage.
findAll: function() { findAll: function() {
// Lodash removed _#chain in v1.0.0-rc.1 var result = [];
return (_.chain || _)(this.records) for (var i = 0, id, data; i < this.records.length; i++) {
.map(function(id){ id = this.records[i];
return this.jsonData(this.localStorage().getItem(this.name+"-"+id)); data = this.serializer.deserialize(this.localStorage().getItem(this._itemName(id)));
}, this) if (data != null) result.push(data);
.compact() }
.value(); return result;
}, },
// Delete a model from `this.data`, returning it. // Delete a model from `this.data`, returning it.
destroy: function(model) { destroy: function(model) {
if (model.isNew()) this.localStorage().removeItem(this._itemName(model.id));
return false var modelId = model.id.toString();
this.localStorage().removeItem(this.name+"-"+model.id); for (var i = 0, id; i < this.records.length; i++) {
this.records = _.reject(this.records, function(id){ if (this.records[i] === modelId) {
return id === model.id.toString(); this.records.splice(i, 1);
}); }
}
this.save(); this.save();
return model; return model;
}, },
...@@ -107,11 +137,6 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -107,11 +137,6 @@ _.extend(Backbone.LocalStorage.prototype, {
return localStorage; return localStorage;
}, },
// fix for "illegal access" error on Android when JSON.parse is passed null
jsonData: function (data) {
return data && JSON.parse(data);
},
// Clear localStorage for specific collection. // Clear localStorage for specific collection.
_clear: function() { _clear: function() {
var local = this.localStorage(), var local = this.localStorage(),
...@@ -120,11 +145,12 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -120,11 +145,12 @@ _.extend(Backbone.LocalStorage.prototype, {
// Remove id-tracking item (e.g., "foo"). // Remove id-tracking item (e.g., "foo").
local.removeItem(this.name); local.removeItem(this.name);
// Lodash removed _#chain in v1.0.0-rc.1
// Match all data items (e.g., "foo-ID") and remove. // Match all data items (e.g., "foo-ID") and remove.
(_.chain || _)(local).keys() for (var k in local) {
.filter(function (k) { return itemRe.test(k); }) if (itemRe.test(k)) {
.each(function (k) { local.removeItem(k); }); local.removeItem(k);
}
}
this.records.length = 0; this.records.length = 0;
}, },
...@@ -132,6 +158,10 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -132,6 +158,10 @@ _.extend(Backbone.LocalStorage.prototype, {
// Size of localStorage. // Size of localStorage.
_storageSize: function() { _storageSize: function() {
return this.localStorage().length; return this.localStorage().length;
},
_itemName: function(id) {
return this.name+"-"+id;
} }
}); });
...@@ -140,9 +170,13 @@ _.extend(Backbone.LocalStorage.prototype, { ...@@ -140,9 +170,13 @@ _.extend(Backbone.LocalStorage.prototype, {
// *localStorage* property, which should be an instance of `Store`. // *localStorage* property, which should be an instance of `Store`.
// window.Store.sync and Backbone.localSync is deprecated, 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) { 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, syncDfd = Backbone.$.Deferred && Backbone.$.Deferred(); //If $ is having Deferred - use it. var resp, errorMessage;
//If $ is having Deferred - use it.
var syncDfd = Backbone.$ ?
(Backbone.$.Deferred && Backbone.$.Deferred()) :
(Backbone.Deferred && Backbone.Deferred());
try { try {
...@@ -204,8 +238,10 @@ Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(m ...@@ -204,8 +238,10 @@ Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(m
Backbone.ajaxSync = Backbone.sync; Backbone.ajaxSync = Backbone.sync;
Backbone.getSyncMethod = function(model) { Backbone.getSyncMethod = function(model, options) {
if(model.localStorage || (model.collection && model.collection.localStorage)) { var forceAjaxSync = options && options.ajaxSync;
if(!forceAjaxSync && (result(model, 'localStorage') || result(model.collection, 'localStorage'))) {
return Backbone.localSync; return Backbone.localSync;
} }
...@@ -215,7 +251,7 @@ Backbone.getSyncMethod = function(model) { ...@@ -215,7 +251,7 @@ Backbone.getSyncMethod = function(model) {
// Override 'Backbone.sync' to default to localSync, // Override 'Backbone.sync' to default to localSync,
// the original 'Backbone.sync' is still available in 'Backbone.ajaxSync' // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
Backbone.sync = function(method, model, options) { 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]);
}; };
return Backbone.LocalStorage; return Backbone.LocalStorage;
......
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": {
"backbone": "^1.1.2",
"backbone.localstorage": "^1.1.7",
"jquery": "^2.1.0",
"react": "^0.12.0",
"todomvc-app-css": "^1.0.0",
"todomvc-common": "^1.0.1",
"underscore": "^1.6.0"
}
}
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