client/js/paper-renderer.js
changeset 284 fa8035885814
parent 283 67f3a24a7c01
--- a/client/js/paper-renderer.js	Tue Apr 29 23:53:13 2014 +0200
+++ b/client/js/paper-renderer.js	Mon May 05 17:43:37 2014 +0200
@@ -11,94 +11,7 @@
 
     /* This object contains constants, utility functions and classes for Renkan's Graph Manipulation GUI */
 
-    var Renderer = Rkns.Renderer = {},
-    /* The minimum distance (in pixels) the mouse has to move to consider an element was dragged */
-    _MIN_DRAG_DISTANCE = 2,
-    /* Distance between the inner and outer radius of buttons that appear when hovering on a node */
-    _NODE_BUTTON_WIDTH = 40,
-
-    _EDGE_BUTTON_INNER = 2,
-    _EDGE_BUTTON_OUTER = 40,
-    /* Constants used to know if a specific action is to be performed when clicking on the canvas */
-    _CLICKMODE_ADDNODE = 1,
-    _CLICKMODE_STARTEDGE = 2,
-    _CLICKMODE_ENDEDGE = 3,
-    /* Node size step: Used to calculate the size change when clicking the +/- buttons */
-    _NODE_SIZE_STEP = Math.LN2/4,
-    _MIN_SCALE = 1/20,
-    _MAX_SCALE = 20,
-    _MOUSEMOVE_RATE = 80,
-    _DOUBLETAP_DELAY = 800,
-    /* Maximum distance in pixels (squared, to reduce calculations)
-     * between two taps when double-tapping on a touch terminal */
-    _DOUBLETAP_DISTANCE = 20*20,
-    /* A placeholder so a default colour is displayed when a node has a null value for its user property */
-    _USER_PLACEHOLDER = function(_renkan) {
-        return {
-            color: _renkan.options.default_user_color,
-            title: _renkan.translate("(unknown user)"),
-            get: function(attr) {
-                return this[attr] || false;
-            }
-        };
-    },
-    /* The code for the "Drag and Add Bookmarklet", slightly minified and with whitespaces removed, though
-     * it doesn't seem that it's still a requirement in newer browsers (i.e. the ones compatibles with canvas drawing)
-     */
-    _BOOKMARKLET_CODE = function(_renkan) {
-        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;\">"
-        + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
-        + "</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);})();";
-    },
-    /* Shortens text to the required length then adds ellipsis */
-    shortenText = function(_text, _maxlength) {
-        return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
-    },
-    /* Drawing an edit box with an arrow and positioning the edit box according to the position of the node/edge being edited
-     * Called by Rkns.Renderer.NodeEditor and Rkns.Renderer.EdgeEditor */
-    drawEditBox = function(_options, _coords, _path, _xmargin, _selector) {
-        _selector.css({
-            width: ( _options.tooltip_width - 2* _options.tooltip_padding )
-        });
-        var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
-        _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
-        _left = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length ),
-        _right = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length + _options.tooltip_width ),
-        _top = _coords.y - _height / 2;
-        if (_top + _height > (paper.view.size.height - _options.tooltip_margin)) {
-            _top = Math.max( paper.view.size.height - _options.tooltip_margin, _coords.y + _options.tooltip_arrow_width / 2 ) - _height;
-        }
-        if (_top < _options.tooltip_margin) {
-            _top = Math.min( _options.tooltip_margin, _coords.y - _options.tooltip_arrow_width / 2 );
-        }
-        var _bottom = _top + _height;
-        _path.segments[0].point
-        = _path.segments[7].point
-        = _coords.add([_isLeft * _xmargin, 0]);
-        _path.segments[1].point.x
-        = _path.segments[2].point.x
-        = _path.segments[5].point.x
-        = _path.segments[6].point.x
-        = _left;
-        _path.segments[3].point.x
-        = _path.segments[4].point.x
-        = _right;
-        _path.segments[2].point.y
-        = _path.segments[3].point.y
-        = _top;
-        _path.segments[4].point.y
-        = _path.segments[5].point.y
-        = _bottom;
-        _path.segments[1].point.y = _coords.y - _options.tooltip_arrow_width / 2;
-        _path.segments[6].point.y = _coords.y + _options.tooltip_arrow_width / 2;
-        _path.closed = true;
-        _path.fillColor = new paper.GradientColor(new paper.Gradient([_options.tooltip_top_color, _options.tooltip_bottom_color]), [0,_top], [0, _bottom]);
-        _selector.css({
-            left: (_options.tooltip_padding + Math.min(_left, _right)),
-            top: (_options.tooltip_padding + _top)
-        });
-        return _path;
-    };
+    var Renderer = Rkns.Renderer = {};
 
     /* Rkns.Renderer._BaseRepresentation Class */
 
@@ -261,7 +174,7 @@
         },
         redraw: function(_dontRedrawEdges) {
             var _model_coords = new paper.Point(this.model.get("position")),
-            _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * _NODE_SIZE_STEP);
+            _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * Rkns.Utils._NODE_SIZE_STEP);
             if (!this.is_dragging || !this.paper_coords) {
                 this.paper_coords = this.renderer.toPaperCoords(_model_coords);
             }
@@ -314,7 +227,7 @@
             this.circle.opacity = this.options.show_node_circles ? opacity : .01;
 
             var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
-            _text = shortenText(_text, this.options.node_label_max_length);
+            _text = Rkns.Utils.shortenText(_text, this.options.node_label_max_length);
 
             if (typeof this.highlighted === "object") {
                 this.title.html(this.highlighted.replace(_(_text).escape(),'<span class="Rk-Highlighted">$1</span>'));
@@ -327,7 +240,7 @@
                 top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
                 opacity: opacity
             });
-            var _color = this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color");
+            var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan)).get("color");
             this.circle.strokeColor = _color;
             var _pc = this.paper_coords;
             this.all_buttons.forEach(function(b) {
@@ -694,7 +607,7 @@
             _a = _v.angle,
             _textdelta = _ortho.multiply(this.options.edge_label_distance),
             _handle = _v.divide(3),
-            _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
+            _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
             opacity = 1;
 
             if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
@@ -740,7 +653,7 @@
                 _textdelta = _textdelta.multiply(-1);
             }
             var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
-            _text = shortenText(_text, this.options.node_label_max_length);
+            _text = Rkns.Utils.shortenText(_text, this.options.node_label_max_length);
             this.text.text(_text);
             var _textpos = this.paper_coords.add(_textdelta);
             this.text.css({
@@ -853,7 +766,7 @@
             this.renderer.edge_layer.activate();
             this.type = "Temp-edge";
 
-            var _color = (this.project.get("users").get(this.renkan.current_user) || _USER_PLACEHOLDER(this.renkan)).get("color");
+            var _color = (this.project.get("users").get(this.renkan.current_user) || Rkns.Utils._USER_PLACEHOLDER(this.renkan)).get("color");
             this.line = new paper.Path();
             this.line.strokeColor = _color;
             this.line.dashArray = [4, 2];
@@ -988,7 +901,7 @@
         ),
         draw: function() {
             var _model = this.source_representation.model,
-            _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
+            _created_by = _model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan),
             _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),
             _image_placeholder = this.options.static_url + "img/image-placeholder.png",
             _size = (_model.get("size") || 0);
@@ -998,7 +911,7 @@
                     has_creator: !!_model.get("created_by"),
                     title: _model.get("title"),
                     uri: _model.get("uri"),
-                    short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
+                    short_uri:  Rkns.Utils.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
                     description: _model.get("description"),
                     image: _model.get("image") || "",
                     image_placeholder: _image_placeholder,
@@ -1010,7 +923,7 @@
                 },
                 renkan: this.renkan,
                 options: this.options,
-                shortenText: shortenText
+                shortenText: Rkns.Utils.shortenText
             }));
             this.redraw();
             var _this = this,
@@ -1104,7 +1017,7 @@
                         },
                         function(_e) {
                             _e.preventDefault();
-                            _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
+                            _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(_this.renkan)).get("color"));
                         }
                 ).click(function(_e) {
                     _e.preventDefault();
@@ -1151,7 +1064,7 @@
         },
         redraw: function() {
             var _coords = this.source_representation.paper_coords;
-            drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
+            Rkns.Utils.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
             this.editor_$.show();
             paper.view.draw();
         }
@@ -1191,7 +1104,7 @@
             var _model = this.source_representation.model,
             _from_model = _model.get("from"),
             _to_model = _model.get("to"),
-            _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
+            _created_by = _model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan),
             _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
             this.editor_$
             .html(_template({
@@ -1199,18 +1112,18 @@
                     has_creator: !!_model.get("created_by"),
                     title: _model.get("title"),
                     uri: _model.get("uri"),
-                    short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
+                    short_uri:  Rkns.Utils.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
                     description: _model.get("description"),
                     color: _model.get("color") || _created_by.get("color"),
                     from_title: _from_model.get("title"),
                     to_title: _to_model.get("title"),
-                    from_color: _from_model.get("color") || (_from_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
-                    to_color: _to_model.get("color") || (_to_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
+                    from_color: _from_model.get("color") || (_from_model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
+                    to_color: _to_model.get("color") || (_to_model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
                     created_by_color: _created_by.get("color"),
                     created_by_title: _created_by.get("title")
                 },
                 renkan: this.renkan,
-                shortenText: shortenText,
+                shortenText: Rkns.Utils.shortenText,
                 options: this.options
             }));
             this.redraw();
@@ -1295,7 +1208,7 @@
                         },
                         function(_e) {
                             _e.preventDefault();
-                            _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
+                            _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Utils._USER_PLACEHOLDER(_this.renkan)).get("color"));
                         }
                 ).click(function(_e) {
                     _e.preventDefault();
@@ -1311,7 +1224,7 @@
         },
         redraw: function() {
             var _coords = this.source_representation.paper_coords;
-            drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
+            Rkns.Utils.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
             this.editor_$.show();
             paper.view.draw();
         }
@@ -1330,7 +1243,7 @@
                 }
                 this.sector = this.renderer.drawSector(
                         this, 1 + sectorInner,
-                        _NODE_BUTTON_WIDTH + sectorInner,
+                        Rkns.Utils._NODE_BUTTON_WIDTH + sectorInner,
                         this.startAngle,
                         this.endAngle,
                         1,
@@ -1496,7 +1409,7 @@
     _(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"));
+            this.sector = this.renderer.drawSector(this, Rkns.Utils._EDGE_BUTTON_INNER, Rkns.Utils._EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
         },
         mouseup: function() {
             if (!this.renderer.is_dragging) {
@@ -1512,7 +1425,7 @@
     _(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"));
+            this.sector = this.renderer.drawSector(this, Rkns.Utils._EDGE_BUTTON_INNER, Rkns.Utils._EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
         },
         mouseup: function() {
             this.renderer.click_target = null;
@@ -1542,7 +1455,7 @@
     _(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"));
+            this.sector = this.renderer.drawSector(this, Rkns.Utils._EDGE_BUTTON_INNER, Rkns.Utils._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
         },
         mouseup: function() {
             this.renderer.click_target = null;
@@ -1646,10 +1559,10 @@
             img.src = _renkan.options.static_url + 'img/' + imgname + '.png';
             _this.icon_cache[imgname] = img;
         });
-
+        
         var throttledMouseMove = _.throttle(function(_event, _isTouch) {
             _this.onMouseMove(_event, _isTouch);
-        }, _MOUSEMOVE_RATE);
+        }, Rkns.Utils._MOUSEMOVE_RATE);
 
         this.canvas_$.on({
             mousedown: function(_event) {
@@ -1677,8 +1590,8 @@
                 var _touches = _event.originalEvent.touches[0];
                 if (
                         _renkan.options.allow_double_click
-                        && new Date() - _lastTap < _DOUBLETAP_DELAY
-                        && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < _DOUBLETAP_DISTANCE )
+                        && new Date() - _lastTap < Rkns.Utils._DOUBLETAP_DELAY
+                        && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Rkns.Utils._DOUBLETAP_DISTANCE )
                 ) {
                     _lastTap = 0;
                     _this.onDoubleClick(_touches);
@@ -1820,7 +1733,7 @@
         bindClick(".Rk-Save-Button", "save");
         bindClick(".Rk-Open-Button", "open");
         this.$.find(".Rk-Bookmarklet-Button")
-        .attr("href","javascript:" + _BOOKMARKLET_CODE(_renkan))
+        .attr("href","javascript:" + Rkns.Utils._BOOKMARKLET_CODE(_renkan))
         .click(function(){
             _this.notif_$
             .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."))
@@ -2201,7 +2114,7 @@
             this.redrawUsers();
         },
         setScale: function(_newScale, _offset) {
-            if ((_newScale/this.initialScale) > _MIN_SCALE && (_newScale/this.initialScale) < _MAX_SCALE) {
+            if ((_newScale/this.initialScale) > Rkns.Utils._MIN_SCALE && (_newScale/this.initialScale) < Rkns.Utils._MAX_SCALE) {
                 this.scale = _newScale;
                 if (_offset) {
                     this.offset = _offset;
@@ -2272,6 +2185,8 @@
         },
         addRepresentation: function(_type, _model) {
             var _repr = new Renderer[_type](this, _model);
+            console.log("REPR RENKAN",_repr);
+            console.log("REPR RENKAN",Renderer[_type]);
             this.representations.push(_repr);
             return _repr;
         },
@@ -2426,7 +2341,7 @@
                                       ]),
                                       _delta = _point.subtract(this.last_point);
             this.last_point = _point;
-            if (!this.is_dragging && this.mouse_down && _delta.length > _MIN_DRAG_DISTANCE) {
+            if (!this.is_dragging && this.mouse_down && _delta.length > Rkns.Utils._MIN_DRAG_DISTANCE) {
                 this.is_dragging = true;
             }
             var _hitResult = paper.project.hitTest(_point);
@@ -2458,7 +2373,7 @@
                     this.click_target.mousedown(_event, _isTouch);
                 } else {
                     this.click_target = null;
-                    if (this.isEditable() && this.click_mode === _CLICKMODE_ADDNODE) {
+                    if (this.isEditable() && this.click_mode === Rkns.Utils._CLICKMODE_ADDNODE) {
                         var _coords = this.toModelCoords(_point),
                         _data = {
                             id: Rkns.Utils.getUID('node'),
@@ -2474,10 +2389,10 @@
                 }
             }
             if (this.click_mode) {
-                if (this.isEditable() && this.click_mode === _CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
+                if (this.isEditable() && this.click_mode === Rkns.Utils._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
                     this.removeRepresentationsOfType("editor");
                     this.addTempEdge(this.click_target, _point);
-                    this.click_mode = _CLICKMODE_ENDEDGE;
+                    this.click_mode = Rkns.Utils._CLICKMODE_ENDEDGE;
                     this.notif_$.fadeOut(function() {
                         $(this).html(this.renkan.translate("Click on a second node to complete the edge")).fadeIn();
                     });
@@ -2716,21 +2631,21 @@
             this.setScale( _newScale, _offset );
         },
         addNodeBtn: function() {
-            if (this.click_mode === _CLICKMODE_ADDNODE) {
+            if (this.click_mode === Rkns.Utils._CLICKMODE_ADDNODE) {
                 this.click_mode = false;
                 this.notif_$.hide();
             } else {
-                this.click_mode = _CLICKMODE_ADDNODE;
+                this.click_mode = Rkns.Utils._CLICKMODE_ADDNODE;
                 this.notif_$.text(this.renkan.translate("Click on the background canvas to add a node")).fadeIn();
             }
             return false;
         },
         addEdgeBtn: function() {
-            if (this.click_mode === _CLICKMODE_STARTEDGE || this.click_mode === _CLICKMODE_ENDEDGE) {
+            if (this.click_mode === Rkns.Utils._CLICKMODE_STARTEDGE || this.click_mode === Rkns.Utils._CLICKMODE_ENDEDGE) {
                 this.click_mode = false;
                 this.notif_$.hide();
             } else {
-                this.click_mode = _CLICKMODE_STARTEDGE;
+                this.click_mode = Rkns.Utils._CLICKMODE_STARTEDGE;
                 this.notif_$.text(this.renkan.translate("Click on a first node to start the edge")).fadeIn();
             }
             return false;