client/js/paper-renderer.js
changeset 70 47b3125130a2
parent 69 f0873867143a
child 72 dbd90c784424
equal deleted inserted replaced
69:f0873867143a 70:47b3125130a2
    28         color: "#000000",
    28         color: "#000000",
    29         title: "(unknown user)",
    29         title: "(unknown user)",
    30         get: function(attr) {
    30         get: function(attr) {
    31             return this[attr] || false;
    31             return this[attr] || false;
    32         }
    32         }
       
    33     },
       
    34     _BOOKMARKLET_CODE: function(_renkan) {
       
    35     	return "(function(a,b,c,d,e,f,h,i,j,l,m,n,o,p,q,r){a=document;b=a.body;c=a.location.href;j='draggable';m='text/x-iri-';d=a.createElement('div');d.innerHTML='<p_style=\"position:fixed;top:0;right:0;font:bold_18px_sans-serif;color:#fff;background:#909;padding:10px;z-index:100000;\">"
       
    36 	    + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
       
    37 	    + "</p>'.replace(/_/g,String.fromCharCode(32));b.appendChild(d);e=[{r:/https?:\\/\\/[^\\/]*twitter\\.com\\//,s:'.tweet',n:'twitter'},{r:/https?:\\/\\/[^\\/]*google\\.[^\\/]+\\//,s:'.g',n:'google'},{r:/^http:\\/\\/ldt\\.iri\\.centrepompidou\\.fr/,s:'.Ldt-AnnotationsList-li,.Ldt-Polemic-TweetDiv,.Ldt-Segments-Segment',n:'ldt'}];f=false;e.forEach(function(g){if(g.r.test(c)){f=g;}});if(f){h=function(){Array.prototype.forEach.call(a.querySelectorAll(f.s),function(i){i[j]=true})};window.setInterval(h,500);h();};a.addEventListener('dragstart',function(k){l=k.dataTransfer;l.setData(m+'source-uri',c);l.setData(m+'source-title',a.title);n=k.target;if(f){o=n;while(!o.attributes[j]){o=o.parentNode;if(o==b){break;}}}if(f&&o.attributes[j]){p=o.cloneNode(true);l.setData(m+'specific-site',f.n)}else{q=a.getSelection();if(q.type==='Range'||!q.type){p=q.getRangeAt(0).cloneContents();}else{p=n.cloneNode();}}r=a.createElement('div');r.appendChild(p);l.setData('text/x-iri-selected-text',r.textContent.trim());l.setData('text/x-iri-selected-html',r.innerHTML);},false);})();"
    33     }
    38     }
    34 }
    39 }
    35 
    40 
    36 Rkns.Renderer.Utils = {
    41 Rkns.Renderer.Utils = {
    37     drawEditBox : function(_coords, _path, _width, _xmargin, _selector) {
    42     drawEditBox : function(_coords, _path, _width, _xmargin, _selector) {
   670         .hide();
   675         .hide();
   671 }
   676 }
   672 
   677 
   673 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
   678 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
   674     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Node")%></span></h2>'
   679     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Node")%></span></h2>'
   675     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%=node.title%>"/></p>'
   680     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
   676     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%=node.uri%>"/><a class="Rk-Edit-Goto" href="<%=node.uri%>" target="_blank"></a></p>'
   681     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-node.uri%>"/><a class="Rk-Edit-Goto" href="<%-node.uri%>" target="_blank"></a></p>'
   677     + '<p><label><%-translate("Description:")%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
   682     + '<p><label><%-translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p>'
   678     + '<p><span class="Rk-Editor-Label"><%-translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%=node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p>'
   683     + '<p><span class="Rk-Editor-Label"><%-translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%-node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p>'
   679     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%=node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   684     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   680     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   685     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   681     + '<img class="Rk-Edit-ImgPreview" src="<%=node.image || node.image_placeholder%>" />'
   686     + '<img class="Rk-Edit-ImgPreview" src="<%-node.image || node.image_placeholder%>" />'
   682     + '<p><label><%-translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%=node.image%>"/></p>'
   687     + '<p><label><%-translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
   683     + '<p><label><%-translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p>'    
   688     + '<p><label><%-translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p>'    
   684     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%=node.created_by_color%>;"></span><%=node.created_by_title%></p>'
   689     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%-node.created_by_title%></p>'
   685 );
   690 );
   686 
   691 
   687 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
   692 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
   688     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%=node.color%>;"></span><%-node.title%></span></h2>'
   693     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><%-node.title%></span></h2>'
   689     + '<p><a href="<%-node.uri%>" target="_blank"><%-node.uri%></a></p>'
   694     + '<p><a href="<%-node.uri%>" target="_blank"><%-node.uri%></a></p>'
   690     + '<p><%-node.description%></p>'
   695     + '<p><%-node.description%></p>'
   691     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%=node.created_by_color%>;"></span><%=node.created_by_title%></p>'
   696     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%-node.created_by_title%></p>'
   692 );
   697 );
   693 
   698 
   694 Rkns.Renderer.NodeEditor.prototype.draw = function() {
   699 Rkns.Renderer.NodeEditor.prototype.draw = function() {
   695     var _model = this.node_representation.model,
   700     var _model = this.node_representation.model,
   696         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER,
   701         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER,
   826         .hide();
   831         .hide();
   827 }
   832 }
   828 
   833 
   829 Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template(
   834 Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template(
   830     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Edge")%></span></h2>'
   835     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Edge")%></span></h2>'
   831     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%=edge.title%>"/></p>'
   836     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
   832     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%=edge.uri%>"/><a class="Rk-Edit-Goto" href="<%=edge.uri%>" target="_blank"></a></p>'
   837     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-edge.uri%>"/><a class="Rk-Edit-Goto" href="<%-edge.uri%>" target="_blank"></a></p>'
   833     + '<% if (properties.length) { %><p><label><%-translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
   838     + '<% if (properties.length) { %><p><label><%-translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
   834     + '<% _(properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- translate(ontology.label) %></option>'
   839     + '<% _(properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- translate(ontology.label) %></option>'
   835     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
   840     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
   836     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- translate(property.label) %></option>'
   841     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- translate(property.label) %></option>'
   837     + '<% }) %><% }) %></select></p><% } %>'
   842     + '<% }) %><% }) %></select></p><% } %>'
   838     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Edge color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%=edge.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   843     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Edge color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-edge.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   839     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   844     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   840     + '<p><span class="Rk-Editor-Label"><%-translate("From:")%></span><span class="Rk-UserColor" style="background:<%=edge.from_color%>;"></span><%=edge.from_title%></p>'
   845     + '<p><span class="Rk-Editor-Label"><%-translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%-edge.from_title%></p>'
   841     + '<p><span class="Rk-Editor-Label"><%-translate("To:")%></span><span class="Rk-UserColor" style="background:<%=edge.to_color%>;"></span><%=edge.to_title%></p>'
   846     + '<p><span class="Rk-Editor-Label"><%-translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%-edge.to_title%></p>'
   842     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%=edge.created_by_color%>;"></span><%=edge.created_by_title%></p>'
   847     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%-edge.created_by_title%></p>'
   843 );
   848 );
   844 
   849 
   845 Rkns.Renderer.EdgeEditor.prototype.readOnlyTemplate = Rkns._.template(
   850 Rkns.Renderer.EdgeEditor.prototype.readOnlyTemplate = Rkns._.template(
   846     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%=edge.color%>;"></span><%- edge.title %></span></h2>'
   851     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><%- edge.title %></span></h2>'
   847     + '<p><a href="<%-edge.uri%>" target="_blank"><%-edge.uri%></a></p>'
   852     + '<p><a href="<%-edge.uri%>" target="_blank"><%-edge.uri%></a></p>'
   848     + '<p><%-edge.description%></p>'
   853     + '<p><%-edge.description%></p>'
   849     + '<p><span class="Rk-Editor-Label"><%-translate("From:")%></span><span class="Rk-UserColor" style="background:<%=edge.from_color%>;"></span><%=edge.from_title%></p>'
   854     + '<p><span class="Rk-Editor-Label"><%-translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%-edge.from_title%></p>'
   850     + '<p><span class="Rk-Editor-Label"><%-translate("To:")%></span><span class="Rk-UserColor" style="background:<%=edge.to_color%>;"></span><%=edge.to_title%></p>'
   855     + '<p><span class="Rk-Editor-Label"><%-translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%-edge.to_title%></p>'
   851     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%=edge.created_by_color%>;"></span><%=edge.created_by_title%></p>'
   856     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%-edge.created_by_title%></p>'
   852 );
   857 );
   853 
   858 
   854 Rkns.Renderer.EdgeEditor.prototype.draw = function() {
   859 Rkns.Renderer.EdgeEditor.prototype.draw = function() {
   855     var _model = this.edge_representation.model,
   860     var _model = this.edge_representation.model,
   856         _from_model = _model.get("from"),
   861         _from_model = _model.get("from"),
  1169     this.sector.destroy();
  1174     this.sector.destroy();
  1170 }
  1175 }
  1171 
  1176 
  1172 /* */
  1177 /* */
  1173 
  1178 
       
  1179 Rkns.Renderer.MiniFrame = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
       
  1180 
       
  1181 Rkns.Renderer.MiniFrame.prototype.paperShift = function(_delta) {
       
  1182 	this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
       
  1183     this.renderer.resetCoords();
       
  1184     this.renderer.redraw();
       
  1185 }
       
  1186 
       
  1187 Rkns.Renderer.MiniFrame.prototype.mouseup = function(_delta) {
       
  1188 	this.renderer.click_target = null;
       
  1189     this.renderer.is_dragging = false;
       
  1190 }
       
  1191 
       
  1192 /* */
       
  1193 
  1174 Rkns.Renderer.Scene = function(_renkan) {
  1194 Rkns.Renderer.Scene = function(_renkan) {
  1175     this.renkan = _renkan;
  1195     this.renkan = _renkan;
  1176     this.$ = Rkns.$(".Rk-Render");
  1196     this.$ = Rkns.$(".Rk-Render");
  1177     this.representations = [];
  1197     this.representations = [];
  1178     this.$.html(this.template(_renkan));
  1198     this.$.html(this.template(_renkan));
  1201     this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4]));
  1221     this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4]));
  1202     this.minimap.rectangle.fillColor = '#ffffff';
  1222     this.minimap.rectangle.fillColor = '#ffffff';
  1203     this.minimap.rectangle.strokeColor = '#cccccc';
  1223     this.minimap.rectangle.strokeColor = '#cccccc';
  1204     this.minimap.rectangle.strokeWidth = 4;
  1224     this.minimap.rectangle.strokeWidth = 4;
  1205     this.minimap.offset = new paper.Point(this.minimap.size.divide(2));
  1225     this.minimap.offset = new paper.Point(this.minimap.size.divide(2));
  1206     this.minimap.scale = .25;
  1226     this.minimap.scale = .1;
  1207     
  1227     
  1208     this.node_layer.activate();
  1228     this.node_layer.activate();
  1209     this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
  1229     this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
  1210     this.minimap.node_group.addChild(this.minimap.cliprectangle);
  1230     this.minimap.node_group.addChild(this.minimap.cliprectangle);
  1211     this.minimap.node_group.clipped = true;
  1231     this.minimap.node_group.clipped = true;
  1212     this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
  1232     this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
  1213     this.minimap.node_group.addChild(this.minimap.miniframe);
  1233     this.minimap.node_group.addChild(this.minimap.miniframe);
  1214     this.minimap.miniframe.fillColor = '#f0f0ff';
  1234     this.minimap.miniframe.fillColor = '#f0f0ff';
  1215     this.minimap.miniframe.strokeColor = '#8080ff';
  1235     this.minimap.miniframe.strokeColor = '#8080ff';
  1216     this.minimap.miniframe.strokeWidth = 2;
  1236     this.minimap.miniframe.strokeWidth = 2;
       
  1237     this.minimap.miniframe.__representation = new Rkns.Renderer.MiniFrame(this, null);
  1217     
  1238     
  1218     this.bundles = [];
  1239     this.bundles = [];
  1219     this.click_mode = false;
  1240     this.click_mode = false;
  1220     var _tool = new paper.Tool(),
  1241     var _tool = new paper.Tool(),
  1221         _this = this;
  1242         _this = this,
       
  1243         _allowScroll = true;
       
  1244     
  1222     _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
  1245     _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
  1223     _tool.onMouseMove = function(_event) {
  1246     _tool.onMouseMove = function(_event) {
  1224         _this.onMouseMove(_event);
  1247         _this.onMouseMove(_event);
  1225     }
  1248     }
  1226     _tool.onMouseDown = function(_event) {
  1249     _tool.onMouseDown = function(_event) {
  1231     }
  1254     }
  1232     this.canvas_$.mouseup(function(_event) {
  1255     this.canvas_$.mouseup(function(_event) {
  1233         _this.onMouseUp(_event);
  1256         _this.onMouseUp(_event);
  1234     });
  1257     });
  1235     this.canvas_$.mousewheel(function(_event, _delta) {
  1258     this.canvas_$.mousewheel(function(_event, _delta) {
  1236         _this.onScroll(_event, _delta);
  1259         if (_allowScroll) {
       
  1260         	_this.onScroll(_event, _delta);
       
  1261         }
  1237     });
  1262     });
  1238     this.canvas_$.dblclick(function(_event) {
  1263     this.canvas_$.dblclick(function(_event) {
  1239         _this.onDoubleClick(_event);
  1264         _this.onDoubleClick(_event);
  1240     });
  1265     });
  1241     this.canvas_$.on("dragover", function(_event) {
  1266     this.canvas_$.on("dragover", function(_event) {
  1242     	_event.stopPropagation();
  1267     	_event.stopPropagation();
  1243     	_event.preventDefault();
  1268     	_event.preventDefault();
  1244     })
  1269     });
       
  1270     this.canvas_$.on("dragenter", function(_e) {
       
  1271     	_allowScroll = false;
       
  1272     });
       
  1273     this.canvas_$.on("dragleave", function(_e) {
       
  1274     	_allowScroll = true;
       
  1275     });
  1245     this.canvas_$.on("drop", function(_event) {
  1276     this.canvas_$.on("drop", function(_event) {
  1246     	_event.stopPropagation();
  1277     	_event.stopPropagation();
  1247     	_event.preventDefault();
  1278     	_event.preventDefault();
       
  1279     	_allowScroll = true;
  1248     	if (_this.renkan.read_only) {
  1280     	if (_this.renkan.read_only) {
  1249     		return;
  1281     		return;
  1250     	}
  1282     	}
  1251     	var res = {}
  1283     	var res = {}
  1252     	Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
  1284     	Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
  1253     		return res[t] = _event.originalEvent.dataTransfer.getData(t);
  1285     		return res[t] = _event.originalEvent.dataTransfer.getData(t);
  1254     	});
  1286     	});
  1255     	var newNode = {};
  1287     	var newNode = {};
  1256     	if (res["text/x-iri-source-uri"]) {
  1288     	console.log(res);
  1257     		newNode.uri = res["text/x-iri-source-uri"];
  1289     	switch(res["text/x-iri-specific-site"]) {
  1258     	}
  1290     		case "twitter":
  1259     	if (res["text/plain"]) {
  1291     			var snippet = Rkns.$('<div>').html(res["text/x-iri-selected-html"]),
  1260     		newNode.description = res["text/plain"].replace(/[\s\n]+/gm,' ').trim();
  1292     				tweetdiv = snippet.find(".tweet")
  1261     	}
  1293     			newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
  1262     	if (res["text/html"]) {
  1294     			newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
  1263     		var snippet = Rkns.$('<div>').html(res["text/html"]);
  1295     			newNode.image = tweetdiv.find(".avatar").attr("src");
  1264     		newNode.image = snippet.find("img").attr("src") || '';
  1296     			newNode.description = tweetdiv.find(".js-tweet-text:first").text();
  1265     		newNode.uri = snippet.find("a").attr("href") || newNode.uri;
  1297     		break;
  1266     		newNode.title = snippet.find("[title]").attr("title");
  1298     		case "google":
  1267     	}
  1299     			var snippet = Rkns.$('<div>').html(res["text/x-iri-selected-html"]);
  1268     	if (res["text/uri-list"]) {
  1300     			newNode.title = snippet.find("h3:first").text().trim();
  1269     		newNode.uri = res["text/uri-list"];
  1301     			newNode.uri = snippet.find("h3 a").attr("href");
  1270     	}
  1302     			newNode.description = snippet.find(".st:first").text().trim();
  1271     	if (res["text/x-moz-url"] && !newNode.title) {
  1303     		break;
  1272     		newNode.title = (res["text/x-moz-url"].split("\n")[1] || "").trim();
  1304     		case "ldt":
  1273     		if (newNode.title === newNode.uri) {
  1305     			var snippet = Rkns.$('<div>').html(res["text/x-iri-selected-html"]),
  1274     			newNode.title = false;
  1306     				tweetel = snippet.children().first();
  1275     		}
  1307 				if (tweetel.hasClass("Ldt-AnnotationsList-li")) {
  1276     	}
  1308 					newNode.title = tweetel.find(".Ldt-AnnotationsList-Title").text().trim();
  1277     	if (res["text/x-iri-source-title"] && !newNode.title) {
  1309 					newNode.description = tweetel.find(".Ldt-AnnotationsList-Description").text().trim();
  1278     		newNode.title = res["text/x-iri-source-title"];
  1310 					newNode.image = tweetel.find(".Ldt-AnnotationsList-Thumbnail").attr("src");
       
  1311 					var url = tweetel.find("a").attr("href");
       
  1312 					if (/^https?:\/\//.test(url)) {
       
  1313 						newNode.uri = url;
       
  1314 					} else {
       
  1315 						newNode.uri = res["text/x-iri-source-uri"].replace(/#.*$/,'') + '#' + url.replace(/^.*#/,'')
       
  1316 					}
       
  1317 					newNode.color = tweetel[0].style.backgroundColor;
       
  1318 				}
       
  1319 				if (tweetel.hasClass("Ldt-Polemic-TweetDiv")) {
       
  1320 					newNode.title = _renkan.translate("Annotation from PolemicTweet");
       
  1321 					newNode.uri = res["text/x-iri-source-uri"].replace(/#.*$/,'') + '#id=' + tweetel.attr("annotation-id");
       
  1322 					newNode.description = tweetel.attr("tweet-title");
       
  1323 					newNode.color = tweetel.attr("polemic-color");
       
  1324 				}
       
  1325 				if (tweetel.hasClass("Ldt-Segments-Segment")) {
       
  1326 					var text = tweetel.attr("segment-text").split(/<[^>]+>/g);
       
  1327 					newNode.title = text[0];
       
  1328 					newNode.description = text.slice(1).join("");
       
  1329 					
       
  1330 					newNode.uri = res["text/x-iri-source-uri"].replace(/#.*$/,'');
       
  1331 					var match = tweetel.attr("trace-info").match(/segment-id:([\d\w_-]+)/);
       
  1332 					if (match) {
       
  1333 						 newNode.uri += '#id=' + match[1];
       
  1334 					}
       
  1335 					newNode.color = tweetel.attr("data-base-color");
       
  1336 				}
       
  1337     		break;
       
  1338     		case undefined:
       
  1339 	    	default:
       
  1340 		    	if (res["text/x-iri-source-uri"]) {
       
  1341 		    		newNode.uri = res["text/x-iri-source-uri"];
       
  1342 		    	}
       
  1343 		    	if (res["text/plain"] || res["text/x-iri-selected-text"]) {
       
  1344 		    		newNode.description = (res["text/plain"] || res["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
       
  1345 		    	}
       
  1346 		    	if (res["text/html"] || res["text/x-iri-selected-html"]) {
       
  1347 		    		var snippet = Rkns.$('<div>').html(res["text/html"] || res["text/x-iri-selected-html"]);
       
  1348 		    		newNode.image = snippet.find("img").attr("src") || '';
       
  1349 		    		newNode.uri = snippet.find("a").attr("href") || newNode.uri;
       
  1350 		    		newNode.title = snippet.find("[title]").attr("title");
       
  1351 		    	}
       
  1352 		    	if (res["text/uri-list"]) {
       
  1353 		    		newNode.uri = res["text/uri-list"];
       
  1354 		    	}
       
  1355 		    	if (res["text/x-moz-url"] && !newNode.title) {
       
  1356 		    		newNode.title = (res["text/x-moz-url"].split("\n")[1] || "").trim();
       
  1357 		    		if (newNode.title === newNode.uri) {
       
  1358 		    			newNode.title = false;
       
  1359 		    		}
       
  1360 		    	}
       
  1361 		    	if (res["text/x-iri-source-title"] && !newNode.title) {
       
  1362 		    		newNode.title = res["text/x-iri-source-title"];
       
  1363 		    	}
  1279     	}
  1364     	}
  1280     	var fields = ["title", "description", "uri", "image"];
  1365     	var fields = ["title", "description", "uri", "image"];
  1281     	for (var i = 0; i < fields.length; i++) {
  1366     	for (var i = 0; i < fields.length; i++) {
  1282     		var f = fields[i];
  1367     		var f = fields[i];
  1283     		if (res["text/x-iri-" + f]) {
  1368     		if (res["text/x-iri-" + f]) {
  1296                 created_by: _this.renkan.current_user,
  1381                 created_by: _this.renkan.current_user,
  1297                 uri: newNode.uri || "",
  1382                 uri: newNode.uri || "",
  1298                 title: newNode.title || _this.renkan.translate("Dragged resource"),
  1383                 title: newNode.title || _this.renkan.translate("Dragged resource"),
  1299                 description: newNode.description || "",
  1384                 description: newNode.description || "",
  1300                 image: newNode.image || "",
  1385                 image: newNode.image || "",
       
  1386                 color: newNode.color || undefined,
  1301                 position: {
  1387                 position: {
  1302                     x: _coords.x,
  1388                     x: _coords.x,
  1303                     y: _coords.y
  1389                     y: _coords.y
  1304                 }
  1390                 }
  1305             };
  1391             };
  1366         } else {
  1452         } else {
  1367             _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
  1453             _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
  1368             _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
  1454             _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
  1369         }
  1455         }
  1370     });
  1456     });
  1371     this.$.find(".Rk-Bookmarklet-Button").click(function(){
  1457     this.$.find(".Rk-Bookmarklet-Button")
  1372     	_this.notif_$
  1458 	    .attr("href","javascript:" + Rkns.Renderer._BOOKMARKLET_CODE(_renkan))
  1373     		.text(_renkan.translate("Drag this bookmarklet to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan."))
  1459 		.click(function(){
  1374     		.fadeIn()
  1460 	    	_this.notif_$
  1375     		.delay(5000)
  1461 	    		.text(_renkan.translate("Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan."))
  1376     		.fadeOut();
  1462 	    		.fadeIn()
  1377 		return false;
  1463 	    		.delay(5000)
  1378     });
  1464 	    		.fadeOut();
       
  1465 			return false;
       
  1466 	    });
  1379     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  1467     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  1380         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
  1468         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
  1381     }).mouseout(function() {
  1469     }).mouseout(function() {
  1382         Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
  1470         Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
  1383     });
  1471     });
       
  1472     this.$.find(".Rk-Fold-Bins").click(function() {
       
  1473     	var bins = _renkan.$.find(".Rk-Bins");
       
  1474     	if (bins.offset().left < 0) {
       
  1475     		bins.animate({left: 0},250);
       
  1476     		_this.$.animate({left: 300},250,function() {
       
  1477     			var w = _this.$.width();
       
  1478     			paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  1479     		});
       
  1480     		$(this).html("&laquo;");
       
  1481     	} else {
       
  1482     		bins.animate({left: -300},250);
       
  1483     		_this.$.animate({left: 0},250,function() {
       
  1484     			var w = _this.$.width();
       
  1485     			paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  1486     		});
       
  1487     		$(this).html("&raquo;");
       
  1488     	}
       
  1489     });
  1384     
  1490     
  1385     paper.view.onResize = function(_event) {
  1491     paper.view.onResize = function(_event) {
  1386         _this.offset = _this.offset.add(_event.delta.divide(2));
  1492     	_this.offset = _this.offset.add(_event.delta.divide(2));
  1387         _this.resetCoords();
  1493         _this.resetCoords();
  1388         _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size)
  1494         _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size)
  1389         _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4]));
  1495         _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4]));
  1390         _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  1496         _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  1391         _this.redraw();
  1497         _this.redraw();
  1444     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div>'
  1550     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div>'
  1445     + '<% if (!read_only) { %>'
  1551     + '<% if (!read_only) { %>'
  1446     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div>'
  1552     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div>'
  1447     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div>'
  1553     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div>'
  1448     + '<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"><%-translate("Archive Project")%></div></div></div>'
  1554     + '<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"><%-translate("Archive Project")%></div></div></div>'
  1449     + '<div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="javascript:(function(){a=document;'
  1555     + '<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">'
  1450     + 'b=function(c){d=a.createElement(\'script\');d.type=\'text/javascript\';d.src=c;a.getElementsByTagName(\'head\')[0].appendChild(d);};'
  1556     + '<%-translate("Renkan \'Drag-to-Add\' bookmarklet")%></div></div></a>'
  1451     + 'b(\'<%- bookmarklet_url %>\');})();"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents">'
       
  1452     + '<%-translate("Renkan \'Drag and Add\' bookmarklet")%></div></div></a>'
       
  1453     + '<div class="Rk-TopBar-Separator"></div></div>'
  1557     + '<div class="Rk-TopBar-Separator"></div></div>'
  1454     + '<% } %>'
  1558     + '<% } %>'
  1455     + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
  1559     + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
       
  1560     + '<% if (show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
  1456     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  1561     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  1457     + '</div>'
  1562     + '</div>'
  1458 );
  1563 );
  1459 
  1564 
  1460 Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
  1565 Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
  1505         var _scale = Math.min(this.scale * .8 * Rkns.Renderer._MINIMAP_WIDTH / paper.view.bounds.width, this.scale * .8 * Rkns.Renderer._MINIMAP_HEIGHT / paper.view.bounds.height, (Rkns.Renderer._MINIMAP_WIDTH - 2 * Rkns.Renderer._MINIMAP_MARGIN_X) / (_maxx - _minx), (Rkns.Renderer._MINIMAP_HEIGHT - 2 * Rkns.Renderer._MINIMAP_MARGIN_Y) / (_maxy - _miny));
  1610         var _scale = Math.min(this.scale * .8 * Rkns.Renderer._MINIMAP_WIDTH / paper.view.bounds.width, this.scale * .8 * Rkns.Renderer._MINIMAP_HEIGHT / paper.view.bounds.height, (Rkns.Renderer._MINIMAP_WIDTH - 2 * Rkns.Renderer._MINIMAP_MARGIN_X) / (_maxx - _minx), (Rkns.Renderer._MINIMAP_HEIGHT - 2 * Rkns.Renderer._MINIMAP_MARGIN_Y) / (_maxy - _miny));
  1506         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
  1611         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
  1507         this.minimap.scale = _scale;
  1612         this.minimap.scale = _scale;
  1508     }
  1613     }
  1509     if (nodes.length === 1) {
  1614     if (nodes.length === 1) {
  1510         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
  1615     	this.minimap.scale = .1;
  1511         this.minimap.scale = .25;
  1616         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]).multiply(this.minimap.scale));
  1512     }
  1617     }
  1513     this.redraw();
  1618     this.redraw();
  1514 }
  1619 }
  1515 
  1620 
  1516 Rkns.Renderer.Scene.prototype.resetCoords = function(_point) {
  1621 Rkns.Renderer.Scene.prototype.resetCoords = function(_point) {