diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 840474e..0189f84 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -43,10 +43,10 @@ def destroy
task = Task.find(params[:id])
if (task.board == params[:board])
- task.destroy
-
Pusher[params[:board]].trigger('task-destroy', task.as_json, params[:socket_id])
+ task.destroy
+
render :json => task
end
end
diff --git a/app/views/common/application_board_selected.jst b/app/views/common/application_board_selected.jst
index 12c3249..5d600f8 100644
--- a/app/views/common/application_board_selected.jst
+++ b/app/views/common/application_board_selected.jst
@@ -9,7 +9,7 @@
Clear Tasks?
- Edit
+
diff --git a/config/assets.yml b/config/assets.yml
index a2efbce..b0f6cac 100644
--- a/config/assets.yml
+++ b/config/assets.yml
@@ -1,5 +1,6 @@
javascripts:
core:
+ - public/javascripts/vendor/modernizr.js
- public/javascripts/vendor/jquery.js
- public/javascripts/vendor/underscore.js
- public/javascripts/vendor/backbone.js
diff --git a/public/javascripts/models/task_store.js b/public/javascripts/models/task_store.js
index 20cc06b..3f2694c 100644
--- a/public/javascripts/models/task_store.js
+++ b/public/javascripts/models/task_store.js
@@ -48,12 +48,13 @@ var TaskStore = Backbone.Collection.extend(function(){
updateTask: function(task) {
this.findById(task._id).set(task);
+ this.trigger('taskToggled');
},
removeTask: function(task) {
var task = this.findById(task._id);
-
this.remove(task);
+ this.trigger('taskToggled');
},
//internal get function doesn't work on tasks which
@@ -63,10 +64,6 @@ var TaskStore = Backbone.Collection.extend(function(){
return this.find(function(task) {
return task.id == id;
});
- },
-
- toggleEditMode: function() {
- this.trigger('editableChange');
}
};
}());
\ No newline at end of file
diff --git a/public/javascripts/vendor/modernizr.js b/public/javascripts/vendor/modernizr.js
new file mode 100644
index 0000000..c6a800a
--- /dev/null
+++ b/public/javascripts/vendor/modernizr.js
@@ -0,0 +1,30 @@
+/*
+ * Modernizr v1.6
+ * http://www.modernizr.com
+ *
+ * Developed by:
+ * - Faruk Ates http://farukat.es/
+ * - Paul Irish http://paulirish.com/
+ *
+ * Copyright (c) 2009-2010
+ * Dual-licensed under the BSD or MIT licenses.
+ * http://www.modernizr.com/license/
+ */
+window.Modernizr=function(i,e,u){function s(a,b){return(""+a).indexOf(b)!==-1}function D(a,b){for(var c in a)if(j[a[c]]!==u&&(!b||b(a[c],E)))return true}function n(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1);c=(a+" "+F.join(c+" ")+c).split(" ");return!!D(c,b)}function S(){f.input=function(a){for(var b=0,c=a.length;b7)};d.history=function(){return!!(i.history&&history.pushState)};d.draganddrop=function(){return o("drag")&&
+o("dragstart")&&o("dragenter")&&o("dragover")&&o("dragleave")&&o("dragend")&&o("drop")};d.websockets=function(){return"WebSocket"in i};d.rgba=function(){j.cssText="background-color:rgba(150,255,150,.5)";return s(j.backgroundColor,"rgba")};d.hsla=function(){j.cssText="background-color:hsla(120,40%,100%,.5)";return s(j.backgroundColor,"rgba")||s(j.backgroundColor,"hsla")};d.multiplebgs=function(){j.cssText="background:url(//:),url(//:),red url(//:)";return/(url\s*\(.*?){3}/.test(j.background)};d.backgroundsize=
+function(){return n("backgroundSize")};d.borderimage=function(){return n("borderImage")};d.borderradius=function(){return n("borderRadius","",function(a){return s(a,"orderRadius")})};d.boxshadow=function(){return n("boxShadow")};d.textshadow=function(){return e.createElement("div").style.textShadow===""};d.opacity=function(){var a=q.join("opacity:.5;")+"";j.cssText=a;return s(j.opacity,"0.5")};d.cssanimations=function(){return n("animationName")};d.csscolumns=function(){return n("columnCount")};d.cssgradients=
+function(){var a=("background-image:"+q.join("gradient(linear,left top,right bottom,from(#9f9),to(white));background-image:")+q.join("linear-gradient(left top,#9f9, white);background-image:")).slice(0,-17);j.cssText=a;return s(j.backgroundImage,"gradient")};d.cssreflections=function(){return n("boxReflect")};d.csstransforms=function(){return!!D(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])};d.csstransforms3d=function(){var a=!!D(["perspectiveProperty","WebkitPerspective",
+"MozPerspective","OPerspective","msPerspective"]);if(a)a=Q("@media ("+q.join("transform-3d),(")+"modernizr)");return a};d.csstransitions=function(){return n("transitionProperty")};d.fontface=function(){var a,b=e.head||e.getElementsByTagName("head")[0]||l,c=e.createElement("style"),k=e.implementation||{hasFeature:function(){return false}};c.type="text/css";b.insertBefore(c,b.firstChild);a=c.sheet||c.styleSheet;b=k.hasFeature("CSS2","")?function(g){if(!(a&&g))return false;var r=false;try{a.insertRule(g,
+0);r=!/unknown/i.test(a.cssRules[0].cssText);a.deleteRule(a.cssRules.length-1)}catch(x){}return r}:function(g){if(!(a&&g))return false;a.cssText=g;return a.cssText.length!==0&&!/unknown/i.test(a.cssText)&&a.cssText.replace(/\r+|\n+/g,"").indexOf(g.split(" ")[0])===0};f._fontfaceready=function(g){g(f.fontface)};return b('@font-face { font-family: "font"; src: "font.ttf"; }')};d.video=function(){var a=e.createElement("video"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('video/ogg; codecs="theora"');
+b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"')||a.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return b};d.audio=function(){var a=e.createElement("audio"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"');b.mp3=a.canPlayType("audio/mpeg;");b.wav=a.canPlayType('audio/wav; codecs="1"');b.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}return b};d.localstorage=function(){try{return"localStorage"in
+i&&i.localStorage!==null}catch(a){return false}};d.sessionstorage=function(){try{return"sessionStorage"in i&&i.sessionStorage!==null}catch(a){return false}};d.webWorkers=function(){return!!i.Worker};d.applicationcache=function(){return!!i.applicationCache};d.svg=function(){return!!e.createElementNS&&!!e.createElementNS(v.svg,"svg").createSVGRect};d.inlinesvg=function(){var a=document.createElement("div");a.innerHTML="";return(a.firstChild&&a.firstChild.namespaceURI)==v.svg};d.smil=function(){return!!e.createElementNS&&
+/SVG/.test(O.call(e.createElementNS(v.svg,"animate")))};d.svgclippaths=function(){return!!e.createElementNS&&/SVG/.test(O.call(e.createElementNS(v.svg,"clipPath")))};for(var H in d)if(R(d,H)){w=H.toLowerCase();f[w]=d[H]();P.push((f[w]?"":"no-")+w)}f.input||S();f.crosswindowmessaging=f.postmessage;f.historymanagement=f.history;f.addTest=function(a,b){a=a.toLowerCase();if(!f[a]){b=!!b();l.className+=" "+(b?"":"no-")+a;f[a]=b;return f}};j.cssText="";E=h=null;i.attachEvent&&function(){var a=e.createElement("div");
+a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function c(p){for(var m=-1;++m (defaults.threshold.y*-1)) {
+ changeX = originalCoord.x - finalCoord.x
+
+ if(changeX > defaults.threshold.x) {
+ defaults.swipeLeft()
+ }
+ if(changeX < (defaults.threshold.x*-1)) {
+ defaults.swipeRight()
+ }
+ }
+ }
+
+ // Swipe was started
+ function touchStart(event) {
+ //console.log('Starting swipe gesture...')
+ originalCoord.x = event.targetTouches[0].pageX
+ originalCoord.y = event.targetTouches[0].pageY
+
+ finalCoord.x = originalCoord.x
+ finalCoord.y = originalCoord.y
+ }
+
+ // Swipe was canceled
+ function touchCancel(event) {
+ //console.log('Canceling swipe gesture...')
+ }
+
+ // Add gestures to all swipable areas
+ this.addEventListener("touchstart", touchStart, false);
+ this.addEventListener("touchmove", touchMove, false);
+ this.addEventListener("touchend", touchEnd, false);
+ this.addEventListener("touchcancel", touchCancel, false);
+
+ });
+ };
+})(jQuery);
\ No newline at end of file
diff --git a/public/javascripts/vendor/plugins/toggleDoneButton.js b/public/javascripts/vendor/plugins/toggleDoneButton.js
deleted file mode 100644
index 4508319..0000000
--- a/public/javascripts/vendor/plugins/toggleDoneButton.js
+++ /dev/null
@@ -1,19 +0,0 @@
-(function( $ ){
- $.fn.toggleDoneButton = function() {
- this.each(function() {
- var done = false;
- var originalLabel = $(this).html();
-
- $(this).click(function() {
-
- if (done) {
- $(this).html(originalLabel);
- done = false;
- } else {
- $(this).html("Done");
- done = true;
- }
- });
- });
- }
-})( jQuery );
\ No newline at end of file
diff --git a/public/javascripts/views/big_board_view.js b/public/javascripts/views/big_board_view.js
index 81961a8..32c39b0 100644
--- a/public/javascripts/views/big_board_view.js
+++ b/public/javascripts/views/big_board_view.js
@@ -64,7 +64,6 @@ var BigBoardView = Backbone.View.extend(Stately).extend(function() {
},
taskDestroyedEventListener: function(task) {
- console.log("SOMEONE DESTROYED!");
taskStore.removeTask(task);
},
@@ -84,8 +83,7 @@ var BigBoardView = Backbone.View.extend(Stately).extend(function() {
"keypress .board_selected input[type=text]" : "keyPressListener",
"click .clearCompleted" : "clearCompletedListener",
"confirm .clearCompleted" : "clearCompletedConfirmListener",
- "cancelConfirm .clearCompleted" : "clearCompletedCancelListener",
- "click #editTasks" : "editTasksClickListener"
+ "cancelConfirm .clearCompleted" : "clearCompletedCancelListener"
},
initialize: function() {
@@ -110,8 +108,6 @@ var BigBoardView = Backbone.View.extend(Stately).extend(function() {
showEffect: 'slideDown',
hideEffect: 'slideUp'
});
-
- this.$('.toggleDoneButton').toggleDoneButton();
},
getState: function() {
@@ -183,10 +179,6 @@ var BigBoardView = Backbone.View.extend(Stately).extend(function() {
taskStore.clearCompleted();
},
- editTasksClickListener: function() {
- taskStore.toggleEditMode();
- },
-
log: function(str) {
if (window['console'])
console.log(str);
diff --git a/public/javascripts/views/task_store_view.js b/public/javascripts/views/task_store_view.js
index 62379ae..164f575 100644
--- a/public/javascripts/views/task_store_view.js
+++ b/public/javascripts/views/task_store_view.js
@@ -27,8 +27,7 @@ var TaskStoreView = Backbone.View.extend(Stately).extend(function() {
states: {
NO_ITEMS: "no_items",
LOADING: "loading",
- NORMAL: "normal",
- EDITABLE: "editable"
+ NORMAL: "normal"
},
initialize: function() {
@@ -37,7 +36,6 @@ var TaskStoreView = Backbone.View.extend(Stately).extend(function() {
this.model.bind('refresh', _.bind(this.render, this));
this.model.bind('loadingChange', _.bind(this.render, this));
this.model.bind('taskToggled', _.bind(this.updateTasksRemaining, this));
- this.model.bind('editableChange', _.bind(this.editableChangeListener, this));
},
render: function() {
@@ -103,10 +101,6 @@ var TaskStoreView = Backbone.View.extend(Stately).extend(function() {
$('.numTasks').html(numTasks);
$('.tasksNoun').html(tasksNoun);
- },
-
- editableChangeListener: function() {
- $(this.el).toggleClass(this.states.EDITABLE);
}
};
}());
\ No newline at end of file
diff --git a/public/javascripts/views/task_view.js b/public/javascripts/views/task_view.js
index b9ee38c..7b14b59 100644
--- a/public/javascripts/views/task_view.js
+++ b/public/javascripts/views/task_view.js
@@ -1,6 +1,8 @@
var TaskView = Backbone.View.extend(Stately).extend(function() {
return {
+ controlsVisible: false,
+
tagName: "li",
states: {
@@ -28,6 +30,8 @@ var TaskView = Backbone.View.extend(Stately).extend(function() {
this.processComponents();
this.delegateEvents();
+ $(this.el).swipe({ swipeRight: _.bind(this.swipedTaskListener, this) });
+
return this;
},
@@ -51,7 +55,26 @@ var TaskView = Backbone.View.extend(Stately).extend(function() {
},
deleteTaskListener: function() {
- this.model.destroy();
- }
+ this.model.destroy();
+ this.model.collection.remove(this.model);
+ },
+
+ swipedTaskListener: function() {
+ if (!this.controlsVisible) {
+ $(this.el).addClass('editable');
+ this.controlsVisible = true;
+ $(document).bind('touchstart', _.bind(this.swipedTaskCancelListener, this));
+ } else {
+ $(this.el).removeClass('editable');
+ this.controlsVisible = false;
+ $(document).unbind('touchstart');
+ }
+ },
+
+ swipedTaskCancelListener: function(event) {
+ if ($(event.target).parent('.controls').length == 0) {
+ this.swipedTaskListener();
+ }
+ }
};
}());
\ No newline at end of file
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index 02abced..a7b2892 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -114,17 +114,22 @@ footer .app_name {
display:block;
}
-.controls {
- display:none;
+/* show controls on hover for browsers with drag and drop AKA mouse */
+.no-touch #taskStoreView li:hover .controls {
+ visibility:visible;
}
-.editable .controls {
- display:inline;
+.controls {
+ visibility:hidden;
position:absolute;
right:10px;
top:10px;
}
+.editable .controls {
+ visibility:visible;
+}
+
.addTask {
position:absolute;
left:5px;
diff --git a/spec/javascripts/views/task_store_view_spec.js b/spec/javascripts/views/task_store_view_spec.js
index d189478..ad78c92 100644
--- a/spec/javascripts/views/task_store_view_spec.js
+++ b/spec/javascripts/views/task_store_view_spec.js
@@ -24,13 +24,4 @@ describe("Task Store View", function() {
expect(sut.getState()).toBe(sut.states.NORMAL);
});
- it("should render the editable class when the model dispatches the editableChange event", function() {
- expect( $(sut.el).hasClass(sut.states.EDITABLE)).toBe(false);
-
- model.trigger('editableChange');
-
- expect( $(sut.el).hasClass(sut.states.EDITABLE)).toBeTruthy();
- });
-
-
});
\ No newline at end of file