diff --git a/jquery.sketchable.js b/jquery.sketchable.js
index 3c71ebb..057f1e6 100644
--- a/jquery.sketchable.js
+++ b/jquery.sketchable.js
@@ -161,9 +161,9 @@
elem.unbind("mouseup", mouseupHandler);
elem.unbind("mousemove", mousemoveHandler);
elem.unbind("mousedown", mousedownHandler);
- elem.unbind("touchstart", touchHandler);
- elem.unbind("touchmove", touchHandler);
- elem.unbind("touchend", touchHandler);
+ elem.unbind("touchstart", touchdownHandler);
+ elem.unbind("touchmove", touchmoveHandler);
+ elem.unbind("touchend", touchupHandler);
}
elem.removeData(_ns);
diff --git a/jquery.sketchable.memento.js b/jquery.sketchable.memento.js
index d134460..3218583 100644
--- a/jquery.sketchable.memento.js
+++ b/jquery.sketchable.memento.js
@@ -3,14 +3,14 @@
*/
/**
* @name $
- * @class
- * See the jQuery library for full details.
+ * @class
+ * See the jQuery library for full details.
* This just documents the method that is added to jQuery by this plugin.
*/
/**
* @name $.fn
- * @class
- * See the jQuery library for full details.
+ * @class
+ * See the jQuery library for full details.
* This just documents the method that is added to jQuery by this plugin.
*/
;(function($) {
@@ -23,12 +23,12 @@
* var mc = new MementoCanvas( $('canvas-selector') );
*/
var MementoCanvas = function($canvas) {
-
+
// Private stuff //////////////////////////////////////////////////////////
var stack = [];
var stpos = -1;
var self = this;
-
+
function prev() {
if (stpos > 0) {
stpos--;
@@ -59,8 +59,8 @@
data.sketch.graphics.drawImage(snapshot, 0,0);
});
};
-
- // Key event manager.
+
+ // Key event manager.
// Undo: "Ctrl + Z"
// Redo: "Ctrl + Y" or "Ctrl + Shift + Z"
// TODO: decouple shortcut definition, perhaps via jquery.hotkeys plugin.
@@ -79,10 +79,10 @@
}
}
};
-
+
// Public stuff ///////////////////////////////////////////////////////////
-
- /**
+
+ /**
* Goes back to the last saved state, if available.
* @name undo
* @memberOf MementoCanvas
@@ -90,10 +90,11 @@
this.undo = function() {
prev();
$canvas.sketchable('handler', function(elem, data) {
- data.strokes = stack[stpos].strokes.slice();
+ if (stack[stpos])
+ data.strokes = stack[stpos].strokes.slice();
});
};
- /**
+ /**
* Goes forward to the last saved state, if available.
* @name redo
* @memberOf MementoCanvas
@@ -101,10 +102,11 @@
this.redo = function() {
next();
$canvas.sketchable('handler', function(elem, data) {
- data.strokes = stack[stpos].strokes.slice();
+ if (stack[stpos])
+ data.strokes = stack[stpos].strokes.slice();
});
};
- /**
+ /**
* Resets stack.
* @name reset
* @memberOf MementoCanvas
@@ -113,7 +115,7 @@
stack = [];
stpos = -1;
};
- /**
+ /**
* Save state.
* @name save
* @memberOf MementoCanvas
@@ -125,7 +127,7 @@
stack.push({ image: elem[0].toDataURL(), strokes: data.strokes.slice() });
});
};
- /**
+ /**
* Init instance.
* @name init
* @memberOf MementoCanvas
@@ -135,7 +137,7 @@
$(document).off("keypress", keyManager);
$(document).on("keypress", keyManager);
};
- /**
+ /**
* Destroy instance.
* @name destroy
* @memberOf MementoCanvas
@@ -144,19 +146,19 @@
$(document).off("keypress", keyManager);
this.reset();
};
-
+
};
-
+
// Bind plugin extension ////////////////////////////////////////////////////
-
+
var plugin = $.fn.sketchable;
var availMethods = plugin('methods');
-
+
function configure(elem, opts) {
var self = elem, options = $.extend(true, plugin.defaults, opts);
// Actually this plugin is singleton, so exit early.
if (!options.interactive) return opts;
-
+
var mc = new MementoCanvas(elem);
var callbacks = {
init: function(elem, data) {
@@ -171,7 +173,7 @@
data.memento.destroy();
}
};
-
+
// A helper function to override user-defined event listeners.
function override(ev) {
if (options && options.events && typeof options.events[ev] === 'function') {
@@ -196,7 +198,7 @@
}
plugin.isMementoReady = true;
}
-
+
// Expose public API for jquery.sketchable plugin.
$.extend(availMethods, {
undo: function() {
@@ -206,13 +208,13 @@
mc.redo();
}
});
-
+
return plugin.defaults;
};
-
- /**
+
+ /**
* Creates a new memento-capable jQuery.sketchable object.
- * @param {String|Object} method name of the method to invoke,
+ * @param {String|Object} method name of the method to invoke,
* or a configuration object.
* @return jQuery
* @class
@@ -225,5 +227,5 @@
var conf = configure(this, opts);
return initfn.call(this, conf);
};
-
+
})(jQuery);
diff --git a/jquery.sketchable.memento.min.js b/jquery.sketchable.memento.min.js
index fd74865..f774995 100644
--- a/jquery.sketchable.memento.min.js
+++ b/jquery.sketchable.memento.min.js
@@ -1,4 +1 @@
-/*!
- * Memento plugin for jQuery sketchable | v1.1 | Luis A. Leiva | MIT license
- */
-(function(e){var a=function(m){var h=[];var g=-1;var i=this;function l(){if(g>0){g--;var o=new Image();o.src=h[g].image;o.onload=function(){j(this)}}}function k(){if(g0){stpos--;var snapshot=new Image;snapshot.src=stack[stpos].image;snapshot.onload=function(){restore(this)}}}function next(){if(stpos-1){return methods}else if(methods[method]){return methods[method].apply(this,Array.prototype.slice.call(arguments,1))}else if(typeof method==="object"||!method){return methods.init.apply(this,arguments)}else{$.error("Method "+method+' does not exist. See jQuery.sketchable("methods").')}return this};$.fn.sketchable.defaults={interactive:true,mouseupMovements:false,relTimestamps:false,multitouch:true,events:{},graphics:{firstPointSize:3,lineWidth:3,strokeStyle:"#F0F",fillStyle:"#F0F",lineCap:"round",lineJoin:"round",miterLimit:10}};function getMousePos(e){var elem=$(e.target),pos=elem.offset();return{x:Math.round(e.pageX-pos.left),y:Math.round(e.pageY-pos.top)}}function saveMousePos(idx,data,pt){if(!data.coords[idx]){data.coords[idx]=[]}var time=(new Date).getTime();if(data.options.relTimestamps){if(data.strokes.length===0&&data.coords[idx].length===0)data.timestamp=time;time-=data.timestamp}data.coords[idx].push([pt.x,pt.y,time,+data.sketch.isDrawing])}function mousedownHandler(e){if(e.originalEvent.touches)return false;downHandler(e)}function mousemoveHandler(e){if(e.originalEvent.touches)return false;moveHandler(e)}function mouseupHandler(e){if(e.originalEvent.touches)return false;upHandler(e)}function touchdownHandler(e){var elem=$(e.target),data=elem.data(_ns),options=data.options;var touches=e.originalEvent.changedTouches;if(options.multitouch){for(var i=0;i0){data.sketch.fillCircle(p.x,p.y,options.graphics.firstPointSize)}if(!data.coords[idx]){data.coords[idx]=[]}if(data.coords[idx].length>0){data.strokes.push(data.coords[idx]);data.coords[idx]=[]}saveMousePos(idx,data,p);if(typeof options.events.mousedown==="function"){options.events.mousedown(elem,data,e)}}function moveHandler(e){var idx=e.identifier||0;var elem=$(e.target),data=elem.data(_ns),options=data.options;if((!options.mouseupMovements||data.strokes.length===0)&&!data.sketch.isDrawing)return;var p=getMousePos(e);if(data.sketch.isDrawing){var last=data.coords[idx][data.coords[idx].length-1];data.sketch.beginPath().line(last[0],last[1],p.x,p.y).stroke().closePath()}saveMousePos(idx,data,p);if(typeof options.events.mousemove==="function"){options.events.mousemove(elem,data,e)}}function upHandler(e){var idx=e.identifier||0;var elem=$(e.target),data=elem.data(_ns),options=data.options;data.sketch.isDrawing=false;data.strokes.push(data.coords[idx]);data.coords[idx]=[];if(typeof options.events.mouseup==="function"){options.events.mouseup(elem,data,e)}}})(jQuery);
+(function($){var _ns="sketchable";var methods={init:function(opts){var options=$.extend(true,{},$.fn.sketchable.defaults,opts||{});return this.each(function(){var elem=$(this),data=elem.data(_ns);if(!data){if(options.interactive){elem.bind("mousedown",mousedownHandler);elem.bind("mousemove",mousemoveHandler);elem.bind("mouseup",mouseupHandler);elem.bind("touchstart",touchdownHandler);elem.bind("touchmove",touchmoveHandler);elem.bind("touchend",touchupHandler);this.onselectstart=function(){return false}}}var sketch=new jSketch(this,options.graphics);sketch.isDrawing=false;elem.data(_ns,{strokes:[],coords:{},timestamp:(new Date).getTime(),sketch:sketch,options:options});if(typeof options.events.init==="function"){options.events.init(elem,elem.data(_ns))}})},strokes:function(arr){if(arr){return this.each(function(){var elem=$(this),data=elem.data(_ns);data.strokes=arr})}else{var data=$(this).data(_ns);return data.strokes}},handler:function(callback){return this.each(function(){var elem=$(this),data=elem.data(_ns);callback(elem,data)})},clear:function(){return this.each(function(){var elem=$(this),data=elem.data(_ns)||{},options=data.options;if(data.sketch){data.sketch.clear();data.strokes=[];data.coords={}}if(options&&typeof options.events.clear==="function"){options.events.clear(elem,data)}})},reset:function(opts){return this.each(function(){var elem=$(this),data=elem.data(_ns)||{},options=data.options;elem.sketchable("destroy").sketchable(opts);if(options&&typeof options.events.reset==="function"){options.events.reset(elem,data)}})},destroy:function(){return this.each(function(){var elem=$(this),data=elem.data(_ns)||{},options=data.options;if(options.interactive){elem.unbind("mouseup",mouseupHandler);elem.unbind("mousemove",mousemoveHandler);elem.unbind("mousedown",mousedownHandler);elem.unbind("touchstart",touchdownHandler);elem.unbind("touchmove",touchmoveHandler);elem.unbind("touchend",touchupHandler)}elem.removeData(_ns);if(options&&typeof options.events.destroy==="function"){options.events.destroy(elem,data)}})}};$.fn.sketchable=function(method){if("methods functions hooks".split(" ").indexOf(method)>-1){return methods}else if(methods[method]){return methods[method].apply(this,Array.prototype.slice.call(arguments,1))}else if(typeof method==="object"||!method){return methods.init.apply(this,arguments)}else{$.error("Method "+method+' does not exist. See jQuery.sketchable("methods").')}return this};$.fn.sketchable.defaults={interactive:true,mouseupMovements:false,relTimestamps:false,multitouch:true,events:{},graphics:{firstPointSize:3,lineWidth:3,strokeStyle:"#F0F",fillStyle:"#F0F",lineCap:"round",lineJoin:"round",miterLimit:10}};function getMousePos(e){var elem=$(e.target),pos=elem.offset();return{x:Math.round(e.pageX-pos.left),y:Math.round(e.pageY-pos.top)}}function saveMousePos(idx,data,pt){if(!data.coords[idx]){data.coords[idx]=[]}var time=(new Date).getTime();if(data.options.relTimestamps){if(data.strokes.length===0&&data.coords[idx].length===0)data.timestamp=time;time-=data.timestamp}data.coords[idx].push([pt.x,pt.y,time,+data.sketch.isDrawing])}function mousedownHandler(e){if(e.originalEvent.touches)return false;downHandler(e)}function mousemoveHandler(e){if(e.originalEvent.touches)return false;moveHandler(e)}function mouseupHandler(e){if(e.originalEvent.touches)return false;upHandler(e)}function touchdownHandler(e){var elem=$(e.target),data=elem.data(_ns),options=data.options;var touches=e.originalEvent.changedTouches;if(options.multitouch){for(var i=0;i0){data.sketch.fillCircle(p.x,p.y,options.graphics.firstPointSize)}if(!data.coords[idx]){data.coords[idx]=[]}if(data.coords[idx].length>0){data.strokes.push(data.coords[idx]);data.coords[idx]=[]}saveMousePos(idx,data,p);if(typeof options.events.mousedown==="function"){options.events.mousedown(elem,data,e)}}function moveHandler(e){var idx=e.identifier||0;var elem=$(e.target),data=elem.data(_ns),options=data.options;if((!options.mouseupMovements||data.strokes.length===0)&&!data.sketch.isDrawing)return;var p=getMousePos(e);if(data.sketch.isDrawing){var last=data.coords[idx][data.coords[idx].length-1];data.sketch.beginPath().line(last[0],last[1],p.x,p.y).stroke().closePath()}saveMousePos(idx,data,p);if(typeof options.events.mousemove==="function"){options.events.mousemove(elem,data,e)}}function upHandler(e){var idx=e.identifier||0;var elem=$(e.target),data=elem.data(_ns),options=data.options;data.sketch.isDrawing=false;data.strokes.push(data.coords[idx]);data.coords[idx]=[];if(typeof options.events.mouseup==="function"){options.events.mouseup(elem,data,e)}}})(jQuery);