client/js/paper-renderer.js
changeset 195 15e048e00002
parent 194 f53a7999ae7b
child 196 2a2fcec209d0
equal deleted inserted replaced
194:f53a7999ae7b 195:15e048e00002
     1 /* paper-renderer.js */
     1 /* paper-renderer.js */
     2 
     2 
     3 (function() {
     3 (function(root) {
     4     
     4 
     5 var Rkns = this.Rkns;
     5 "use strict";
       
     6 
       
     7 var Rkns = root.Rkns,
       
     8     _ = Rkns._,
       
     9     $ = Rkns.$;
     6 
    10 
     7 var Renderer = Rkns.Renderer = {},
    11 var Renderer = Rkns.Renderer = {},
     8     _MIN_DRAG_DISTANCE = 2,
    12     _MIN_DRAG_DISTANCE = 2,
     9     _NODE_BUTTON_WIDTH = 40,
    13     _NODE_BUTTON_WIDTH = 40,
    10     _EDGE_BUTTON_INNER = 2,
    14     _EDGE_BUTTON_INNER = 2,
   109             this.model.on("unselect", this._unselectBinding );
   113             this.model.on("unselect", this._unselectBinding );
   110         }
   114         }
   111     }
   115     }
   112 };
   116 };
   113 
   117 
   114 Rkns._(_BaseRepresentation.prototype).extend({
   118 _(_BaseRepresentation.prototype).extend({
   115     _super: function(_func) {
   119     _super: function(_func) {
   116         return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
   120         return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
   117     },
   121     },
   118     redraw: function() {},
   122     redraw: function() {},
   119     moveTo: function() {},
   123     moveTo: function() {},
   149 
   153 
   150 /* */
   154 /* */
   151 
   155 
   152 var _BaseButton = Renderer._BaseButton = Rkns.Utils.inherit(_BaseRepresentation);
   156 var _BaseButton = Renderer._BaseButton = Rkns.Utils.inherit(_BaseRepresentation);
   153 
   157 
   154 Rkns._(_BaseButton.prototype).extend({
   158 _(_BaseButton.prototype).extend({
   155 moveTo: function(_pos) {
   159 moveTo: function(_pos) {
   156     this.sector.moveTo(_pos);
   160     this.sector.moveTo(_pos);
   157 },
   161 },
   158 show: function() {
   162 show: function() {
   159     this.sector.show();
   163     this.sector.show();
   177 
   181 
   178 /* */
   182 /* */
   179 
   183 
   180 var NodeRepr = Renderer.Node = Rkns.Utils.inherit(_BaseRepresentation);
   184 var NodeRepr = Renderer.Node = Rkns.Utils.inherit(_BaseRepresentation);
   181 
   185 
   182 Rkns._(NodeRepr.prototype).extend({
   186 _(NodeRepr.prototype).extend({
   183 _init: function() {
   187 _init: function() {
   184     this.renderer.node_layer.activate();
   188     this.renderer.node_layer.activate();
   185     this.type = "Node";
   189     this.type = "Node";
   186     this.circle = new paper.Path.Circle([0, 0], 1);
   190     this.circle = new paper.Path.Circle([0, 0], 1);
   187     this.circle.__representation = this;
   191     this.circle.__representation = this;
   189         this.circle.strokeWidth = this.options.node_stroke_width;
   193         this.circle.strokeWidth = this.options.node_stroke_width;
   190         this.h_ratio = 1;
   194         this.h_ratio = 1;
   191     } else {
   195     } else {
   192         this.h_ratio = 0;
   196         this.h_ratio = 0;
   193     }
   197     }
   194     this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
   198     this.title = $('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
   195     if (this.options.editor_mode) {
   199     if (this.options.editor_mode) {
   196         this.normal_buttons = [
   200         this.normal_buttons = [
   197             new NodeEditButton(this.renderer, null),
   201             new NodeEditButton(this.renderer, null),
   198             new NodeRemoveButton(this.renderer, null),
   202             new NodeRemoveButton(this.renderer, null),
   199             new NodeLinkButton(this.renderer, null),
   203             new NodeLinkButton(this.renderer, null),
   307             minisize = new paper.Size([miniradius, miniradius]);
   311             minisize = new paper.Size([miniradius, miniradius]);
   308         this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
   312         this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
   309     }
   313     }
   310     
   314     
   311     if (!_dontRedrawEdges) {
   315     if (!_dontRedrawEdges) {
   312         Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){
   316         var _this = this;
   313             var repr = this.renderer.getRepresentationByModel(edge);
   317         _.each(
   314             if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
   318             this.project.get("edges").filter(
   315                 repr.redraw();
   319                 function (ed) {
   316             }
   320                     return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
   317         }, this);
   321                 }
       
   322             ),
       
   323             function(edge, index, list) {
       
   324                 var repr = _this.renderer.getRepresentationByModel(edge);
       
   325                 if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
       
   326                     repr.redraw();
       
   327                 }
       
   328             }
       
   329         );
   318     }
   330     }
   319 
   331 
   320 },
   332 },
   321 showImage: function() {
   333 showImage: function() {
   322     if (typeof this.renderer.image_cache[this.img] === "undefined") {
   334     if (typeof this.renderer.image_cache[this.img] === "undefined") {
   342                 minX = Infinity,
   354                 minX = Infinity,
   343                 minY = Infinity,
   355                 minY = Infinity,
   344                 maxX = -Infinity,
   356                 maxX = -Infinity,
   345                 maxY = -Infinity;
   357                 maxY = -Infinity;
   346                 
   358                 
   347             function transformCoords(tabc, relative) {
   359             var transformCoords = function(tabc, relative) {
   348                 var newCoords = tabc.slice(1).map(function(v, k) {
   360                 var newCoords = tabc.slice(1).map(function(v, k) {
   349                     var res = parseFloat(v),
   361                     var res = parseFloat(v),
   350                         isY = k % 2;
   362                         isY = k % 2;
   351                     if (isY) {
   363                     if (isY) {
   352                         res = ( res - .5 ) * height;
   364                         res = ( res - .5 ) * height;
   435         this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
   447         this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
   436         this.redraw();
   448         this.redraw();
   437         this.renderer.throttledPaperDraw();
   449         this.renderer.throttledPaperDraw();
   438     } else {
   450     } else {
   439         var _this = this;
   451         var _this = this;
   440         Rkns.$(_image).on("load", function() {
   452         $(_image).on("load", function() {
   441             _this.showImage();
   453             _this.showImage();
   442         });
   454         });
   443     }
   455     }
   444 },
   456 },
   445 paperShift: function(_delta) {
   457 paperShift: function(_delta) {
   467             b.show();
   479             b.show();
   468         });
   480         });
   469     }
   481     }
   470     var _uri = this.model.get("uri");
   482     var _uri = this.model.get("uri");
   471     if (_uri) {
   483     if (_uri) {
   472         Rkns.$('.Rk-Bin-Item').each(function() {
   484         $('.Rk-Bin-Item').each(function() {
   473             var _el = Rkns.$(this);
   485             var _el = $(this);
   474             if (_el.attr("data-uri") == _uri) {
   486             if (_el.attr("data-uri") == _uri) {
   475                 _el.addClass("selected");
   487                 _el.addClass("selected");
   476             }
   488             }
   477         });
   489         });
   478     }
   490     }
   491         this.selected = false;
   503         this.selected = false;
   492         this.all_buttons.forEach(function(b) {
   504         this.all_buttons.forEach(function(b) {
   493             b.hide();
   505             b.hide();
   494         });
   506         });
   495         this.circle.strokeWidth = this.options.node_stroke_width;
   507         this.circle.strokeWidth = this.options.node_stroke_width;
   496         Rkns.$('.Rk-Bin-Item').removeClass("selected");
   508         $('.Rk-Bin-Item').removeClass("selected");
   497         if (this.renderer.minimap) {
   509         if (this.renderer.minimap) {
   498             this.minimap_circle.strokeColor = undefined;
   510             this.minimap_circle.strokeColor = undefined;
   499         }
   511         }
   500         this._super("unselect");
   512         this._super("unselect");
   501     }
   513     }
   565 
   577 
   566 /* */
   578 /* */
   567 
   579 
   568 var Edge = Renderer.Edge = Rkns.Utils.inherit(_BaseRepresentation);
   580 var Edge = Renderer.Edge = Rkns.Utils.inherit(_BaseRepresentation);
   569 
   581 
   570 Rkns._(Edge.prototype).extend({
   582 _(Edge.prototype).extend({
   571 _init: function() {
   583 _init: function() {
   572     this.renderer.edge_layer.activate();
   584     this.renderer.edge_layer.activate();
   573     this.type = "Edge";
   585     this.type = "Edge";
   574     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
   586     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
   575     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
   587     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
   583         [ 0, 0 ],
   595         [ 0, 0 ],
   584         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
   596         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
   585         [ 0, this.options.edge_arrow_width ]
   597         [ 0, this.options.edge_arrow_width ]
   586     );
   598     );
   587     this.arrow.__representation = this;
   599     this.arrow.__representation = this;
   588     this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
   600     this.text = $('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
   589     this.arrow_angle = 0;
   601     this.arrow_angle = 0;
   590     if (this.options.editor_mode) {
   602     if (this.options.editor_mode) {
   591         this.normal_buttons = [
   603         this.normal_buttons = [
   592             new EdgeEditButton(this.renderer, null),
   604             new EdgeEditButton(this.renderer, null),
   593             new EdgeRemoveButton(this.renderer, null),
   605             new EdgeRemoveButton(this.renderer, null),
   777     }
   789     }
   778     this.all_buttons.forEach(function(b) {
   790     this.all_buttons.forEach(function(b) {
   779         b.destroy();
   791         b.destroy();
   780     });
   792     });
   781     var _this = this;
   793     var _this = this;
   782     this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
   794     this.bundle.edges = _(this.bundle.edges).reject(function(_edge) {
   783         return _edge === _this;
   795         return _edge === _this;
   784     });
   796     });
   785 }
   797 }
   786 });
   798 });
   787 
   799 
   788 /* */
   800 /* */
   789 
   801 
   790 var TempEdge = Renderer.TempEdge = Rkns.Utils.inherit(_BaseRepresentation);
   802 var TempEdge = Renderer.TempEdge = Rkns.Utils.inherit(_BaseRepresentation);
   791 
   803 
   792 Rkns._(TempEdge.prototype).extend({
   804 _(TempEdge.prototype).extend({
   793 _init: function() {
   805 _init: function() {
   794     this.renderer.edge_layer.activate();
   806     this.renderer.edge_layer.activate();
   795     this.type = "Temp-edge";
   807     this.type = "Temp-edge";
   796     
   808     
   797     var _color = (this.project.get("users").get(this.renkan.current_user) || _USER_PLACEHOLDER(this.renkan)).get("color");
   809     var _color = (this.project.get("users").get(this.renkan.current_user) || _USER_PLACEHOLDER(this.renkan)).get("color");
   874 
   886 
   875 /* */
   887 /* */
   876 
   888 
   877 var _BaseEditor = Renderer._BaseEditor = Rkns.Utils.inherit(_BaseRepresentation);
   889 var _BaseEditor = Renderer._BaseEditor = Rkns.Utils.inherit(_BaseRepresentation);
   878 
   890 
   879 Rkns._(_BaseEditor.prototype).extend({
   891 _(_BaseEditor.prototype).extend({
   880 _init: function() {
   892 _init: function() {
   881     this.renderer.buttons_layer.activate();
   893     this.renderer.buttons_layer.activate();
   882     this.type = "editor";
   894     this.type = "editor";
   883     this.editor_block = new paper.Path();
   895     this.editor_block = new paper.Path();
   884     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0];});
   896     var _pts = _(_.range(8)).map(function() {return [0,0];});
   885     this.editor_block.add.apply(this.editor_block, _pts);
   897     this.editor_block.add.apply(this.editor_block, _pts);
   886     this.editor_block.strokeWidth = this.options.tooltip_border_width;
   898     this.editor_block.strokeWidth = this.options.tooltip_border_width;
   887     this.editor_block.strokeColor = this.options.tooltip_border_color;
   899     this.editor_block.strokeColor = this.options.tooltip_border_color;
   888     this.editor_block.opacity = .8;
   900     this.editor_block.opacity = .8;
   889     this.editor_$ = Rkns.$('<div>')
   901     this.editor_$ = $('<div>')
   890         .appendTo(this.renderer.editor_$)
   902         .appendTo(this.renderer.editor_$)
   891         .css({
   903         .css({
   892             position: "absolute",
   904             position: "absolute",
   893             opacity: .8
   905             opacity: .8
   894         })
   906         })
   902 
   914 
   903 /* */
   915 /* */
   904 
   916 
   905 var NodeEditor = Renderer.NodeEditor = Rkns.Utils.inherit(_BaseEditor);
   917 var NodeEditor = Renderer.NodeEditor = Rkns.Utils.inherit(_BaseEditor);
   906 
   918 
   907 Rkns._(NodeEditor.prototype).extend({
   919 _(NodeEditor.prototype).extend({
   908 template: Rkns._.template(
   920 template: _.template(
   909     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
   921     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
   910     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
   922     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
   911     + '<% if (options.show_node_editor_uri) { %><p><label><%-renkan.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><% } %>'
   923     + '<% if (options.show_node_editor_uri) { %><p><label><%-renkan.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><% } %>'
   912     + '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
   924     + '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
   913     + '<% if (options.show_node_editor_size) { %><p><span class="Rk-Editor-Label"><%-renkan.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><% } %>'
   925     + '<% if (options.show_node_editor_size) { %><p><span class="Rk-Editor-Label"><%-renkan.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><% } %>'
   914     + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.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">'
   926     + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.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>'
   915     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
   927     + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
   916     + '<% if (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
   928     + '<% if (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
   917     + '<% if (node.clip_path) { %><svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none"><path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="<%- node.clip_path %>"/></svg><% }%>'
   929     + '<% if (node.clip_path) { %><svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none"><path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="<%- node.clip_path %>"/></svg><% }%>'
   918     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
   930     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
   919     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
   931     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
   920     + '<% if (options.show_node_editor_creator && node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'
   932     + '<% if (options.show_node_editor_creator && node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'
   921 ),
   933 ),
   922 readOnlyTemplate: Rkns._.template(
   934 readOnlyTemplate: _.template(
   923     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
   935     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
   924     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
   936     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
   925     + '<% if (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
   937     + '<% if (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
   926     + '<% if (options.show_node_tooltip_description) { %><p><%-node.description%></p><% } %>'
   938     + '<% if (options.show_node_tooltip_description) { %><p><%-node.description%></p><% } %>'
   927     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
   939     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
   968         }
   980         }
   969     });
   981     });
   970     
   982     
   971     if (this.renderer.isEditable()) {
   983     if (this.renderer.isEditable()) {
   972         
   984         
   973         var onFieldChange = Rkns._(function() {
   985         var onFieldChange = _(function() {
   974             Rkns._(function() {
   986             _(function() {
   975                 if (_this.renderer.isEditable()) {
   987                 if (_this.renderer.isEditable()) {
   976                     var _data = {
   988                     var _data = {
   977                         title: _this.editor_$.find(".Rk-Edit-Title").val()
   989                         title: _this.editor_$.find(".Rk-Edit-Title").val()
   978                     };
   990                     };
   979                     if (_this.options.show_node_editor_uri) {
   991                     if (_this.options.show_node_editor_uri) {
  1056             } else {
  1068             } else {
  1057                 closeEditor();
  1069                 closeEditor();
  1058             }
  1070             }
  1059         });
  1071         });
  1060         
  1072         
  1061         function shiftSize(n) {
  1073         var shiftSize = function(n) {
  1062             if (_this.renderer.isEditable()) {
  1074             if (_this.renderer.isEditable()) {
  1063                 var _newsize = n+(_model.get("size") || 0);
  1075                 var _newsize = n+(_model.get("size") || 0);
  1064                 _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
  1076                 _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
  1065                 _model.set("size", _newsize);
  1077                 _model.set("size", _newsize);
  1066                 paper.view.draw();
  1078                 paper.view.draw();
  1092 
  1104 
  1093 /* */
  1105 /* */
  1094 
  1106 
  1095 var EdgeEditor = Renderer.EdgeEditor = Rkns.Utils.inherit(_BaseEditor);
  1107 var EdgeEditor = Renderer.EdgeEditor = Rkns.Utils.inherit(_BaseEditor);
  1096 
  1108 
  1097 Rkns._(EdgeEditor.prototype).extend({
  1109 _(EdgeEditor.prototype).extend({
  1098 template: Rkns._.template(
  1110 template: _.template(
  1099     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  1111     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  1100     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  1112     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  1101     + '<% if (options.show_edge_editor_uri) { %><p><label><%-renkan.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>'
  1113     + '<% if (options.show_edge_editor_uri) { %><p><label><%-renkan.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>'
  1102     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  1114     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  1103     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  1115     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  1104     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
  1116     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
  1105     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  1117     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  1106     + '<% }) %><% }) %></select></p><% } } %>'
  1118     + '<% }) %><% }) %></select></p><% } } %>'
  1107     + '<% if (options.show_edge_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.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">'
  1119     + '<% if (options.show_edge_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.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>'
  1108     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  1120     + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  1109     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  1121     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  1110     + '<% if (options.show_edge_editor_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  1122     + '<% if (options.show_edge_editor_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  1111     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- shortenText(edge.to_title, 25) %></p><% } %>'
  1123     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- shortenText(edge.to_title, 25) %></p><% } %>'
  1112     + '<% if (options.show_edge_editor_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'
  1124     + '<% if (options.show_edge_editor_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'
  1113 ),
  1125 ),
  1114 readOnlyTemplate: Rkns._.template(
  1126 readOnlyTemplate: _.template(
  1115     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  1127     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  1116     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  1128     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  1117     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  1129     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  1118     + '<p><%-edge.description%></p>'
  1130     + '<p><%-edge.description%></p>'
  1119     + '<% if (options.show_edge_tooltip_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  1131     + '<% if (options.show_edge_tooltip_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  1142                 created_by_color: _created_by.get("color"),
  1154                 created_by_color: _created_by.get("color"),
  1143                 created_by_title: _created_by.get("title")
  1155                 created_by_title: _created_by.get("title")
  1144             },
  1156             },
  1145             renkan: this.renkan,
  1157             renkan: this.renkan,
  1146             shortenText: shortenText,
  1158             shortenText: shortenText,
  1147             options: this.options,
  1159             options: this.options
  1148         }));
  1160         }));
  1149     this.redraw();
  1161     this.redraw();
  1150     var _this = this,
  1162     var _this = this,
  1151         closeEditor = function() {
  1163         closeEditor = function() {
  1152             _this.renderer.removeRepresentation(_this);
  1164             _this.renderer.removeRepresentation(_this);
  1159         }
  1171         }
  1160     });
  1172     });
  1161     
  1173     
  1162     if (this.renderer.isEditable()) {
  1174     if (this.renderer.isEditable()) {
  1163         
  1175         
  1164         var onFieldChange = Rkns._(function() {
  1176         var onFieldChange = _(function() {
  1165             Rkns._(function() {
  1177             _(function() {
  1166                 if (_this.renderer.isEditable()) {
  1178                 if (_this.renderer.isEditable()) {
  1167                     var _data = {
  1179                     var _data = {
  1168                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  1180                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  1169                     };
  1181                     };
  1170                     if (_this.options.show_edge_editor_uri) {
  1182                     if (_this.options.show_edge_editor_uri) {
  1252 
  1264 
  1253 /* */
  1265 /* */
  1254 
  1266 
  1255 var _NodeButton = Renderer._NodeButton = Rkns.Utils.inherit(_BaseButton);
  1267 var _NodeButton = Renderer._NodeButton = Rkns.Utils.inherit(_BaseButton);
  1256 
  1268 
  1257 Rkns._(_NodeButton.prototype).extend({
  1269 _(_NodeButton.prototype).extend({
  1258 setSectorSize: function() {
  1270 setSectorSize: function() {
  1259     var sectorInner = this.source_representation.circle_radius;
  1271     var sectorInner = this.source_representation.circle_radius;
  1260     if (sectorInner !== this.lastSectorInner) {
  1272     if (sectorInner !== this.lastSectorInner) {
  1261         if (this.sector) {
  1273         if (this.sector) {
  1262             this.sector.destroy();
  1274             this.sector.destroy();
  1277 
  1289 
  1278 /* */
  1290 /* */
  1279 
  1291 
  1280 var NodeEditButton = Renderer.NodeEditButton = Rkns.Utils.inherit(_NodeButton);
  1292 var NodeEditButton = Renderer.NodeEditButton = Rkns.Utils.inherit(_NodeButton);
  1281 
  1293 
  1282 Rkns._(NodeEditButton.prototype).extend({
  1294 _(NodeEditButton.prototype).extend({
  1283 _init: function() {
  1295 _init: function() {
  1284     this.type = "Node-edit-button";
  1296     this.type = "Node-edit-button";
  1285     this.lastSectorInner = 0;
  1297     this.lastSectorInner = 0;
  1286     this.startAngle = -135;
  1298     this.startAngle = -135;
  1287     this.endAngle = -45;
  1299     this.endAngle = -45;
  1297 
  1309 
  1298 /* */
  1310 /* */
  1299 
  1311 
  1300 var NodeRemoveButton = Renderer.NodeRemoveButton = Rkns.Utils.inherit(_NodeButton);
  1312 var NodeRemoveButton = Renderer.NodeRemoveButton = Rkns.Utils.inherit(_NodeButton);
  1301 
  1313 
  1302 Rkns._(NodeRemoveButton.prototype).extend({
  1314 _(NodeRemoveButton.prototype).extend({
  1303 _init: function() {
  1315 _init: function() {
  1304     this.type = "Node-remove-button";
  1316     this.type = "Node-remove-button";
  1305     this.lastSectorInner = 0;
  1317     this.lastSectorInner = 0;
  1306     this.startAngle = 0;
  1318     this.startAngle = 0;
  1307     this.endAngle = 90;
  1319     this.endAngle = 90;
  1331 
  1343 
  1332 /* */
  1344 /* */
  1333 
  1345 
  1334 var NodeRevertButton = Renderer.NodeRevertButton = Rkns.Utils.inherit(_NodeButton);
  1346 var NodeRevertButton = Renderer.NodeRevertButton = Rkns.Utils.inherit(_NodeButton);
  1335 
  1347 
  1336 Rkns._(NodeRevertButton.prototype).extend({
  1348 _(NodeRevertButton.prototype).extend({
  1337 _init: function() {
  1349 _init: function() {
  1338     this.type = "Node-revert-button";
  1350     this.type = "Node-revert-button";
  1339     this.lastSectorInner = 0;
  1351     this.lastSectorInner = 0;
  1340     this.startAngle = -135;
  1352     this.startAngle = -135;
  1341     this.endAngle = 135;
  1353     this.endAngle = 135;
  1353 
  1365 
  1354 /* */
  1366 /* */
  1355 
  1367 
  1356 var NodeLinkButton = Renderer.NodeLinkButton = Rkns.Utils.inherit(_NodeButton);
  1368 var NodeLinkButton = Renderer.NodeLinkButton = Rkns.Utils.inherit(_NodeButton);
  1357 
  1369 
  1358 Rkns._(NodeLinkButton.prototype).extend({
  1370 _(NodeLinkButton.prototype).extend({
  1359 _init: function() {
  1371 _init: function() {
  1360     this.type = "Node-link-button";
  1372     this.type = "Node-link-button";
  1361     this.lastSectorInner = 0;
  1373     this.lastSectorInner = 0;
  1362     this.startAngle = 90;
  1374     this.startAngle = 90;
  1363     this.endAngle = 180;
  1375     this.endAngle = 180;
  1380 
  1392 
  1381 /* */
  1393 /* */
  1382 
  1394 
  1383 var NodeEnlargeButton = Renderer.NodeEnlargeButton = Rkns.Utils.inherit(_NodeButton);
  1395 var NodeEnlargeButton = Renderer.NodeEnlargeButton = Rkns.Utils.inherit(_NodeButton);
  1384 
  1396 
  1385 Rkns._(NodeEnlargeButton.prototype).extend({
  1397 _(NodeEnlargeButton.prototype).extend({
  1386 _init: function() {
  1398 _init: function() {
  1387     this.type = "Node-enlarge-button";
  1399     this.type = "Node-enlarge-button";
  1388     this.lastSectorInner = 0;
  1400     this.lastSectorInner = 0;
  1389     this.startAngle = -45;
  1401     this.startAngle = -45;
  1390     this.endAngle = 0;
  1402     this.endAngle = 0;
  1402 
  1414 
  1403 /* */
  1415 /* */
  1404 
  1416 
  1405 var NodeShrinkButton = Renderer.NodeShrinkButton = Rkns.Utils.inherit(_NodeButton);
  1417 var NodeShrinkButton = Renderer.NodeShrinkButton = Rkns.Utils.inherit(_NodeButton);
  1406 
  1418 
  1407 Rkns._(NodeShrinkButton.prototype).extend({
  1419 _(NodeShrinkButton.prototype).extend({
  1408 _init: function() {
  1420 _init: function() {
  1409     this.type = "Node-shrink-button";
  1421     this.type = "Node-shrink-button";
  1410     this.lastSectorInner = 0;
  1422     this.lastSectorInner = 0;
  1411     this.startAngle = -180;
  1423     this.startAngle = -180;
  1412     this.endAngle = -135;
  1424     this.endAngle = -135;
  1424 
  1436 
  1425 /* */
  1437 /* */
  1426 
  1438 
  1427 var EdgeEditButton = Renderer.EdgeEditButton = Rkns.Utils.inherit(_BaseButton);
  1439 var EdgeEditButton = Renderer.EdgeEditButton = Rkns.Utils.inherit(_BaseButton);
  1428 
  1440 
  1429 Rkns._(EdgeEditButton.prototype).extend({
  1441 _(EdgeEditButton.prototype).extend({
  1430 _init: function() {
  1442 _init: function() {
  1431     this.type = "Edge-edit-button";
  1443     this.type = "Edge-edit-button";
  1432     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  1444     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  1433 },
  1445 },
  1434 mouseup: function() {
  1446 mouseup: function() {
  1440 
  1452 
  1441 /* */
  1453 /* */
  1442 
  1454 
  1443 var EdgeRemoveButton = Renderer.EdgeRemoveButton = Rkns.Utils.inherit(_BaseButton);
  1455 var EdgeRemoveButton = Renderer.EdgeRemoveButton = Rkns.Utils.inherit(_BaseButton);
  1444 
  1456 
  1445 Rkns._(EdgeRemoveButton.prototype).extend({
  1457 _(EdgeRemoveButton.prototype).extend({
  1446 _init: function() {
  1458 _init: function() {
  1447     this.type = "Edge-remove-button";
  1459     this.type = "Edge-remove-button";
  1448     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  1460     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  1449 },
  1461 },
  1450 mouseup: function() {
  1462 mouseup: function() {
  1470 
  1482 
  1471 /* */
  1483 /* */
  1472 
  1484 
  1473 var EdgeRevertButton = Renderer.EdgeRevertButton = Rkns.Utils.inherit(_BaseButton);
  1485 var EdgeRevertButton = Renderer.EdgeRevertButton = Rkns.Utils.inherit(_BaseButton);
  1474 
  1486 
  1475 Rkns._(EdgeRevertButton.prototype).extend({
  1487 _(EdgeRevertButton.prototype).extend({
  1476 _init: function() {
  1488 _init: function() {
  1477     this.type = "Edge-revert-button";
  1489     this.type = "Edge-revert-button";
  1478     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  1490     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  1479 },
  1491 },
  1480 mouseup: function() {
  1492 mouseup: function() {
  1488 
  1500 
  1489 /* */
  1501 /* */
  1490 
  1502 
  1491 var MiniFrame = Renderer.MiniFrame = Rkns.Utils.inherit(_BaseRepresentation);
  1503 var MiniFrame = Renderer.MiniFrame = Rkns.Utils.inherit(_BaseRepresentation);
  1492 
  1504 
  1493 Rkns._(MiniFrame.prototype).extend({
  1505 _(MiniFrame.prototype).extend({
  1494 paperShift: function(_delta) {
  1506 paperShift: function(_delta) {
  1495     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  1507     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  1496     this.renderer.redraw();
  1508     this.renderer.redraw();
  1497 },
  1509 },
  1498 mouseup: function(_delta) {
  1510 mouseup: function(_delta) {
  1503 
  1515 
  1504 /* */
  1516 /* */
  1505 
  1517 
  1506 var Scene = Renderer.Scene = function(_renkan) {
  1518 var Scene = Renderer.Scene = function(_renkan) {
  1507     this.renkan = _renkan;
  1519     this.renkan = _renkan;
  1508     this.$ = Rkns.$(".Rk-Render");
  1520     this.$ = $(".Rk-Render");
  1509     this.representations = [];
  1521     this.representations = [];
  1510     this.$.html(this.template(_renkan));
  1522     this.$.html(this.template(_renkan));
  1511     this.onStatusChange();
  1523     this.onStatusChange();
  1512     this.canvas_$ = this.$.find(".Rk-Canvas");
  1524     this.canvas_$ = this.$.find(".Rk-Canvas");
  1513     this.labels_$ = this.$.find(".Rk-Labels");
  1525     this.labels_$ = this.$.find(".Rk-Labels");
  1554         this.minimap.miniframe.strokeColor = '#000080';
  1566         this.minimap.miniframe.strokeColor = '#000080';
  1555         this.minimap.miniframe.strokeWidth = 3;
  1567         this.minimap.miniframe.strokeWidth = 3;
  1556         this.minimap.miniframe.__representation = new MiniFrame(this, null);
  1568         this.minimap.miniframe.__representation = new MiniFrame(this, null);
  1557     }
  1569     }
  1558     
  1570     
  1559     this.throttledPaperDraw = Rkns._(function() {
  1571     this.throttledPaperDraw = _(function() {
  1560         paper.view.draw();
  1572         paper.view.draw();
  1561     }).throttle(100);
  1573     }).throttle(100);
  1562     
  1574     
  1563     this.bundles = [];
  1575     this.bundles = [];
  1564     this.click_mode = false;
  1576     this.click_mode = false;
  1675         },
  1687         },
  1676         drop: function(_event) {
  1688         drop: function(_event) {
  1677             _event.preventDefault();
  1689             _event.preventDefault();
  1678             _allowScroll = true;
  1690             _allowScroll = true;
  1679             var res = {};
  1691             var res = {};
  1680             Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
  1692             _(_event.originalEvent.dataTransfer.types).each(function(t) {
  1681                 try {
  1693                 try {
  1682                     res[t] = _event.originalEvent.dataTransfer.getData(t);
  1694                     res[t] = _event.originalEvent.dataTransfer.getData(t);
  1683                 } catch(e) {}
  1695                 } catch(e) {}
  1684             });
  1696             });
  1685             var text = _event.originalEvent.dataTransfer.getData("Text");
  1697             var text = _event.originalEvent.dataTransfer.getData("Text");
  1745                 .delay(5000)
  1757                 .delay(5000)
  1746                 .fadeOut();
  1758                 .fadeOut();
  1747             return false;
  1759             return false;
  1748         });
  1760         });
  1749     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  1761     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  1750         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
  1762         $(this).find(".Rk-TopBar-Tooltip").show();
  1751     }).mouseout(function() {
  1763     }).mouseout(function() {
  1752         Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
  1764         $(this).find(".Rk-TopBar-Tooltip").hide();
  1753     });
  1765     });
  1754     bindClick(".Rk-Fold-Bins", "foldBins");
  1766     bindClick(".Rk-Fold-Bins", "foldBins");
  1755     
  1767     
  1756     paper.view.onResize = function(_event) {
  1768     paper.view.onResize = function(_event) {
  1757         _this.offset = _this.offset.add(_event.delta.divide(2));
  1769         _this.offset = _this.offset.add(_event.delta.divide(2));
  1761             _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  1773             _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  1762         }
  1774         }
  1763         _this.redraw();
  1775         _this.redraw();
  1764     };
  1776     };
  1765     
  1777     
  1766     var _thRedraw = Rkns._.throttle(function() {
  1778     var _thRedraw = _.throttle(function() {
  1767         _this.redraw();
  1779         _this.redraw();
  1768     },50);
  1780     },50);
  1769     
  1781     
  1770     this.addRepresentations("Node", this.renkan.project.get("nodes"));
  1782     this.addRepresentations("Node", this.renkan.project.get("nodes"));
  1771     this.addRepresentations("Edge", this.renkan.project.get("edges"));
  1783     this.addRepresentations("Edge", this.renkan.project.get("edges"));
  1775     
  1787     
  1776     this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
  1788     this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
  1777         _renkan.project.set({"title": $(this).val()});
  1789         _renkan.project.set({"title": $(this).val()});
  1778     });
  1790     });
  1779     
  1791     
  1780     this.renkan.project.get("users").each(function(_user) {
  1792     var _thRedrawUsers = _.throttle(function() {
  1781         _this.addUser(_user);
  1793         _this.redrawUsers();
  1782     });
  1794     }, 100);
  1783     
  1795     
  1784     this.renkan.project.on("add:users", function(_user) {
  1796     _thRedrawUsers();
  1785         _this.addUser(_user);
  1797     
  1786     });
  1798     this.renkan.project.on("add:users remove:users", _thRedrawUsers);
       
  1799     
  1787     this.renkan.project.on("add:nodes", function(_node) {
  1800     this.renkan.project.on("add:nodes", function(_node) {
  1788         _this.addRepresentation("Node", _node);
  1801         _this.addRepresentation("Node", _node);
  1789         _thRedraw();
  1802         _thRedraw();
  1790     });
  1803     });
  1791     this.renkan.project.on("add:edges", function(_edge) {
  1804     this.renkan.project.on("add:edges", function(_edge) {
  1821         $(window).resize(function() {
  1834         $(window).resize(function() {
  1822             _this.fixSize(false);
  1835             _this.fixSize(false);
  1823         });
  1836         });
  1824     }
  1837     }
  1825     
  1838     
       
  1839     if (_renkan.options.show_user_list) {
       
  1840         var $cpwrapper = this.$.find(".Rk-Users .Rk-Edit-ColorPicker-Wrapper"),
       
  1841             $cplist = this.$.find(".Rk-Users .Rk-Edit-ColorPicker");
       
  1842         
       
  1843         $cpwrapper.hover(
       
  1844             function(_e) {
       
  1845                 if (_this.isEditable()) {
       
  1846                     _e.preventDefault();
       
  1847                     $cplist.show();
       
  1848                 }
       
  1849             },
       
  1850             function(_e) {
       
  1851                 _e.preventDefault();
       
  1852                 $cplist.hide();
       
  1853             }
       
  1854         );
       
  1855         
       
  1856         $cplist.find("li").mouseenter(
       
  1857             function(_e) {
       
  1858                 if (_this.isEditable()) {
       
  1859                     _e.preventDefault();
       
  1860                     _this.$.find(".Rk-CurrentUser-Color").css("background", $(this).attr("data-color"));
       
  1861                 }
       
  1862             }
       
  1863         );
       
  1864     }
       
  1865     
  1826     this.redraw();
  1866     this.redraw();
  1827     
  1867     
  1828     window.setInterval(function() {
  1868     window.setInterval(function() {
  1829         var _now = new Date().valueOf();
  1869         var _now = new Date().valueOf();
  1830         _this.delete_list.forEach(function(d) {
  1870         _this.delete_list.forEach(function(d) {
  1850         }, 2000);
  1890         }, 2000);
  1851     }
  1891     }
  1852 
  1892 
  1853 };
  1893 };
  1854 
  1894 
  1855 Rkns._(Scene.prototype).extend({
  1895 _(Scene.prototype).extend({
  1856 template: Rkns._.template(
  1896 template: _.template(
  1857     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  1897     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  1858     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  1898     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  1859     + '<% if (options.show_user_list) { %><div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div><% } %>'
  1899     + '<% if (options.show_user_list) { %><div class="Rk-Users"><div class="Rk-CurrentUser"><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-CurrentUser-Color"><span class="Rk-Edit-ColorTip"></span></span>'
       
  1900     + '<%= colorPicker %></div><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div><% } %>'
  1860     + '<% if (options.home_button_url) {%><div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Home-Button" href="<%- options.home_button_url %>"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents">'
  1901     + '<% if (options.home_button_url) {%><div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Home-Button" href="<%- options.home_button_url %>"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents">'
  1861     + '<%- translate(options.home_button_title) %></div></div></a><% } %>'
  1902     + '<%- translate(options.home_button_title) %></div></div></a><% } %>'
  1862     + '<% if (options.show_fullscreen_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div><% } %>'
  1903     + '<% if (options.show_fullscreen_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div><% } %>'
  1863     + '<% if (options.editor_mode) { %>'
  1904     + '<% if (options.editor_mode) { %>'
  1864     + '<% if (options.show_addnode_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip">'
  1905     + '<% if (options.show_addnode_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip">'
  1990         _grp.addChild(_raster);
  2031         _grp.addChild(_raster);
  1991     }
  2032     }
  1992     if (_img.width) {
  2033     if (_img.width) {
  1993         showImage();
  2034         showImage();
  1994     } else {
  2035     } else {
  1995         Rkns.$(_img).on("load",showImage);
  2036         $(_img).on("load",showImage);
  1996     }
  2037     }
  1997     
  2038     
  1998     return _res;
  2039     return _res;
  1999 },
  2040 },
  2000 addToBundles: function(_edgeRepr) {
  2041 addToBundles: function(_edgeRepr) {
  2001     var _bundle = Rkns._(this.bundles).find(function(_bundle) {
  2042     var _bundle = _(this.bundles).find(function(_bundle) {
  2002         return ( 
  2043         return ( 
  2003             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  2044             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  2004             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  2045             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  2005         );
  2046         );
  2006     });
  2047     });
  2011             from: _edgeRepr.from_representation,
  2052             from: _edgeRepr.from_representation,
  2012             to: _edgeRepr.to_representation,
  2053             to: _edgeRepr.to_representation,
  2013             edges: [ _edgeRepr ],
  2054             edges: [ _edgeRepr ],
  2014             getPosition: function(_er) {
  2055             getPosition: function(_er) {
  2015                 var _dir = (_er.from_representation === this.from) ? 1 : -1;
  2056                 var _dir = (_er.from_representation === this.from) ? 1 : -1;
  2016                 return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
  2057                 return _dir * ( _(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
  2017             }
  2058             }
  2018         };
  2059         };
  2019         this.bundles.push(_bundle);
  2060         this.bundles.push(_bundle);
  2020     }
  2061     }
  2021     return _bundle;
  2062     return _bundle;
  2036         } else {
  2077         } else {
  2037             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  2078             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  2038             tip.text(this.renkan.translate("Auto-save enabled"));
  2079             tip.text(this.renkan.translate("Auto-save enabled"));
  2039         }
  2080         }
  2040     }
  2081     }
       
  2082     this.redrawUsers();
  2041 },
  2083 },
  2042 setScale: function(_newScale, _offset) {
  2084 setScale: function(_newScale, _offset) {
  2043     if (_newScale > _MIN_SCALE && _newScale < _MAX_SCALE) {
  2085     if (_newScale > _MIN_SCALE && _newScale < _MAX_SCALE) {
  2044         this.scale = _newScale;
  2086         this.scale = _newScale;
  2045         if (_offset) {
  2087         if (_offset) {
  2111     var _this = this;
  2153     var _this = this;
  2112     _collection.forEach(function(_model) {
  2154     _collection.forEach(function(_model) {
  2113         _this.addRepresentation(_type, _model);
  2155         _this.addRepresentation(_type, _model);
  2114     });
  2156     });
  2115 },
  2157 },
  2116 userTemplate: Rkns._.template(
  2158 userTemplate: _.template(
  2117     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  2159     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  2118 ),
  2160 ),
  2119 addUser: function(_user) {
  2161 redrawUsers: function() {
  2120     if (_user.get("_id") === this.renkan.current_user) {
  2162     if (!this.renkan.options.show_user_list) {
  2121         this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
  2163         return;
  2122         this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
  2164     }
  2123     } else {
  2165     var allUsers = [].concat((this.renkan.project.current_user_list || {}).models || [], (this.renkan.project.get("users") || {}).models || []),
  2124         this.$.find(".Rk-UserList").append(
  2166         ulistHtml = '',
  2125             Rkns.$(
  2167         $userpanel = this.$.find(".Rk-Users"),
  2126                 this.userTemplate({
  2168         $name = $userpanel.find(".Rk-CurrentUser-Name"),
  2127                     name: _user.get("title"),
  2169         $cpwrapper = $userpanel.find(".Rk-Edit-ColorPicker-Wrapper"),
  2128                     background: _user.get("color")
  2170         $cpitems = $userpanel.find(".Rk-Edit-ColorPicker li"),
  2129                 })
  2171         $colorsquare = $userpanel.find(".Rk-CurrentUser-Color"),
  2130             )
  2172         _this = this;
  2131         );
  2173     $name.off("click").text(this.renkan.translate("<unknown user>"));
  2132     }
  2174     $cpitems.off("mouseleave click");
       
  2175     allUsers.forEach(function(_user) {
       
  2176         if (_user.get("_id") === _this.renkan.current_user) {
       
  2177             $name.text(_user.get("title"));
       
  2178             if (_this.isEditable()) {
       
  2179                 $name.click(function() {
       
  2180                     var $this = $(this),
       
  2181                         $input = $('<input>').val(_user.get("title")).blur(function() {
       
  2182                             _user.set("title", $(this).val());
       
  2183                             _this.redrawUsers();
       
  2184                             _this.redraw();
       
  2185                         });
       
  2186                     $this.empty().html($input);
       
  2187                     $input.select();
       
  2188                 });
       
  2189                 
       
  2190                 $cpitems.click(
       
  2191                     function(_e) {
       
  2192                         _e.preventDefault();
       
  2193                         if (_this.isEditable()) {
       
  2194                             _user.set("color", $(this).attr("data-color"));
       
  2195                         }
       
  2196                         $(this).parent().hide();
       
  2197                     }
       
  2198                 ).mouseleave(function() {
       
  2199                     $colorsquare.css("background", _user.get("color"));
       
  2200                 });
       
  2201                 $colorsquare.css("background", _user.get("color"));
       
  2202             }
       
  2203             
       
  2204         } else {
       
  2205             ulistHtml += _this.userTemplate({
       
  2206                 name: _user.get("title"),
       
  2207                 background: _user.get("color")
       
  2208             });
       
  2209         }
       
  2210     });
       
  2211     $userpanel.find(".Rk-UserList").html(ulistHtml);
  2133 },
  2212 },
  2134 removeRepresentation: function(_representation) {
  2213 removeRepresentation: function(_representation) {
  2135     _representation.destroy();
  2214     _representation.destroy();
  2136     this.representations = Rkns._(this.representations).reject(
  2215     this.representations = _(this.representations).reject(
  2137         function(_repr) {
  2216         function(_repr) {
  2138             return _repr == _representation;
  2217             return _repr == _representation;
  2139         }
  2218         }
  2140     );
  2219     );
  2141 },
  2220 },
  2142 getRepresentationByModel: function(_model) {
  2221 getRepresentationByModel: function(_model) {
  2143     if (!_model) {
  2222     if (!_model) {
  2144         return undefined;
  2223         return undefined;
  2145     }
  2224     }
  2146     return Rkns._(this.representations).find(function(_repr) {
  2225     return _(this.representations).find(function(_repr) {
  2147         return _repr.model === _model;
  2226         return _repr.model === _model;
  2148     });
  2227     });
  2149 },
  2228 },
  2150 removeRepresentationsOfType: function(_type) {
  2229 removeRepresentationsOfType: function(_type) {
  2151     var _representations = Rkns._(this.representations).filter(function(_repr) {
  2230     var _representations = _(this.representations).filter(function(_repr) {
  2152             return _repr.type == _type;
  2231             return _repr.type == _type;
  2153         }),
  2232         }),
  2154         _this = this;
  2233         _this = this;
  2155     Rkns._(_representations).each(function(_repr) {
  2234     _(_representations).each(function(_repr) {
  2156         _this.removeRepresentation(_repr);
  2235         _this.removeRepresentation(_repr);
  2157     });
  2236     });
  2158 },
  2237 },
  2159 highlightModel: function(_model) {
  2238 highlightModel: function(_model) {
  2160     var _repr = this.getRepresentationByModel(_model);
  2239     var _repr = this.getRepresentationByModel(_model);
  2161     if (_repr) {
  2240     if (_repr) {
  2162         _repr.highlight();
  2241         _repr.highlight();
  2163     }
  2242     }
  2164 },
  2243 },
  2165 unhighlightAll: function(_model) {
  2244 unhighlightAll: function(_model) {
  2166     Rkns._(this.representations).each(function(_repr) {
  2245     _(this.representations).each(function(_repr) {
  2167         _repr.unhighlight();
  2246         _repr.unhighlight();
  2168     });
  2247     });
  2169 },
  2248 },
  2170 unselectAll: function(_model) {
  2249 unselectAll: function(_model) {
  2171     Rkns._(this.representations).each(function(_repr) {
  2250     _(this.representations).each(function(_repr) {
  2172         _repr.unselect();
  2251         _repr.unselect();
  2173     });
  2252     });
  2174 },
  2253 },
  2175 redraw: function() {
  2254 redraw: function() {
  2176     Rkns._(this.representations).each(function(_representation) {
  2255     _(this.representations).each(function(_representation) {
  2177         _representation.redraw(true);
  2256         _representation.redraw(true);
  2178     });
  2257     });
  2179     if (this.minimap) {
  2258     if (this.minimap) {
  2180         this.redrawMiniframe();
  2259         this.redrawMiniframe();
  2181     }
  2260     }
  2268         if (this.isEditable() && this.click_mode === _CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  2347         if (this.isEditable() && this.click_mode === _CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  2269             this.removeRepresentationsOfType("editor");
  2348             this.removeRepresentationsOfType("editor");
  2270             this.addTempEdge(this.click_target, _point);
  2349             this.addTempEdge(this.click_target, _point);
  2271             this.click_mode = _CLICKMODE_ENDEDGE;
  2350             this.click_mode = _CLICKMODE_ENDEDGE;
  2272             this.notif_$.fadeOut(function() {
  2351             this.notif_$.fadeOut(function() {
  2273                 Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  2352                 $(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  2274             });
  2353             });
  2275         } else {
  2354         } else {
  2276             this.notif_$.hide();
  2355             this.notif_$.hide();
  2277             this.click_mode = false;
  2356             this.click_mode = false;
  2278         }
  2357         }
  2334                 created_by: this.renkan.current_user,
  2413                 created_by: this.renkan.current_user,
  2335                 position: {
  2414                 position: {
  2336                     x: _coords.x,
  2415                     x: _coords.x,
  2337                     y: _coords.y
  2416                     y: _coords.y
  2338                 }
  2417                 }
  2339             };
  2418             },
  2340             _node = this.renkan.project.addNode(_data);
  2419             _node = this.renkan.project.addNode(_data);
  2341             this.getRepresentationByModel(_node).openEditor();
  2420         this.getRepresentationByModel(_node).openEditor();
  2342     }
  2421     }
  2343     paper.view.draw();
  2422     paper.view.draw();
  2344 },
  2423 },
  2345 dropData: function(_data, _event) {
  2424 dropData: function(_data, _event) {
  2346     if (!this.isEditable()) {
  2425     if (!this.isEditable()) {
  2354         catch(e) {}
  2433         catch(e) {}
  2355     }
  2434     }
  2356     var newNode = {};
  2435     var newNode = {};
  2357     switch(_data["text/x-iri-specific-site"]) {
  2436     switch(_data["text/x-iri-specific-site"]) {
  2358         case "twitter":
  2437         case "twitter":
  2359             var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]),
  2438             var snippet = $('<div>').html(_data["text/x-iri-selected-html"]),
  2360                 tweetdiv = snippet.find(".tweet");
  2439                 tweetdiv = snippet.find(".tweet");
  2361             newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
  2440             newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
  2362             newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
  2441             newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
  2363             newNode.image = tweetdiv.find(".avatar").attr("src");
  2442             newNode.image = tweetdiv.find(".avatar").attr("src");
  2364             newNode.description = tweetdiv.find(".js-tweet-text:first").text();
  2443             newNode.description = tweetdiv.find(".js-tweet-text:first").text();
  2365         break;
  2444         break;
  2366         case "google":
  2445         case "google":
  2367             var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]);
  2446             var snippet = $('<div>').html(_data["text/x-iri-selected-html"]);
  2368             newNode.title = snippet.find("h3:first").text().trim();
  2447             newNode.title = snippet.find("h3:first").text().trim();
  2369             newNode.uri = snippet.find("h3 a").attr("href");
  2448             newNode.uri = snippet.find("h3 a").attr("href");
  2370             newNode.description = snippet.find(".st:first").text().trim();
  2449             newNode.description = snippet.find(".st:first").text().trim();
  2371         break;
  2450         break;
  2372         case undefined:
  2451         case undefined:
  2376             }
  2455             }
  2377             if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
  2456             if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
  2378                 newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
  2457                 newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
  2379             }
  2458             }
  2380             if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
  2459             if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
  2381                 var snippet = Rkns.$('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
  2460                 var snippet = $('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
  2382                 var _svgimgs = snippet.find("image");
  2461                 var _svgimgs = snippet.find("image");
  2383                 if (_svgimgs.length) {
  2462                 if (_svgimgs.length) {
  2384                     newNode.image = _svgimgs.attr("xlink:href");
  2463                     newNode.image = _svgimgs.attr("xlink:href");
  2385                 }
  2464                 }
  2386                 var _svgpaths = snippet.find("path");
  2465                 var _svgpaths = snippet.find("path");
  2536     }
  2615     }
  2537 },
  2616 },
  2538 save: function() { },
  2617 save: function() { },
  2539 open: function() { }
  2618 open: function() { }
  2540 });
  2619 });
  2541 }).call(window);
  2620 })(window);
  2542 
  2621 
  2543 /* END paper-renderer.js */
  2622 /* END paper-renderer.js */