Commit 73817d73 authored by Aaron Boushley's avatar Aaron Boushley

Merge pull request #47 from sindresorhus/jquery-example-fixes

Updated jQuery example
parents 696bcc05 19636817
html, body {
html,
body {
margin: 0;
padding: 0;
}
......@@ -81,16 +82,24 @@ body {
cursor: pointer;
width: 20px;
height: 20px;
background: url(../img/destroy.png) no-repeat center center;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAABGdBTUEAALGPC/xhBQAAACdQTFRFzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAA////zMzMhnu0WAAAAAt0Uk5T5u3pqtV3jFQEKAC0bVelAAAAfUlEQVQI12NYtWpFsc8R865VqxhWrZpyBgg8QcylZ8AgCsjMgTCPrWJYfgYKqhjWwJgaDDVnzpw+c2bPmTPHGWzOnNm95/TuM2cOM/AARXfvBooeZAAp270bRCIz4QoOIGtDMqwJZoUEQzvCYrhzuhhWtUKYEahOX7UK6iEA3A6NUGwCTZIAAAAASUVORK5CYII=') no-repeat center center;
}
#todoapp .item:hover .destroy {
display: block;
}
#todoapp .item .edit { display: none; }
#todoapp .item.editing .edit { display: block; }
#todoapp .item.editing .view { display: none; }
#todoapp .item .edit {
display: none;
}
#todoapp .item.editing .edit {
display: block;
}
#todoapp .item.editing .view {
display: none;
}
#todoapp footer {
display: none;
......@@ -116,7 +125,7 @@ body {
color: #555555;
font-size: 11px;
margin-top: 8px;
margin-bottom:8px;
margin-bottom: 8px;
padding: 0 10px 1px;
-moz-border-radius: 12px;
-webkit-border-radius: 12px;
......@@ -165,6 +174,7 @@ body {
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
\ No newline at end of file
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery</title>
<link rel="stylesheet" href="css/app.css">
<script src="js/json2.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/jquery.tmpl.js"></script>
<script src="js/store.js"></script>
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/handlebars-1.0.0.beta.6.js"></script>
<script src="js/app.js"></script>
<script type="text/x-jquery-tmpl" id="todo-template">
<li class="item {{if done}}done{{/if}}" data-id="${id}">
<div class="view" title="Double click to edit...">
<input type="checkbox" {{if done}}checked="checked"{{/if}}>
<span>${title}</span>
<a class="destroy"></a>
</div>
<div class="edit">
<input type="text" value="${title}">
</div>
</li>
</script>
</head>
<body>
<div id="todoapp">
......@@ -33,11 +21,25 @@
<div class="count"></div>
</footer>
</div>
<div id='instructions'>
<div id="instructions">
Double-click to edit a todo.
</div>
<div id="credits">
Created by <a href="http://sindresorhus.com">Sindre Sorhus</a>.
</div>
<script type="text/x-handlebars-template" id="todo-template">
{{#this}}
<li class="item {{#if done}}done{{/if}}" data-id="{{id}}">
<div class="view" title="Double click to edit...">
<input class="toggle" type="checkbox" {{#if done}}checked="checked"{{/if}}>
<span>{{title}}</span>
<a class="destroy"></a>
</div>
<div class="edit">
<input type="text" value="{{title}}">
</div>
</li>
{{/this}}
</script>
</body>
</html>
\ No newline at end of file
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
/*
By Sindre Sorhus
sindresorhus.com
[MIT licensed](http://en.wikipedia.org/wiki/MIT_License)
(c) [Sindre Sorhus](http://sindresorhus.com)
*/
jQuery(function($){
jQuery(function($) {
"use strict";
var Utils = {
// https://gist.github.com/823878
uuid: function() {
var uuid = "", i, random;
for ( i = 0; i < 32; i++ ) {
random = Math.random() * 16 | 0;
if ( i == 8 || i == 12 || i == 16 || i == 20 ) {
uuid += "-";
}
uuid += (i == 12 ? 4 : (i == 16 ? (random & 3 | 8) : random)).toString(16);
}
return uuid;
},
pluralize: function(count, word) {
// https://gist.github.com/1308368
uuid: function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b},
pluralize: function( count, word ) {
return count === 1 ? word : word + 's';
}
};
var App = {
init: function() {
this.$template = $('#todo-template');
this.todos = this.store();
this.cacheElements();
this.bindEvents();
this.render();
},
cacheElements: function() {
this.template = Handlebars.compile( $('#todo-template').html() );
this.$todoApp = $('#todoapp');
this.$todoList = this.$todoApp.find('.items');
this.$footer = this.$todoApp.find('footer');
this.$count = this.$footer.find('.count');
this.$clearBtn = this.$footer.find('.clear');
// localStorage support
this.store = new Store('todo-jquery');
this.todos = this.store.get('todos') || [];
this.bindEvents();
this.render();
},
render: function() {
var html = this.$template.tmpl( this.todos );
this.$todoList.html( html );
this.renderFooter();
this.store.set('todos', this.todos);
store: function( data ) {
if ( arguments.length ) {
return localStorage.setItem( 'todo-jquery', JSON.stringify( data ) );
} else {
var store = localStorage.getItem('todo-jquery');
return ( store && JSON.parse( store ) ) || [];
}
},
bindEvents: function() {
var elem = this.$todoApp,
var app = this.$todoApp,
list = this.$todoList;
elem.on('click', '.clear', this.destroyDone);
elem.on('submit', 'form', this.create);
list.on('change', 'input[type="checkbox"]', this.toggle);
list.on('dblclick', '.view', this.edit);
list.on('keypress', 'input[type="text"]', this.blurOnEnter);
list.on('blur', 'input[type="text"]', this.update);
list.on('click', '.destroy', this.destroy);
app.on( 'click', '.clear', this.destroyDone );
app.on( 'submit', 'form', this.create );
list.on( 'change', '.toggle', this.toggle );
list.on( 'dblclick', '.view', this.edit );
list.on( 'keypress', '.edit input', this.blurOnEnter );
list.on( 'blur', '.edit input', this.update );
list.on( 'click', '.destroy', this.destroy );
},
activeTodoCount: function() {
var count = 0;
$.each(this.todos, function(i, val) {
if ( !val.done ) {
count++;
}
});
return count;
render: function() {
this.$todoList.html( this.template( this.todos ) );
this.renderFooter();
this.store( this.todos );
},
renderFooter: function() {
var todoCount = this.todos.length,
activeTodos = this.activeTodoCount(),
completedTodos = todoCount - activeTodos,
countTitle = '<b>' + activeTodos + '</b> ' + Utils.pluralize( activeTodos, 'item' ) + ' left';
countTitle = '<b>' + activeTodos + '</b> ' + Utils.pluralize( activeTodos, 'item' ) + ' left',
clearTitle = 'Clear ' + completedTodos + ' completed ' + Utils.pluralize( completedTodos, 'item' );
// Only show the footer when there are at least one todo.
this.$footer.toggle( !!todoCount );
......@@ -84,21 +68,31 @@ jQuery(function($){
// Toggle clear button and update title
this.$clearBtn.text( clearTitle ).toggle( !!completedTodos );
},
activeTodoCount: function() {
var count = 0;
$.each( this.todos, function( i, val ) {
if ( !val.done ) {
count++;
}
});
return count;
},
destroyDone: function() {
// Reverse loop; since we are dynamically removing items from the todos array
for ( var i = App.todos.length; i--; ) {
if ( App.todos[i].done ) {
App.todos.remove(i);
var todos = App.todos,
l = todos.length;
while ( l-- ) {
if ( todos[l].done ) {
todos.splice( l, 1 );
}
}
App.render();
},
// Accepts an element from inside the ".item" div, and returns the corresponding todo in the todos array.
getTodo: function(elem, callback) {
var id = $(elem).closest('.item').data('id');
$.each(this.todos, function(i, val) {
// Accepts an element from inside the ".item" div and returns the corresponding todo in the todos array.
getTodo: function( elem, callback ) {
var id = $( elem ).closest('.item').data('id');
$.each( this.todos, function( i, val ) {
if ( val.id === id ) {
callback.apply(App, arguments);
callback.apply( App, arguments );
return false;
}
});
......@@ -119,7 +113,7 @@ jQuery(function($){
App.render();
},
toggle: function() {
App.getTodo(this, function(i, val) {
App.getTodo( this, function( i, val ) {
val.done = !val.done;
});
App.render();
......@@ -133,15 +127,15 @@ jQuery(function($){
}
},
update: function() {
var newVal = $(this).removeClass('editing').val();
App.getTodo(this, function(i) {
this.todos[i].title = newVal;
var val = $(this).removeClass('editing').val();
App.getTodo( this, function(i) {
this.todos[i].title = val;
});
App.render();
},
destroy: function() {
App.getTodo(this, function(i) {
this.todos.remove(i);
App.getTodo( this, function(i) {
this.todos.splice( i, 1 );
this.render();
});
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//
// Copyright (c) 2011 Frank Kohlhepp
// https://github.com/frankkohlhepp/store-js
// License: MIT-license
//
(function () {
var Store = this.Store = function (name, defaults, watcherSpeed) {
var that = this;
this.name = name;
this.listeners = {};
// Set defaults
if (defaults) {
for (var key in defaults) {
if (defaults.hasOwnProperty(key) && this.get(key) === undefined) {
this.set(key, defaults[key]);
}
}
}
// Fake events
var fireEvent = function (name, value) {
([name, "*"]).each(function (selector) {
if (that.listeners[selector]) {
that.listeners[selector].each(function (callback) {
callback(value, name, that.name);
});
}
});
};
var oldObj = this.toObject();
var standby = function () { watcher(true); };
var watcher = function (skipCheck) {
if (Object.keys(that.listeners).length !== 0) {
var newObj = that.toObject();
if (!skipCheck) {
for (var key in newObj) {
if (newObj.hasOwnProperty(key) && newObj[key] !== oldObj[key]) {
fireEvent(key, newObj[key]);
}
}
for (var key in oldObj) {
if (oldObj.hasOwnProperty(key) && !newObj.hasOwnProperty(key)) {
fireEvent(key, newObj[key]);
}
}
}
oldObj = newObj;
setTimeout(watcher, (watcherSpeed || 300));
} else {
setTimeout(standby, 1000);
}
};
standby();
};
Store.__proto__ = function Empty() {};
Store.__proto__.clear = function () {
localStorage.clear();
};
Store.prototype.get = function (name) {
var value = localStorage.getItem("store." + this.name + "." + name);
if (value === null) { return; }
try { return JSON.parse(value); } catch (e) { return null; }
};
Store.prototype.set = function (name, value) {
if (value === undefined) {
this.remove(name);
} else {
if (typeof value === "function") {
value = null;
} else {
try {
value = JSON.stringify(value);
} catch (e) {
value = null;
}
}
localStorage.setItem("store." + this.name + "." + name, value);
}
return this;
};
Store.prototype.remove = function (name) {
localStorage.removeItem("store." + this.name + "." + name);
return this;
};
Store.prototype.removeAll = function () {
var name = "store." + this.name + ".";
for (var i = (localStorage.length - 1); i >= 0; i--) {
if (localStorage.key(i).substring(0, name.length) === name) {
localStorage.removeItem(localStorage.key(i));
}
}
return this;
};
Store.prototype.toObject = function () {
var values = {};
var name = "store." + this.name + ".";
for (var i = (localStorage.length - 1); i >= 0; i--) {
if (localStorage.key(i).substring(0, name.length) === name) {
var key = localStorage.key(i).substring(name.length);
var value = this.get(key);
if (value !== undefined) { values[key] = value; }
}
}
return values;
};
Store.prototype.fromObject = function (values, merge) {
if (!merge) { this.removeAll(); }
for (var key in values) {
if (values.hasOwnProperty(key)) {
this.set(key, values[key]);
}
}
return this;
};
Store.prototype.addEvent = function (selector, callback) {
if (!this.listeners[selector]) { this.listeners[selector] = []; }
this.listeners[selector].push(callback);
return this;
};
Store.prototype.removeEvent = function (selector, callback) {
for (var i = (this.listeners[selector].length - 1); i >= 0; i--) {
if (this.listeners[selector][i] === callback) { this.listeners[selector].splice(i, 1); }
}
if (this.listeners[selector].length === 0) { delete this.listeners[selector]; }
return this;
};
}());
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