client/js/paper-renderer.js
changeset 187 ba5022639c76
parent 185 ad8c900d87e5
child 189 f7b5ae0d2681
equal deleted inserted replaced
186:a260675bdef7 187:ba5022639c76
     1 Rkns.Renderer = {
     1 /* paper-renderer.js */
     2     _MIN_DRAG_DISTANCE: 2,
     2 
     3     _NODE_BUTTON_WIDTH: 40,
     3 (function() {
     4     _EDGE_BUTTON_INNER: 2,
     4     
     5     _EDGE_BUTTON_OUTER: 40,
     5 var Rkns = this.Rkns;
     6     _CLICKMODE_ADDNODE : 1,
     6 
     7     _CLICKMODE_STARTEDGE : 2,
     7 var Renderer = Rkns.Renderer = {},
     8     _CLICKMODE_ENDEDGE : 3,
     8     _MIN_DRAG_DISTANCE = 2,
     9     _IMAGE_MAX_KB : 500,
     9     _NODE_BUTTON_WIDTH = 40,
    10     _NODE_SIZE_STEP: Math.LN2/4,
    10     _EDGE_BUTTON_INNER = 2,
    11     _MIN_SCALE: 1/20,
    11     _EDGE_BUTTON_OUTER = 40,
    12     _MAX_SCALE: 20,
    12     _CLICKMODE_ADDNODE = 1,
    13     _MOUSEMOVE_RATE: 80,
    13     _CLICKMODE_STARTEDGE = 2,
    14     _DOUBLETAP_DELAY: 800,
    14     _CLICKMODE_ENDEDGE = 3,
    15     _DOUBLETAP_DISTANCE: 20*20,
    15     _IMAGE_MAX_KB = 500,
    16     _USER_PLACEHOLDER : function(_renkan) {
    16     _NODE_SIZE_STEP = Math.LN2/4,
       
    17     _MIN_SCALE = 1/20,
       
    18     _MAX_SCALE = 20,
       
    19     _MOUSEMOVE_RATE = 80,
       
    20     _DOUBLETAP_DELAY = 800,
       
    21     _DOUBLETAP_DISTANCE = 20*20,
       
    22     _USER_PLACEHOLDER = function(_renkan) {
    17         return {
    23         return {
    18             color: _renkan.options.default_user_color,
    24             color: _renkan.options.default_user_color,
    19             title: _renkan.translate("(unknown user)"),
    25             title: _renkan.translate("(unknown user)"),
    20             get: function(attr) {
    26             get: function(attr) {
    21                 return this[attr] || false;
    27                 return this[attr] || false;
    22             }
    28             }
    23         };
    29         };
    24     },
    30     },
    25     _BOOKMARKLET_CODE: function(_renkan) {
    31     _BOOKMARKLET_CODE = function(_renkan) {
    26         return "(function(a,b,c,d,e,f,h,i,j,k,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;\">"
    32         return "(function(a,b,c,d,e,f,h,i,j,k,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;\">"
    27         + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
    33         + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
    28         + "</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:/https?:\\/\\/[^\\/]*lemonde\\.fr\\//,s:'[data-vr-contentbox]',n:'lemonde'}];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;k=i.style;k.borderWidth='2px';k.borderColor='#909';k.borderStyle='solid';k.backgroundColor='rgba(200,0,180,.1)';})};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);})();";
    34         + "</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:/https?:\\/\\/[^\\/]*lemonde\\.fr\\//,s:'[data-vr-contentbox]',n:'lemonde'}];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;k=i.style;k.borderWidth='2px';k.borderColor='#909';k.borderStyle='solid';k.backgroundColor='rgba(200,0,180,.1)';})};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);})();";
    29     },
    35     },
    30     shortenText : function(_text, _maxlength) {
    36     shortenText = function(_text, _maxlength) {
    31         return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
    37         return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
    32     },
    38     },
    33     drawEditBox : function(_options, _coords, _path, _xmargin, _selector) {
    39     drawEditBox = function(_options, _coords, _path, _xmargin, _selector) {
    34         _selector.css({
    40         _selector.css({
    35             width: ( _options.tooltip_width - 2* _options.tooltip_padding ),
    41             width: ( _options.tooltip_width - 2* _options.tooltip_padding ),
    36         });
    42         });
    37         var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
    43         var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
    38             _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
    44             _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
    70         _selector.css({
    76         _selector.css({
    71             left: (_options.tooltip_padding + Math.min(_left, _right)),
    77             left: (_options.tooltip_padding + Math.min(_left, _right)),
    72             top: (_options.tooltip_padding + _top)
    78             top: (_options.tooltip_padding + _top)
    73         });
    79         });
    74         return _path;
    80         return _path;
    75     }
    81     };
    76 };
    82 
    77 
    83 var _BaseRepresentation = Renderer._BaseRepresentation = function(_renderer, _model) {
    78 Rkns.Renderer._BaseRepresentation = function(_renderer, _model) {
       
    79     if (typeof _renderer !== "undefined") {
    84     if (typeof _renderer !== "undefined") {
    80         this.renderer = _renderer;
    85         this.renderer = _renderer;
    81         this.renkan = _renderer.renkan;
    86         this.renkan = _renderer.renkan;
    82         this.project = _renderer.renkan.project;
    87         this.project = _renderer.renkan.project;
    83         this.options = _renderer.renkan.options;
    88         this.options = _renderer.renkan.options;
   105             this.model.on("unselect", this._unselectBinding );
   110             this.model.on("unselect", this._unselectBinding );
   106         }
   111         }
   107     }
   112     }
   108 };
   113 };
   109 
   114 
   110 Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) {
   115 Rkns._(_BaseRepresentation.prototype).extend({
   111     Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
   116     super: function(_func) {
   112 };
   117         _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
   113 
   118     },
   114 Rkns.Renderer._BaseRepresentation.prototype.redraw = function() {};
   119     redraw: function() {},
   115 
   120     moveTo: function() {},
   116 Rkns.Renderer._BaseRepresentation.prototype.moveTo = function() {};
   121     show: function() {},
   117 
   122     hide: function() {},
   118 Rkns.Renderer._BaseRepresentation.prototype.show = function() {};
   123     select: function() {
   119 
   124         if (this.model) {
   120 Rkns.Renderer._BaseRepresentation.prototype.hide = function() {};
   125             this.model.trigger("selected");
   121 
   126         }
   122 Rkns.Renderer._BaseRepresentation.prototype.select = function() {
   127     },
   123     if (this.model) {
   128     unselect: function() {
   124         this.model.trigger("selected");
   129         if (this.model) {
   125     }
   130             this.model.trigger("unselected");
   126 };
   131         }
   127 
   132     },
   128 Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {
   133     highlight: function() {},
   129     if (this.model) {
   134     unhighlight: function() {},
   130         this.model.trigger("unselected");
   135     mousedown: function() {},
   131     }
   136     mouseup: function() {
   132 };
   137         if (this.model) {
   133 
   138             this.model.trigger("clicked");
   134 Rkns.Renderer._BaseRepresentation.prototype.highlight = function() {};
   139         }
   135 
   140     },
   136 Rkns.Renderer._BaseRepresentation.prototype.unhighlight = function() {};
   141     destroy: function() {
   137 
   142         if (this.model) {
   138 Rkns.Renderer._BaseRepresentation.prototype.mousedown = function() {};
   143             this.model.off("change", this._changeBinding );
   139 
   144             this.model.off("remove", this._removeBinding );
   140 Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {
   145             this.model.off("select", this._selectBinding );
   141     if (this.model) {
   146             this.model.off("unselect", this._unselectBinding );
   142         this.model.trigger("clicked");
   147         }
   143     }
   148     }
   144 };
   149 });
   145 
       
   146 Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {
       
   147     if (this.model) {
       
   148         this.model.off("change", this._changeBinding );
       
   149         this.model.off("remove", this._removeBinding );
       
   150         this.model.off("select", this._selectBinding );
       
   151         this.model.off("unselect", this._unselectBinding );
       
   152     }
       
   153 };
       
   154 
   150 
   155 /* */
   151 /* */
   156 
   152 
   157 Rkns.Renderer._BaseButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   153 var _BaseButton = Renderer._BaseButton = Rkns.Utils.inherit(_BaseRepresentation);
   158 
   154 
   159 Rkns.Renderer._BaseButton.prototype.moveTo = function(_pos) {
   155 Rkns._(_BaseButton.prototype).extend({
       
   156 moveTo: function(_pos) {
   160     this.sector.moveTo(_pos);
   157     this.sector.moveTo(_pos);
   161 };
   158 },
   162 
   159 show: function() {
   163 Rkns.Renderer._BaseButton.prototype.show = function() {
       
   164     this.sector.show();
   160     this.sector.show();
   165 };
   161 },
   166 
   162 hide: function() {
   167 Rkns.Renderer._BaseButton.prototype.hide = function() {
       
   168     this.sector.hide();
   163     this.sector.hide();
   169 };
   164 },
   170 
   165 select: function() {
   171 Rkns.Renderer._BaseButton.prototype.select = function() {
       
   172     this.sector.select();
   166     this.sector.select();
   173 };
   167 },
   174 
   168 unselect: function(_newTarget) {
   175 Rkns.Renderer._BaseButton.prototype.unselect = function(_newTarget) {
       
   176     this.sector.unselect();
   169     this.sector.unselect();
   177     if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {
   170     if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {
   178         this.source_representation.unselect();
   171         this.source_representation.unselect();
   179     }
   172     }
   180 };
   173 },
   181 
   174 destroy: function() {
   182 Rkns.Renderer._BaseButton.prototype.destroy = function() {
       
   183     this.sector.destroy();
   175     this.sector.destroy();
   184 };
   176 }
       
   177 });
   185 
   178 
   186 /* */
   179 /* */
   187 
   180 
   188 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   181 var NodeRepr = Renderer.Node = Rkns.Utils.inherit(_BaseRepresentation);
   189 
   182 
   190 Rkns.Renderer.Node.prototype._init = function() {
   183 Rkns._(NodeRepr.prototype).extend({
       
   184 _init: function() {
   191     this.renderer.node_layer.activate();
   185     this.renderer.node_layer.activate();
   192     this.type = "Node";
   186     this.type = "Node";
   193     this.circle = new paper.Path.Circle([0, 0], 1);
   187     this.circle = new paper.Path.Circle([0, 0], 1);
   194     this.circle.__representation = this;
   188     this.circle.__representation = this;
   195     if (this.options.show_node_circles) {
   189     if (this.options.show_node_circles) {
   199         this.h_ratio = 0;
   193         this.h_ratio = 0;
   200     }
   194     }
   201     this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
   195     this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
   202     if (this.options.editor_mode) {
   196     if (this.options.editor_mode) {
   203         this.normal_buttons = [
   197         this.normal_buttons = [
   204             new Rkns.Renderer.NodeEditButton(this.renderer, null),
   198             new NodeEditButton(this.renderer, null),
   205             new Rkns.Renderer.NodeRemoveButton(this.renderer, null),
   199             new NodeRemoveButton(this.renderer, null),
   206             new Rkns.Renderer.NodeLinkButton(this.renderer, null),
   200             new NodeLinkButton(this.renderer, null),
   207             new Rkns.Renderer.NodeEnlargeButton(this.renderer, null),
   201             new NodeEnlargeButton(this.renderer, null),
   208             new Rkns.Renderer.NodeShrinkButton(this.renderer, null)
   202             new NodeShrinkButton(this.renderer, null)
   209         ];
   203         ];
   210         this.pending_delete_buttons = [
   204         this.pending_delete_buttons = [
   211             new Rkns.Renderer.NodeRevertButton(this.renderer, null)
   205             new NodeRevertButton(this.renderer, null)
   212         ];
   206         ];
   213         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
   207         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
   214         for (var i = 0; i < this.all_buttons.length; i++) {
   208         for (var i = 0; i < this.all_buttons.length; i++) {
   215             this.all_buttons[i].source_representation = this;
   209             this.all_buttons[i].source_representation = this;
   216         }
   210         }
   224         this.renderer.minimap.node_layer.activate();
   218         this.renderer.minimap.node_layer.activate();
   225         this.minimap_circle = new paper.Path.Circle([0, 0], 1);
   219         this.minimap_circle = new paper.Path.Circle([0, 0], 1);
   226         this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;
   220         this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;
   227         this.renderer.minimap.node_group.addChild(this.minimap_circle);
   221         this.renderer.minimap.node_group.addChild(this.minimap_circle);
   228     }
   222     }
   229 };
   223 },
   230 
   224 redraw: function(_dontRedrawEdges) {
   231 Rkns.Renderer.Node.prototype.redraw = function(_dontRedrawEdges) {
       
   232     var _model_coords = new paper.Point(this.model.get("position")),
   225     var _model_coords = new paper.Point(this.model.get("position")),
   233         _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP);
   226         _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * _NODE_SIZE_STEP);
   234     if (!this.is_dragging || !this.paper_coords) {
   227     if (!this.is_dragging || !this.paper_coords) {
   235         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
   228         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
   236     }
   229     }
   237     this.circle_radius = _baseRadius * this.renderer.scale;
   230     this.circle_radius = _baseRadius * this.renderer.scale;
   238     if (this.last_circle_radius !== this.circle_radius) {
   231     if (this.last_circle_radius !== this.circle_radius) {
   283     this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
   276     this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
   284     
   277     
   285     this.circle.opacity = this.options.show_node_circles ? opacity : .01;
   278     this.circle.opacity = this.options.show_node_circles ? opacity : .01;
   286     
   279     
   287     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
   280     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
   288     _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length);
   281     _text = shortenText(_text, this.options.node_label_max_length);
   289     this.title.text(_text);
   282     this.title.text(_text);
   290     this.title.css({
   283     this.title.css({
   291         left: this.paper_coords.x,
   284         left: this.paper_coords.x,
   292         top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
   285         top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
   293         opacity: opacity
   286         opacity: opacity
   294     });
   287     });
   295     var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
   288     var _color = this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color");
   296     this.circle.strokeColor = _color;
   289     this.circle.strokeColor = _color;
   297     var _pc = this.paper_coords;
   290     var _pc = this.paper_coords;
   298     this.all_buttons.forEach(function(b) {
   291     this.all_buttons.forEach(function(b) {
   299         b.moveTo(_pc);
   292         b.moveTo(_pc);
   300     });
   293     });
   323                 repr.redraw();
   316                 repr.redraw();
   324             }
   317             }
   325         }, this);
   318         }, this);
   326     }
   319     }
   327 
   320 
   328 };
   321 },
   329 
   322 showImage: function() {
   330 Rkns.Renderer.Node.prototype.showImage = function() {
       
   331     if (typeof this.renderer.image_cache[this.img] === "undefined") {
   323     if (typeof this.renderer.image_cache[this.img] === "undefined") {
   332         var _image = new Image();
   324         var _image = new Image();
   333         this.renderer.image_cache[this.img] = _image;
   325         this.renderer.image_cache[this.img] = _image;
   334         _image.src = this.img;
   326         _image.src = this.img;
   335     } else {
   327     } else {
   448         var _this = this;
   440         var _this = this;
   449         Rkns.$(_image).on("load", function() {
   441         Rkns.$(_image).on("load", function() {
   450             _this.showImage();
   442             _this.showImage();
   451         });
   443         });
   452     }
   444     }
   453 }
   445 },
   454 
   446 paperShift: function(_delta) {
   455 Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
       
   456     if (this.options.editor_mode) {
   447     if (this.options.editor_mode) {
   457         if (!this.renkan.read_only) {
   448         if (!this.renkan.read_only) {
   458             this.is_dragging = true;
   449             this.is_dragging = true;
   459             this.paper_coords = this.paper_coords.add(_delta);
   450             this.paper_coords = this.paper_coords.add(_delta);
   460             this.redraw();
   451             this.redraw();
   461         }
   452         }
   462     } else {
   453     } else {
   463         this.renderer.paperShift(_delta);
   454         this.renderer.paperShift(_delta);
   464     }
   455     }
   465 };
   456 },
   466 
   457 openEditor: function() {
   467 Rkns.Renderer.Node.prototype.openEditor = function() {
       
   468     this.renderer.removeRepresentationsOfType("editor");
   458     this.renderer.removeRepresentationsOfType("editor");
   469     var _editor = this.renderer.addRepresentation("NodeEditor",null);
   459     var _editor = this.renderer.addRepresentation("NodeEditor",null);
   470     _editor.source_representation = this;
   460     _editor.source_representation = this;
   471     _editor.draw();
   461     _editor.draw();
   472 };
   462 },
   473 
   463 select: function() {
   474 Rkns.Renderer.Node.prototype.select = function() {
       
   475     this.selected = true;
   464     this.selected = true;
   476     this.circle.strokeWidth = this.options.selected_node_stroke_width;
   465     this.circle.strokeWidth = this.options.selected_node_stroke_width;
   477     if (this.renderer.isEditable()) {
   466     if (this.renderer.isEditable()) {
   478         this.active_buttons.forEach(function(b) {
   467         this.active_buttons.forEach(function(b) {
   479             b.show();
   468             b.show();
   495     if (this.renderer.minimap) {
   484     if (this.renderer.minimap) {
   496         this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
   485         this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
   497         this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
   486         this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
   498     }
   487     }
   499     this.super("select");
   488     this.super("select");
   500 };
   489 },
   501 
   490 unselect: function(_newTarget) {
   502 Rkns.Renderer.Node.prototype.unselect = function(_newTarget) {
       
   503     if (!_newTarget || _newTarget.source_representation !== this) {
   491     if (!_newTarget || _newTarget.source_representation !== this) {
   504         this.selected = false;
   492         this.selected = false;
   505         this.all_buttons.forEach(function(b) {
   493         this.all_buttons.forEach(function(b) {
   506             b.hide();
   494             b.hide();
   507         });
   495         });
   510         if (this.renderer.minimap) {
   498         if (this.renderer.minimap) {
   511             this.minimap_circle.strokeColor = undefined;
   499             this.minimap_circle.strokeColor = undefined;
   512         }
   500         }
   513         this.super("unselect");
   501         this.super("unselect");
   514     }
   502     }
   515 };
   503 },
   516     
   504 highlight: function() {
   517 Rkns.Renderer.Node.prototype.highlight = function() {
       
   518     if (this.highlighted) {
   505     if (this.highlighted) {
   519         return;
   506         return;
   520     }
   507     }
   521     this.highlighted = true;
   508     this.highlighted = true;
   522     this.redraw();
   509     this.redraw();
   523     this.renderer.throttledPaperDraw();
   510     this.renderer.throttledPaperDraw();
   524 };
   511 },
   525 
   512 unhighlight: function() {
   526 Rkns.Renderer.Node.prototype.unhighlight = function() {
       
   527     if (!this.highlighted) {
   513     if (!this.highlighted) {
   528         return;
   514         return;
   529     }
   515     }
   530     this.highlighted = false;
   516     this.highlighted = false;
   531     this.redraw();
   517     this.redraw();
   532     this.renderer.throttledPaperDraw();
   518     this.renderer.throttledPaperDraw();
   533 };
   519 },
   534 
   520 saveCoords: function() {
   535 Rkns.Renderer.Node.prototype.saveCoords = function() {
       
   536     var _coords = this.renderer.toModelCoords(this.paper_coords),
   521     var _coords = this.renderer.toModelCoords(this.paper_coords),
   537         _data = {
   522         _data = {
   538             position: {
   523             position: {
   539                 x: _coords.x,
   524                 x: _coords.x,
   540                 y: _coords.y
   525                 y: _coords.y
   541             }
   526             }
   542         };
   527         };
   543     if (this.renderer.isEditable()) {
   528     if (this.renderer.isEditable()) {
   544         this.model.set(_data);
   529         this.model.set(_data);
   545     }
   530     }
   546 };
   531 },
   547 
   532 mousedown: function(_event, _isTouch) {
   548 Rkns.Renderer.Node.prototype.mousedown = function(_event, _isTouch) {
       
   549     if (_isTouch) {
   533     if (_isTouch) {
   550         this.renderer.unselectAll();
   534         this.renderer.unselectAll();
   551         this.select();
   535         this.select();
   552     }
   536     }
   553 };
   537 },
   554 
   538 mouseup: function(_event, _isTouch) {
   555 Rkns.Renderer.Node.prototype.mouseup = function(_event, _isTouch) {
       
   556     if (this.renderer.is_dragging && this.renderer.isEditable()) {
   539     if (this.renderer.is_dragging && this.renderer.isEditable()) {
   557         this.saveCoords();
   540         this.saveCoords();
   558     } else {
   541     } else {
   559         if (!_isTouch && !this.model.get("delete_scheduled")) {
   542         if (!_isTouch && !this.model.get("delete_scheduled")) {
   560             this.openEditor();
   543             this.openEditor();
   562         this.model.trigger("clicked");
   545         this.model.trigger("clicked");
   563     }
   546     }
   564     this.renderer.click_target = null;
   547     this.renderer.click_target = null;
   565     this.renderer.is_dragging = false;
   548     this.renderer.is_dragging = false;
   566     this.is_dragging = false;
   549     this.is_dragging = false;
   567 };
   550 },
   568 
   551 destroy: function(_event) {
   569 Rkns.Renderer.Node.prototype.destroy = function(_event) {
       
   570     this.super("destroy");
   552     this.super("destroy");
   571     this.all_buttons.forEach(function(b) {
   553     this.all_buttons.forEach(function(b) {
   572         b.destroy();
   554         b.destroy();
   573     });
   555     });
   574     this.circle.remove();
   556     this.circle.remove();
   577         this.minimap_circle.remove();
   559         this.minimap_circle.remove();
   578     }
   560     }
   579     if (this.node_image) {
   561     if (this.node_image) {
   580         this.node_image.remove();
   562         this.node_image.remove();
   581     }
   563     }
   582 };
   564 }
       
   565 });
   583 
   566 
   584 /* */
   567 /* */
   585 
   568 
   586 Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   569 var Edge = Renderer.Edge = Rkns.Utils.inherit(_BaseRepresentation);
   587 
   570 
   588 Rkns.Renderer.Edge.prototype._init = function() {
   571 Rkns._(Edge.prototype).extend({
       
   572 _init: function() {
   589     this.renderer.edge_layer.activate();
   573     this.renderer.edge_layer.activate();
   590     this.type = "Edge";
   574     this.type = "Edge";
   591     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
   575     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
   592     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
   576     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
   593     this.bundle = this.renderer.addToBundles(this);
   577     this.bundle = this.renderer.addToBundles(this);
   604     this.arrow.__representation = this;
   588     this.arrow.__representation = this;
   605     this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
   589     this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
   606     this.arrow_angle = 0;
   590     this.arrow_angle = 0;
   607     if (this.options.editor_mode) {
   591     if (this.options.editor_mode) {
   608         this.normal_buttons = [
   592         this.normal_buttons = [
   609             new Rkns.Renderer.EdgeEditButton(this.renderer, null),
   593             new EdgeEditButton(this.renderer, null),
   610             new Rkns.Renderer.EdgeRemoveButton(this.renderer, null),
   594             new EdgeRemoveButton(this.renderer, null),
   611         ];
   595         ];
   612         this.pending_delete_buttons = [
   596         this.pending_delete_buttons = [
   613             new Rkns.Renderer.EdgeRevertButton(this.renderer, null)
   597             new EdgeRevertButton(this.renderer, null)
   614         ];
   598         ];
   615         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
   599         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
   616         for (var i = 0; i < this.all_buttons.length; i++) {
   600         for (var i = 0; i < this.all_buttons.length; i++) {
   617             this.all_buttons[i].source_representation = this;
   601             this.all_buttons[i].source_representation = this;
   618         }
   602         }
   626         this.minimap_line = new paper.Path();
   610         this.minimap_line = new paper.Path();
   627         this.minimap_line.add([0,0],[0,0]);
   611         this.minimap_line.add([0,0],[0,0]);
   628         this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;
   612         this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;
   629         this.minimap_line.strokeWidth = 1;
   613         this.minimap_line.strokeWidth = 1;
   630     }
   614     }
   631 };
   615 },
   632 
   616 redraw: function() {
   633 Rkns.Renderer.Edge.prototype.redraw = function() {
       
   634     var from = this.model.get("from"),
   617     var from = this.model.get("from"),
   635         to = this.model.get("to");
   618         to = this.model.get("to");
   636     if (!from || !to) {
   619     if (!from || !to) {
   637         return;
   620         return;
   638     }
   621     }
   652         _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
   635         _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
   653         _p1b = _p1a.add(_delta), /* to differentiate bundled links */
   636         _p1b = _p1a.add(_delta), /* to differentiate bundled links */
   654         _a = _v.angle,
   637         _a = _v.angle,
   655         _textdelta = _ortho.multiply(this.options.edge_label_distance),
   638         _textdelta = _ortho.multiply(this.options.edge_label_distance),
   656         _handle = _v.divide(3),
   639         _handle = _v.divide(3),
   657         _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
   640         _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color");
   658     
   641     
   659     if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
   642     if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
   660         var opacity = .5;
   643         var opacity = .5;
   661         this.line.dashArray = [2, 2];
   644         this.line.dashArray = [2, 2];
   662     } else {
   645     } else {
   697     if (_a < -90) {
   680     if (_a < -90) {
   698         _a += 180;
   681         _a += 180;
   699         _textdelta = _textdelta.multiply(-1);
   682         _textdelta = _textdelta.multiply(-1);
   700     }
   683     }
   701     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
   684     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
   702     _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length);
   685     _text = shortenText(_text, this.options.node_label_max_length);
   703     this.text.text(_text);
   686     this.text.text(_text);
   704     var _textpos = this.paper_coords.add(_textdelta);
   687     var _textpos = this.paper_coords.add(_textdelta);
   705     this.text.css({
   688     this.text.css({
   706         left: _textpos.x,
   689         left: _textpos.x,
   707         top: _textpos.y,
   690         top: _textpos.y,
   720     if (this.renderer.minimap) {
   703     if (this.renderer.minimap) {
   721         this.minimap_line.strokeColor = _color;
   704         this.minimap_line.strokeColor = _color;
   722         this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position")));
   705         this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position")));
   723          this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
   706          this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
   724     }
   707     }
   725 };
   708 },
   726 
   709 openEditor: function() {
   727 Rkns.Renderer.Edge.prototype.openEditor = function() {
       
   728     this.renderer.removeRepresentationsOfType("editor");
   710     this.renderer.removeRepresentationsOfType("editor");
   729     var _editor = this.renderer.addRepresentation("EdgeEditor",null);
   711     var _editor = this.renderer.addRepresentation("EdgeEditor",null);
   730     _editor.source_representation = this;
   712     _editor.source_representation = this;
   731     _editor.draw();
   713     _editor.draw();
   732 };
   714 },
   733 
   715 select: function() {
   734 Rkns.Renderer.Edge.prototype.select = function() {
       
   735     this.selected = true;
   716     this.selected = true;
   736     this.line.strokeWidth = this.options.selected_edge_stroke_width;
   717     this.line.strokeWidth = this.options.selected_edge_stroke_width;
   737     if (this.renderer.isEditable()) {
   718     if (this.renderer.isEditable()) {
   738         this.active_buttons.forEach(function(b) {
   719         this.active_buttons.forEach(function(b) {
   739             b.show();
   720             b.show();
   741     }
   722     }
   742     if (!this.options.editor_mode) {
   723     if (!this.options.editor_mode) {
   743         this.openEditor();
   724         this.openEditor();
   744     }
   725     }
   745     this.super("select");
   726     this.super("select");
   746 };
   727 },
   747 
   728 unselect: function(_newTarget) {
   748 Rkns.Renderer.Edge.prototype.unselect = function(_newTarget) {
       
   749     if (!_newTarget || _newTarget.source_representation !== this) {
   729     if (!_newTarget || _newTarget.source_representation !== this) {
   750         this.selected = false;
   730         this.selected = false;
   751         if (this.options.editor_mode) {
   731         if (this.options.editor_mode) {
   752             this.all_buttons.forEach(function(b) {
   732             this.all_buttons.forEach(function(b) {
   753                 b.hide();
   733                 b.hide();
   754             });
   734             });
   755         }
   735         }
   756         this.line.strokeWidth = this.options.edge_stroke_width;
   736         this.line.strokeWidth = this.options.edge_stroke_width;
   757         this.super("unselect");
   737         this.super("unselect");
   758     }
   738     }
   759 };
   739 },
   760 
   740 mousedown: function(_event, _isTouch) {
   761 Rkns.Renderer.Edge.prototype.mousedown = function(_event, _isTouch) {
       
   762     if (_isTouch) {
   741     if (_isTouch) {
   763         this.renderer.unselectAll();
   742         this.renderer.unselectAll();
   764         this.select();
   743         this.select();
   765     }
   744     }
   766 };
   745 },
   767 
   746 mouseup: function(_event, _isTouch) {
   768 Rkns.Renderer.Edge.prototype.mouseup = function(_event, _isTouch) {
       
   769     if (!this.renkan.read_only && this.renderer.is_dragging) {
   747     if (!this.renkan.read_only && this.renderer.is_dragging) {
   770         this.from_representation.saveCoords();
   748         this.from_representation.saveCoords();
   771         this.to_representation.saveCoords();
   749         this.to_representation.saveCoords();
   772         this.from_representation.is_dragging = false;
   750         this.from_representation.is_dragging = false;
   773         this.to_representation.is_dragging = false;
   751         this.to_representation.is_dragging = false;
   777         }
   755         }
   778         this.model.trigger("clicked");
   756         this.model.trigger("clicked");
   779     }
   757     }
   780     this.renderer.click_target = null;
   758     this.renderer.click_target = null;
   781     this.renderer.is_dragging = false;
   759     this.renderer.is_dragging = false;
   782 };
   760 },
   783 
   761 paperShift: function(_delta) {
   784 Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
       
   785     if (this.options.editor_mode) {
   762     if (this.options.editor_mode) {
   786         if (!this.options.read_only) {
   763         if (!this.options.read_only) {
   787             this.from_representation.paperShift(_delta);
   764             this.from_representation.paperShift(_delta);
   788             this.to_representation.paperShift(_delta);
   765             this.to_representation.paperShift(_delta);
   789         }
   766         }
   790     } else {
   767     } else {
   791         this.renderer.paperShift(_delta);
   768         this.renderer.paperShift(_delta);
   792     }
   769     }
   793 };
   770 },
   794 
   771 destroy: function() {
   795 Rkns.Renderer.Edge.prototype.destroy = function() {
       
   796     this.super("destroy");
   772     this.super("destroy");
   797     this.line.remove();
   773     this.line.remove();
   798     this.arrow.remove();
   774     this.arrow.remove();
   799     this.text.remove();
   775     this.text.remove();
   800     if (this.renderer.minimap) {
   776     if (this.renderer.minimap) {
   805     });
   781     });
   806     var _this = this;
   782     var _this = this;
   807     this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
   783     this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
   808         return _edge === _this;
   784         return _edge === _this;
   809     });
   785     });
   810 };
   786 }
       
   787 });
   811 
   788 
   812 /* */
   789 /* */
   813 
   790 
   814 Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   791 var TempEdge = Renderer.TempEdge = Rkns.Utils.inherit(_BaseRepresentation);
   815 
   792 
   816 Rkns.Renderer.TempEdge.prototype._init = function() {
   793 Rkns._(TempEdge.prototype).extend({
       
   794 _init: function() {
   817     this.renderer.edge_layer.activate();
   795     this.renderer.edge_layer.activate();
   818     this.type = "Temp-edge";
   796     this.type = "Temp-edge";
   819     
   797     
   820     var _color = (this.project.get("users").get(this.renkan.current_user) || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
   798     var _color = (this.project.get("users").get(this.renkan.current_user) || _USER_PLACEHOLDER(this.renkan)).get("color");
   821     this.line = new paper.Path();
   799     this.line = new paper.Path();
   822     this.line.strokeColor = _color;
   800     this.line.strokeColor = _color;
   823     this.line.dashArray = [4, 2];
   801     this.line.dashArray = [4, 2];
   824     this.line.strokeWidth = this.options.selected_edge_stroke_width;
   802     this.line.strokeWidth = this.options.selected_edge_stroke_width;
   825     this.line.add([0,0],[0,0]);
   803     this.line.add([0,0],[0,0]);
   831         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
   809         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
   832         [ 0, this.options.edge_arrow_width ]
   810         [ 0, this.options.edge_arrow_width ]
   833     );
   811     );
   834     this.arrow.__representation = this;
   812     this.arrow.__representation = this;
   835     this.arrow_angle = 0;
   813     this.arrow_angle = 0;
   836 };
   814 },
   837 
   815 redraw: function() {
   838 Rkns.Renderer.TempEdge.prototype.redraw = function() {
       
   839     var _p0 = this.from_representation.paper_coords,
   816     var _p0 = this.from_representation.paper_coords,
   840         _p1 = this.end_pos,
   817         _p1 = this.end_pos,
   841         _a = _p1.subtract(_p0).angle,
   818         _a = _p1.subtract(_p0).angle,
   842         _c = _p0.add(_p1).divide(2);
   819         _c = _p0.add(_p1).divide(2);
   843     this.line.segments[0].point = _p0;
   820     this.line.segments[0].point = _p0;
   844     this.line.segments[1].point = _p1;
   821     this.line.segments[1].point = _p1;
   845     this.arrow.rotate(_a - this.arrow_angle);
   822     this.arrow.rotate(_a - this.arrow_angle);
   846     this.arrow.position = _c;
   823     this.arrow.position = _c;
   847     this.arrow_angle = _a;
   824     this.arrow_angle = _a;
   848 };
   825 },
   849 
   826 paperShift: function(_delta) {
   850 Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
       
   851     if (!this.renderer.isEditable()) {
   827     if (!this.renderer.isEditable()) {
   852         this.renderer.removeRepresentation(_this);
   828         this.renderer.removeRepresentation(_this);
   853         paper.view.draw();
   829         paper.view.draw();
   854         return;
   830         return;
   855     }
   831     }
   856     this.end_pos = this.end_pos.add(_delta);
   832     this.end_pos = this.end_pos.add(_delta);
   857     var _hitResult = paper.project.hitTest(this.end_pos);
   833     var _hitResult = paper.project.hitTest(this.end_pos);
   858     this.renderer.findTarget(_hitResult);
   834     this.renderer.findTarget(_hitResult);
   859     this.redraw();
   835     this.redraw();
   860 };
   836 },
   861 
   837 mouseup: function(_event, _isTouch) {
   862 Rkns.Renderer.TempEdge.prototype.mouseup = function(_event, _isTouch) {
       
   863     var _hitResult = paper.project.hitTest(_event.point),
   838     var _hitResult = paper.project.hitTest(_event.point),
   864         _model = this.from_representation.model,
   839         _model = this.from_representation.model,
   865         _endDrag = true;
   840         _endDrag = true;
   866     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
   841     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
   867         var _target = _hitResult.item.__representation;
   842         var _target = _hitResult.item.__representation;
   889         this.renderer.click_target = null;
   864         this.renderer.click_target = null;
   890         this.renderer.is_dragging = false;
   865         this.renderer.is_dragging = false;
   891         this.renderer.removeRepresentation(this);
   866         this.renderer.removeRepresentation(this);
   892         paper.view.draw();
   867         paper.view.draw();
   893     }
   868     }
   894 };
   869 },
   895 
   870 destroy: function() {
   896 Rkns.Renderer.TempEdge.prototype.destroy = function() {
       
   897     this.arrow.remove();
   871     this.arrow.remove();
   898     this.line.remove();
   872     this.line.remove();
   899 };
   873 }
       
   874 });
   900 
   875 
   901 /* */
   876 /* */
   902 
   877 
   903 Rkns.Renderer._BaseEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   878 var _BaseEditor = Renderer._BaseEditor = Rkns.Utils.inherit(_BaseRepresentation);
   904 
   879 
   905 Rkns.Renderer._BaseEditor.prototype._init = function() {
   880 Rkns._(_BaseEditor.prototype).extend({
       
   881 _init: function() {
   906     this.renderer.buttons_layer.activate();
   882     this.renderer.buttons_layer.activate();
   907     this.type = "editor";
   883     this.type = "editor";
   908     this.editor_block = new paper.Path();
   884     this.editor_block = new paper.Path();
   909     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0];});
   885     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0];});
   910     this.editor_block.add.apply(this.editor_block, _pts);
   886     this.editor_block.add.apply(this.editor_block, _pts);
   916         .css({
   892         .css({
   917             position: "absolute",
   893             position: "absolute",
   918             opacity: .8
   894             opacity: .8
   919         })
   895         })
   920         .hide();
   896         .hide();
   921 };
   897 },
   922 
   898 destroy: function() {
   923 Rkns.Renderer._BaseEditor.prototype.destroy = function() {
       
   924     this.editor_block.remove();
   899     this.editor_block.remove();
   925     this.editor_$.remove();
   900     this.editor_$.remove();
   926 };
   901 }
       
   902 });
   927 
   903 
   928 /* */
   904 /* */
   929 
   905 
   930 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor);
   906 var NodeEditor = Renderer.NodeEditor = Rkns.Utils.inherit(_BaseEditor);
   931 
   907 
   932 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
   908 Rkns._(NodeEditor.prototype).extend({
       
   909 template: Rkns._.template(
   933     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
   910     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
   934     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
   911     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
   935     + '<% 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_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><% } %>'
   936     + '<% 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_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
   937     + '<% 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_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><% } %>'
   939     + '<% _(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><% } %>'
   916     + '<% _(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><% } %>'
   940     + '<% 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 (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
   941     + '<% 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     + '<% 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><% }%>'
   942     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
   919     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
   943     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
   920     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
   944     + '<% 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><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>'
   921     + '<% 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><% } %>'
   945 );
   922 ),
   946 
   923 readOnlyTemplate: Rkns._.template(
   947 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
       
   948     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
   924     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
   949     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
   925     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
   950     + '<% 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 (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
   951     + '<% if (options.show_node_tooltip_description) { %><p><%-node.description%></p><% } %>'
   927     + '<% if (options.show_node_tooltip_description) { %><p><%-node.description%></p><% } %>'
   952     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
   928     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
   953     + '<% if (node.has_creator && options.show_node_tooltip_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>'
   929     + '<% if (node.has_creator && options.show_node_tooltip_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><% } %>'
   954 );
   930 ),
   955 
   931 draw: function() {
   956 Rkns.Renderer.NodeEditor.prototype.draw = function() {
       
   957     var _model = this.source_representation.model,
   932     var _model = this.source_representation.model,
   958         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan),
   933         _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
   959         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),
   934         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),
   960         _image_placeholder = this.options.static_url + "img/image-placeholder.png",
   935         _image_placeholder = this.options.static_url + "img/image-placeholder.png",
   961         _size = (_model.get("size") || 0);
   936         _size = (_model.get("size") || 0);
   962     this.editor_$
   937     this.editor_$
   963         .html(_template({
   938         .html(_template({
   964             node: {
   939             node: {
   965                 has_creator: !!_model.get("created_by"),
   940                 has_creator: !!_model.get("created_by"),
   966                 title: _model.get("title"),
   941                 title: _model.get("title"),
   967                 uri: _model.get("uri"),
   942                 uri: _model.get("uri"),
   968                 short_uri:  Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
   943                 short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
   969                 description: _model.get("description"),
   944                 description: _model.get("description"),
   970                 image: _model.get("image") || "",
   945                 image: _model.get("image") || "",
   971                 image_placeholder: _image_placeholder,
   946                 image_placeholder: _image_placeholder,
   972                 color: _model.get("color") || _created_by.get("color"),
   947                 color: _model.get("color") || _created_by.get("color"),
   973                 clip_path: _model.get("clip-path") || false,
   948                 clip_path: _model.get("clip-path") || false,
   974                 created_by_color: _created_by.get("color"),
   949                 created_by_color: _created_by.get("color"),
   975                 created_by_title: _created_by.get("title"),
   950                 created_by_title: _created_by.get("title"),
   976                 size: (_size > 0 ? "+" : "") + _size
   951                 size: (_size > 0 ? "+" : "") + _size
   977             },
   952             },
   978             renkan: this.renkan,
   953             renkan: this.renkan,
   979             options: this.options
   954             options: this.options,
       
   955             shortenText: shortenText
   980         }));
   956         }));
   981     this.redraw();
   957     this.redraw();
   982     var _this = this,
   958     var _this = this,
   983         closeEditor = function() {
   959         closeEditor = function() {
   984             _this.renderer.removeRepresentation(_this);
   960             _this.renderer.removeRepresentation(_this);
  1028                     fr = new FileReader();
  1004                     fr = new FileReader();
  1029                 if (f.type.substr(0,5) !== "image") {
  1005                 if (f.type.substr(0,5) !== "image") {
  1030                     alert(_this.renkan.translate("This file is not an image"));
  1006                     alert(_this.renkan.translate("This file is not an image"));
  1031                     return;
  1007                     return;
  1032                 }
  1008                 }
  1033                 if (f.size > (Rkns.Renderer._IMAGE_MAX_KB * 1024)) {
  1009                 if (f.size > (_IMAGE_MAX_KB * 1024)) {
  1034                     alert(_this.renkan.translate("Image size must be under ")+Rkns.Renderer._IMAGE_MAX_KB+_this.renkan.translate("KB"));
  1010                     alert(_this.renkan.translate("Image size must be under ")+_IMAGE_MAX_KB+_this.renkan.translate("KB"));
  1035                     return;
  1011                     return;
  1036                 }
  1012                 }
  1037                 fr.onload = function(e) {
  1013                 fr.onload = function(e) {
  1038                     _this.editor_$.find(".Rk-Edit-Image").val(e.target.result);
  1014                     _this.editor_$.find(".Rk-Edit-Image").val(e.target.result);
  1039                     onFieldChange();
  1015                     onFieldChange();
  1061                 _e.preventDefault();
  1037                 _e.preventDefault();
  1062                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  1038                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  1063             },
  1039             },
  1064             function(_e) {
  1040             function(_e) {
  1065                 _e.preventDefault();
  1041                 _e.preventDefault();
  1066                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color"));
  1042                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
  1067             }
  1043             }
  1068         ).click(function(_e) {
  1044         ).click(function(_e) {
  1069             _e.preventDefault();
  1045             _e.preventDefault();
  1070             if (_this.renderer.isEditable()) {
  1046             if (_this.renderer.isEditable()) {
  1071                 _model.set("color", $(this).attr("data-color"));
  1047                 _model.set("color", $(this).attr("data-color"));
  1097         });
  1073         });
  1098     }
  1074     }
  1099     this.editor_$.find("img").load(function() {
  1075     this.editor_$.find("img").load(function() {
  1100         _this.redraw();
  1076         _this.redraw();
  1101     });
  1077     });
  1102 };
  1078 },
  1103 
  1079 redraw: function() {
  1104 Rkns.Renderer.NodeEditor.prototype.redraw = function() {
       
  1105     var _coords = this.source_representation.paper_coords;
  1080     var _coords = this.source_representation.paper_coords;
  1106     Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
  1081     drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
  1107     this.editor_$.show();
  1082     this.editor_$.show();
  1108     paper.view.draw();
  1083     paper.view.draw();
  1109 };
  1084 }
       
  1085 });
  1110 
  1086 
  1111 /* */
  1087 /* */
  1112 
  1088 
  1113 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor);
  1089 var EdgeEditor = Renderer.EdgeEditor = Rkns.Utils.inherit(_BaseEditor);
  1114 
  1090 
  1115 Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template(
  1091 Rkns._(EdgeEditor.prototype).extend({
       
  1092 template: Rkns._.template(
  1116     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  1093     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  1117     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  1094     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  1118     + '<% 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>'
  1095     + '<% 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>'
  1119     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  1096     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  1120     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  1097     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  1122     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  1099     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  1123     + '<% }) %><% }) %></select></p><% } } %>'
  1100     + '<% }) %><% }) %></select></p><% } } %>'
  1124     + '<% 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">'
  1101     + '<% 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">'
  1125     + '<% _(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><% } %>'
  1102     + '<% _(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><% } %>'
  1126     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  1103     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  1127     + '<% 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><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>'
  1104     + '<% 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>'
  1128     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p><% } %>'
  1105     + '<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><% } %>'
  1129     + '<% 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><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>'
  1106     + '<% 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><% } %>'
  1130 );
  1107 ),
  1131 
  1108 readOnlyTemplate: Rkns._.template(
  1132 Rkns.Renderer.EdgeEditor.prototype.readOnlyTemplate = Rkns._.template(
       
  1133     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  1109     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  1134     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  1110     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  1135     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  1111     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  1136     + '<p><%-edge.description%></p>'
  1112     + '<p><%-edge.description%></p>'
  1137     + '<% 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><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>'
  1113     + '<% 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>'
  1138     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p><% } %>'
  1114     + '<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><% } %>'
  1139     + '<% if (options.show_edge_tooltip_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><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>'
  1115     + '<% if (options.show_edge_tooltip_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><% } %>'
  1140 );
  1116 ),
  1141 
  1117 draw: function() {
  1142 Rkns.Renderer.EdgeEditor.prototype.draw = function() {
       
  1143     var _model = this.source_representation.model,
  1118     var _model = this.source_representation.model,
  1144         _from_model = _model.get("from"),
  1119         _from_model = _model.get("from"),
  1145         _to_model = _model.get("to"),
  1120         _to_model = _model.get("to"),
  1146         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan),
  1121         _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
  1147         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
  1122         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
  1148     this.editor_$
  1123     this.editor_$
  1149         .html(_template({
  1124         .html(_template({
  1150             edge: {
  1125             edge: {
  1151                 has_creator: !!_model.get("created_by"),
  1126                 has_creator: !!_model.get("created_by"),
  1152                 title: _model.get("title"),
  1127                 title: _model.get("title"),
  1153                 uri: _model.get("uri"),
  1128                 uri: _model.get("uri"),
  1154                 short_uri:  Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  1129                 short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  1155                 description: _model.get("description"),
  1130                 description: _model.get("description"),
  1156                 color: _model.get("color") || _created_by.get("color"),
  1131                 color: _model.get("color") || _created_by.get("color"),
  1157                 from_title: _from_model.get("title"),
  1132                 from_title: _from_model.get("title"),
  1158                 to_title: _to_model.get("title"),
  1133                 to_title: _to_model.get("title"),
  1159                 from_color: _from_model.get("color") || (_from_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"),
  1134                 from_color: _from_model.get("color") || (_from_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
  1160                 to_color: _to_model.get("color") || (_to_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"),
  1135                 to_color: _to_model.get("color") || (_to_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
  1161                 created_by_color: _created_by.get("color"),
  1136                 created_by_color: _created_by.get("color"),
  1162                 created_by_title: _created_by.get("title")
  1137                 created_by_title: _created_by.get("title")
  1163             },
  1138             },
  1164             renkan: this.renkan,
  1139             renkan: this.renkan,
       
  1140             shortenText: shortenText,
  1165             options: this.options,
  1141             options: this.options,
  1166         }));
  1142         }));
  1167     this.redraw();
  1143     this.redraw();
  1168     var _this = this,
  1144     var _this = this,
  1169         closeEditor = function() {
  1145         closeEditor = function() {
  1239                 _e.preventDefault();
  1215                 _e.preventDefault();
  1240                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  1216                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  1241             },
  1217             },
  1242             function(_e) {
  1218             function(_e) {
  1243                 _e.preventDefault();
  1219                 _e.preventDefault();
  1244                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color"));
  1220                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
  1245             }
  1221             }
  1246         ).click(function(_e) {
  1222         ).click(function(_e) {
  1247             _e.preventDefault();
  1223             _e.preventDefault();
  1248             if (_this.renderer.isEditable()) {
  1224             if (_this.renderer.isEditable()) {
  1249                 _model.set("color", $(this).attr("data-color"));
  1225                 _model.set("color", $(this).attr("data-color"));
  1252             } else {
  1228             } else {
  1253                 closeEditor();
  1229                 closeEditor();
  1254             }
  1230             }
  1255         });
  1231         });
  1256     }
  1232     }
  1257 };
  1233 },
  1258 
  1234 redraw: function() {
  1259 Rkns.Renderer.EdgeEditor.prototype.redraw = function() {
       
  1260     var _coords = this.source_representation.paper_coords;
  1235     var _coords = this.source_representation.paper_coords;
  1261     Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
  1236     drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
  1262     this.editor_$.show();
  1237     this.editor_$.show();
  1263     paper.view.draw();
  1238     paper.view.draw();
  1264 };
  1239 }
       
  1240 });
  1265 
  1241 
  1266 /* */
  1242 /* */
  1267 
  1243 
  1268 Rkns.Renderer._NodeButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  1244 var _NodeButton = Renderer._NodeButton = Rkns.Utils.inherit(_BaseButton);
  1269 
  1245 
  1270 Rkns.Renderer._NodeButton.prototype.setSectorSize = function() {
  1246 Rkns._(_NodeButton.prototype).extend({
       
  1247 setSectorSize: function() {
  1271     var sectorInner = this.source_representation.circle_radius;
  1248     var sectorInner = this.source_representation.circle_radius;
  1272     if (sectorInner !== this.lastSectorInner) {
  1249     if (sectorInner !== this.lastSectorInner) {
  1273         if (this.sector) {
  1250         if (this.sector) {
  1274             this.sector.destroy();
  1251             this.sector.destroy();
  1275         }
  1252         }
  1276         this.sector = this.renderer.drawSector(
  1253         this.sector = this.renderer.drawSector(
  1277             this, 1 + sectorInner,
  1254             this, 1 + sectorInner,
  1278             Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner,
  1255             _NODE_BUTTON_WIDTH + sectorInner,
  1279             this.startAngle,
  1256             this.startAngle,
  1280             this.endAngle,
  1257             this.endAngle,
  1281             1,
  1258             1,
  1282             this.imageName,
  1259             this.imageName,
  1283             this.renkan.translate(this.text)
  1260             this.renkan.translate(this.text)
  1284         );
  1261         );
  1285         this.lastSectorInner = sectorInner;
  1262         this.lastSectorInner = sectorInner;
  1286     }
  1263     }
  1287 };
  1264 }
       
  1265 });
  1288 
  1266 
  1289 /* */
  1267 /* */
  1290 
  1268 
  1291 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1269 var NodeEditButton = Renderer.NodeEditButton = Rkns.Utils.inherit(_NodeButton);
  1292 
  1270 
  1293 Rkns.Renderer.NodeEditButton.prototype._init = function() {
  1271 Rkns._(NodeEditButton.prototype).extend({
       
  1272 _init: function() {
  1294     this.type = "Node-edit-button";
  1273     this.type = "Node-edit-button";
  1295     this.lastSectorInner = 0;
  1274     this.lastSectorInner = 0;
  1296     this.startAngle = -135;
  1275     this.startAngle = -135;
  1297     this.endAngle = -45;
  1276     this.endAngle = -45;
  1298     this.imageName = "edit";
  1277     this.imageName = "edit";
  1299     this.text = "Edit";
  1278     this.text = "Edit";
  1300 };
  1279 },
  1301 
  1280 mouseup: function() {
  1302 Rkns.Renderer.NodeEditButton.prototype.mouseup = function() {
       
  1303     if (!this.renderer.is_dragging) {
  1281     if (!this.renderer.is_dragging) {
  1304         this.source_representation.openEditor();
  1282         this.source_representation.openEditor();
  1305     }
  1283     }
  1306 };
  1284 }
       
  1285 });
  1307 
  1286 
  1308 /* */
  1287 /* */
  1309 
  1288 
  1310 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1289 var NodeRemoveButton = Renderer.NodeRemoveButton = Rkns.Utils.inherit(_NodeButton);
  1311 
  1290 
  1312 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
  1291 Rkns._(NodeRemoveButton.prototype).extend({
       
  1292 _init: function() {
  1313     this.type = "Node-remove-button";
  1293     this.type = "Node-remove-button";
  1314     this.lastSectorInner = 0;
  1294     this.lastSectorInner = 0;
  1315     this.startAngle = 0;
  1295     this.startAngle = 0;
  1316     this.endAngle = 90;
  1296     this.endAngle = 90;
  1317     this.imageName = "remove";
  1297     this.imageName = "remove";
  1318     this.text = "Remove";
  1298     this.text = "Remove";
  1319 };
  1299 },
  1320 
  1300 mouseup: function() {
  1321 Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
       
  1322     this.renderer.click_target = null;
  1301     this.renderer.click_target = null;
  1323     this.renderer.is_dragging = false;
  1302     this.renderer.is_dragging = false;
  1324     this.renderer.removeRepresentationsOfType("editor");
  1303     this.renderer.removeRepresentationsOfType("editor");
  1325     if (this.renderer.isEditable()) {
  1304     if (this.renderer.isEditable()) {
  1326         if (this.options.element_delete_delay) {
  1305         if (this.options.element_delete_delay) {
  1334             if (confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
  1313             if (confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
  1335                 this.project.removeNode(this.source_representation.model);
  1314                 this.project.removeNode(this.source_representation.model);
  1336             }
  1315             }
  1337         }
  1316         }
  1338     }
  1317     }
  1339 };
  1318 }
       
  1319 });
  1340 
  1320 
  1341 /* */
  1321 /* */
  1342 
  1322 
  1343 Rkns.Renderer.NodeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1323 var NodeRevertButton = Renderer.NodeRevertButton = Rkns.Utils.inherit(_NodeButton);
  1344 
  1324 
  1345 Rkns.Renderer.NodeRevertButton.prototype._init = function() {
  1325 Rkns._(NodeRevertButton.prototype).extend({
       
  1326 _init: function() {
  1346     this.type = "Node-revert-button";
  1327     this.type = "Node-revert-button";
  1347     this.lastSectorInner = 0;
  1328     this.lastSectorInner = 0;
  1348     this.startAngle = -135;
  1329     this.startAngle = -135;
  1349     this.endAngle = 135;
  1330     this.endAngle = 135;
  1350     this.imageName = "revert";
  1331     this.imageName = "revert";
  1351     this.text = "Cancel deletion";
  1332     this.text = "Cancel deletion";
  1352 };
  1333 },
  1353 
  1334 mouseup: function() {
  1354 Rkns.Renderer.NodeRevertButton.prototype.mouseup = function() {
       
  1355     this.renderer.click_target = null;
  1335     this.renderer.click_target = null;
  1356     this.renderer.is_dragging = false;
  1336     this.renderer.is_dragging = false;
  1357     if (this.renderer.isEditable()) {
  1337     if (this.renderer.isEditable()) {
  1358         this.source_representation.model.unset("delete_scheduled");
  1338         this.source_representation.model.unset("delete_scheduled");
  1359     }
  1339     }
  1360 };
  1340 }
       
  1341 });
  1361 
  1342 
  1362 /* */
  1343 /* */
  1363 
  1344 
  1364 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1345 var NodeLinkButton = Renderer.NodeLinkButton = Rkns.Utils.inherit(_NodeButton);
  1365 
  1346 
  1366 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
  1347 Rkns._(NodeLinkButton.prototype).extend({
       
  1348 _init: function() {
  1367     this.type = "Node-link-button";
  1349     this.type = "Node-link-button";
  1368     this.lastSectorInner = 0;
  1350     this.lastSectorInner = 0;
  1369     this.startAngle = 90;
  1351     this.startAngle = 90;
  1370     this.endAngle = 180;
  1352     this.endAngle = 180;
  1371     this.imageName = "link";
  1353     this.imageName = "link";
  1372     this.text = "Link to another node";
  1354     this.text = "Link to another node";
  1373 };
  1355 },
  1374 
  1356 mousedown: function(_event, _isTouch) {
  1375 Rkns.Renderer.NodeLinkButton.prototype.mousedown = function(_event, _isTouch) {
       
  1376     if (this.renderer.isEditable()) {
  1357     if (this.renderer.isEditable()) {
  1377         var _off = this.renderer.canvas_$.offset(),
  1358         var _off = this.renderer.canvas_$.offset(),
  1378             _point = new paper.Point([
  1359             _point = new paper.Point([
  1379                 _event.pageX - _off.left,
  1360                 _event.pageX - _off.left,
  1380                 _event.pageY - _off.top
  1361                 _event.pageY - _off.top
  1381             ]);
  1362             ]);
  1382         this.renderer.click_target = null;
  1363         this.renderer.click_target = null;
  1383         this.renderer.removeRepresentationsOfType("editor");
  1364         this.renderer.removeRepresentationsOfType("editor");
  1384         this.renderer.addTempEdge(this.source_representation, _point);
  1365         this.renderer.addTempEdge(this.source_representation, _point);
  1385     }
  1366     }
  1386 };
  1367 }
       
  1368 });
  1387 
  1369 
  1388 /* */
  1370 /* */
  1389 
  1371 
  1390 Rkns.Renderer.NodeEnlargeButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1372 var NodeEnlargeButton = Renderer.NodeEnlargeButton = Rkns.Utils.inherit(_NodeButton);
  1391 
  1373 
  1392 Rkns.Renderer.NodeEnlargeButton.prototype._init = function() {
  1374 Rkns._(NodeEnlargeButton.prototype).extend({
       
  1375 _init: function() {
  1393     this.type = "Node-enlarge-button";
  1376     this.type = "Node-enlarge-button";
  1394     this.lastSectorInner = 0;
  1377     this.lastSectorInner = 0;
  1395     this.startAngle = -45;
  1378     this.startAngle = -45;
  1396     this.endAngle = 0;
  1379     this.endAngle = 0;
  1397     this.imageName = "enlarge";
  1380     this.imageName = "enlarge";
  1398     this.text = "Enlarge";
  1381     this.text = "Enlarge";
  1399 };
  1382 },
  1400 
  1383 mouseup: function() {
  1401 Rkns.Renderer.NodeEnlargeButton.prototype.mouseup = function() {
       
  1402     var _newsize = 1 + (this.source_representation.model.get("size") || 0);
  1384     var _newsize = 1 + (this.source_representation.model.get("size") || 0);
  1403     this.source_representation.model.set("size", _newsize);
  1385     this.source_representation.model.set("size", _newsize);
  1404     this.source_representation.select();
  1386     this.source_representation.select();
  1405     this.select();
  1387     this.select();
  1406     paper.view.draw();
  1388     paper.view.draw();
  1407 };
  1389 }
       
  1390 });
  1408 
  1391 
  1409 /* */
  1392 /* */
  1410 
  1393 
  1411 Rkns.Renderer.NodeShrinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  1394 var NodeShrinkButton = Renderer.NodeShrinkButton = Rkns.Utils.inherit(_NodeButton);
  1412 
  1395 
  1413 Rkns.Renderer.NodeShrinkButton.prototype._init = function() {
  1396 Rkns._(NodeShrinkButton.prototype).extend({
       
  1397 _init: function() {
  1414     this.type = "Node-shrink-button";
  1398     this.type = "Node-shrink-button";
  1415     this.lastSectorInner = 0;
  1399     this.lastSectorInner = 0;
  1416     this.startAngle = -180;
  1400     this.startAngle = -180;
  1417     this.endAngle = -135;
  1401     this.endAngle = -135;
  1418     this.imageName = "shrink";
  1402     this.imageName = "shrink";
  1419     this.text = "Shrink";
  1403     this.text = "Shrink";
  1420 };
  1404 },
  1421 
  1405 mouseup: function() {
  1422 Rkns.Renderer.NodeShrinkButton.prototype.mouseup = function() {
       
  1423     var _newsize = -1 + (this.source_representation.model.get("size") || 0);
  1406     var _newsize = -1 + (this.source_representation.model.get("size") || 0);
  1424     this.source_representation.model.set("size", _newsize);
  1407     this.source_representation.model.set("size", _newsize);
  1425     this.source_representation.select();
  1408     this.source_representation.select();
  1426     this.select();
  1409     this.select();
  1427     paper.view.draw();
  1410     paper.view.draw();
  1428 };
  1411 }
       
  1412 });
  1429 
  1413 
  1430 /* */
  1414 /* */
  1431 
  1415 
  1432 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  1416 var EdgeEditButton = Renderer.EdgeEditButton = Rkns.Utils.inherit(_BaseButton);
  1433 
  1417 
  1434 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
  1418 Rkns._(EdgeEditButton.prototype).extend({
       
  1419 _init: function() {
  1435     this.type = "Edge-edit-button";
  1420     this.type = "Edge-edit-button";
  1436     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  1421     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  1437 };
  1422 },
  1438 
  1423 mouseup: function() {
  1439 Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() {
       
  1440     if (!this.renderer.is_dragging) {
  1424     if (!this.renderer.is_dragging) {
  1441         this.source_representation.openEditor();
  1425         this.source_representation.openEditor();
  1442     }
  1426     }
  1443 };
  1427 }
       
  1428 });
  1444 
  1429 
  1445 /* */
  1430 /* */
  1446 
  1431 
  1447 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  1432 var EdgeRemoveButton = Renderer.EdgeRemoveButton = Rkns.Utils.inherit(_BaseButton);
  1448 
  1433 
  1449 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
  1434 Rkns._(EdgeRemoveButton.prototype).extend({
       
  1435 _init: function() {
  1450     this.type = "Edge-remove-button";
  1436     this.type = "Edge-remove-button";
  1451     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  1437     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  1452 };
  1438 },
  1453 
  1439 mouseup: function() {
  1454 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
       
  1455     this.renderer.click_target = null;
  1440     this.renderer.click_target = null;
  1456     this.renderer.is_dragging = false;
  1441     this.renderer.is_dragging = false;
  1457     this.renderer.removeRepresentationsOfType("editor");
  1442     this.renderer.removeRepresentationsOfType("editor");
  1458     if (this.renderer.isEditable()) {
  1443     if (this.renderer.isEditable()) {
  1459         if (this.options.element_delete_delay) {
  1444         if (this.options.element_delete_delay) {
  1467             if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
  1452             if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
  1468                 this.project.removeEdge(this.source_representation.model);
  1453                 this.project.removeEdge(this.source_representation.model);
  1469             }
  1454             }
  1470         }
  1455         }
  1471     }
  1456     }
  1472 };
  1457 }
       
  1458 });
  1473 
  1459 
  1474 /* */
  1460 /* */
  1475 
  1461 
  1476 Rkns.Renderer.EdgeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  1462 var EdgeRevertButton = Renderer.EdgeRevertButton = Rkns.Utils.inherit(_BaseButton);
  1477 
  1463 
  1478 Rkns.Renderer.EdgeRevertButton.prototype._init = function() {
  1464 Rkns._(EdgeRevertButton.prototype).extend({
       
  1465 _init: function() {
  1479     this.type = "Edge-revert-button";
  1466     this.type = "Edge-revert-button";
  1480     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  1467     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  1481 };
  1468 },
  1482 
  1469 mouseup: function() {
  1483 Rkns.Renderer.EdgeRevertButton.prototype.mouseup = function() {
       
  1484     this.renderer.click_target = null;
  1470     this.renderer.click_target = null;
  1485     this.renderer.is_dragging = false;
  1471     this.renderer.is_dragging = false;
  1486     if (this.renderer.isEditable()) {
  1472     if (this.renderer.isEditable()) {
  1487         this.source_representation.model.unset("delete_scheduled");
  1473         this.source_representation.model.unset("delete_scheduled");
  1488     }
  1474     }
  1489 };
  1475 }
       
  1476 });
  1490 
  1477 
  1491 /* */
  1478 /* */
  1492 
  1479 
  1493 Rkns.Renderer.MiniFrame = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1480 var MiniFrame = Renderer.MiniFrame = Rkns.Utils.inherit(_BaseRepresentation);
  1494 
  1481 
  1495 Rkns.Renderer.MiniFrame.prototype.paperShift = function(_delta) {
  1482 Rkns._(MiniFrame.prototype).extend({
       
  1483 paperShift: function(_delta) {
  1496     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  1484     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  1497     this.renderer.redraw();
  1485     this.renderer.redraw();
  1498 };
  1486 },
  1499 
  1487 mouseup: function(_delta) {
  1500 Rkns.Renderer.MiniFrame.prototype.mouseup = function(_delta) {
       
  1501     this.renderer.click_target = null;
  1488     this.renderer.click_target = null;
  1502     this.renderer.is_dragging = false;
  1489     this.renderer.is_dragging = false;
  1503 };
  1490 }
       
  1491 });
  1504 
  1492 
  1505 /* */
  1493 /* */
  1506 
  1494 
  1507 Rkns.Renderer.Scene = function(_renkan) {
  1495 var Scene = Renderer.Scene = function(_renkan) {
  1508     this.renkan = _renkan;
  1496     this.renkan = _renkan;
  1509     this.$ = Rkns.$(".Rk-Render");
  1497     this.$ = Rkns.$(".Rk-Render");
  1510     this.representations = [];
  1498     this.representations = [];
  1511     this.$.html(this.template(_renkan));
  1499     this.$.html(this.template(_renkan));
  1512     this.onStatusChange();
  1500     this.onStatusChange();
  1552         this.minimap.node_group.addChild(this.minimap.miniframe);
  1540         this.minimap.node_group.addChild(this.minimap.miniframe);
  1553         this.minimap.miniframe.fillColor = '#c0c0ff';
  1541         this.minimap.miniframe.fillColor = '#c0c0ff';
  1554         this.minimap.miniframe.opacity = .3;
  1542         this.minimap.miniframe.opacity = .3;
  1555         this.minimap.miniframe.strokeColor = '#000080';
  1543         this.minimap.miniframe.strokeColor = '#000080';
  1556         this.minimap.miniframe.strokeWidth = 3;
  1544         this.minimap.miniframe.strokeWidth = 3;
  1557         this.minimap.miniframe.__representation = new Rkns.Renderer.MiniFrame(this, null);
  1545         this.minimap.miniframe.__representation = new MiniFrame(this, null);
  1558     }
  1546     }
  1559     
  1547     
  1560     this.throttledPaperDraw = Rkns._(function() {
  1548     this.throttledPaperDraw = Rkns._(function() {
  1561         paper.view.draw();
  1549         paper.view.draw();
  1562     }).throttle(100);
  1550     }).throttle(100);
  1581         _this.icon_cache[imgname] = img;
  1569         _this.icon_cache[imgname] = img;
  1582     });
  1570     });
  1583     
  1571     
  1584     var throttledMouseMove = _.throttle(function(_event, _isTouch) {
  1572     var throttledMouseMove = _.throttle(function(_event, _isTouch) {
  1585         _this.onMouseMove(_event, _isTouch);
  1573         _this.onMouseMove(_event, _isTouch);
  1586     }, Rkns.Renderer._MOUSEMOVE_RATE);
  1574     }, _MOUSEMOVE_RATE);
  1587     
  1575     
  1588     this.canvas_$.on({
  1576     this.canvas_$.on({
  1589         mousedown: function(_event) {
  1577         mousedown: function(_event) {
  1590             _event.preventDefault();
  1578             _event.preventDefault();
  1591             _this.onMouseDown(_event, false);
  1579             _this.onMouseDown(_event, false);
  1607         touchstart: function(_event) {
  1595         touchstart: function(_event) {
  1608             _event.preventDefault();
  1596             _event.preventDefault();
  1609             var _touches = _event.originalEvent.touches[0];
  1597             var _touches = _event.originalEvent.touches[0];
  1610             if (
  1598             if (
  1611                 _renkan.options.allow_double_click
  1599                 _renkan.options.allow_double_click
  1612                 && new Date() - _lastTap < Rkns.Renderer._DOUBLETAP_DELAY
  1600                 && new Date() - _lastTap < _DOUBLETAP_DELAY
  1613                 && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Rkns.Renderer._DOUBLETAP_DISTANCE )
  1601                 && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < _DOUBLETAP_DISTANCE )
  1614             ) {
  1602             ) {
  1615                 _lastTap = 0;
  1603                 _lastTap = 0;
  1616                 _this.onDoubleClick(_touches);
  1604                 _this.onDoubleClick(_touches);
  1617             } else {
  1605             } else {
  1618                 _lastTap = new Date();
  1606                 _lastTap = new Date();
  1758                 }
  1746                 }
  1759             }
  1747             }
  1760         }
  1748         }
  1761     });
  1749     });
  1762     this.$.find(".Rk-AddNode-Button").click(function() {
  1750     this.$.find(".Rk-AddNode-Button").click(function() {
  1763         if (_this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
  1751         if (_this.click_mode === _CLICKMODE_ADDNODE) {
  1764             _this.click_mode = false;
  1752             _this.click_mode = false;
  1765             _this.notif_$.hide();
  1753             _this.notif_$.hide();
  1766         } else {
  1754         } else {
  1767             _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE;
  1755             _this.click_mode = _CLICKMODE_ADDNODE;
  1768             _this.notif_$.text(_renkan.translate("Click on the background canvas to add a node")).fadeIn();
  1756             _this.notif_$.text(_renkan.translate("Click on the background canvas to add a node")).fadeIn();
  1769         }
  1757         }
  1770     });
  1758     });
  1771     this.$.find(".Rk-AddEdge-Button").click(function() {
  1759     this.$.find(".Rk-AddEdge-Button").click(function() {
  1772         if (_this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE || _this.click_mode === Rkns.Renderer._CLICKMODE_ENDEDGE) {
  1760         if (_this.click_mode === _CLICKMODE_STARTEDGE || _this.click_mode === _CLICKMODE_ENDEDGE) {
  1773             _this.click_mode = false;
  1761             _this.click_mode = false;
  1774             _this.notif_$.hide();
  1762             _this.notif_$.hide();
  1775         } else {
  1763         } else {
  1776             _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
  1764             _this.click_mode = _CLICKMODE_STARTEDGE;
  1777             _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
  1765             _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
  1778         }
  1766         }
  1779     });
  1767     });
  1780     this.$.find(".Rk-Bookmarklet-Button")
  1768     this.$.find(".Rk-Bookmarklet-Button")
  1781         .attr("href","javascript:" + Rkns.Renderer._BOOKMARKLET_CODE(_renkan))
  1769         .attr("href","javascript:" + _BOOKMARKLET_CODE(_renkan))
  1782         .click(function(){
  1770         .click(function(){
  1783             _this.notif_$
  1771             _this.notif_$
  1784                 .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."))
  1772                 .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."))
  1785                 .fadeIn()
  1773                 .fadeIn()
  1786                 .delay(5000)
  1774                 .delay(5000)
  1908         }, 2000);
  1896         }, 2000);
  1909     }
  1897     }
  1910 
  1898 
  1911 };
  1899 };
  1912 
  1900 
  1913 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
  1901 Rkns._(Scene.prototype).extend({
       
  1902 template: Rkns._.template(
  1914     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  1903     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  1915     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  1904     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  1916     + '<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>'
  1905     + '<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>'
  1917     + '<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>'
  1906     + '<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>'
  1918     + '<% if (options.editor_mode) { %>'
  1907     + '<% if (options.editor_mode) { %>'
  1926     + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>">'
  1915     + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>">'
  1927     + '<div class="Rk-Labels"></div><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
  1916     + '<div class="Rk-Labels"></div><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
  1928     + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
  1917     + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
  1929     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  1918     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  1930     + '</div></div>'
  1919     + '</div></div>'
  1931 );
  1920 ),
  1932 
  1921 fixSize: function(_autoscale) {
  1933 Rkns.Renderer.Scene.prototype.fixSize = function(_autoscale) {
       
  1934     var w = this.$.width(),
  1922     var w = this.$.width(),
  1935         h = this.$.height();
  1923         h = this.$.height();
  1936     if (this.renkan.options.show_top_bar) {
  1924     if (this.renkan.options.show_top_bar) {
  1937         h -= this.$.find(".Rk-TopBar").height();
  1925         h -= this.$.find(".Rk-TopBar").height();
  1938     }
  1926     }
  1944     paper.view.viewSize = new paper.Size([w, h]);
  1932     paper.view.viewSize = new paper.Size([w, h]);
  1945     
  1933     
  1946     if (_autoscale) {
  1934     if (_autoscale) {
  1947         this.autoScale();
  1935         this.autoScale();
  1948     }
  1936     }
  1949 };
  1937 },
  1950 
  1938 drawSector: function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {
  1951 Rkns.Renderer.Scene.prototype.drawSector = function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {
       
  1952     var _options = this.renkan.options,
  1939     var _options = this.renkan.options,
  1953         _startRads = _startAngle * Math.PI / 180,
  1940         _startRads = _startAngle * Math.PI / 180,
  1954         _endRads = _endAngle * Math.PI / 180,
  1941         _endRads = _endAngle * Math.PI / 180,
  1955         _img = this.icon_cache[_imgname],
  1942         _img = this.icon_cache[_imgname],
  1956         _span = _endRads - _startRads,
  1943         _span = _endRads - _startRads,
  2048     } else {
  2035     } else {
  2049         Rkns.$(_img).on("load",showImage);
  2036         Rkns.$(_img).on("load",showImage);
  2050     }
  2037     }
  2051     
  2038     
  2052     return _res;
  2039     return _res;
  2053 };
  2040 },
  2054 
  2041 addToBundles: function(_edgeRepr) {
  2055 Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
       
  2056     var _bundle = Rkns._(this.bundles).find(function(_bundle) {
  2042     var _bundle = Rkns._(this.bundles).find(function(_bundle) {
  2057         return ( 
  2043         return ( 
  2058             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  2044             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  2059             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  2045             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  2060         );
  2046         );
  2072             }
  2058             }
  2073         };
  2059         };
  2074         this.bundles.push(_bundle);
  2060         this.bundles.push(_bundle);
  2075     }
  2061     }
  2076     return _bundle;
  2062     return _bundle;
  2077 };
  2063 },
  2078 
  2064 isEditable: function() {
  2079 Rkns.Renderer.Scene.prototype.isEditable = function() {
       
  2080     return (this.renkan.options.editor_mode && !this.renkan.read_only);
  2065     return (this.renkan.options.editor_mode && !this.renkan.read_only);
  2081 };
  2066 },
  2082 
  2067 onStatusChange: function() {
  2083 Rkns.Renderer.Scene.prototype.onStatusChange = function() {
       
  2084     var savebtn = this.$.find(".Rk-Save-Button"),
  2068     var savebtn = this.$.find(".Rk-Save-Button"),
  2085         tip = savebtn.find(".Rk-TopBar-Tooltip-Contents");
  2069         tip = savebtn.find(".Rk-TopBar-Tooltip-Contents");
  2086     if (this.renkan.read_only) {
  2070     if (this.renkan.read_only) {
  2087         savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly");
  2071         savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly");
  2088         tip.text(this.renkan.translate("Connection lost"));
  2072         tip.text(this.renkan.translate("Connection lost"));
  2093         } else {
  2077         } else {
  2094             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  2078             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  2095             tip.text(this.renkan.translate("Auto-save enabled"));
  2079             tip.text(this.renkan.translate("Auto-save enabled"));
  2096         }
  2080         }
  2097     }
  2081     }
  2098 };
  2082 },
  2099 
  2083 setScale: function(_newScale, _offset) {
  2100 Rkns.Renderer.Scene.prototype.setScale = function(_newScale, _offset) {
  2084     if (_newScale > _MIN_SCALE && _newScale < _MAX_SCALE) {
  2101     if (_newScale > Rkns.Renderer._MIN_SCALE && _newScale < Rkns.Renderer._MAX_SCALE) {
       
  2102         this.scale = _newScale;
  2085         this.scale = _newScale;
  2103         if (_offset) {
  2086         if (_offset) {
  2104             this.offset = _offset;
  2087             this.offset = _offset;
  2105         }
  2088         }
  2106         this.redraw();
  2089         this.redraw();
  2107     }
  2090     }
  2108 };
  2091 },
  2109 
  2092 autoScale: function() {
  2110 Rkns.Renderer.Scene.prototype.autoScale = function() {
       
  2111     var nodes = this.renkan.project.get("nodes");
  2093     var nodes = this.renkan.project.get("nodes");
  2112     if (nodes.length > 1) {
  2094     if (nodes.length > 1) {
  2113         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  2095         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  2114             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  2096             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  2115             _minx = Math.min.apply(Math, _xx),
  2097             _minx = Math.min.apply(Math, _xx),
  2116             _miny = Math.min.apply(Math, _yy),
  2098             _miny = Math.min.apply(Math, _yy),
  2117             _maxx = Math.max.apply(Math, _xx),
  2099             _maxx = Math.max.apply(Math, _xx),
  2118             _maxy = Math.max.apply(Math, _yy);
  2100             _maxy = Math.max.apply(Math, _yy);
  2119         var _scale = Math.max(Rkns.Renderer._MIN_SCALE, Math.min(Rkns.Renderer._MAX_SCALE, (paper.view.size.width - 2 * this.renkan.options.autoscale_padding) / (_maxx - _minx), (paper.view.size.height - 2 * this.renkan.options.autoscale_padding) / (_maxy - _miny)));
  2101         var _scale = Math.max(_MIN_SCALE, Math.min(_MAX_SCALE, (paper.view.size.width - 2 * this.renkan.options.autoscale_padding) / (_maxx - _minx), (paper.view.size.height - 2 * this.renkan.options.autoscale_padding) / (_maxy - _miny)));
  2120         this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));
  2102         this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));
  2121     }
  2103     }
  2122     if (nodes.length === 1) {
  2104     if (nodes.length === 1) {
  2123         this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y])));
  2105         this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y])));
  2124     }
  2106     }
  2125 };
  2107 },
  2126 
  2108 redrawMiniframe: function() {
  2127 Rkns.Renderer.Scene.prototype.redrawMiniframe = function() {
       
  2128     var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
  2109     var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
  2129         bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
  2110         bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
  2130     this.minimap.miniframe.fitBounds(topleft, bottomright);
  2111     this.minimap.miniframe.fitBounds(topleft, bottomright);
  2131 };
  2112 },
  2132 
  2113 rescaleMinimap: function() {
  2133 Rkns.Renderer.Scene.prototype.rescaleMinimap = function() {
       
  2134     var nodes = this.renkan.project.get("nodes");
  2114     var nodes = this.renkan.project.get("nodes");
  2135     if (nodes.length > 1) {
  2115     if (nodes.length > 1) {
  2136         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  2116         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  2137             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  2117             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  2138             _minx = Math.min.apply(Math, _xx),
  2118             _minx = Math.min.apply(Math, _xx),
  2151     if (nodes.length === 1) {
  2131     if (nodes.length === 1) {
  2152         this.minimap.scale = .1;
  2132         this.minimap.scale = .1;
  2153         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));
  2133         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));
  2154     }
  2134     }
  2155     this.redraw();
  2135     this.redraw();
  2156 };
  2136 },
  2157 
  2137 toPaperCoords: function(_point) {
  2158 Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) {
       
  2159     return _point.multiply(this.scale).add(this.offset);
  2138     return _point.multiply(this.scale).add(this.offset);
  2160 };
  2139 },
  2161 
  2140 toMinimapCoords: function(_point) {
  2162 Rkns.Renderer.Scene.prototype.toMinimapCoords = function(_point) {
       
  2163     return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
  2141     return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
  2164 };
  2142 },
  2165 
  2143 toModelCoords: function(_point) {
  2166 Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
       
  2167     return _point.subtract(this.offset).divide(this.scale);
  2144     return _point.subtract(this.offset).divide(this.scale);
  2168 };
  2145 },
  2169 
  2146 addRepresentation: function(_type, _model) {
  2170 Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) {
  2147     var _repr = new Renderer[_type](this, _model);
  2171     var _repr = new Rkns.Renderer[_type](this, _model);
       
  2172     this.representations.push(_repr);
  2148     this.representations.push(_repr);
  2173     return _repr;
  2149     return _repr;
  2174 };
  2150 },
  2175 
  2151 addRepresentations: function(_type, _collection) {
  2176 Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) {
       
  2177     var _this = this;
  2152     var _this = this;
  2178     _collection.forEach(function(_model) {
  2153     _collection.forEach(function(_model) {
  2179         _this.addRepresentation(_type, _model);
  2154         _this.addRepresentation(_type, _model);
  2180     });
  2155     });
  2181 };
  2156 },
  2182 
  2157 userTemplate: Rkns._.template(
  2183 Rkns.Renderer.Scene.prototype.userTemplate = Rkns._.template(
       
  2184     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  2158     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  2185 );
  2159 ),
  2186 
  2160 addUser: function(_user) {
  2187 Rkns.Renderer.Scene.prototype.addUser = function(_user) {
       
  2188     if (_user.get("_id") === this.renkan.current_user) {
  2161     if (_user.get("_id") === this.renkan.current_user) {
  2189         this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
  2162         this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
  2190         this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
  2163         this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
  2191     } else {
  2164     } else {
  2192         this.$.find(".Rk-UserList").append(
  2165         this.$.find(".Rk-UserList").append(
  2196                     background: _user.get("color")
  2169                     background: _user.get("color")
  2197                 })
  2170                 })
  2198             )
  2171             )
  2199         );
  2172         );
  2200     }
  2173     }
  2201 };
  2174 },
  2202 
  2175 removeRepresentation: function(_representation) {
  2203 Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) {
       
  2204     _representation.destroy();
  2176     _representation.destroy();
  2205     this.representations = Rkns._(this.representations).reject(
  2177     this.representations = Rkns._(this.representations).reject(
  2206         function(_repr) {
  2178         function(_repr) {
  2207             return _repr == _representation;
  2179             return _repr == _representation;
  2208         }
  2180         }
  2209     );
  2181     );
  2210 };
  2182 },
  2211 
  2183 getRepresentationByModel: function(_model) {
  2212 Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) {
       
  2213     if (!_model) {
  2184     if (!_model) {
  2214         return undefined;
  2185         return undefined;
  2215     }
  2186     }
  2216     return Rkns._(this.representations).find(function(_repr) {
  2187     return Rkns._(this.representations).find(function(_repr) {
  2217         return _repr.model === _model;
  2188         return _repr.model === _model;
  2218     });
  2189     });
  2219 };
  2190 },
  2220 
  2191 removeRepresentationsOfType: function(_type) {
  2221 Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) {
       
  2222     var _representations = Rkns._(this.representations).filter(function(_repr) {
  2192     var _representations = Rkns._(this.representations).filter(function(_repr) {
  2223             return _repr.type == _type;
  2193             return _repr.type == _type;
  2224         }),
  2194         }),
  2225         _this = this;
  2195         _this = this;
  2226     Rkns._(_representations).each(function(_repr) {
  2196     Rkns._(_representations).each(function(_repr) {
  2227         _this.removeRepresentation(_repr);
  2197         _this.removeRepresentation(_repr);
  2228     });
  2198     });
  2229 };
  2199 },
  2230 
  2200 highlightModel: function(_model) {
  2231 Rkns.Renderer.Scene.prototype.highlightModel = function(_model) {
       
  2232     var _repr = this.getRepresentationByModel(_model);
  2201     var _repr = this.getRepresentationByModel(_model);
  2233     if (_repr) {
  2202     if (_repr) {
  2234         _repr.highlight();
  2203         _repr.highlight();
  2235     }
  2204     }
  2236 };
  2205 },
  2237 
  2206 unhighlightAll: function(_model) {
  2238 Rkns.Renderer.Scene.prototype.unhighlightAll = function(_model) {
       
  2239     Rkns._(this.representations).each(function(_repr) {
  2207     Rkns._(this.representations).each(function(_repr) {
  2240         _repr.unhighlight();
  2208         _repr.unhighlight();
  2241     });
  2209     });
  2242 };
  2210 },
  2243 
  2211 unselectAll: function(_model) {
  2244 Rkns.Renderer.Scene.prototype.unselectAll = function(_model) {
       
  2245     Rkns._(this.representations).each(function(_repr) {
  2212     Rkns._(this.representations).each(function(_repr) {
  2246         _repr.unselect();
  2213         _repr.unselect();
  2247     });
  2214     });
  2248 };
  2215 },
  2249 
  2216 redraw: function() {
  2250 Rkns.Renderer.Scene.prototype.redraw = function() {
       
  2251     Rkns._(this.representations).each(function(_representation) {
  2217     Rkns._(this.representations).each(function(_representation) {
  2252         _representation.redraw(true);
  2218         _representation.redraw(true);
  2253     });
  2219     });
  2254     if (this.minimap) {
  2220     if (this.minimap) {
  2255         this.redrawMiniframe();
  2221         this.redrawMiniframe();
  2256     }
  2222     }
  2257     paper.view.draw();
  2223     paper.view.draw();
  2258 };
  2224 },
  2259 
  2225 addTempEdge: function(_from, _point) {
  2260 Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
       
  2261     var _tmpEdge = this.addRepresentation("TempEdge",null);
  2226     var _tmpEdge = this.addRepresentation("TempEdge",null);
  2262     _tmpEdge.end_pos = _point;
  2227     _tmpEdge.end_pos = _point;
  2263     _tmpEdge.from_representation = _from;
  2228     _tmpEdge.from_representation = _from;
  2264     _tmpEdge.redraw();
  2229     _tmpEdge.redraw();
  2265     this.click_target = _tmpEdge;
  2230     this.click_target = _tmpEdge;
  2266 };
  2231 },
  2267 
  2232 findTarget: function(_hitResult) {
  2268 Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
       
  2269     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  2233     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  2270         var _newTarget = _hitResult.item.__representation;
  2234         var _newTarget = _hitResult.item.__representation;
  2271         if (this.selected_target !== _hitResult.item.__representation) {
  2235         if (this.selected_target !== _hitResult.item.__representation) {
  2272             if (this.selected_target) {
  2236             if (this.selected_target) {
  2273                 this.selected_target.unselect(_newTarget);
  2237                 this.selected_target.unselect(_newTarget);
  2279         if (this.selected_target) {
  2243         if (this.selected_target) {
  2280             this.selected_target.unselect();
  2244             this.selected_target.unselect();
  2281         }
  2245         }
  2282         this.selected_target = null;
  2246         this.selected_target = null;
  2283     }
  2247     }
  2284 };
  2248 },
  2285 
  2249 paperShift: function(_delta) {
  2286 Rkns.Renderer.Scene.prototype.paperShift = function(_delta) {
       
  2287     this.offset = this.offset.add(_delta);
  2250     this.offset = this.offset.add(_delta);
  2288     this.redraw();
  2251     this.redraw();
  2289 };
  2252 },
  2290 
  2253 onMouseMove: function(_event) {
  2291 Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
       
  2292     var _off = this.canvas_$.offset(),
  2254     var _off = this.canvas_$.offset(),
  2293         _point = new paper.Point([
  2255         _point = new paper.Point([
  2294             _event.pageX - _off.left,
  2256             _event.pageX - _off.left,
  2295             _event.pageY - _off.top
  2257             _event.pageY - _off.top
  2296         ]),
  2258         ]),
  2297         _delta = _point.subtract(this.last_point);
  2259         _delta = _point.subtract(this.last_point);
  2298     this.last_point = _point;
  2260     this.last_point = _point;
  2299     if (!this.is_dragging && this.mouse_down && _delta.length > Rkns.Renderer._MIN_DRAG_DISTANCE) {
  2261     if (!this.is_dragging && this.mouse_down && _delta.length > _MIN_DRAG_DISTANCE) {
  2300         this.is_dragging = true;
  2262         this.is_dragging = true;
  2301     }
  2263     }
  2302     var _hitResult = paper.project.hitTest(_point);
  2264     var _hitResult = paper.project.hitTest(_point);
  2303     if (this.is_dragging) {
  2265     if (this.is_dragging) {
  2304         if (this.click_target && typeof this.click_target.paperShift === "function") {
  2266         if (this.click_target && typeof this.click_target.paperShift === "function") {
  2308         }
  2270         }
  2309     } else {
  2271     } else {
  2310         this.findTarget(_hitResult);
  2272         this.findTarget(_hitResult);
  2311     }
  2273     }
  2312     paper.view.draw();
  2274     paper.view.draw();
  2313 };
  2275 },
  2314 
  2276 onMouseDown: function(_event, _isTouch) {
  2315 Rkns.Renderer.Scene.prototype.onMouseDown = function(_event, _isTouch) {
       
  2316     var _off = this.canvas_$.offset(),
  2277     var _off = this.canvas_$.offset(),
  2317         _point = new paper.Point([
  2278         _point = new paper.Point([
  2318             _event.pageX - _off.left,
  2279             _event.pageX - _off.left,
  2319             _event.pageY - _off.top
  2280             _event.pageY - _off.top
  2320         ]);
  2281         ]);
  2327         if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  2288         if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  2328             this.click_target = _hitResult.item.__representation;
  2289             this.click_target = _hitResult.item.__representation;
  2329             this.click_target.mousedown(_event, _isTouch);
  2290             this.click_target.mousedown(_event, _isTouch);
  2330         } else {
  2291         } else {
  2331             this.click_target = null;
  2292             this.click_target = null;
  2332             if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
  2293             if (this.isEditable() && this.click_mode === _CLICKMODE_ADDNODE) {
  2333                 var _coords = this.toModelCoords(_point),
  2294                 var _coords = this.toModelCoords(_point),
  2334                     _data = {
  2295                     _data = {
  2335                         id: Rkns.Utils.getUID('node'),
  2296                         id: Rkns.Utils.getUID('node'),
  2336                         created_by: this.renkan.current_user,
  2297                         created_by: this.renkan.current_user,
  2337                         position: {
  2298                         position: {
  2343                 this.getRepresentationByModel(_node).openEditor();
  2304                 this.getRepresentationByModel(_node).openEditor();
  2344             }
  2305             }
  2345         }
  2306         }
  2346     }
  2307     }
  2347     if (this.click_mode) {
  2308     if (this.click_mode) {
  2348         if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  2309         if (this.isEditable() && this.click_mode === _CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  2349             this.removeRepresentationsOfType("editor");
  2310             this.removeRepresentationsOfType("editor");
  2350             this.addTempEdge(this.click_target, _point);
  2311             this.addTempEdge(this.click_target, _point);
  2351             this.click_mode = Rkns.Renderer._CLICKMODE_ENDEDGE;
  2312             this.click_mode = _CLICKMODE_ENDEDGE;
  2352             this.notif_$.fadeOut(function() {
  2313             this.notif_$.fadeOut(function() {
  2353                 Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  2314                 Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  2354             });
  2315             });
  2355         } else {
  2316         } else {
  2356             this.notif_$.hide();
  2317             this.notif_$.hide();
  2357             this.click_mode = false;
  2318             this.click_mode = false;
  2358         }
  2319         }
  2359     }
  2320     }
  2360     paper.view.draw();
  2321     paper.view.draw();
  2361 };
  2322 },
  2362 
  2323 onMouseUp: function(_event, _isTouch) {
  2363 Rkns.Renderer.Scene.prototype.onMouseUp = function(_event, _isTouch) {
       
  2364     this.mouse_down = false;
  2324     this.mouse_down = false;
  2365     if (this.click_target) {
  2325     if (this.click_target) {
  2366         var _off = this.canvas_$.offset();
  2326         var _off = this.canvas_$.offset();
  2367         this.click_target.mouseup(
  2327         this.click_target.mouseup(
  2368             {
  2328             {
  2379         if (_isTouch) {
  2339         if (_isTouch) {
  2380             this.unselectAll();
  2340             this.unselectAll();
  2381         }
  2341         }
  2382     }
  2342     }
  2383     paper.view.draw();
  2343     paper.view.draw();
  2384 };
  2344 },
  2385 
  2345 onScroll: function(_event, _scrolldelta) {
  2386 Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {
       
  2387     this.totalScroll += _scrolldelta;
  2346     this.totalScroll += _scrolldelta;
  2388     if (Math.abs(this.totalScroll) >= 1) {
  2347     if (Math.abs(this.totalScroll) >= 1) {
  2389         var _off = this.canvas_$.offset(),
  2348         var _off = this.canvas_$.offset(),
  2390             _delta = new paper.Point([
  2349             _delta = new paper.Point([
  2391                 _event.pageX - _off.left,
  2350                 _event.pageX - _off.left,
  2396         } else {
  2355         } else {
  2397             this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2)));
  2356             this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2)));
  2398         }
  2357         }
  2399         this.totalScroll = 0;
  2358         this.totalScroll = 0;
  2400     }
  2359     }
  2401 };
  2360 },
  2402 
  2361 onDoubleClick: function(_event) {
  2403 Rkns.Renderer.Scene.prototype.onDoubleClick = function(_event) {
       
  2404     if (!this.isEditable()) {
  2362     if (!this.isEditable()) {
  2405         return;
  2363         return;
  2406     }
  2364     }
  2407     var _off = this.canvas_$.offset(),
  2365     var _off = this.canvas_$.offset(),
  2408         _point = new paper.Point([
  2366         _point = new paper.Point([
  2422             };
  2380             };
  2423             _node = this.renkan.project.addNode(_data);
  2381             _node = this.renkan.project.addNode(_data);
  2424             this.getRepresentationByModel(_node).openEditor();
  2382             this.getRepresentationByModel(_node).openEditor();
  2425     }
  2383     }
  2426     paper.view.draw();
  2384     paper.view.draw();
  2427 };
  2385 },
  2428 
  2386 dropData: function(_data, _event) {
  2429 Rkns.Renderer.Scene.prototype.dropData = function(_data, _event) {
       
  2430     if (!this.isEditable()) {
  2387     if (!this.isEditable()) {
  2431         return;
  2388         return;
  2432     }
  2389     }
  2433     if (_data["text/json"] || _data["application/json"]) {
  2390     if (_data["text/json"] || _data["application/json"]) {
  2434         try {
  2391         try {
  2538     var _node = this.renkan.project.addNode(_nodedata),
  2495     var _node = this.renkan.project.addNode(_nodedata),
  2539         _repr = this.getRepresentationByModel(_node);
  2496         _repr = this.getRepresentationByModel(_node);
  2540     if (_event.type === "drop") {
  2497     if (_event.type === "drop") {
  2541         _repr.openEditor();
  2498         _repr.openEditor();
  2542     }
  2499     }
  2543 };
  2500 }
       
  2501 });
       
  2502 }).call(window);
       
  2503 
       
  2504 /* END paper-renderer.js */