client/js/paper-renderer.js
changeset 155 7d5f722d76b2
parent 154 0f87088e03bc
child 156 83d7a10e1ad7
--- a/client/js/paper-renderer.js	Fri Apr 12 19:10:40 2013 +0200
+++ b/client/js/paper-renderer.js	Mon Apr 15 18:36:59 2013 +0200
@@ -222,6 +222,8 @@
 
 Rkns.Renderer._BaseRepresentation.prototype.unhighlight = function() {}
 
+Rkns.Renderer._BaseRepresentation.prototype.mousedown = function() {}
+
 Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {}
 
 Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {
@@ -507,14 +509,17 @@
     }
 }
 
+Rkns.Renderer.Node.prototype.mousedown = function(_event, _isTouch) {
+	if (_isTouch) {
+		this.toggleSelect();
+	}
+}
+
 Rkns.Renderer.Node.prototype.mouseup = function(_event, _isTouch) {
     if (this.renderer.isEditable() && this.renderer.is_dragging) {
         this.saveCoords();
     } else {
-    	if (_isTouch) {
-    		this.toggleSelect();
-    		paper.view.draw();
-    	} else {
+    	if (!_isTouch) {
     		this.openEditor();
     	}
     }
@@ -679,22 +684,23 @@
 	}
 }
 
+Rkns.Renderer.Edge.prototype.mousedown = function(_event, _isTouch) {
+	if (_isTouch) {
+		this.toggleSelect();
+	}
+}
+
 Rkns.Renderer.Edge.prototype.mouseup = function(_event, _isTouch) {
-    if (!this.renkan.read_only) {
-        if (this.renderer.is_dragging) {
-            this.from_representation.saveCoords();
-            this.to_representation.saveCoords();
-            this.from_representation.is_dragging = false;
-            this.to_representation.is_dragging = false;
-        } else {
-	    	if (_isTouch) {
-	    		this.toggleSelect();
-	    		paper.view.draw();
-	    	} else {
-	    		this.openEditor();
-	    	}
+    if (!this.renkan.read_only && this.renderer.is_dragging) {
+        this.from_representation.saveCoords();
+        this.to_representation.saveCoords();
+        this.from_representation.is_dragging = false;
+        this.to_representation.is_dragging = false;
+    } else {
+    	if (!_isTouch) {
+    		this.openEditor();
     	}
-    }
+	}
     this.renderer.click_target = null;
     this.renderer.is_dragging = false;
 }
@@ -1234,6 +1240,19 @@
     this.text = "Link to another node";
 }
 
+Rkns.Renderer.NodeLinkButton.prototype.mousedown = function(_event, _isTouch) {
+    if (this.renderer.isEditable()) {
+	    var _off = this.renderer.canvas_$.offset(),
+	    	_point = new paper.Point([
+	            _event.pageX - _off.left,
+	            _event.pageY - _off.top
+	        ]);
+        this.renderer.click_target = null;
+        this.renderer.removeRepresentationsOfType("editor");
+        this.renderer.addTempEdge(this.source_representation, _point);
+    }
+}
+
 /* */
 
 Rkns.Renderer.NodeEnlargeButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
@@ -1301,6 +1320,8 @@
 }
 
 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
     this.renderer.removeRepresentationsOfType("editor");
     if (this.renderer.isEditable() && confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
         this.project.removeEdge(this.source_representation.model);
@@ -1332,10 +1353,6 @@
     this.canvas_$ = this.$.find(".Rk-Canvas");
     this.editor_$ = this.$.find(".Rk-Editor");
     this.notif_$ = this.$.find(".Rk-Notifications");
-    this.canvas_$.attr({
-    	width: this.canvas_$.width(),
-    	height: this.canvas_$.height()
-    })
     paper.setup(this.canvas_$[0]);
     this.scale = 1;
     this.offset = paper.view.center;
@@ -1413,7 +1430,8 @@
 	    },
 	    touchmove: function(_event) {
 	    	_event.preventDefault();
-	    	if (_event.originalEvent.scale == 1) {
+	    	if (typeof _event.originalEvent.scale === "undefined" || _event.originalEvent.scale == 1) {
+	    		// On Android, scale is undefined, so no zooming..
 	    		_this.onMouseMove(_event.originalEvent.changedTouches[0], true);
 	    	} else {
 	    		if (!_zooming) {
@@ -1422,8 +1440,12 @@
 			        _this.is_dragging = false;
 			        _zooming = true;
 	    		}
-	    		var _newScale = _event.originalEvent.scale * _originalScale;
-	    		//TODO: Correct Offset !
+	    		var _newScale = _event.originalEvent.scale * _originalScale,
+	    			_scaleRatio = _newScale / _this.scale,
+	    			_newOffset = new paper.Point([
+			            _this.canvas_$.width(),
+			            _this.canvas_$.height()
+			        ]).multiply( .5 * ( 1 - _scaleRatio ) ).add(_this.offset.multiply( _scaleRatio ));
 	    		_this.setScale(_newScale, _this.offset);
 	    	}
 	    },
@@ -1450,145 +1472,47 @@
 	    	_allowScroll = true;
 	    	_event.preventDefault();
 	    },
-    drop: function(_event) {
-    	_event.preventDefault();
-    	_allowScroll = true;
-    	if (!_this.isEditable()) {
-    		return;
-    	}
-    	var res = {};
-    	Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
-    		try {
-    			res[t] = _event.originalEvent.dataTransfer.getData(t);
-    		} catch(e) {}
-    	});
-		var text = _event.originalEvent.dataTransfer.getData("Text");
-		if (typeof text === "string") {
-			switch(text[0]) {
-    			case "{":
-    			case "[":
-    				try {
-    					var data = JSON.parse(text);
-    					_(res).extend(data);
-    				}
-    				catch(e) {
-    					if (!res["text/plain"]) {
-    						res["text/plain"] = text;
-    					}
-    				}
-				break;
-				case "<":
-					if (!res["text/html"]) {
-						res["text/html"] = text;
-					}
-				break;
-				default:
-					if (!res["text/plain"]) {
-						res["text/plain"] = text;
-					}
-    		}
-		}
-		var url = _event.originalEvent.dataTransfer.getData("URL");
-		if (url && !res["text/uri-list"]) {
-			res["text/uri-list"] = url;
-		}
-		if (res["text/json"] || res["application/json"]) {
-			try {
-				var data = JSON.parse(res["text/json"] || res["application/json"]);
-				_(res).extend(data);
+	    drop: function(_event) {
+	    	_event.preventDefault();
+	    	_allowScroll = true;
+	    	var res = {};
+	    	Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
+	    		try {
+	    			res[t] = _event.originalEvent.dataTransfer.getData(t);
+	    		} catch(e) {}
+	    	});
+			var text = _event.originalEvent.dataTransfer.getData("Text");
+			if (typeof text === "string") {
+				switch(text[0]) {
+	    			case "{":
+	    			case "[":
+	    				try {
+	    					var data = JSON.parse(text);
+	    					_(res).extend(data);
+	    				}
+	    				catch(e) {
+	    					if (!res["text/plain"]) {
+	    						res["text/plain"] = text;
+	    					}
+	    				}
+					break;
+					case "<":
+						if (!res["text/html"]) {
+							res["text/html"] = text;
+						}
+					break;
+					default:
+						if (!res["text/plain"]) {
+							res["text/plain"] = text;
+						}
+	    		}
 			}
-			catch(e) {}
-		}
-    	var newNode = {};
-    	switch(res["text/x-iri-specific-site"]) {
-    		case "twitter":
-    			var snippet = Rkns.$('<div>').html(res["text/x-iri-selected-html"]),
-    				tweetdiv = snippet.find(".tweet")
-    			newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
-    			newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
-    			newNode.image = tweetdiv.find(".avatar").attr("src");
-    			newNode.description = tweetdiv.find(".js-tweet-text:first").text();
-    		break;
-    		case "google":
-    			var snippet = Rkns.$('<div>').html(res["text/x-iri-selected-html"]);
-    			newNode.title = snippet.find("h3:first").text().trim();
-    			newNode.uri = snippet.find("h3 a").attr("href");
-    			newNode.description = snippet.find(".st:first").text().trim();
-    		break;
-    		case undefined:
-	    	default:
-		    	if (res["text/x-iri-source-uri"]) {
-		    		newNode.uri = res["text/x-iri-source-uri"];
-		    	}
-		    	if (res["text/plain"] || res["text/x-iri-selected-text"]) {
-		    		newNode.description = (res["text/plain"] || res["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
-		    	}
-		    	if (res["text/html"] || res["text/x-iri-selected-html"]) {
-		    		var snippet = Rkns.$('<div>').html(res["text/html"] || res["text/x-iri-selected-html"]);
-		    		var _imgs = snippet.find("img");
-		    		if (_imgs.length) {
-		    			newNode.image = _imgs[0].src;
-		    		}
-		    		var _as = snippet.find("a");
-		    		if (_as.length) {
-		    			newNode.uri = _as[0].href;
-		    		}
-		    		newNode.title = snippet.find("[title]").attr("title") || newNode.title;
-		    		newNode.description = snippet.text().replace(/[\s\n]+/gm,' ').trim();
-		    	}
-		    	if (res["text/uri-list"]) {
-		    		newNode.uri = res["text/uri-list"];
-		    	}
-		    	if (res["text/x-moz-url"] && !newNode.title) {
-		    		newNode.title = (res["text/x-moz-url"].split("\n")[1] || "").trim();
-		    		if (newNode.title === newNode.uri) {
-		    			newNode.title = false;
-		    		}
-		    	}
-		    	if (res["text/x-iri-source-title"] && !newNode.title) {
-		    		newNode.title = res["text/x-iri-source-title"];
-		    	}
-		    	if (res["text/html"] || res["text/x-iri-selected-html"]) {
-		    		newNode.image = snippet.find("[data-image]").attr("data-image") || newNode.image;
-		    		newNode.uri = snippet.find("[data-uri]").attr("data-uri") || newNode.uri;
-		    		newNode.title = snippet.find("[data-title]").attr("data-title") || newNode.title;
-		    		newNode.description = snippet.find("[data-description]").attr("data-description") || newNode.description;
-		    	}
-    	}
-    	var fields = ["title", "description", "uri", "image"];
-    	for (var i = 0; i < fields.length; i++) {
-    		var f = fields[i];
-    		if (res["text/x-iri-" + f] || res[f]) {
-    			newNode[f] = res["text/x-iri-" + f] || res[f];
-    		}
-    		if (newNode[f] === "none" || newNode[f] === "null") {
-    			newNode[f] = undefined;
-    		}
-    	}
-    	if (newNode.title || newNode.description || newNode.uri) {
-    		var _off = _this.canvas_$.offset(),
-            _point = new paper.Point([
-                _event.originalEvent.pageX - _off.left,
-                _event.originalEvent.pageY - _off.top
-            ]),
-            _coords = _this.toModelCoords(_point),
-            _data = {
-                id: Rkns.Utils.getUID('node'),
-                created_by: _this.renkan.current_user,
-                uri: newNode.uri || "",
-                title: newNode.title || _this.renkan.translate("Dragged resource"),
-                description: newNode.description || "",
-                image: newNode.image || "",
-                color: newNode.color || undefined,
-                position: {
-                    x: _coords.x,
-                    y: _coords.y
-                }
-            };
-        	var _node = _this.renkan.project.addNode(_data);
-            _this.getRepresentationByModel(_node).openEditor();
-    	}
-    }
+			var url = _event.originalEvent.dataTransfer.getData("URL");
+			if (url && !res["text/uri-list"]) {
+				res["text/uri-list"] = url;
+			}
+			_this.dropData(res, _event.originalEvent);
+	    }
     });
     this.editor_$.find(".Rk-ZoomOut").click(function() {
     	var _newScale = _this.scale * Math.SQRT1_2,
@@ -1725,7 +1649,7 @@
         _thRedraw();
     });
     this.renkan.project.on("change:title", function(_model, _title) {
-        var el = $(".Rk-PadTitle");
+        var el = _this.$.find(".Rk-PadTitle");
         if (el.is("input")) {
             if (el.val() !== _title) {
                 el.val(_title);
@@ -1735,6 +1659,26 @@
         }
     });
     
+    if (_renkan.options.size_bug_fix) {
+	    window.setTimeout(
+	    	function() {
+	    		var w = _this.$.width(),
+	    			h = _this.$.height();
+				if (_renkan.options.show_top_bar) {
+					h -= _this.$.find(".Rk-TopBar").height();
+				}
+				_this.canvas_$.attr({
+					width: w,
+					height: h
+				});
+				
+	    		paper.view.viewSize = new paper.Size([w, h]);
+	    		_this.autoScale();
+	    	},
+	    	500
+	    );
+    }
+    
     this.redraw();
     
     if (this.minimap) {
@@ -1756,8 +1700,8 @@
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"> </div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents">'
     + '<%-translate("Renkan \'Drag-to-Add\' bookmarklet")%></div></div></a>'
-    + '<div class="Rk-TopBar-Separator"></div></div>'
-    + '<% } } %>'
+    + '<div class="Rk-TopBar-Separator"></div>'
+    + '<% } %></div><% } %>'
     + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>"><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
     + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
@@ -2002,8 +1946,8 @@
     	_point = new paper.Point([
             _event.pageX - _off.left,
             _event.pageY - _off.top
-        ]);
-	var _delta = _point.subtract(this.last_point);
+        ]),
+        _delta = _point.subtract(this.last_point);
 	this.last_point = _point;
     if (!this.is_dragging && this.mouse_down && _delta.length > Rkns.Renderer._MIN_DRAG_DISTANCE) {
     	this.is_dragging = true;
@@ -2033,12 +1977,9 @@
         this.removeRepresentationsOfType("editor");
         this.is_dragging = false;
         var _hitResult = paper.project.hitTest(_point);
-        if (this.isEditable() && _hitResult && typeof _hitResult.item.__representation !== "undefined") {
+        if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
             this.click_target = _hitResult.item.__representation;
-            if (this.click_target.type === "Node-link-button") {
-                this.removeRepresentationsOfType("editor");
-                this.addTempEdge(this.click_target.source_representation, _point);
-            }
+            this.click_target.mousedown(_event, _isTouch);
         } else {
             this.click_target = null;
             if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
@@ -2069,6 +2010,7 @@
             this.click_mode = false;
         }
     }
+    paper.view.draw();
 }
 
 Rkns.Renderer.Scene.prototype.onMouseUp = function(_event, _isTouch) {
@@ -2089,9 +2031,9 @@
         this.is_dragging = false;
         if (_isTouch) {
         	this.unselectAll();
-        	paper.view.draw();
         }
     }
+    paper.view.draw();
 }
 
 Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {
@@ -2136,3 +2078,108 @@
     }
     paper.view.draw();
 }
+
+Rkns.Renderer.Scene.prototype.dropData = function(_data, _event) {
+	if (!this.isEditable()) {
+		return;
+	}
+	if (_data["text/json"] || _data["application/json"]) {
+		try {
+			var jsondata = JSON.parse(_data["text/json"] || _data["application/json"]);
+			_(_data).extend(jsondata);
+		}
+		catch(e) {}
+	}
+	var newNode = {};
+	switch(_data["text/x-iri-specific-site"]) {
+		case "twitter":
+			var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]),
+				tweetdiv = snippet.find(".tweet")
+			newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
+			newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
+			newNode.image = tweetdiv.find(".avatar").attr("src");
+			newNode.description = tweetdiv.find(".js-tweet-text:first").text();
+		break;
+		case "google":
+			var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]);
+			newNode.title = snippet.find("h3:first").text().trim();
+			newNode.uri = snippet.find("h3 a").attr("href");
+			newNode.description = snippet.find(".st:first").text().trim();
+		break;
+		case undefined:
+    	default:
+	    	if (_data["text/x-iri-source-uri"]) {
+	    		newNode.uri = _data["text/x-iri-source-uri"];
+	    	}
+	    	if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
+	    		newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
+	    	}
+	    	if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
+	    		var snippet = Rkns.$('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
+	    		var _imgs = snippet.find("img");
+	    		if (_imgs.length) {
+	    			newNode.image = _imgs[0].src;
+	    		}
+	    		var _as = snippet.find("a");
+	    		if (_as.length) {
+	    			newNode.uri = _as[0].href;
+	    		}
+	    		newNode.title = snippet.find("[title]").attr("title") || newNode.title;
+	    		newNode.description = snippet.text().replace(/[\s\n]+/gm,' ').trim();
+	    	}
+	    	if (_data["text/uri-list"]) {
+	    		newNode.uri = _data["text/uri-list"];
+	    	}
+	    	if (_data["text/x-moz-url"] && !newNode.title) {
+	    		newNode.title = (_data["text/x-moz-url"].split("\n")[1] || "").trim();
+	    		if (newNode.title === newNode.uri) {
+	    			newNode.title = false;
+	    		}
+	    	}
+	    	if (_data["text/x-iri-source-title"] && !newNode.title) {
+	    		newNode.title = _data["text/x-iri-source-title"];
+	    	}
+	    	if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
+	    		newNode.image = snippet.find("[data-image]").attr("data-image") || newNode.image;
+	    		newNode.uri = snippet.find("[data-uri]").attr("data-uri") || newNode.uri;
+	    		newNode.title = snippet.find("[data-title]").attr("data-title") || newNode.title;
+	    		newNode.description = snippet.find("[data-description]").attr("data-description") || newNode.description;
+	    	}
+	}
+	var fields = ["title", "description", "uri", "image"];
+	for (var i = 0; i < fields.length; i++) {
+		var f = fields[i];
+		if (_data["text/x-iri-" + f] || _data[f]) {
+			newNode[f] = _data["text/x-iri-" + f] || _data[f];
+		}
+		if (newNode[f] === "none" || newNode[f] === "null") {
+			newNode[f] = undefined;
+		}
+	}
+	if (newNode.title || newNode.description || newNode.uri) {
+		var _off = this.canvas_$.offset(),
+        _point = new paper.Point([
+            _event.pageX - _off.left,
+            _event.pageY - _off.top
+        ]),
+        _coords = this.toModelCoords(_point),
+        _nodedata = {
+            id: Rkns.Utils.getUID('node'),
+            created_by: this.renkan.current_user,
+            uri: newNode.uri || "",
+            title: newNode.title || this.renkan.translate("Dragged resource"),
+            description: newNode.description || "",
+            image: newNode.image || "",
+            color: newNode.color || undefined,
+            position: {
+                x: _coords.x,
+                y: _coords.y
+            }
+        };
+    	var _node = this.renkan.project.addNode(_nodedata),
+    		_repr = this.getRepresentationByModel(_node);
+    	if (_event.type === "drop") {
+        	_repr.openEditor();
+        }
+	}
+}