summaryrefslogtreecommitdiffstats
path: root/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'app.js')
-rw-r--r--app.js224
1 files changed, 224 insertions, 0 deletions
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..92feaf4
--- /dev/null
+++ b/app.js
@@ -0,0 +1,224 @@
+(function($) {
+ var app = $.sammy(function() {
+
+ this.use(Sammy.Template);
+
+ this.notFound = function(verb, path) {
+ this.runRoute('get', '#/404');
+ };
+
+ this.get('#/about', function() {
+ this.partial('templates/about.template', {}, function(html) {
+ $('#page').html(html);
+ });
+ });
+
+ this.get('#/404', function() {
+ this.partial('templates/404.template', {}, function(html) {
+ $('#page').html(html);
+ });
+ });
+
+ this.get('#/list/:id', function() {
+ var list = Lists.get(this.params['id']);
+ if (list) {
+ this.partial('templates/todolist.template', {
+ list: list,
+ todos: Todos.filter('listId', list.id)
+ }, function(html) {
+ $('#page').html(html);
+ });
+ } else {
+ this.notFound();
+ }
+ });
+
+ this.get('#/about', function() {
+ this.log('about');
+ });
+
+
+ // events
+ this.bind('run', function(e, data) {
+ var context = this;
+
+ var title = localStorage.getItem('title') || "Sammy's Todos";
+ $('h1').text(title);
+
+ $('.new')
+ .live('click', function() {
+ var $this = $(this),
+ type = $this.attr('data-type');
+
+ switch (type) {
+ case "list":
+ var list = Lists.create({ name: 'My new list' });
+ Todos.create({ name: 'Something todo', done: false, listId: list.id });
+ context.redirect('#/list/'+list.id);
+ app.trigger('updateLists');
+ break;
+ case "todo":
+ var todo = Todos.create({ name: 'My new todo', done: false, listId: parseInt($('h2').attr('data-id'), 10) });
+ context.partial('templates/_todo.template', todo, function(html) {
+ $(html).insertBefore('#page li:last');
+ });
+ break;
+ }
+ });
+
+ $('#lists')
+ .delegate('dd[data-id]', 'click', function() {
+ context.redirect('#/list/'+$(this).attr('data-id'));
+ app.trigger('updateList');
+ });
+
+ $('.trashcan')
+ .live('click', function() {
+ var $this = $(this);
+ app.trigger('delete', {
+ type: $this.attr('data-type'),
+ id: $this.attr('data-id')
+ });
+ });
+
+ $('.checkbox')
+ .live('click', function() {
+ var $this = $(this),
+ $li = $this.parents('li').toggleClass('done'),
+ isDone = $li.is('.done');
+ app.trigger('mark' + (isDone ? 'Done' : 'Undone'), { id: $li.attr('data-id') });
+ });
+
+ $('[contenteditable]')
+ .live('focus', function() {
+ // store the current value
+ $.data(this, 'prevValue', $(this).text());
+ })
+ .live('blur', function() {
+ var $this = $(this),
+ // grab the, likely, modified value
+ text = $.trim($this.text());
+ if (!text) {
+ // restore the previous value if text is empty
+ $this.text($.data(this, 'prevValue'));
+ } else {
+ if ($this.is('h1')) {
+ // it is the title
+ localStorage.setItem('title', text);
+ } else {
+ // save it
+ app.trigger('save', {
+ type: $this.attr('data-type'),
+ id: $this.attr('data-id'),
+ name: text
+ });
+ }
+ }
+ })
+ .live('keypress', function(event) {
+ // save on enter
+ if (event.which === 13) {
+ this.blur();
+ return false;
+ }
+ });
+
+ if (!localStorage.getItem('initialized')) {
+ // create first list and todo
+ var listId = Lists.create({
+ name: 'My first list'
+ }).id;
+ Todos.create({
+ name: 'My first todo',
+ done: false,
+ listId: listId
+ });
+
+ localStorage.setItem('initialized', 'yup');
+ this.redirect('#/list/'+listId);
+ } else {
+ var lastViewedOrFirstList = localStorage.getItem('lastviewed') || '#/list/' + Lists.first().id;
+ this.redirect(lastViewedOrFirstList);
+ }
+
+ app.trigger('updateLists');
+ });
+
+ this.bind('route-found', function(e, data) {
+ // save the route as the lastviewed
+ localStorage.setItem('lastviewed', document.location.hash);
+ });
+
+ this.bind('save', function(e, data) {
+ var model = data.type == 'todo' ? Todos : Lists;
+ model.update(data.id, { name: data.name });
+ if (data.type == 'list') {
+ app.trigger('updateLists');
+ }
+ });
+
+ this.bind('markDone', function(e, data) {
+ this.log('marking todo with id ' + data.id + ' as done');
+ Todos.update(data.id, { done: true });
+ });
+
+ this.bind('markUndone', function(e, data) {
+ this.log('marking todo with id ' + data.id + ' as not done');
+ Todos.update(data.id, { done: false });
+ });
+
+ this.bind('delete', function(e, data) {
+ if (confirm('Are you sure you want to delete this ' + data.type + '?')) {
+ var model = data.type == 'list' ? Lists : Todos;
+ model.destroy(data.id);
+
+ if (data.type == 'list') {
+ var list = Lists.first();
+ if (list) {
+ this.redirect('#/list/'+list.id);
+ } else {
+ // create first list and todo
+ var listId = Lists.create({
+ name: 'My first list'
+ }).id;
+ Todos.create({
+ name: 'My first todo',
+ done: false,
+ listId: listId
+ });
+
+ this.redirect('#/list/'+listId);
+ }
+ app.trigger('updateLists');
+ } else {
+ // delete the todo from the view
+ $('li[data-id=' + data.id + ']').remove();
+ }
+ }
+ });
+
+ this.bind('updateLists', function(e, data) {
+ var selected = parseInt(location.hash.substr(location.hash.lastIndexOf('/')+1), 10);
+ this.partial('templates/_lists.template', {
+ lists: Lists.getAll(),
+ selected: selected
+ }, function(html) {
+ $('#lists').html(html);
+ });
+ });
+
+ });
+
+ // lists model
+ Lists = Object.create(Model);
+ Lists.name = 'lists';
+ Lists.init();
+
+ // todos model
+ Todos = Object.create(Model);
+ Todos.name = 'todos';
+ Todos.init();
+
+
+ $(function() { app.run(); });
+})(jQuery); \ No newline at end of file