client/js/paper-renderer.js
changeset 195 15e048e00002
parent 194 f53a7999ae7b
child 196 2a2fcec209d0
--- a/client/js/paper-renderer.js	Fri Jun 14 12:36:32 2013 +0200
+++ b/client/js/paper-renderer.js	Wed Jul 03 13:42:59 2013 +0200
@@ -1,8 +1,12 @@
 /* paper-renderer.js */
 
-(function() {
-    
-var Rkns = this.Rkns;
+(function(root) {
+
+"use strict";
+
+var Rkns = root.Rkns,
+    _ = Rkns._,
+    $ = Rkns.$;
 
 var Renderer = Rkns.Renderer = {},
     _MIN_DRAG_DISTANCE = 2,
@@ -111,7 +115,7 @@
     }
 };
 
-Rkns._(_BaseRepresentation.prototype).extend({
+_(_BaseRepresentation.prototype).extend({
     _super: function(_func) {
         return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
     },
@@ -151,7 +155,7 @@
 
 var _BaseButton = Renderer._BaseButton = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(_BaseButton.prototype).extend({
+_(_BaseButton.prototype).extend({
 moveTo: function(_pos) {
     this.sector.moveTo(_pos);
 },
@@ -179,7 +183,7 @@
 
 var NodeRepr = Renderer.Node = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(NodeRepr.prototype).extend({
+_(NodeRepr.prototype).extend({
 _init: function() {
     this.renderer.node_layer.activate();
     this.type = "Node";
@@ -191,7 +195,7 @@
     } else {
         this.h_ratio = 0;
     }
-    this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
+    this.title = $('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
     if (this.options.editor_mode) {
         this.normal_buttons = [
             new NodeEditButton(this.renderer, null),
@@ -309,12 +313,20 @@
     }
     
     if (!_dontRedrawEdges) {
-        Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){
-            var repr = this.renderer.getRepresentationByModel(edge);
-            if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
-                repr.redraw();
+        var _this = this;
+        _.each(
+            this.project.get("edges").filter(
+                function (ed) {
+                    return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
+                }
+            ),
+            function(edge, index, list) {
+                var repr = _this.renderer.getRepresentationByModel(edge);
+                if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
+                    repr.redraw();
+                }
             }
-        }, this);
+        );
     }
 
 },
@@ -344,7 +356,7 @@
                 maxX = -Infinity,
                 maxY = -Infinity;
                 
-            function transformCoords(tabc, relative) {
+            var transformCoords = function(tabc, relative) {
                 var newCoords = tabc.slice(1).map(function(v, k) {
                     var res = parseFloat(v),
                         isY = k % 2;
@@ -437,7 +449,7 @@
         this.renderer.throttledPaperDraw();
     } else {
         var _this = this;
-        Rkns.$(_image).on("load", function() {
+        $(_image).on("load", function() {
             _this.showImage();
         });
     }
@@ -469,8 +481,8 @@
     }
     var _uri = this.model.get("uri");
     if (_uri) {
-        Rkns.$('.Rk-Bin-Item').each(function() {
-            var _el = Rkns.$(this);
+        $('.Rk-Bin-Item').each(function() {
+            var _el = $(this);
             if (_el.attr("data-uri") == _uri) {
                 _el.addClass("selected");
             }
@@ -493,7 +505,7 @@
             b.hide();
         });
         this.circle.strokeWidth = this.options.node_stroke_width;
-        Rkns.$('.Rk-Bin-Item').removeClass("selected");
+        $('.Rk-Bin-Item').removeClass("selected");
         if (this.renderer.minimap) {
             this.minimap_circle.strokeColor = undefined;
         }
@@ -567,7 +579,7 @@
 
 var Edge = Renderer.Edge = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(Edge.prototype).extend({
+_(Edge.prototype).extend({
 _init: function() {
     this.renderer.edge_layer.activate();
     this.type = "Edge";
@@ -585,7 +597,7 @@
         [ 0, this.options.edge_arrow_width ]
     );
     this.arrow.__representation = this;
-    this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
+    this.text = $('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
     this.arrow_angle = 0;
     if (this.options.editor_mode) {
         this.normal_buttons = [
@@ -779,7 +791,7 @@
         b.destroy();
     });
     var _this = this;
-    this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
+    this.bundle.edges = _(this.bundle.edges).reject(function(_edge) {
         return _edge === _this;
     });
 }
@@ -789,7 +801,7 @@
 
 var TempEdge = Renderer.TempEdge = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(TempEdge.prototype).extend({
+_(TempEdge.prototype).extend({
 _init: function() {
     this.renderer.edge_layer.activate();
     this.type = "Temp-edge";
@@ -876,17 +888,17 @@
 
 var _BaseEditor = Renderer._BaseEditor = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(_BaseEditor.prototype).extend({
+_(_BaseEditor.prototype).extend({
 _init: function() {
     this.renderer.buttons_layer.activate();
     this.type = "editor";
     this.editor_block = new paper.Path();
-    var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0];});
+    var _pts = _(_.range(8)).map(function() {return [0,0];});
     this.editor_block.add.apply(this.editor_block, _pts);
     this.editor_block.strokeWidth = this.options.tooltip_border_width;
     this.editor_block.strokeColor = this.options.tooltip_border_color;
     this.editor_block.opacity = .8;
-    this.editor_$ = Rkns.$('<div>')
+    this.editor_$ = $('<div>')
         .appendTo(this.renderer.editor_$)
         .css({
             position: "absolute",
@@ -904,22 +916,22 @@
 
 var NodeEditor = Renderer.NodeEditor = Rkns.Utils.inherit(_BaseEditor);
 
-Rkns._(NodeEditor.prototype).extend({
-template: Rkns._.template(
+_(NodeEditor.prototype).extend({
+template: _.template(
     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
     + '<% 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><% } %>'
     + '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
     + '<% 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><% } %>'
-    + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
-    + '<% _(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><% } %>'
+    + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span>'
+    + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
     + '<% if (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
     + '<% 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><% }%>'
     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
     + '<% 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><% } %>'
 ),
-readOnlyTemplate: Rkns._.template(
+readOnlyTemplate: _.template(
     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
     + '<% if (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
@@ -970,8 +982,8 @@
     
     if (this.renderer.isEditable()) {
         
-        var onFieldChange = Rkns._(function() {
-            Rkns._(function() {
+        var onFieldChange = _(function() {
+            _(function() {
                 if (_this.renderer.isEditable()) {
                     var _data = {
                         title: _this.editor_$.find(".Rk-Edit-Title").val()
@@ -1058,7 +1070,7 @@
             }
         });
         
-        function shiftSize(n) {
+        var shiftSize = function(n) {
             if (_this.renderer.isEditable()) {
                 var _newsize = n+(_model.get("size") || 0);
                 _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
@@ -1094,8 +1106,8 @@
 
 var EdgeEditor = Renderer.EdgeEditor = Rkns.Utils.inherit(_BaseEditor);
 
-Rkns._(EdgeEditor.prototype).extend({
-template: Rkns._.template(
+_(EdgeEditor.prototype).extend({
+template: _.template(
     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
     + '<% 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>'
@@ -1104,14 +1116,14 @@
     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
     + '<% }) %><% }) %></select></p><% } } %>'
-    + '<% 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">'
-    + '<% _(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><% } %>'
+    + '<% 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>'
+    + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
     + '<% 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>'
     + '<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><% } %>'
     + '<% 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><% } %>'
 ),
-readOnlyTemplate: Rkns._.template(
+readOnlyTemplate: _.template(
     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
@@ -1144,7 +1156,7 @@
             },
             renkan: this.renkan,
             shortenText: shortenText,
-            options: this.options,
+            options: this.options
         }));
     this.redraw();
     var _this = this,
@@ -1161,8 +1173,8 @@
     
     if (this.renderer.isEditable()) {
         
-        var onFieldChange = Rkns._(function() {
-            Rkns._(function() {
+        var onFieldChange = _(function() {
+            _(function() {
                 if (_this.renderer.isEditable()) {
                     var _data = {
                         title: _this.editor_$.find(".Rk-Edit-Title").val()
@@ -1254,7 +1266,7 @@
 
 var _NodeButton = Renderer._NodeButton = Rkns.Utils.inherit(_BaseButton);
 
-Rkns._(_NodeButton.prototype).extend({
+_(_NodeButton.prototype).extend({
 setSectorSize: function() {
     var sectorInner = this.source_representation.circle_radius;
     if (sectorInner !== this.lastSectorInner) {
@@ -1279,7 +1291,7 @@
 
 var NodeEditButton = Renderer.NodeEditButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeEditButton.prototype).extend({
+_(NodeEditButton.prototype).extend({
 _init: function() {
     this.type = "Node-edit-button";
     this.lastSectorInner = 0;
@@ -1299,7 +1311,7 @@
 
 var NodeRemoveButton = Renderer.NodeRemoveButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeRemoveButton.prototype).extend({
+_(NodeRemoveButton.prototype).extend({
 _init: function() {
     this.type = "Node-remove-button";
     this.lastSectorInner = 0;
@@ -1333,7 +1345,7 @@
 
 var NodeRevertButton = Renderer.NodeRevertButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeRevertButton.prototype).extend({
+_(NodeRevertButton.prototype).extend({
 _init: function() {
     this.type = "Node-revert-button";
     this.lastSectorInner = 0;
@@ -1355,7 +1367,7 @@
 
 var NodeLinkButton = Renderer.NodeLinkButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeLinkButton.prototype).extend({
+_(NodeLinkButton.prototype).extend({
 _init: function() {
     this.type = "Node-link-button";
     this.lastSectorInner = 0;
@@ -1382,7 +1394,7 @@
 
 var NodeEnlargeButton = Renderer.NodeEnlargeButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeEnlargeButton.prototype).extend({
+_(NodeEnlargeButton.prototype).extend({
 _init: function() {
     this.type = "Node-enlarge-button";
     this.lastSectorInner = 0;
@@ -1404,7 +1416,7 @@
 
 var NodeShrinkButton = Renderer.NodeShrinkButton = Rkns.Utils.inherit(_NodeButton);
 
-Rkns._(NodeShrinkButton.prototype).extend({
+_(NodeShrinkButton.prototype).extend({
 _init: function() {
     this.type = "Node-shrink-button";
     this.lastSectorInner = 0;
@@ -1426,7 +1438,7 @@
 
 var EdgeEditButton = Renderer.EdgeEditButton = Rkns.Utils.inherit(_BaseButton);
 
-Rkns._(EdgeEditButton.prototype).extend({
+_(EdgeEditButton.prototype).extend({
 _init: function() {
     this.type = "Edge-edit-button";
     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
@@ -1442,7 +1454,7 @@
 
 var EdgeRemoveButton = Renderer.EdgeRemoveButton = Rkns.Utils.inherit(_BaseButton);
 
-Rkns._(EdgeRemoveButton.prototype).extend({
+_(EdgeRemoveButton.prototype).extend({
 _init: function() {
     this.type = "Edge-remove-button";
     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
@@ -1472,7 +1484,7 @@
 
 var EdgeRevertButton = Renderer.EdgeRevertButton = Rkns.Utils.inherit(_BaseButton);
 
-Rkns._(EdgeRevertButton.prototype).extend({
+_(EdgeRevertButton.prototype).extend({
 _init: function() {
     this.type = "Edge-revert-button";
     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
@@ -1490,7 +1502,7 @@
 
 var MiniFrame = Renderer.MiniFrame = Rkns.Utils.inherit(_BaseRepresentation);
 
-Rkns._(MiniFrame.prototype).extend({
+_(MiniFrame.prototype).extend({
 paperShift: function(_delta) {
     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
     this.renderer.redraw();
@@ -1505,7 +1517,7 @@
 
 var Scene = Renderer.Scene = function(_renkan) {
     this.renkan = _renkan;
-    this.$ = Rkns.$(".Rk-Render");
+    this.$ = $(".Rk-Render");
     this.representations = [];
     this.$.html(this.template(_renkan));
     this.onStatusChange();
@@ -1556,7 +1568,7 @@
         this.minimap.miniframe.__representation = new MiniFrame(this, null);
     }
     
-    this.throttledPaperDraw = Rkns._(function() {
+    this.throttledPaperDraw = _(function() {
         paper.view.draw();
     }).throttle(100);
     
@@ -1677,7 +1689,7 @@
             _event.preventDefault();
             _allowScroll = true;
             var res = {};
-            Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
+            _(_event.originalEvent.dataTransfer.types).each(function(t) {
                 try {
                     res[t] = _event.originalEvent.dataTransfer.getData(t);
                 } catch(e) {}
@@ -1747,9 +1759,9 @@
             return false;
         });
     this.$.find(".Rk-TopBar-Button").mouseover(function() {
-        Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
+        $(this).find(".Rk-TopBar-Tooltip").show();
     }).mouseout(function() {
-        Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
+        $(this).find(".Rk-TopBar-Tooltip").hide();
     });
     bindClick(".Rk-Fold-Bins", "foldBins");
     
@@ -1763,7 +1775,7 @@
         _this.redraw();
     };
     
-    var _thRedraw = Rkns._.throttle(function() {
+    var _thRedraw = _.throttle(function() {
         _this.redraw();
     },50);
     
@@ -1777,13 +1789,14 @@
         _renkan.project.set({"title": $(this).val()});
     });
     
-    this.renkan.project.get("users").each(function(_user) {
-        _this.addUser(_user);
-    });
+    var _thRedrawUsers = _.throttle(function() {
+        _this.redrawUsers();
+    }, 100);
     
-    this.renkan.project.on("add:users", function(_user) {
-        _this.addUser(_user);
-    });
+    _thRedrawUsers();
+    
+    this.renkan.project.on("add:users remove:users", _thRedrawUsers);
+    
     this.renkan.project.on("add:nodes", function(_node) {
         _this.addRepresentation("Node", _node);
         _thRedraw();
@@ -1823,6 +1836,33 @@
         });
     }
     
+    if (_renkan.options.show_user_list) {
+        var $cpwrapper = this.$.find(".Rk-Users .Rk-Edit-ColorPicker-Wrapper"),
+            $cplist = this.$.find(".Rk-Users .Rk-Edit-ColorPicker");
+        
+        $cpwrapper.hover(
+            function(_e) {
+                if (_this.isEditable()) {
+                    _e.preventDefault();
+                    $cplist.show();
+                }
+            },
+            function(_e) {
+                _e.preventDefault();
+                $cplist.hide();
+            }
+        );
+        
+        $cplist.find("li").mouseenter(
+            function(_e) {
+                if (_this.isEditable()) {
+                    _e.preventDefault();
+                    _this.$.find(".Rk-CurrentUser-Color").css("background", $(this).attr("data-color"));
+                }
+            }
+        );
+    }
+    
     this.redraw();
     
     window.setInterval(function() {
@@ -1852,11 +1892,12 @@
 
 };
 
-Rkns._(Scene.prototype).extend({
-template: Rkns._.template(
+_(Scene.prototype).extend({
+template: _.template(
     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
-    + '<% if (options.show_user_list) { %><div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div><% } %>'
+    + '<% if (options.show_user_list) { %><div class="Rk-Users"><div class="Rk-CurrentUser"><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-CurrentUser-Color"><span class="Rk-Edit-ColorTip"></span></span>'
+    + '<%= colorPicker %></div><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div><% } %>'
     + '<% if (options.home_button_url) {%><div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Home-Button" href="<%- options.home_button_url %>"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents">'
     + '<%- translate(options.home_button_title) %></div></div></a><% } %>'
     + '<% if (options.show_fullscreen_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div><% } %>'
@@ -1992,13 +2033,13 @@
     if (_img.width) {
         showImage();
     } else {
-        Rkns.$(_img).on("load",showImage);
+        $(_img).on("load",showImage);
     }
     
     return _res;
 },
 addToBundles: function(_edgeRepr) {
-    var _bundle = Rkns._(this.bundles).find(function(_bundle) {
+    var _bundle = _(this.bundles).find(function(_bundle) {
         return ( 
             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
@@ -2013,7 +2054,7 @@
             edges: [ _edgeRepr ],
             getPosition: function(_er) {
                 var _dir = (_er.from_representation === this.from) ? 1 : -1;
-                return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
+                return _dir * ( _(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
             }
         };
         this.bundles.push(_bundle);
@@ -2038,6 +2079,7 @@
             tip.text(this.renkan.translate("Auto-save enabled"));
         }
     }
+    this.redrawUsers();
 },
 setScale: function(_newScale, _offset) {
     if (_newScale > _MIN_SCALE && _newScale < _MAX_SCALE) {
@@ -2113,27 +2155,64 @@
         _this.addRepresentation(_type, _model);
     });
 },
-userTemplate: Rkns._.template(
+userTemplate: _.template(
     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
 ),
-addUser: function(_user) {
-    if (_user.get("_id") === this.renkan.current_user) {
-        this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
-        this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
-    } else {
-        this.$.find(".Rk-UserList").append(
-            Rkns.$(
-                this.userTemplate({
-                    name: _user.get("title"),
-                    background: _user.get("color")
-                })
-            )
-        );
+redrawUsers: function() {
+    if (!this.renkan.options.show_user_list) {
+        return;
     }
+    var allUsers = [].concat((this.renkan.project.current_user_list || {}).models || [], (this.renkan.project.get("users") || {}).models || []),
+        ulistHtml = '',
+        $userpanel = this.$.find(".Rk-Users"),
+        $name = $userpanel.find(".Rk-CurrentUser-Name"),
+        $cpwrapper = $userpanel.find(".Rk-Edit-ColorPicker-Wrapper"),
+        $cpitems = $userpanel.find(".Rk-Edit-ColorPicker li"),
+        $colorsquare = $userpanel.find(".Rk-CurrentUser-Color"),
+        _this = this;
+    $name.off("click").text(this.renkan.translate("<unknown user>"));
+    $cpitems.off("mouseleave click");
+    allUsers.forEach(function(_user) {
+        if (_user.get("_id") === _this.renkan.current_user) {
+            $name.text(_user.get("title"));
+            if (_this.isEditable()) {
+                $name.click(function() {
+                    var $this = $(this),
+                        $input = $('<input>').val(_user.get("title")).blur(function() {
+                            _user.set("title", $(this).val());
+                            _this.redrawUsers();
+                            _this.redraw();
+                        });
+                    $this.empty().html($input);
+                    $input.select();
+                });
+                
+                $cpitems.click(
+                    function(_e) {
+                        _e.preventDefault();
+                        if (_this.isEditable()) {
+                            _user.set("color", $(this).attr("data-color"));
+                        }
+                        $(this).parent().hide();
+                    }
+                ).mouseleave(function() {
+                    $colorsquare.css("background", _user.get("color"));
+                });
+                $colorsquare.css("background", _user.get("color"));
+            }
+            
+        } else {
+            ulistHtml += _this.userTemplate({
+                name: _user.get("title"),
+                background: _user.get("color")
+            });
+        }
+    });
+    $userpanel.find(".Rk-UserList").html(ulistHtml);
 },
 removeRepresentation: function(_representation) {
     _representation.destroy();
-    this.representations = Rkns._(this.representations).reject(
+    this.representations = _(this.representations).reject(
         function(_repr) {
             return _repr == _representation;
         }
@@ -2143,16 +2222,16 @@
     if (!_model) {
         return undefined;
     }
-    return Rkns._(this.representations).find(function(_repr) {
+    return _(this.representations).find(function(_repr) {
         return _repr.model === _model;
     });
 },
 removeRepresentationsOfType: function(_type) {
-    var _representations = Rkns._(this.representations).filter(function(_repr) {
+    var _representations = _(this.representations).filter(function(_repr) {
             return _repr.type == _type;
         }),
         _this = this;
-    Rkns._(_representations).each(function(_repr) {
+    _(_representations).each(function(_repr) {
         _this.removeRepresentation(_repr);
     });
 },
@@ -2163,17 +2242,17 @@
     }
 },
 unhighlightAll: function(_model) {
-    Rkns._(this.representations).each(function(_repr) {
+    _(this.representations).each(function(_repr) {
         _repr.unhighlight();
     });
 },
 unselectAll: function(_model) {
-    Rkns._(this.representations).each(function(_repr) {
+    _(this.representations).each(function(_repr) {
         _repr.unselect();
     });
 },
 redraw: function() {
-    Rkns._(this.representations).each(function(_representation) {
+    _(this.representations).each(function(_representation) {
         _representation.redraw(true);
     });
     if (this.minimap) {
@@ -2270,7 +2349,7 @@
             this.addTempEdge(this.click_target, _point);
             this.click_mode = _CLICKMODE_ENDEDGE;
             this.notif_$.fadeOut(function() {
-                Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
+                $(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
             });
         } else {
             this.notif_$.hide();
@@ -2336,9 +2415,9 @@
                     x: _coords.x,
                     y: _coords.y
                 }
-            };
+            },
             _node = this.renkan.project.addNode(_data);
-            this.getRepresentationByModel(_node).openEditor();
+        this.getRepresentationByModel(_node).openEditor();
     }
     paper.view.draw();
 },
@@ -2356,7 +2435,7 @@
     var newNode = {};
     switch(_data["text/x-iri-specific-site"]) {
         case "twitter":
-            var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]),
+            var snippet = $('<div>').html(_data["text/x-iri-selected-html"]),
                 tweetdiv = snippet.find(".tweet");
             newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
             newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
@@ -2364,7 +2443,7 @@
             newNode.description = tweetdiv.find(".js-tweet-text:first").text();
         break;
         case "google":
-            var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]);
+            var snippet = $('<div>').html(_data["text/x-iri-selected-html"]);
             newNode.title = snippet.find("h3:first").text().trim();
             newNode.uri = snippet.find("h3 a").attr("href");
             newNode.description = snippet.find(".st:first").text().trim();
@@ -2378,7 +2457,7 @@
                 newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
             }
             if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
-                var snippet = Rkns.$('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
+                var snippet = $('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
                 var _svgimgs = snippet.find("image");
                 if (_svgimgs.length) {
                     newNode.image = _svgimgs.attr("xlink:href");
@@ -2538,6 +2617,6 @@
 save: function() { },
 open: function() { }
 });
-}).call(window);
+})(window);
 
 /* END paper-renderer.js */