new sharp resizer
authorHarris Baptiste <harris.baptiste@iri.centrepompidou.fr>
Fri, 17 Jun 2016 19:01:09 +0200
changeset 22 2c58c2c0d7f6
parent 21 dc2faee79031
child 23 713882b2bbb4
new sharp resizer
src/iconolab/apps.py
src/iconolab/forms/__init__.py
src/iconolab/static/iconolab/js/components/cutout/index.js
src/iconolab/static/iconolab/js/components/cutout/resizer.js
src/iconolab/static/iconolab/js/components/snapplugins/index.js
src/iconolab/static/iconolab/js/dist/bundle.js
src/iconolab/static/iconolab/js/package.json
src/iconolab/templates/iconolab/edit_annotation.html
src/iconolab/templates/iconolab/show_annotation.html
src/iconolab/templatetags/__init__.py
src/iconolab/templatetags/iconolab_tags.py
src/iconolab/views.py
--- a/src/iconolab/apps.py	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/apps.py	Fri Jun 17 19:01:09 2016 +0200
@@ -5,4 +5,5 @@
 	verbose_name = 'Iconolab'
 
 	def ready(self):
-		import iconolab.signals.handlers
\ No newline at end of file
+		import iconolab.signals.handlers
+		import iconolab.templatetags.iconolab_tags
\ No newline at end of file
--- a/src/iconolab/forms/__init__.py	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/forms/__init__.py	Fri Jun 17 19:01:09 2016 +0200
@@ -1,8 +1,14 @@
-from django import forms
+from django.forms import ModelForm, HiddenInput
 from iconolab.models import Annotation
 
 
-class AnnotationForm(forms.ModelForm):
+class AnnotationForm(ModelForm):
 	class Meta:
 		model = Annotation
-		fields = ('title', 'description', 'fragment', 'tags',)
\ No newline at end of file
+		fields = ('title', 'description', 'fragment',)
+		widgets = {
+			'fragment': HiddenInput(),
+		}
+
+	def is_valid(self):
+		return True
\ No newline at end of file
--- a/src/iconolab/static/iconolab/js/components/cutout/index.js	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/static/iconolab/js/components/cutout/index.js	Fri Jun 17 19:01:09 2016 +0200
@@ -1,5 +1,7 @@
 
 var Snap = require('snapsvg');
+resizer = require("./resizer");
+console.log(resizer);
 
 /* custom plugin */
 Snap.plugin(function (Snap, Element, Paper, glob) {
@@ -25,8 +27,8 @@
 var canDraw = false;
 var rectZone = null;
 var PATH_COLOR = "#ff00ff";
-var READ_ONLY_STOKE = "";
-var READ_ONLY_FILL = "";
+var STROKE_COLOR = "red";
+var FILL_COLOR = "orange";
 
 var SELECTED_COLOR = "#ffff00";
 var FIRST_NODE_COLOR = "#FF0000";
@@ -39,6 +41,7 @@
 var drawingMode = RECT_MODE; //free
 var FREE_MODE = 'FREE';
 var availableModes = [RECT_MODE, FREE_MODE];
+var onChangeCallback = null;
 
 var getId = (function () {
 		var cpt = 0;
@@ -50,36 +53,29 @@
 		}
 	}());
 
-
-
-var pathToPoint = function (path) {
-
-};
-
 var handleRectPath = function (path) {
 	if (readOnly) {
 		paper.path(path).attr({ stroke:'red', opacity: 0.6});
 		return;
 	}
 
-	var pathInfos = Snap.parsePathString(path);
-	drawing_path = paper.path(path);
-	drawing_path.attr({stroke:'white', opacity: 0.4});
-	handlePathClosed();
+	var bbBox = Snap.path.getBBox(path);
+	rectZone = paper.rect(bbBox.x, bbBox.y, bbBox.width, bbBox.height);
+	rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6});
+	drawing_path = rectZone;
+	drawing_path.drag();
+	canDraw = false;
+	pathIsClosed = true;
+	resizer.apply_resize(paper, drawing_path);
 };
 
-var handlePathClosed = function () {
-	if (drawing_path) {
-		drawing_path.drag();
-	}
-}
 
 var handleFreePath = function (path) {
 
 	if (readOnly) {
 		
 		paper.path(path).attr({
-			stoke: 'orange',
+			stroke: 'orange',
 			fill: 'orange',
 			opacity: 0.5,
 		});
@@ -119,13 +115,7 @@
 	}
 	
 	path += (pathIsClosed) ? " Z": "";
-	
-	console.log("stra", updateCallback);
 
-	if (typeof updateCallback === 'function' && pathIsClosed) {
-		updateCallback();
-	}
-		
 	/* remove prev path */
 	if (drawing_path) {
 		drawing_path.remove();
@@ -134,8 +124,10 @@
 	drawing_path = paper.path(path);
 
 	drawing_path.attr({
-		stroke: "red",
-		opacity: 0.6
+		stroke: STROKE_COLOR,
+		"stroke-width": 3,
+		fill: "white",
+		opacity: 0.1
 	});
 	
 	/* bring all handler to front */
@@ -145,20 +137,27 @@
 		}
 	});
 
-	console.log("radical...", path);
-	console.log({isDragged: isDragged, enablePoint: enablePoint, pathIsClosed: pathIsClosed});
+	if (typeof updateCallback === 'function' && pathIsClosed) {
+		updateCallback();
+	}
+
+	if (!updateCallback && pathIsClosed) {
+		applyClosedStyle();	
+	}
 };
 
+var applyClosedStyle = function () {
+	drawing_path.attr({ fill: FILL_COLOR, strokeWidth: 1, opacity:.6 });
+} 
+
 var onClosePath = function () {
 	ENABLE_NEW_NODE = false;
-	/* Group path an handler - add remove_btn */
-	jQuery("#action-wrapper").show();
+	applyClosedStyle();
 };
 
 
 var onClickOnHandler = function (point, p, e) {
 	//close path
-	console.log("new click handler ...");
 	if (point.isFirst && pointData.length > 2) {
 		pathIsClosed = true;
 	}
@@ -240,8 +239,7 @@
 var createPoint = function (paper, x, y, pointData) {
 
 	var point = {x:x, y:y, id: getId()};
-	
-	/**/
+
 	if (pathIsClosed) {
 		updatePath(paper, onClosePath);
 		return;
@@ -274,7 +272,6 @@
 	});
 
 	paper.mousemove(function (e) {
-		console.log("icic. ... ");
 		if (drawingMode === FREE_MODE) { return; }
 		if (!canDraw) { return; }
 		var x, y;
@@ -311,9 +308,10 @@
 			x = currentPosition.x
 			y = currentPosition.y - height;
 		}
-		if(!x || !y) { return; }		
+		if(!x || !y) { return; }	
+
 		rectZone = paper.rect(x, y, width, height);
-		rectZone.attr({opacity: 0.4});
+		rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6});
 	});
 
 
@@ -343,36 +341,52 @@
 	setPath: function (pathString) {
 		/* redraw the path */
 		var pathInfos = pathString.split(';');
+		console.log(pathInfos);
 		if( availableModes.indexOf(pathInfos[1]) === -1) {
-			new Error("drawing mode: [" + pathInfos[1] + "] is not available");
+			/* We assume then it is a free path */
+			pathInfos[1] = "FREE"; 
 		}
 
 		this.setDrawingMode(pathInfos[1]);
-		if (pathInfos.length === 1) {
-			new Error("A drawing mode must be provided");
+		var pathData =pathInfos[0];
+
+		/* deal with path nomalization x = ImageWith/MaxXBound*/
+		var xRatio = paper.node.clientWidth / viewBoxBounds.X;
+		var yRatio = paper.node.clientHeight / viewBoxBounds.Y;
+		
+		if(isNaN(xRatio) || isNaN(yRatio)) {
+			new Error('Ratio should be a number.');
+		}
+
+		var transformMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
+		path = Snap.path.map(pathData, transformMatrix).toString();
+		
+		/* always close path */
+		if (path.search(/[z|Z]/gi) === -1 ) {
+			path += "Z";
 		}
 
 		if (pathInfos.length >= 2) {
-			var path = pathInfos[0];
 			if (pathInfos[1] === RECT_MODE) {
 				handleRectPath(path);
 			}
-			
+
 			if (pathInfos[1] === FREE_MODE) {
 				handleFreePath(path);
 			}
 		}
 	},
 
-	transform: function () {
-
-	},
-
-
 	setDrawingMode: function (mode) {
+		
 		if (availableModes.indexOf(mode) !== -1) {
 			drawingMode = mode;
 		}
+		console.log(onChangeCallback);
+		if (typeof onChangeCallback === "function") {
+			onChangeCallback(drawingMode);
+		}
+
 		this.clear();
 	},
 	
@@ -396,8 +410,6 @@
 		 	//drawing_path.getBBox().path.toString()
 		 	drawing_path.remove();
 		 }		
-		 
-
 
 		pointData = [];
 		startPoint = null;
@@ -425,28 +437,39 @@
 		var yRatio = viewBoxBounds.Y / paper.node.clientHeight;
 		
 		if(isNaN(xRatio) || isNaN(yRatio)) {
-			new Error('Ratio should be a number.');
+			new Error('ratio should be a number.');
 		}
 
 		var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
 		path = Snap.path.map(path, normalizeMatrix).toString();
-		path += ";" + drawingMode;
+		
+		/* save the type */
+		var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
+		if (path.search(/[z|Z]/gi) === -1) {
+			path += " Z";	
+		}
+		
+		path += type;
+
 		return path;
 	}
 };
 
+/* change to a component */
 module.exports = {
 
 	init: function(config) {
-		/* strange ... */
+
 		var mainImage = jQuery(config.wrapperId).find('img').eq(0);
 		var cutCanvas = jQuery(config.wrapperId).find('.cut-canvas').eq(0);
 		var path = jQuery(config.wrapperId).find('.image-path').eq(0);
 		
-		if (path.length) {
-			jQuery(cutCanvas).append(path);
+		if (typeof config.onDrawingModeChange === 'function') {
+			onChangeCallback = config.onDrawingModeChange;
 		}
-		
+		console.log(config);
+
+		onChangeCallback 
 		if (!cutCanvas.length) {
 			var cutCanvas = jQuery('<svg version="1.1"></svg>').addClass('cut-canvas');
 			jQuery(config.wrapperId).append(cutCanvas);
@@ -459,7 +482,7 @@
 		cutCanvas.css({
 			position: 'absolute', 
 			top: '0px', 
-			left: '15px', //margin from bootstrap
+			left: '15px',
 			marginLeft: 'auto',
 			marginRight: 'auto',
 			width: mainImage.width(),
@@ -473,7 +496,11 @@
 
 		paper = new Snap(cutCanvas.get(0));
 
-		/* handle drawin here */
+		if (path.length) {
+			jQuery(cutCanvas).append(path);
+			API.setPath(path.attr("d"));
+		}
+		
 		attachPointEvents(paper);
 		attachRectEvents(paper);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/static/iconolab/js/components/cutout/resizer.js	Fri Jun 17 19:01:09 2016 +0200
@@ -0,0 +1,42 @@
+/* Enabling us to resize a shape width a handler 
+	#http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types
+*/
+
+
+var Resizer = function (paper, shape) {
+	this.paper = paper;
+	this.shape = shape;
+
+	this.HANDLER_SIZE = 6;
+	this.states = {};
+	this.init();
+}
+
+var api = Resizer.prototype = {
+
+	init: function () {
+		alert(" radical - blaze ");
+		this.showHandlers();
+		this.bindEvents();
+	},
+
+	showHandlers: function () {
+		/* show handler here */
+		var bbox = this.shape.getBBox();
+		var handleX = bbox.x - this.HANDLER_SIZE/2;
+		var handleY = bbox.y - this.HANDLER_SIZE/2;
+		handler = this.paper.rect(handleX, handleY, this.HANDLER_SIZE, this.HANDLER_SIZE).attr({fill: 'red'});
+	},
+
+	bindEvents: function () {
+		this.shape.click(function () { alert("radical ..."); });
+		this.shape.drag();
+	}
+}
+
+module.exports = {
+
+	apply_resize : function (paper, rect) {
+		new Resizer(paper, rect);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/static/iconolab/js/components/snapplugins/index.js	Fri Jun 17 19:01:09 2016 +0200
@@ -0,0 +1,1 @@
+/* Snap svg box resizer plugins */
\ No newline at end of file
--- a/src/iconolab/static/iconolab/js/dist/bundle.js	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/static/iconolab/js/dist/bundle.js	Fri Jun 17 19:01:09 2016 +0200
@@ -70,6 +70,8 @@
 
 	
 	var Snap = __webpack_require__(2);
+	resizer = __webpack_require__(8);
+	console.log(resizer);
 
 	/* custom plugin */
 	Snap.plugin(function (Snap, Element, Paper, glob) {
@@ -95,8 +97,8 @@
 	var canDraw = false;
 	var rectZone = null;
 	var PATH_COLOR = "#ff00ff";
-	var READ_ONLY_STOKE = "";
-	var READ_ONLY_FILL = "";
+	var STROKE_COLOR = "red";
+	var FILL_COLOR = "orange";
 
 	var SELECTED_COLOR = "#ffff00";
 	var FIRST_NODE_COLOR = "#FF0000";
@@ -109,6 +111,7 @@
 	var drawingMode = RECT_MODE; //free
 	var FREE_MODE = 'FREE';
 	var availableModes = [RECT_MODE, FREE_MODE];
+	var onChangeCallback = null;
 
 	var getId = (function () {
 			var cpt = 0;
@@ -120,36 +123,29 @@
 			}
 		}());
 
-
-
-	var pathToPoint = function (path) {
-
-	};
-
 	var handleRectPath = function (path) {
 		if (readOnly) {
 			paper.path(path).attr({ stroke:'red', opacity: 0.6});
 			return;
 		}
 
-		var pathInfos = Snap.parsePathString(path);
-		drawing_path = paper.path(path);
-		drawing_path.attr({stroke:'white', opacity: 0.4});
-		handlePathClosed();
+		var bbBox = Snap.path.getBBox(path);
+		rectZone = paper.rect(bbBox.x, bbBox.y, bbBox.width, bbBox.height);
+		rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6});
+		drawing_path = rectZone;
+		drawing_path.drag();
+		canDraw = false;
+		pathIsClosed = true;
+		resizer.apply_resize(paper, drawing_path);
 	};
 
-	var handlePathClosed = function () {
-		if (drawing_path) {
-			drawing_path.drag();
-		}
-	}
 
 	var handleFreePath = function (path) {
 
 		if (readOnly) {
 			
 			paper.path(path).attr({
-				stoke: 'orange',
+				stroke: 'orange',
 				fill: 'orange',
 				opacity: 0.5,
 			});
@@ -189,13 +185,7 @@
 		}
 		
 		path += (pathIsClosed) ? " Z": "";
-		
-		console.log("stra", updateCallback);
-
-		if (typeof updateCallback === 'function' && pathIsClosed) {
-			updateCallback();
-		}
-			
+
 		/* remove prev path */
 		if (drawing_path) {
 			drawing_path.remove();
@@ -204,8 +194,10 @@
 		drawing_path = paper.path(path);
 
 		drawing_path.attr({
-			stroke: "red",
-			opacity: 0.6
+			stroke: STROKE_COLOR,
+			"stroke-width": 3,
+			fill: "white",
+			opacity: 0.1
 		});
 		
 		/* bring all handler to front */
@@ -215,20 +207,27 @@
 			}
 		});
 
-		console.log("radical...", path);
-		console.log({isDragged: isDragged, enablePoint: enablePoint, pathIsClosed: pathIsClosed});
+		if (typeof updateCallback === 'function' && pathIsClosed) {
+			updateCallback();
+		}
+
+		if (!updateCallback && pathIsClosed) {
+			applyClosedStyle();	
+		}
 	};
 
+	var applyClosedStyle = function () {
+		drawing_path.attr({ fill: FILL_COLOR, strokeWidth: 1, opacity:.6 });
+	} 
+
 	var onClosePath = function () {
 		ENABLE_NEW_NODE = false;
-		/* Group path an handler - add remove_btn */
-		jQuery("#action-wrapper").show();
+		applyClosedStyle();
 	};
 
 
 	var onClickOnHandler = function (point, p, e) {
 		//close path
-		console.log("new click handler ...");
 		if (point.isFirst && pointData.length > 2) {
 			pathIsClosed = true;
 		}
@@ -310,8 +309,7 @@
 	var createPoint = function (paper, x, y, pointData) {
 
 		var point = {x:x, y:y, id: getId()};
-		
-		/**/
+
 		if (pathIsClosed) {
 			updatePath(paper, onClosePath);
 			return;
@@ -344,7 +342,6 @@
 		});
 
 		paper.mousemove(function (e) {
-			console.log("icic. ... ");
 			if (drawingMode === FREE_MODE) { return; }
 			if (!canDraw) { return; }
 			var x, y;
@@ -381,9 +378,10 @@
 				x = currentPosition.x
 				y = currentPosition.y - height;
 			}
-			if(!x || !y) { return; }		
+			if(!x || !y) { return; }	
+
 			rectZone = paper.rect(x, y, width, height);
-			rectZone.attr({opacity: 0.4});
+			rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6});
 		});
 
 
@@ -413,36 +411,52 @@
 		setPath: function (pathString) {
 			/* redraw the path */
 			var pathInfos = pathString.split(';');
+			console.log(pathInfos);
 			if( availableModes.indexOf(pathInfos[1]) === -1) {
-				new Error("drawing mode: [" + pathInfos[1] + "] is not available");
+				/* We assume then it is a free path */
+				pathInfos[1] = "FREE"; 
 			}
 
 			this.setDrawingMode(pathInfos[1]);
-			if (pathInfos.length === 1) {
-				new Error("A drawing mode must be provided");
+			var pathData =pathInfos[0];
+
+			/* deal with path nomalization x = ImageWith/MaxXBound*/
+			var xRatio = paper.node.clientWidth / viewBoxBounds.X;
+			var yRatio = paper.node.clientHeight / viewBoxBounds.Y;
+			
+			if(isNaN(xRatio) || isNaN(yRatio)) {
+				new Error('Ratio should be a number.');
+			}
+
+			var transformMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
+			path = Snap.path.map(pathData, transformMatrix).toString();
+			
+			/* always close path */
+			if (path.search(/[z|Z]/gi) === -1 ) {
+				path += "Z";
 			}
 
 			if (pathInfos.length >= 2) {
-				var path = pathInfos[0];
 				if (pathInfos[1] === RECT_MODE) {
 					handleRectPath(path);
 				}
-				
+
 				if (pathInfos[1] === FREE_MODE) {
 					handleFreePath(path);
 				}
 			}
 		},
 
-		transform: function () {
-
-		},
-
-
 		setDrawingMode: function (mode) {
+			
 			if (availableModes.indexOf(mode) !== -1) {
 				drawingMode = mode;
 			}
+			console.log(onChangeCallback);
+			if (typeof onChangeCallback === "function") {
+				onChangeCallback(drawingMode);
+			}
+
 			this.clear();
 		},
 		
@@ -466,8 +480,6 @@
 			 	//drawing_path.getBBox().path.toString()
 			 	drawing_path.remove();
 			 }		
-			 
-
 
 			pointData = [];
 			startPoint = null;
@@ -495,28 +507,39 @@
 			var yRatio = viewBoxBounds.Y / paper.node.clientHeight;
 			
 			if(isNaN(xRatio) || isNaN(yRatio)) {
-				new Error('Ratio should be a number.');
+				new Error('ratio should be a number.');
 			}
 
 			var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
 			path = Snap.path.map(path, normalizeMatrix).toString();
-			path += ";" + drawingMode;
+			
+			/* save the type */
+			var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
+			if (path.search(/[z|Z]/gi) === -1) {
+				path += " Z";	
+			}
+			
+			path += type;
+
 			return path;
 		}
 	};
 
+	/* change to a component */
 	module.exports = {
 
 		init: function(config) {
-			/* strange ... */
+
 			var mainImage = jQuery(config.wrapperId).find('img').eq(0);
 			var cutCanvas = jQuery(config.wrapperId).find('.cut-canvas').eq(0);
 			var path = jQuery(config.wrapperId).find('.image-path').eq(0);
 			
-			if (path.length) {
-				jQuery(cutCanvas).append(path);
+			if (typeof config.onDrawingModeChange === 'function') {
+				onChangeCallback = config.onDrawingModeChange;
 			}
-			
+			console.log(config);
+
+			onChangeCallback 
 			if (!cutCanvas.length) {
 				var cutCanvas = jQuery('<svg version="1.1"></svg>').addClass('cut-canvas');
 				jQuery(config.wrapperId).append(cutCanvas);
@@ -529,7 +552,7 @@
 			cutCanvas.css({
 				position: 'absolute', 
 				top: '0px', 
-				left: '15px', //margin from bootstrap
+				left: '15px',
 				marginLeft: 'auto',
 				marginRight: 'auto',
 				width: mainImage.width(),
@@ -543,7 +566,11 @@
 
 			paper = new Snap(cutCanvas.get(0));
 
-			/* handle drawin here */
+			if (path.length) {
+				jQuery(cutCanvas).append(path);
+				API.setPath(path.attr("d"));
+			}
+			
 			attachPointEvents(paper);
 			attachRectEvents(paper);
 
@@ -555,7 +582,7 @@
 /* 2 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_0__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
+	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_0__;/*** IMPORTS FROM imports-loader ***/
 	(function() {
 	var fix = module.exports=0;
 
@@ -28707,5 +28734,52 @@
 	process.umask = function() { return 0; };
 
 
+/***/ },
+/* 8 */
+/***/ function(module, exports) {
+
+	/* Enabling us to resize a shape width a handler 
+		#http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types
+	*/
+
+
+	var Resizer = function (paper, shape) {
+		this.paper = paper;
+		this.shape = shape;
+
+		this.HANDLER_SIZE = 6;
+		this.states = {};
+		this.init();
+	}
+
+	var api = Resizer.prototype = {
+
+		init: function () {
+			alert(" radical - blaze ");
+			this.showHandlers();
+			this.bindEvents();
+		},
+
+		showHandlers: function () {
+			/* show handler here */
+			var bbox = this.shape.getBBox();
+			var handleX = bbox.x - this.HANDLER_SIZE/2;
+			var handleY = bbox.y - this.HANDLER_SIZE/2;
+			handler = this.paper.rect(handleX, handleY, this.HANDLER_SIZE, this.HANDLER_SIZE).attr({fill: 'red'});
+		},
+
+		bindEvents: function () {
+			this.shape.click(function () { alert("radical ..."); });
+			this.shape.drag();
+		}
+	}
+
+	module.exports = {
+
+		apply_resize : function (paper, rect) {
+			new Resizer(paper, rect);
+		}
+	}
+
 /***/ }
 /******/ ]);
\ No newline at end of file
--- a/src/iconolab/static/iconolab/js/package.json	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/static/iconolab/js/package.json	Fri Jun 17 19:01:09 2016 +0200
@@ -5,7 +5,7 @@
   "main": "main.js",
   "scripts": {
     "test": "run test",
-    "start": "webpack-dev-server --inline & webpack --progress --colors --watch",
+    "start": "webpack --progress --colors --watch",
     "build": "webpack -p"
   },
   "keywords": [
--- a/src/iconolab/templates/iconolab/edit_annotation.html	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/templates/iconolab/edit_annotation.html	Fri Jun 17 19:01:09 2016 +0200
@@ -5,22 +5,23 @@
 {% load thumbnail %}
 
 {% block content %}
-	<div id="drawing-zone" class="row" style="padding-top: 10px; border:1px solid red">
+
+	<div id="drawing-zone" class="row" style="padding-top: 10px; border:1px solid orange">
 		
 		<div v-show='!formView' class="editor-wrapper col-md-12">
 			<div class='col-md-2'>
 				<ul class="form-drawing-wrapper list-inline">
 					<p class='form-drawing pullright'><strong>Type de dessin</strong></p>
-					<li @click="setRectangleMode" v-bind:class="{ 'selected': isRect }" class='pull-md-left drawingModeBtn'>Rect.</li>
-					<li @click="setFreeMode" v-bind:class="{ 'selected': !isRect }" class='pull-md-left drawingModeBtn'>Libre</li>
+					<li @click="setDrawingMode('RECT')" v-bind:class="{ 'selected': isRect }" class='pull-md-right drawingModeBtn'>Rect.</li>
+					<li @click="setDrawingMode('FREE')" v-bind:class="{ 'selected': !isRect }" class='pull-md-right drawingModeBtn'>Libre</li>
 				</ul>
 
 				<ul class='form-drawing-wrapper list-inline'>
 					<p class='form-drawing pullright'><strong>Actions</strong></p>
 					
-					<li @click="clear" class='pull-md-left drawingModeBtn'><i class='fa fa-trash'></i> Effacer</li>
+					<li @click="clear" class='pull-md-right drawingModeBtn'><i class='fa fa-trash'></i> Effacer</li>
 
-					<li @click="save" class='pull-md-left drawingModeBtn'><i class='fa fa-plus'></i> Créer le fragment</li>
+					<li @click="save" class='pull-md-right drawingModeBtn'><i class='fa fa-plus'></i> Créer le fragment</li>
 				</ul>
 			</div>
 			
@@ -28,6 +29,7 @@
 				<div v-el:image id="iconolab-image-wrapper">
 					{% thumbnail annotation.image.media "x800" crop="center" as im %}
 	    				<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
+	    				<path class="image-path" d="{{ annotation.fragment }}"></path>
 					{% endthumbnail %}
 				</div>
 			</div>
@@ -62,10 +64,9 @@
 					{% endthumbnail %}
 				</div>
 				<ul class="inline">
-				<a @click="showEditor" class="showPointer"> <i class='fa fa-edit'></i> Editer le fragment</a>
-				<a v-show="!displayMask" @click="highLightZone" class="btn showPointer"> <i class='fa fa-eye-slash'></i> </a>
-				<a v-show="displayMask" @click="highLightZone" class="btn showPointer"> <i class='fa fa-eye-slash'></i> </a>
-
+					<li @click="showEditor" class="showPointer"> <i class='fa fa-edit'></i> Editer le fragment</li>
+					<li v-show="!displayMask" @click="highLightZone" class="showPointer"> <i class='fa fa-eye-slash'></i> Afficher la zone</li>
+					<li v-show="displayMask" @click="highLightZone" class="showPointer"> <i class='fa fa-eye-slash'></i> Masquer la zone</li>
 				</ul>
 			</div>
 
@@ -73,6 +74,7 @@
 				 <form method="POST" class="post-form">
 				 	{% csrf_token %}
         			{{ form.as_p }}
+        			<input v-model="normalizePath" type="hidden" name="fragment"></input>
         			<button type="submit" class="save btn btn-default">Enregister</button>
     			</form>
 			</div>
@@ -103,20 +105,28 @@
 			},
 
 			init: function () {
-				//this.mode = this.$options.MODE_RECT;
 				var self = this;
-				self.drawingComponent = iconolab.initCutoutComponent({ 
+				this.drawingComponent = iconolab.initCutoutComponent({ 
 					wrapperId: '#iconolab-image-wrapper',
 						actionWrapper: '#action-wrapper',
-						readOnly: false
-				}); 	
+						readOnly: false,
+						onDrawingModeChange: function (mode) {
+							self.$nextTick(function () {
+								self.setDrawingMode(mode, false);
+							});
+						}
+				});
 			},
 
 			methods: {
-				
-				setRectangleMode: function () {
-					this.mode = this.$options.MODE_RECT;
-					this.isRect = true;
+
+				setDrawingMode: function (mode, updateComponent) {
+					var updateComponent = (typeof updateComponent === "boolean") ? updateComponent: true;
+					this.mode = this.$options['MODE_' + mode];
+					this.isRect = (this.mode === this.$options.MODE_RECT) ? true: false;
+					if (updateComponent) {
+						this.drawingComponent.setDrawingMode(this.mode);
+					}
 				},
 
 				showEditor: function () {
@@ -135,12 +145,6 @@
 					//this.fragmentFill = "none";
 				},
 
-				setFreeMode:  function () {
-					this.mode = this.$options.MODE_FREE;
-					this.isRect = false;
-					this.drawingComponent.setDrawingMode(this.mode);
-				},
-				
 				displayEditedPath: function () {
 					/* path to save */
 					var normalizePath = this.drawingComponent.getPath();
--- a/src/iconolab/templates/iconolab/show_annotation.html	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/templates/iconolab/show_annotation.html	Fri Jun 17 19:01:09 2016 +0200
@@ -4,50 +4,36 @@
 
 {% load thumbnail %}
 
+{% load iconolab_tags %}
+
 {% block content %}
 	<div id="annotation-wrapper" class="row" style="border: 1px solid gray">
 		
 		<div v-show="formView" class="col-md-12">
-			
 			<div class="col-xs-6">
 				<div class="small-image-wrapper" style="position: relative">
 					{% thumbnail annotation.image.media "x300" crop="center" as im %}
-						<img v-el:small-image @click="showEditor" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
+						<img v-el:small-image src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
 
 						<svg width="{{ im.width }}" height="{{ im.height }}" version="1.1" style="position:absolute; top:0px; left: 0px">
-							
-							<defs>
-								<mask xmlns="http://www.w3.org/2000/svg" id="smallImage">
-									<rect x="0" y="0" width="{{ im.width }}", height="{{ im.height }}" fill="white"/>
-									<g v-bind:transform="transformMatrix">
-										<path v-bind:d="fragmentPath"></path>
-									</g>
-								</mask>	
-							</defs>
 
-							<g v-show="!displayMask" v-bind:transform="transformMatrix">
-								<path v-bind:d="fragmentPath" opacity="0.7" fill="orange"></path>
+							<g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
+								<path d="{{ annotation.fragment }}" opacity="0.7" fill="orange"></path>
 							</g>
 
-							<rect v-show="displayMask" v-el:small-mask x="0" y="0" mask="url(#smallImage)" opacity="0.7" fill="white" width="{{ im.width }}" height="{{ im.height }}"></rect>
 						</svg>
 						
 					{% endthumbnail %}
 				</div>
-				<ul class="inline">
-				<a @click="showEditor" class="showPointer"> <i class='fa fa-edit'></i> Editer le fragment</a>
-				<a v-show="!displayMask" @click="highLightZone" class="showPointer"> <i class='fa fa-eye-slash'></i>Masquer l'image</a>
-				<a v-show="displayMask" @click="highLightZone(1)" class="showPointer"> <i class='fa fa-eye-slash'></i>Afficher la zone</a>
-
-				</ul>
 			</div>
 
 			<div class='col-xs-6' style="">
-				title: {{ annotation.title }}
-				Description: {{ annotation.description }}
-				Tags: {{ annotation.tags }}
+				<p> <strong>Title:</strong> {{ annotation.title }}</p>
+				<p> <strong>Description:</strong> {{ annotation.description }}</p>
+				<p> <strong>Tags:</strong> {{ annotation.tags }}</p>
+				<p> <strong>Fragment:</strong> {{ annotation.fragment }}</p>
 
-				<a href="{% url 'annotation_edit' 1 %}">Editer</a>
+				<a href="{% url 'annotation_edit' annotation.id %}">Editer</a> | 
 				<a href="{% url 'annotation_edit' annotation.id %}">Proposer une révision</a>
 			</div>
 		</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templatetags/iconolab_tags.py	Fri Jun 17 19:01:09 2016 +0200
@@ -0,0 +1,25 @@
+from django.template import Library
+import sys
+
+register = Library()
+
+# {% transform_matrix 230 200 100 100 %}
+@register.simple_tag
+def transform_matrix(im_width=0, im_height=0, max_x=0, max_y=0):
+	try :
+		x_ratio = im_width / max_x
+		y_ratio = im_height / max_y
+		value_list = [x_ratio, 0, 0, y_ratio, 0, 0]
+		matrix = ','.join([str(v) for v in value_list])
+	except:
+		matrix = ""
+
+	return matrix
+
+def clean_path(path):
+	if not len(path):
+		return ""
+	else:
+		path_infos = path.split(';')
+		return path_infos[0] 
+		
\ No newline at end of file
--- a/src/iconolab/views.py	Thu Jun 16 12:31:27 2016 +0200
+++ b/src/iconolab/views.py	Fri Jun 17 19:01:09 2016 +0200
@@ -3,6 +3,7 @@
 from django.http import Http404
 from django.contrib.auth.decorators import login_required
 from .forms import AnnotationForm
+from pprint import pprint
 
 @login_required
 def index(request):
@@ -34,12 +35,10 @@
 	annotation = get_object_or_404(Annotation, pk=pk)
 
 	if request.method == 'POST':
-		Annotation_form = AnnotationForm(request.POST, instance=annotation)
-		Annotation_form = AnnotationForm()
-		if Annotation_form.is_valid():
-
-			#redirect to view
-			pass
+		annotation_form = AnnotationForm(request.POST, instance=annotation)
+		if annotation_form.is_valid():
+			annotation = annotation_form.save()
+			return redirect('iconolab.views.show_annotation', pk=pk)	
 	else:
 		Annotation_form = AnnotationForm(instance = annotation)