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; margin: 0;
padding: 0; padding: 0;
} }
...@@ -81,16 +82,24 @@ body { ...@@ -81,16 +82,24 @@ body {
cursor: pointer; cursor: pointer;
width: 20px; width: 20px;
height: 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 { #todoapp .item:hover .destroy {
display: block; display: block;
} }
#todoapp .item .edit { display: none; } #todoapp .item .edit {
#todoapp .item.editing .edit { display: block; } display: none;
#todoapp .item.editing .view { display: none; } }
#todoapp .item.editing .edit {
display: block;
}
#todoapp .item.editing .view {
display: none;
}
#todoapp footer { #todoapp footer {
display: none; display: none;
...@@ -116,7 +125,7 @@ body { ...@@ -116,7 +125,7 @@ body {
color: #555555; color: #555555;
font-size: 11px; font-size: 11px;
margin-top: 8px; margin-top: 8px;
margin-bottom:8px; margin-bottom: 8px;
padding: 0 10px 1px; padding: 0 10px 1px;
-moz-border-radius: 12px; -moz-border-radius: 12px;
-webkit-border-radius: 12px; -webkit-border-radius: 12px;
...@@ -125,7 +134,7 @@ body { ...@@ -125,7 +134,7 @@ body {
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
cursor: pointer; cursor: pointer;
} }
...@@ -165,6 +174,7 @@ body { ...@@ -165,6 +174,7 @@ body {
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center; text-align: center;
} }
#credits a { #credits a {
color: #888; color: #888;
} }
\ No newline at end of file
<!doctype html> <!doctype html>
<html> <html lang="en">
<head> <head>
<meta charset="utf-8">
<title>jQuery</title> <title>jQuery</title>
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
<script src="js/json2.js"></script> <script src="js/json2.js"></script>
<script src="js/jquery.min.js"></script> <script src="js/jquery-1.7.1.min.js"></script>
<script src="js/jquery.tmpl.js"></script> <script src="js/handlebars-1.0.0.beta.6.js"></script>
<script src="js/store.js"></script>
<script src="js/app.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> </head>
<body> <body>
<div id="todoapp"> <div id="todoapp">
...@@ -33,11 +21,25 @@ ...@@ -33,11 +21,25 @@
<div class="count"></div> <div class="count"></div>
</footer> </footer>
</div> </div>
<div id='instructions'> <div id="instructions">
Double-click to edit a todo. Double-click to edit a todo.
</div> </div>
<div id="credits"> <div id="credits">
Created by <a href="http://sindresorhus.com">Sindre Sorhus</a>. Created by <a href="http://sindresorhus.com">Sindre Sorhus</a>.
</div> </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> </body>
</html> </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 [MIT licensed](http://en.wikipedia.org/wiki/MIT_License)
sindresorhus.com (c) [Sindre Sorhus](http://sindresorhus.com)
*/ */
jQuery(function($){ jQuery(function($) {
"use strict";
var Utils = { var Utils = {
// https://gist.github.com/823878 // https://gist.github.com/1308368
uuid: function() { 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},
var uuid = "", i, random; pluralize: function( count, word ) {
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) {
return count === 1 ? word : word + 's'; return count === 1 ? word : word + 's';
} }
}; };
var App = { var App = {
init: function() { 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.$todoApp = $('#todoapp');
this.$todoList = this.$todoApp.find('.items'); this.$todoList = this.$todoApp.find('.items');
this.$footer = this.$todoApp.find('footer'); this.$footer = this.$todoApp.find('footer');
this.$count = this.$footer.find('.count'); this.$count = this.$footer.find('.count');
this.$clearBtn = this.$footer.find('.clear'); 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() { store: function( data ) {
var html = this.$template.tmpl( this.todos ); if ( arguments.length ) {
this.$todoList.html( html ); return localStorage.setItem( 'todo-jquery', JSON.stringify( data ) );
this.renderFooter(); } else {
this.store.set('todos', this.todos); var store = localStorage.getItem('todo-jquery');
return ( store && JSON.parse( store ) ) || [];
}
}, },
bindEvents: function() { bindEvents: function() {
var elem = this.$todoApp, var app = this.$todoApp,
list = this.$todoList; list = this.$todoList;
elem.on('click', '.clear', this.destroyDone); app.on( 'click', '.clear', this.destroyDone );
elem.on('submit', 'form', this.create); app.on( 'submit', 'form', this.create );
list.on('change', 'input[type="checkbox"]', this.toggle); list.on( 'change', '.toggle', this.toggle );
list.on('dblclick', '.view', this.edit); list.on( 'dblclick', '.view', this.edit );
list.on('keypress', 'input[type="text"]', this.blurOnEnter); list.on( 'keypress', '.edit input', this.blurOnEnter );
list.on('blur', 'input[type="text"]', this.update); list.on( 'blur', '.edit input', this.update );
list.on('click', '.destroy', this.destroy); list.on( 'click', '.destroy', this.destroy );
}, },
activeTodoCount: function() { render: function() {
var count = 0; this.$todoList.html( this.template( this.todos ) );
$.each(this.todos, function(i, val) { this.renderFooter();
if ( !val.done ) { this.store( this.todos );
count++;
}
});
return count;
}, },
renderFooter: function() { renderFooter: function() {
var todoCount = this.todos.length, var todoCount = this.todos.length,
activeTodos = this.activeTodoCount(), activeTodos = this.activeTodoCount(),
completedTodos = todoCount - activeTodos, 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' ); clearTitle = 'Clear ' + completedTodos + ' completed ' + Utils.pluralize( completedTodos, 'item' );
// Only show the footer when there are at least one todo. // Only show the footer when there are at least one todo.
this.$footer.toggle( !!todoCount ); this.$footer.toggle( !!todoCount );
...@@ -84,21 +68,31 @@ jQuery(function($){ ...@@ -84,21 +68,31 @@ jQuery(function($){
// Toggle clear button and update title // Toggle clear button and update title
this.$clearBtn.text( clearTitle ).toggle( !!completedTodos ); 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() { destroyDone: function() {
// Reverse loop; since we are dynamically removing items from the todos array var todos = App.todos,
for ( var i = App.todos.length; i--; ) { l = todos.length;
if ( App.todos[i].done ) { while ( l-- ) {
App.todos.remove(i); if ( todos[l].done ) {
todos.splice( l, 1 );
} }
} }
App.render(); App.render();
}, },
// Accepts an element from inside the ".item" div, and returns the corresponding todo in the todos array. // Accepts an element from inside the ".item" div and returns the corresponding todo in the todos array.
getTodo: function(elem, callback) { getTodo: function( elem, callback ) {
var id = $(elem).closest('.item').data('id'); var id = $( elem ).closest('.item').data('id');
$.each(this.todos, function(i, val) { $.each( this.todos, function( i, val ) {
if ( val.id === id ) { if ( val.id === id ) {
callback.apply(App, arguments); callback.apply( App, arguments );
return false; return false;
} }
}); });
...@@ -119,7 +113,7 @@ jQuery(function($){ ...@@ -119,7 +113,7 @@ jQuery(function($){
App.render(); App.render();
}, },
toggle: function() { toggle: function() {
App.getTodo(this, function(i, val) { App.getTodo( this, function( i, val ) {
val.done = !val.done; val.done = !val.done;
}); });
App.render(); App.render();
...@@ -133,20 +127,20 @@ jQuery(function($){ ...@@ -133,20 +127,20 @@ jQuery(function($){
} }
}, },
update: function() { update: function() {
var newVal = $(this).removeClass('editing').val(); var val = $(this).removeClass('editing').val();
App.getTodo(this, function(i) { App.getTodo( this, function(i) {
this.todos[i].title = newVal; this.todos[i].title = val;
}); });
App.render(); App.render();
}, },
destroy: function() { destroy: function() {
App.getTodo(this, function(i) { App.getTodo( this, function(i) {
this.todos.remove(i); this.todos.splice( i, 1 );
this.render(); this.render();
}); });
} }
}; };
window.TodoApp = App.init(); window.TodoApp = App.init();
}); });
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