new zoomviewport
authorHarris Baptiste <harris.baptiste@iri.centrepompidou.fr>
Tue, 26 Jul 2016 14:37:43 +0200
changeset 80 9675cdd079df
parent 79 329606de509a (diff)
parent 77 89bfc5499455 (current diff)
child 81 c600162cc2cd
child 83 0d87dab6f3b0
new zoomviewport
src/iconolab/fixtures/demo_data_dump.json
src/iconolab/fixtures/dev_initial_data.json
src/iconolab/templates/iconolab/change_annotation.html
src/iconolab/templates/iconolab/detail_annotation.html
--- a/src/iconolab/static/iconolab/css/iconolab.css	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/css/iconolab.css	Tue Jul 26 14:37:43 2016 +0200
@@ -7,6 +7,11 @@
 .form-drawing-wrapper .selected {border: 1px solid orange; color: white; background-color: orange}
 .showPointer {cursor: pointer;}
 
+.zoom-action-list {padding-left:21px;}
+.zoomTarget-wrapper { padding: 0px;}
+#zoomTarget, .cut-canvas {border: 1px solid #C3C3C3; padding-top: 2px; padding-bottom: 2px}
+
+.no-padding {padding-left: 0; padding-right: 0;}
 .annotation-content{
 	margin-top: 15px;
 	margin-bottom: 15px;
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js	Tue Jul 26 14:37:43 2016 +0200
@@ -6,13 +6,21 @@
 	constructor (params) {
 		this.zoomFactor = 0.1 || params.zoomFactor;
 		this.paper = params.paper;
-		var width = parseInt(this.paper.select(".main-image").attr("width"));
-		var height = parseInt(this.paper.select(".main-image").attr("height"));
-		this.viewport = {width: width, height: height};
+		this.MIN_SIZE = 40;
+		this.imageWidth = parseInt(this.paper.select(".main-image").attr("width"));
+		this.imageHeight = parseInt(this.paper.select(".main-image").attr("height"));
+		
+		this.viewport = {
+			width: parseInt(this.paper.attr("width")),
+			height: parseInt(this.paper.attr("height"))
+		};
+
 		this.scale = 1;
+		this.paper.attr({stroke: 2, "fill": "blue" });
 		this.disableDrag = false;
-		this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height];
+		this.imgMinSize = Math.min(this.imageWidth, this.imageHeight);
 		this.lastPosition = []; 
+		this.updateViewBox([0 , 0, this.imageWidth, this.imageHeight], false);
 	}
 
 	testShowCenter (cx, cy) {
@@ -33,23 +41,20 @@
 	zoomIn () {
 
 		/* current center */
+		if ( this.scale === 9) { this.scale--; return; }
 		var currentCenterX = this.currentViewBox[0] + (this.currentViewBox[2] / 2);
 		var currentCenterY = this.currentViewBox[1] + (this.currentViewBox[3] / 2);
 		var scaleFactor = this.zoomFactor * this.scale;
-		var viewBoxW = this.viewport.width - (this.viewport.width * scaleFactor);
-		var viewBoxH = this.viewport.height - (this.viewport.height * scaleFactor);
+		var viewBoxW = this.imgMinSize - (this.imgMinSize * scaleFactor);  
+		var viewBoxH = viewBoxW;
 		
-		if (viewBoxW <= 0 && viewBoxH <=0) {
-			return false;
-		}
-
 		this.currentViewBox[0] = currentCenterX - viewBoxW / 2;
 		this.currentViewBox[1] = currentCenterY - viewBoxH / 2;
 
 		this.currentViewBox[2] = viewBoxW;
 		this.currentViewBox[3] = viewBoxH;
+		this.scale ++;
 		this.updateViewBox();
-		this.scale ++;
 	}
 	
 	updateViewBox (currentViewBox, notify) {
@@ -71,6 +76,9 @@
 			},
 			"zoomFactor": this.getZoomFactor(),
 			"viewport": this.viewport,
+			"currentScale": this.scale,
+			"imageSize": {width: this.imageWidth, height: this.imageHeight}, 
+			"minSize": Math.min(this.imageWidth, this.imageHeight),
 			"currentViewBox": this.currentViewBox.slice()
 		});
 	}
@@ -129,33 +137,31 @@
 
 	reset () {
 		this.scale = 1;
-		this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height];
+		this.currentViewBox = [0, 0, this.imageWidth, this.imageHeight];
 		this.updateViewBox();
 	}
 
 	zoomOut () {
-		if (this.scale === 1) { return false; }
-		
+		if (this.scale == 1) { 
+			return false; 
+		}
+
 		var currentCenterX = this.currentViewBox[0] + (this.currentViewBox[2] / 2);
 		var currentCenterY = this.currentViewBox[1] + (this.currentViewBox[3] / 2);
+		var scaleFactor = this.zoomFactor * (this.scale - 1);
 
-		var viewBoxW = this.currentViewBox[2] + (this.viewport.width * this.zoomFactor);
-		var viewBoxH = this.currentViewBox[3] + (this.viewport.height * this.zoomFactor);
-		if (viewBoxW >= this.viewport.width || viewBoxW >= this.viewport.height) {
-			return false;
-		}
+		var viewBoxW = this.imgMinSize - (this.imgMinSize * scaleFactor);
+		var viewBoxH = viewBoxW;
+
 		var topX = currentCenterX - viewBoxW / 2;
 		var topY = currentCenterY - viewBoxH / 2;
 
-		/* fix size */ 
-		this.currentViewBox[0] = topX;
+		this.currentViewBox[0] = topX; //deal with X and Y
 		this.currentViewBox[1] = topY; 
 		this.currentViewBox[2] = viewBoxW;
 		this.currentViewBox[3] = viewBoxH;
-
+		this.updateViewBox();
 		this.scale--;
-		this.updateViewBox();
-		
 	}
 }
 
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js	Tue Jul 26 14:37:43 2016 +0200
@@ -524,21 +524,20 @@
 		
 
 		cutCanvas.css({
-			position: 'absolute', 
+			/*position: 'absolute', 
 			top: '0px', 
-			left: '15px',
+			left: '15px',*/
 			marginLeft: 'auto',
 			marginRight: 'auto',
-			width: mainImage.attr('width'),
-			height: mainImage.attr('height'),
-			//viewBox: '0 0 100 100'
+			width: 850,
+			height: 850
 		});
 		
 		/* fix the container size */
-		jQuery(config.wrapperId).css({ 
+		/*jQuery(config.wrapperId).css({ 
 			width: mainImage.attr('width'),
 			height: parseInt(mainImage.attr('height')) + 5
-		});
+		});*/
 
 		if (typeof config.readOnly === 'boolean' && config.readOnly === true) {
 			readOnly = true;
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/typeahead/data.js	Tue Jul 26 12:09:09 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-export default function () {
-	return [{"id":1090217586,"id_str":"1090217586","name":"typeahead.js","screen_name":"typeahead","location":"","description":"A flexible JavaScript library that provides a strong foundation for building robust typeaheads. Brought to you by @TwitterOSS.","url":"http://t.co/OXnxPojaag","entities":{"url":{"urls":[{"url":"http://t.co/OXnxPojaag","expanded_url":"http://twitter.github.io/typeahead.js/","display_url":"twitter.github.io/typeahead.js/","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":1113,"friends_count":11,"listed_count":46,"created_at":"Mon Jan 14 21:36:30 +0000 2013","favourites_count":18,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":48,"lang":"en","status":{"created_at":"Sun Aug 24 04:54:18 +0000 2014","id":503404914001735700,"id_str":"503404914001735680","text":"If support for IE7 was dropped in future versions, would you be sad?","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]},"source":"<a href=\"https://about.twitter.com/products/tweetdeck\" rel=\"nofollow\">TweetDeck</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":5,"favorite_count":5,"favorited":false,"retweeted":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://pbs.twimg.com/profile_images/378800000017912577/de7d4a2860762bd2f7d7dbef3c2385ee_normal.gif","profile_image_url_https":"https://pbs.twimg.com/profile_images/378800000017912577/de7d4a2860762bd2f7d7dbef3c2385ee_normal.gif","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},{"id":628678010,"id_str":"628678010","name":"Typeahead Tim","screen_name":"TypeaheadTim","location":"","description":"But the problem is...","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":11,"friends_count":0,"listed_count":1,"created_at":"Fri Jul 06 20:01:21 +0000 2012","favourites_count":1,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":10,"lang":"en","status":{"created_at":"Mon May 06 03:19:05 +0000 2013","id":331246715204141060,"id_str":"331246715204141056","text":"RT @CharlieCroom: Spent the day converting Yale Travelogue to use Twitter @typeahead, and it looks badass if I may say so! Cc @vskarich @ja…","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"CharlieCroom","name":"Charlie Croom","id":311738663,"id_str":"311738663","indices":[3,16]},{"screen_name":"typeahead","name":"typeahead.js","id":1090217586,"id_str":"1090217586","indices":[74,84]},{"screen_name":"vskarich","name":"Veljko Skarich","id":24477185,"id_str":"24477185","indices":[126,135]},{"screen_name":"jashenson","name":"Jared Shenson, MD","id":18169340,"id_str":"18169340","indices":[136,140]},{"screen_name":"baygross","name":"Bay Gross","id":125711649,"id_str":"125711649","indices":[139,140]}],"urls":[]},"source":"<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter for  iPhone</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Mon May 06 02:50:00 +0000 2013","id":331239394591784960,"id_str":"331239394591784960","text":"Spent the day converting Yale Travelogue to use Twitter @typeahead, and it looks badass if I may say so! Cc @vskarich @jashenson @baygross","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"typeahead","name":"typeahead.js","id":1090217586,"id_str":"1090217586","indices":[56,66]},{"screen_name":"vskarich","name":"Veljko Skarich","id":24477185,"id_str":"24477185","indices":[108,117]},{"screen_name":"jashenson","name":"Jared Shenson, MD","id":18169340,"id_str":"18169340","indices":[118,128]},{"screen_name":"baygross","name":"Bay Gross","id":125711649,"id_str":"125711649","indices":[129,138]}],"urls":[]},"source":"<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":{"type":"Point","coordinates":[37.7721839,-122.4333896]},"coordinates":{"type":"Point","coordinates":[-122.4333896,37.7721839]},"place":{"id":"8d2591b0d50daf32","url":"https://api.twitter.com/1.1/geo/id/8d2591b0d50daf32.json","place_type":"neighborhood","name":"Lower Haight","full_name":"Lower Haight, San Francisco","country_code":"US","country":"United States","contained_within":[],"bounding_box":{"type":"Polygon","coordinates":[[[-122.43738204,37.76955102],[-122.42148192,37.76955102],[-122.42148192,37.77602004],[-122.43738204,37.77602004]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":1,"favorite_count":3,"favorited":false,"retweeted":false,"lang":"en"},"is_quote_status":false,"retweet_count":1,"favorite_count":0,"favorited":false,"retweeted":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://pbs.twimg.com/profile_images/2373863845/ttim_normal.png","profile_image_url_https":"https://pbs.twimg.com/profile_images/2373863845/ttim_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},{"id":214465198,"id_str":"214465198","name":"Typeaheads","screen_name":"q_typeaheads","location":"","description":"","url":"http://t.co/xWJmBbmPUC","entities":{"url":{"urls":[{"url":"http://t.co/xWJmBbmPUC","expanded_url":"http://www.quora.com/Typeaheads","display_url":"quora.com/Typeaheads","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":0,"friends_count":0,"listed_count":0,"created_at":"Thu Nov 11 13:33:36 +0000 2010","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":2,"lang":"en","status":{"created_at":"Sat Mar 03 19:25:24 +0000 2012","id":176025499447992320,"id_str":"176025499447992320","text":"RT @QuoraQuestions3: What are some autocomplete implementations? Answer: http://t.co/vfgVeFNC","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"QuoraQuestions3","name":"Quora Questions","id":207901281,"id_str":"207901281","indices":[3,19]}],"urls":[{"url":"http://t.co/vfgVeFNC","expanded_url":"http://qr.ae/RtvZr","display_url":"qr.ae/RtvZr","indices":[73,93]}]},"source":"<a href=\"http://www.quora.com/\" rel=\"nofollow\">Quora</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Sat Mar 03 19:23:30 +0000 2012","id":176025021511245820,"id_str":"176025021511245824","text":"What are some autocomplete implementations? Answer: http://t.co/vfgVeFNC","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"http://t.co/vfgVeFNC","expanded_url":"http://qr.ae/RtvZr","display_url":"qr.ae/RtvZr","indices":[52,72]}]},"source":"<a href=\"http://www.quora.com/\" rel=\"nofollow\">Quora</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":5,"favorite_count":0,"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},"is_quote_status":false,"retweet_count":5,"favorite_count":0,"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://pbs.twimg.com/profile_images/1164807343/logo_normal.png","profile_image_url_https":"https://pbs.twimg.com/profile_images/1164807343/logo_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},{"id":1084687550,"id_str":"1084687550","name":"Typeahead Testing","screen_name":"TypeaheadT","location":"","description":"","url":null,"entities":{"description":{"urls":[]}},"protected":true,"followers_count":0,"friends_count":0,"listed_count":0,"created_at":"Sun Jan 13 01:57:43 +0000 2013","favourites_count":0,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":0,"lang":"en","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_image_url_https":"https://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false},{"id":2938107041,"id_str":"2938107041","name":"angular-ui-typeahead","screen_name":"yasuka_158","location":"","description":"We use our original curation technology to create the hottest timeline all about angular-ui-typeahead. We also follow you back 100% guaranteed! #followback #ref","url":"http://t.co/kj0sCh8htQ","entities":{"url":{"urls":[{"url":"http://t.co/kj0sCh8htQ","expanded_url":"http://angular-ui-typeahead.newsin.tk","display_url":"angular-ui-typeahead.newsin.tk","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":0,"friends_count":0,"listed_count":0,"created_at":"Tue Dec 23 09:29:46 +0000 2014","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":62,"lang":"en","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_image_url_https":"https://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false},{"id":69295221,"id_str":"69295221","name":"typeahead","screen_name":"typeaheadd7f2s","location":"","description":"","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":7,"friends_count":26,"listed_count":0,"created_at":"Thu Aug 27 13:51:08 +0000 2009","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":0,"lang":"en","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_image_url_https":"https://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false},{"id":2312457006,"id_str":"2312457006","name":"Typeahead","screen_name":"TypeaheadBlog","location":"Florianópolis","description":"Social Media & Digital Marketing & Advertising News","url":"http://t.co/JNtddeVpId","entities":{"url":{"urls":[{"url":"http://t.co/JNtddeVpId","expanded_url":"http://www.Typeahead.com.br","display_url":"Typeahead.com.br","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":66,"friends_count":305,"listed_count":2,"created_at":"Sun Jan 26 20:53:47 +0000 2014","favourites_count":3,"utc_offset":-10800,"time_zone":"Brasilia","geo_enabled":false,"verified":false,"statuses_count":61,"lang":"en","status":{"created_at":"Tue Apr 22 23:01:52 +0000 2014","id":458742513042722800,"id_str":"458742513042722816","text":"@TypeaheadBlog presente no @OlhoCON !","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"TypeaheadBlog","name":"Typeahead","id":2312457006,"id_str":"2312457006","indices":[0,14]},{"screen_name":"OlhoCON","name":"OlhóCON 2015","id":241129288,"id_str":"241129288","indices":[27,35]}],"urls":[]},"source":"<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":2312457006,"in_reply_to_user_id_str":"2312457006","in_reply_to_screen_name":"TypeaheadBlog","geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":1,"favorited":false,"retweeted":false,"lang":"es"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://pbs.twimg.com/profile_images/428607539349966848/bvVKQImZ_normal.png","profile_image_url_https":"https://pbs.twimg.com/profile_images/428607539349966848/bvVKQImZ_normal.png","profile_banner_url":"https://pbs.twimg.com/profile_banners/2312457006/1390844887","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},{"id":927694424,"id_str":"927694424","name":"Saudi Hacker","screen_name":"dm_typeahead","location":"worldwide","description":"حسابي @SaudiHacker","url":"https://t.co/mpcg5agqyc","entities":{"url":{"urls":[{"url":"https://t.co/mpcg5agqyc","expanded_url":"https://twitter.com/dm_typeahead","display_url":"twitter.com/dm_typeahead","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":11,"friends_count":1,"listed_count":0,"created_at":"Mon Nov 05 14:12:08 +0000 2012","favourites_count":0,"utc_offset":10800,"time_zone":"Minsk","geo_enabled":false,"verified":false,"statuses_count":53,"lang":"ar","status":{"created_at":"Tue Jan 12 20:10:54 +0000 2016","id":687003843738087400,"id_str":"687003843738087425","text":"مراجعة الحاسب المحمول MSI GS60 6QE Ghost Pro https://t.co/uQojOi82Lm","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/uQojOi82Lm","expanded_url":"http://arabhardware.net/2016/01/12/131421/","display_url":"arabhardware.net/2016/01/12/131…","indices":[45,68]}]},"source":"<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"und"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":true,"profile_background_color":"000000","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://pbs.twimg.com/profile_images/723838966311563264/vQXodsYI_normal.jpg","profile_image_url_https":"https://pbs.twimg.com/profile_images/723838966311563264/vQXodsYI_normal.jpg","profile_link_color":"002211","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"000000","profile_text_color":"000000","profile_use_background_image":false,"has_extended_profile":false,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false}]
-}
\ No newline at end of file
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/typeahead/json-server-data.js	Tue Jul 26 12:09:09 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-function randomIntInc (low, high) {
-    return Math.floor(Math.random() * (high - low + 1) + low);
-}
-
-module.exports = function () {
-	
-	var tagList = { tags : [] };
-	for (var i = 0; i <= 10; i++ ) {
-		var tagItem = {};
-		tagItem.id = i + 1;
-		tagItem.name = "tag_no" + i;
-		tagItem.tag_input = "tag no" + i;
-		tagItem.accuracy = randomIntInc(1, 5);
-		tagItem.relevancy = randomIntInc(1, 5);
-		tagItem.type = "dbpedia";
-
-		//tagList.tags.push(tagItem);
-	}
-
-	return tagList;
-}
\ No newline at end of file
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js	Tue Jul 26 14:37:43 2016 +0200
@@ -1,11 +1,12 @@
 import EventEmitter from 'event-emitter' 
 var eventEmitter = EventEmitter({});
 
+
 var generateId = (function () {
 		var cpt = 0;
 		var defautPrefix = "item_"; 
 		return function (prefix) {
-			prefix = (typeof prefix === 'string') ? prefix : defautPrefix;
+			prefix = (typeof prefix === "string") ? prefix : defautPrefix;
 			cpt = cpt + 1;
 			return prefix + cpt; 
 		}
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue	Tue Jul 26 14:37:43 2016 +0200
@@ -3,21 +3,26 @@
 
 <script>
 
-import {eventEmitter} from '../utils'
+import {eventEmitter, computeElementSize} from '../utils'
 import ZoomHandler from '../cutout/snapsvg-zoom'
 
 import Snap from 'snapsvg'
 
 export default {
 
-	props: ['image-url', 'width', 'height', 'zoomTarget'],
+	props: ['image-url', 'image-width', 'image-height', 'zoomTarget', 'main-image-id'],
 	
 	mounted () {
 		this.root = new Snap(this.$refs['root-svg']);
 		this.handler = this.root.select('#zoom-handler');
 		this.image = this.root.select('#small-image');
-		//this.ratio = this.image.attr('width') / this.image.attr('height');
-		this.root.attr({width: this.width, height: this.height});
+		this.root.attr({width: 101, height: 101});
+		var imageWidth = parseInt(this.image.attr("width"));
+		var imageHeight = parseInt(this.image.attr("height"));
+		/* center image in the viewport */
+		this.root.attr({viewBox: [0, 0, imageWidth, imageHeight]});
+		this.imgMinSize = Math.min(imageWidth, imageHeight);
+
 		this.handlerSize = 20;
 		this.handler.attr({'width': this.handlerSize, 'height': this.handlerSize});
 		this.currentViewBox  = null;
@@ -39,12 +44,16 @@
 	methods: {
 		
 		setZoomTarget: function (zoomtarget) {
+			
 			if (zoomtarget.hasOwnProperty("type") && zoomtarget.type === 'svg') {
 				this.paper = zoomtarget; 	
+			} else {
+
+				this.paper = new Snap(zoomtarget);
+				var mainImage = this.paper.select("#" + this.mainImageId);
+				if (!mainImage) { throw new Error("A main image wasn't found."); };
 			}
-			else {
-				this.paper = new Snap(zoomtarget);
-			}
+
 			this.zoomHandler =  ZoomHandler.enable_zoom(this.paper);
 		},
 
@@ -115,8 +124,10 @@
 			 }});
 
 			if (!this.currentViewBox || !this.currentViewport || typeof this.updateFunction !== 'function') { return false; }
-			var xRatio = this.currentViewport.width / this.image.attr('width');
-			var yRatio = this.currentViewport.height / this.image.attr('height');
+
+			/*longueur image=> longueur viewbox */
+			var xRatio = this.currentImageSize.width / this.image.attr('width');
+			var yRatio = this.currentImageSize.height / this.image.attr('height');
 			var newX = x * xRatio;
 			var newY = y * yRatio;
 			this.currentViewBox[0] = newX;
@@ -126,7 +137,7 @@
 
 		handleZoomChanged: function (zoomInfos) {
 			
-			if (zoomInfos.zoomFactor.x === 1 && zoomInfos.zoomFactor.y === 1) { 
+			if (zoomInfos.currentScale === 1) { 
 				this.showHandler = false;
 				return; 
 			}
@@ -135,22 +146,16 @@
 
 			this.currentViewport = zoomInfos.viewport;
 			this.currentViewBox = zoomInfos.currentViewBox;
+			this.currentImageSize = zoomInfos.imageSize; 
 			this.updateFunction = zoomInfos.updateFunction;
-
-			var vpW = zoomInfos.viewport.width;
-			var vpH = zoomInfos.viewport.height;
+			var handlerSize = zoomInfos.currentViewBox[2] * this.imgMinSize / zoomInfos.minSize;
 			
-			/* handler size */
-			var minSize = Math.min(zoomInfos.currentViewBox[2], zoomInfos.currentViewBox[3]);
-			var HSize = minSize * Math.min(this.image.attr("width"),this.image.attr("height")) / Math.min(vpW,vpH);
-			this.handler.attr("width", HSize);
-			this.handler.attr("height", HSize);
-			//this.handler.attr("width", (zoomInfos.currentViewBox[2]) * this.image.attr("width") / vpW);
-			//this.handler.attr("height", (zoomInfos.currentViewBox[2]) * this.image.attr("width") / vpW);
+			this.handler.attr("width", handlerSize);
+			this.handler.attr("height", handlerSize);
 
 			/*compute handler x, y */
-			var x = zoomInfos.currentViewBox[0] * this.image.attr("width") / vpW;
-			var y = zoomInfos.currentViewBox[1] * this.image.attr("height")/ vpH;
+			var x = zoomInfos.currentViewBox[0] * this.image.attr("width") / zoomInfos.imageSize.width;
+			var y = zoomInfos.currentViewBox[1] * this.image.attr("height")/ zoomInfos.imageSize.height;
 			this.handler.transform( "T" + [x, y]);
 		} 
 	}
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html	Tue Jul 26 14:37:43 2016 +0200
@@ -9,12 +9,12 @@
 			y="0" 
 			xmlns:xlink="http://www.w3.org/1999/xlink" 
 			:xlink:href="imageUrl" 
-			:width="width" 
-			:height="height"></image>
-		<rect v-show="showHandler" id="zoom-handler" ref="handler" x="0" y="0" style="fill:orange; opacity:0.7"></rect>
+			:width="imageWidth" 
+			:height="imageHeight"></image>
+		<rect v-show="showHandler" id="zoom-handler" ref="handler" x="0" y="0" style="fill:black; opacity:0.4"></rect>
 	</svg>
 
-	<ul class="form-drawing-wrapper list-inline">
+	<ul class="form-drawing-wrapper zoom-action-list list-inline">
 		<li class="small showPointer" @click="incraseDrawingZoom"><i class="fa fa-search-plus"></i> </li>
 		<li class="small showPointer" @click="resetDrawingZoom"><i class="fa fa-square"></i> </li>
 		<li class="small showPointer" @click="decreaseDrawingZoom"><i class="fa fa-search-minus"></i> </li>
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/webpack.config.js	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/webpack.config.js	Tue Jul 26 14:37:43 2016 +0200
@@ -53,7 +53,8 @@
     }),
     new webpack.optimize.UglifyJsPlugin({
       compress: {
-        warnings: false
+        warnings: false,
+        minimize: true
       }
     }),
     new webpack.optimize.OccurenceOrderPlugin()
--- a/src/iconolab/templates/iconolab/change_annotation.html	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/templates/iconolab/change_annotation.html	Tue Jul 26 14:37:43 2016 +0200
@@ -7,7 +7,11 @@
 {% block content %}
 
 	<div id="drawing-zone" class="row" style="padding-top: 10px; padding-bottom: 10px; border:1px solid orange">
+		
 		<div v-show='!formView' style="display:none" class="editor-wrapper col-md-12">
+			<div class="col-md-12 no-padding">
+				<p @click="cancel" class="btn btn-link pull-right"><i class="fa fa-close"></i> Annuler</p>
+			</div>
 			<div class='col-md-2'>
 				<ul class="form-drawing-wrapper list-inline">
 					<p class='form-drawing pullright'><strong>Type de dessin</strong></p>
@@ -16,7 +20,7 @@
 				</ul>
 
 				{% thumbnail image.media "100x100" crop=False as im %}
-					<zoomview ref="zoomview" :image-url="'{{ im.url }}'" :width="{{ im.width }}" :height="{{ im.height }}">
+					<zoomview ref="zoomview" :image-url="'{{ im.url }}'" :image-width="{{ im.width }}" :image-height="{{ im.height }}">
 					</zoomview>
 				{% endthumbnail %}
 
@@ -29,21 +33,16 @@
 				</ul>
 			</div>
 			
-			<div class="col-md-8">
+			<div class="col-md-10">
 				<div ref="image" id="iconolab-image-wrapper">
 					{% thumbnail image.media "835x835" crop=False as im %}
-						<svg class="cut-canvas">
+						<svg class="cut-canvas" width="850" height="850">
 							<image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
 	    					<path class="image-path" d="{% if annotation %}{{ annotation.current_revision.fragment }}{% endif %}"></path>
 	    				</svg>
 					{% endthumbnail %}
 				</div>
 			</div>
-
-			<div class="col-md-2">
-				<a @click="cancel"><i class="fa fa-close"></i> Annuler</a>
-			</div>
-
 		</div>
 
 		<div v-show="formView" class="col-md-12">
--- a/src/iconolab/templates/iconolab/detail_annotation.html	Tue Jul 26 12:09:09 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_annotation.html	Tue Jul 26 14:37:43 2016 +0200
@@ -50,28 +50,22 @@
         </div>
         <!-- zoomView -->
         <div class="col-md-12 zoom-view" style="display:none" v-show="showZoom">
-          
+          <div class="col-md-12 no-padding"><p @click="toggleZoomView" class="btn btn-link pull-right"><i class="fa fa-close"></i></i> Fermer</p></div>
           <div class="col-md-2">
             {% thumbnail annotation.image.media "100x100" crop=False as im %}
-            <zoomview ref="zoomview" :zoomtarget="'zoomTarget'" :image-url="'{{ im.url }}'" :width="{{ im.width }}" :height="{{ im.height }}"></zoomview>
+            <zoomview ref="zoomview" main-image-id="main-image" zoomtarget="zoomTarget" :image-url="'{{ im.url }}'" :image-width="{{ im.width }}" :image-height="{{ im.height }}"></zoomview>
             {% endthumbnail %}
           </div>
-  
-          <div class="col-md-8">
-            {% thumbnail annotation.image.media "900x900" crop=False as im %}
-              <svg id="zoomTarget" ref="zoomTarget" width="{{ im.width }}" height="{{ im.height }}">
-                <image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
+          <div class="col-md-10 zoomTarget-wrapper">
+            {% thumbnail annotation.image.media "835x835" crop=False as im %}
+              <svg id="zoomTarget" ref="zoomTarget" width="920" height="920"> 
+                <image id="main-image" class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
                 <g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
                   <path d="{{ annotation.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
                 </g>
               </svg>
             {% endthumbnail %}
             </div>
-            <div class="col-md-2">
-              <p class="showPointer" @click="toggleZoomView">
-              <i class="fa fa-close"></i>Voir le détail</p>
-            
-            </div>
           </div>
 
 		</div>