Merge with 4732f078d0fecc226b4b790097c58a6cd30c3832
authorrougeronj
Fri, 22 May 2015 17:50:10 +0200
changeset 454 03e8815a012d
parent 453 04b7d46e9d67 (diff)
parent 441 4732f078d0fe (current diff)
child 455 18b9be54174d
Merge with 4732f078d0fecc226b4b790097c58a6cd30c3832
client/img/show.png
--- a/client/css/renkan.css	Wed May 13 10:02:04 2015 +0200
+++ b/client/css/renkan.css	Fri May 22 17:50:10 2015 +0200
@@ -527,7 +527,7 @@
     top: 0;
 }
 
-.Rk-ZoomIn, .Rk-ZoomOut, .Rk-ZoomFit, .Rk-ZoomSave, .Rk-ZoomSetSaved {
+.Rk-ZoomIn, .Rk-ZoomOut, .Rk-ZoomFit, .Rk-ZoomSave, .Rk-ZoomSetSaved, .Rk-ShowHiddenNodes {
     width: 21px; height: 20px; background: url(../img/zoombuttons.png); margin: 5px;
 }
 .Rk-ZoomIn:hover {
@@ -557,6 +557,12 @@
 .Rk-ZoomSetSaved:hover {
     background-position: -84px -20px;
 }
+.Rk-ShowHiddenNodes {
+    background-position: -105px 0;
+}
+.Rk-ShowHiddenNodes:hover {
+    background-position: -105px -20px;
+}
 
 /* Bins */
 
Binary file client/img/hide.png has changed
Binary file client/img/show.png has changed
Binary file client/img/zoombuttons.png has changed
--- a/client/js/defaults.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/defaults.js	Fri May 22 17:50:10 2015 +0200
@@ -10,6 +10,10 @@
            /* List of Bins */
     static_url: "",
         /* URL for static resources */
+    popup_editor: true,
+        /* show the node editor as a popup inside the renkan view */
+    editor_panel: 'editor-panel',
+        /* GUI continer DOM element ID of the editor panel */
     show_bins: true,
         /* Show bins in left column */
     properties: [],
--- a/client/js/main-renderer.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/main-renderer.js	Fri May 22 17:50:10 2015 +0200
@@ -24,6 +24,8 @@
          'renderer/nodebutton',
          'renderer/nodeeditbutton',
          'renderer/noderemovebutton',
+         'renderer/nodehidebutton',
+         'renderer/nodeshowbutton',
          'renderer/noderevertbutton',
          'renderer/nodelinkbutton',
          'renderer/nodeenlargebutton',
@@ -33,7 +35,7 @@
          'renderer/edgerevertbutton',
          'renderer/miniframe',
          'renderer/scene'
-         ], function(BaseRepresentation, BaseButton, NodeRepr, Edge, TempEdge, BaseEditor, NodeEditor, EdgeEditor, NodeButton, NodeEditButton, NodeRemoveButton, NodeRevertButton, NodeLinkButton, NodeEnlargeButton, NodeShrinkButton, EdgeEditButton, EdgeRemoveButton, EdgeRevertButton, MiniFrame, Scene){
+         ], function(BaseRepresentation, BaseButton, NodeRepr, Edge, TempEdge, BaseEditor, NodeEditor, EdgeEditor, NodeButton, NodeEditButton, NodeRemoveButton, NodeHideButton, NodeShowButton, NodeRevertButton, NodeLinkButton, NodeEnlargeButton, NodeShrinkButton, EdgeEditButton, EdgeRemoveButton, EdgeRevertButton, MiniFrame, Scene){
 
     'use strict';
 
@@ -55,6 +57,8 @@
     Renderer._NodeButton = NodeButton;
     Renderer.NodeEditButton = NodeEditButton;
     Renderer.NodeRemoveButton = NodeRemoveButton;
+    Renderer.NodeHideButton = NodeHideButton;
+    Renderer.NodeShowButton = NodeShowButton;
     Renderer.NodeRevertButton = NodeRevertButton;
     Renderer.NodeLinkButton = NodeLinkButton;
     Renderer.NodeEnlargeButton = NodeEnlargeButton;
--- a/client/js/main.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/main.js	Fri May 22 17:50:10 2015 +0200
@@ -111,12 +111,12 @@
     this.project = new Rkns.Models.Project();
 
     this.setCurrentUser = function (user_id, user_name) {
-    	this.project.addUser({
-    		_id:user_id,
-    		title: user_name
-    	});
-    	this.current_user = user_id;
-    	this.renderer.redrawUsers();
+        this.project.addUser({
+            _id:user_id,
+            title: user_name
+        });
+        this.current_user = user_id;
+        this.renderer.redrawUsers();
     };
 
     if (typeof this.options.user_id !== "undefined") {
@@ -307,7 +307,7 @@
     this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass());
     var listClasses = this.search_engine.getBgClass().split(" ");
     var classes = "";
-    for	(var i= 0; i < listClasses.length; i++) {
+    for (var i= 0; i < listClasses.length; i++) {
         classes += "." + listClasses[i];
     }
     this.$.find(".Rk-Web-Search-Input.Rk-Search-Input").attr("placeholder", this.translate("Search in ") + this.$.find(".Rk-Search-List "+ classes).html());
--- a/client/js/models.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/models.js	Fri May 22 17:50:10 2015 +0200
@@ -100,9 +100,8 @@
                         .get("_id") : null,
                 size : this.get("size"),
                 clip_path : this.get("clip_path"),
-                shape : this.get("shape"),
-                type : this.get("type"),
-                hidden : this.get("hidden")
+                shape : this.get("shape"),  
+                type : this.get("type")
             };
         }
     });
@@ -183,7 +182,8 @@
                 title : this.get("title"),
                 description : this.get("description"),
                 created_by : this.get("created_by") ? this.get("created_by")
-                        .get("_id") : null
+                        .get("_id") : null,
+                hidden_nodes: this.get("hidden_nodes")
             // Don't need project id
             };
         }
--- a/client/js/renderer/edge.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/edge.js	Fri May 22 17:50:10 2015 +0200
@@ -13,6 +13,8 @@
         _init: function() {
             this.renderer.edge_layer.activate();
             this.type = "Edge";
+            this.hidden = false;
+            this.ghost = false;
             this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
             this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
             this.bundle = this.renderer.addToBundles(this);
@@ -58,12 +60,15 @@
         redraw: function() {
             var from = this.model.get("from"),
             to = this.model.get("to");
-            if (!from || !to) {
+            if (!from || !to || (this.hidden && !this.ghost)) {
                 return;
             }
             this.from_representation = this.renderer.getRepresentationByModel(from);
             this.to_representation = this.renderer.getRepresentationByModel(to);
-            if (typeof this.from_representation === "undefined" || typeof this.to_representation === "undefined") {
+            if (typeof this.from_representation === "undefined" || typeof this.to_representation === "undefined" ||
+                    (this.from_representation.hidden && !this.from_representation.ghost) ||
+                    (this.to_representation.hidden && !this.to_representation.ghost)){
+                this.hide();
                 return;
             }
             var _p0a = this.from_representation.paper_coords,
@@ -105,7 +110,7 @@
 
             this.paper_coords = _p0b.add(_p1b).divide(2);
             this.line.strokeColor = _color;
-            this.line.opacity = opacity;
+            this.line.opacity = this.ghost ? 0.3 : opacity;
             this.line.segments[0].point = _p0a;
             this.line.segments[1].point = this.paper_coords;
             this.line.segments[1].handleIn = _handle.multiply(-1);
@@ -113,7 +118,7 @@
             this.line.segments[2].point = _p1a;
             this.arrow.rotate(_a - this.arrow_angle);
             this.arrow.fillColor = _color;
-            this.arrow.opacity = opacity;
+            this.arrow.opacity = this.ghost ? 0.3 : opacity;
             this.arrow.position = this.paper_coords;
             this.arrow_angle = _a;
             if (_a > 90) {
@@ -134,7 +139,7 @@
                 transform: "rotate(" + _a + "deg)",
                 "-moz-transform": "rotate(" + _a + "deg)",
                 "-webkit-transform": "rotate(" + _a + "deg)",
-                opacity: opacity
+                opacity: this.ghost ? 0.3 : opacity
             });
             this.text_angle = _a;
 
@@ -149,6 +154,36 @@
                 this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
             }
         },
+        hide: function(){
+            this.hidden = true;
+            this.ghost = false;
+            
+            this.text.hide();
+            this.line.visible = false;
+            this.arrow.visible = false;
+            this.minimap_line.visible = false;
+        },
+        show: function(ghost){
+            this.ghost = ghost;
+            if (this.ghost){
+                this.text.css('opacity', 0.3);
+                this.line.opacity = 0.3;
+                this.arrow.opacity = 0.3;
+                this.minimap_line.opacity = 0.3;
+            }else{
+                this.hidden = false;
+                
+                this.text.css('opacity', 1);
+                this.line.opacity = 1;
+                this.arrow.opacity = 1;
+                this.minimap_line.opacity = 1;
+            }
+            this.text.show();
+            this.line.visible = true;
+            this.arrow.visible = true;
+            this.minimap_line.visible = true;
+            this.redraw();
+        },
         openEditor: function() {
             this.renderer.removeRepresentationsOfType("editor");
             var _editor = this.renderer.addRepresentation("EdgeEditor",null);
--- a/client/js/renderer/edgeeditor.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/edgeeditor.js	Fri May 22 17:50:10 2015 +0200
@@ -138,8 +138,10 @@
             }
         },
         redraw: function() {
-            var _coords = this.source_representation.paper_coords;
-            Utils.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
+            if (this.options.popup_editor){
+                var _coords = this.source_representation.paper_coords;
+                Utils.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
+            }
             this.editor_$.show();
             paper.view.draw();
         }
--- a/client/js/renderer/nodeeditbutton.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/nodeeditbutton.js	Fri May 22 17:50:10 2015 +0200
@@ -13,8 +13,8 @@
         _init: function() {
             this.type = "Node-edit-button";
             this.lastSectorInner = 0;
-            this.startAngle = -135;
-            this.endAngle = -45;
+            this.startAngle = -125;
+            this.endAngle = -55;
             this.imageName = "edit";
             this.text = "Edit";
         },
--- a/client/js/renderer/nodeeditor.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/nodeeditor.js	Fri May 22 17:50:10 2015 +0200
@@ -12,6 +12,8 @@
         _init: function() {
             BaseEditor.prototype._init.apply(this);
             this.template = this.options.templates['templates/nodeeditor.html'];
+            //this.templates['default']= this.options.templates['templates/nodeeditor.html'];
+            //fusionner avec this.options.node_editor_templates
             this.readOnlyTemplate = this.options.templates['templates/nodeeditor_readonly.html'];
         },
         draw: function() {
@@ -202,8 +204,10 @@
             });
         },
         redraw: function() {
-            var _coords = this.source_representation.paper_coords;
-            Utils.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * 0.75, this.editor_$);
+            if (this.options.popup_editor){
+                var _coords = this.source_representation.paper_coords;
+                Utils.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * 0.75, this.editor_$);                
+            }
             this.editor_$.show();
             paper.view.draw();
         }
--- a/client/js/renderer/nodeenlargebutton.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/nodeenlargebutton.js	Fri May 22 17:50:10 2015 +0200
@@ -14,8 +14,8 @@
         _init: function() {
             this.type = "Node-enlarge-button";
             this.lastSectorInner = 0;
-            this.startAngle = -45;
-            this.endAngle = 0;
+            this.startAngle = -55;
+            this.endAngle = -10;
             this.imageName = "enlarge";
             this.text = "Enlarge";
         },
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/js/renderer/nodehidebutton.js	Fri May 22 17:50:10 2015 +0200
@@ -0,0 +1,35 @@
+
+define(['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+    'use strict';
+
+    var Utils = requtils.getUtils();
+
+    /* NodeRemoveButton Begin */
+
+    //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);
+    var NodeHideButton = Utils.inherit(NodeButton);
+
+    _(NodeHideButton.prototype).extend({
+        _init: function() {
+            this.type = "Node-hide-button";
+            this.lastSectorInner = 0;
+            this.startAngle = 45;
+            this.endAngle = 90;
+            this.imageName = "hide";
+            this.text = "Hide";
+        },
+        mouseup: function() {
+            this.renderer.click_target = null;
+            this.renderer.is_dragging = false;
+            this.renderer.removeRepresentationsOfType("editor");
+            if (this.renderer.isEditable()) {
+                this.renderer.addHiddenNode(this.source_representation.model);
+            }
+        }
+    }).value();
+
+    /* NodeRemoveButton End */
+
+    return NodeHideButton;
+
+});
--- a/client/js/renderer/nodelinkbutton.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/nodelinkbutton.js	Fri May 22 17:50:10 2015 +0200
@@ -13,8 +13,8 @@
         _init: function() {
             this.type = "Node-link-button";
             this.lastSectorInner = 0;
-            this.startAngle = 90;
-            this.endAngle = 180;
+            this.startAngle = 135;
+            this.endAngle = 190;
             this.imageName = "link";
             this.text = "Link to another node";
         },
--- a/client/js/renderer/noderemovebutton.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/noderemovebutton.js	Fri May 22 17:50:10 2015 +0200
@@ -13,8 +13,8 @@
         _init: function() {
             this.type = "Node-remove-button";
             this.lastSectorInner = 0;
-            this.startAngle = 0;
-            this.endAngle = 90;
+            this.startAngle = -10;
+            this.endAngle = 45;
             this.imageName = "remove";
             this.text = "Remove";
         },
--- a/client/js/renderer/noderepr.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/noderepr.js	Fri May 22 17:50:10 2015 +0200
@@ -17,6 +17,8 @@
             this.renderer.node_layer.activate();
             this.type = "Node";
             this.buildShape();
+            this.hidden = false;
+            this.ghost= false;
             if (this.options.show_node_circles) {
                 this.circle.strokeWidth = this.options.node_stroke_width;
                 this.h_ratio = 1;
@@ -30,6 +32,8 @@
                 this.normal_buttons = [
                                        new Renderer.NodeEditButton(this.renderer, null),
                                        new Renderer.NodeRemoveButton(this.renderer, null),
+                                       new Renderer.NodeHideButton(this.renderer, null),
+                                       new Renderer.NodeShowButton(this.renderer, null),
                                        new Renderer.NodeLinkButton(this.renderer, null),
                                        new Renderer.NodeEnlargeButton(this.renderer, null),
                                        new Renderer.NodeShrinkButton(this.renderer, null)
@@ -97,7 +101,7 @@
             this.last_circle_radius = this.circle_radius;
 
             var old_act_btn = this.active_buttons;
-
+            
             var opacity = 1;
             if (this.model.get("delete_scheduled")) {
                 opacity = 0.5;
@@ -108,8 +112,7 @@
                 this.active_buttons = this.normal_buttons;
                 this.circle.dashArray = null;
             }
-
-            if (this.selected && this.renderer.isEditable()) {
+            if (this.selected && this.renderer.isEditable() && !this.ghost) {
                 if (old_act_btn !== this.active_buttons) {
                     old_act_btn.forEach(function(b) {
                         b.hide();
@@ -136,7 +139,6 @@
             } else {
                 this.title.text(_text);
             }
-
             this.title.css({
                 left: this.paper_coords.x,
                 top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
@@ -160,7 +162,8 @@
                 this.node_image.remove();
                 delete this.node_image;
             }
-
+            
+            
             if (this.renderer.minimap) {
                 this.minimap_circle.fillColor = _color;
                 var minipos = this.renderer.toMinimapCoords(_model_coords),
@@ -185,7 +188,11 @@
                         }
                 );
             }
-
+            if (this.ghost){
+                this.show(true);
+            } else {
+                if (this.hidden) { this.hide(); }
+            }
         },
         showImage: function() {
             var _image = null;
@@ -336,7 +343,7 @@
         select: function() {
             this.selected = true;
             this.circle.strokeWidth = this.options.selected_node_stroke_width;
-            if (this.renderer.isEditable()) {
+            if (this.renderer.isEditable() && !this.hidden) {
                 this.active_buttons.forEach(function(b) {
                     b.show();
                 });
@@ -358,6 +365,12 @@
                 this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
                 this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
             }
+            //if the node is hidden and the mouse hover it, it appears as a ghost
+            if (this.hidden){
+                this.show(true);
+            }else{
+                this.showNeighbors(true);
+            }
             this._super("select");
         },
         hideButtons: function() {
@@ -376,9 +389,110 @@
                 if (this.renderer.minimap) {
                     this.minimap_circle.strokeColor = undefined;
                 }
+                //when the mouse don't hover the node anymore, we hide it
+                if (this.hidden){
+                    this.hide();
+                }else{
+                    this.hideNeighbors();
+                }
                 this._super("unselect");
             }
         },
+        hide: function(){
+            var _this = this;
+            this.ghost = false;
+            this.hidden = true;
+            if (typeof this.node_image !== 'undefined'){
+                this.node_image.opacity = 0;                
+            }
+            this.hideButtons();
+            this.circle.opacity = 0;
+            this.title.css('opacity', 0);
+            this.minimap_circle.opacity = 0;
+            
+            
+            _.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.hide();
+                        }
+                    }
+            );
+            this.hideNeighbors();
+        },
+        show: function(ghost){
+            var _this = this;
+            this.ghost = ghost;
+            if (this.ghost){
+                if (typeof this.node_image !== 'undefined'){
+                    this.node_image.opacity = 0.3;
+                }
+                this.circle.opacity = 0.3;
+                this.title.css('opacity', 0.3);
+                this.minimap_circle.opacity = 0.3;
+            } else {
+                this.hidden = false;
+                this.redraw();
+            }
+            
+            _.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.show(_this.ghost);
+                        }
+                    }
+            );            
+        },
+        hideNeighbors: function(){
+            var _this = this;
+            _.each(
+                    this.project.get("edges").filter(
+                            function (ed) {
+                                return (ed.get("from") === _this.model);
+                            }
+                    ),
+                    function(edge, index, list) {
+                        var repr = _this.renderer.getRepresentationByModel(edge.get("to"));
+                        if (repr && repr.ghost) {
+                            repr.hide();
+                        }
+                    }
+            );
+        },
+        showNeighbors: function(ghost){
+            var _this = this;
+            _.each(
+                    this.project.get("edges").filter(
+                            function (ed) {
+                                return (ed.get("from") === _this.model);
+                            }
+                    ),
+                    function(edge, index, list) {
+                        var repr = _this.renderer.getRepresentationByModel(edge.get("to"));
+                        if (repr && repr.hidden) {
+                            repr.show(ghost);
+                            if (!ghost){
+                                var indexNode = _this.renderer.hiddenNodes.indexOf(repr.model.id);
+                                if (indexNode !== -1){
+                                    _this.renderer.hiddenNodes.splice(indexNode, 1);
+                                }
+                            }
+                        }
+                    }
+            );
+        },
         highlight: function(textToReplace) {
             var hlvalue = textToReplace || true;
             if (this.highlighted === hlvalue) {
@@ -418,10 +532,19 @@
             if (this.renderer.is_dragging && this.renderer.isEditable()) {
                 this.saveCoords();
             } else {
-                if (!_isTouch && !this.model.get("delete_scheduled")) {
-                    this.openEditor();
+                if (this.hidden){
+                    var index = this.renderer.hiddenNodes.indexOf(this.model.id);
+                    if (index !== -1){
+                        this.renderer.hiddenNodes.splice(index, 1);
+                    }
+                    this.show(false);
+                    this.select();
+                }else{
+                    if (!_isTouch && !this.model.get("delete_scheduled")) {
+                        this.openEditor();
+                    }
+                    this.model.trigger("clicked");                    
                 }
-                this.model.trigger("clicked");
             }
             this.renderer.click_target = null;
             this.renderer.is_dragging = false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/js/renderer/nodeshowbutton.js	Fri May 22 17:50:10 2015 +0200
@@ -0,0 +1,35 @@
+
+define(['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+    'use strict';
+
+    var Utils = requtils.getUtils();
+
+    /* NodeRemoveButton Begin */
+
+    //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);
+    var NodeShowButton = Utils.inherit(NodeButton);
+
+    _(NodeShowButton.prototype).extend({
+        _init: function() {
+            this.type = "Node-show-button";
+            this.lastSectorInner = 0;
+            this.startAngle = 90;
+            this.endAngle = 135;
+            this.imageName = "show";
+            this.text = "Show";
+        },
+        mouseup: function() {
+            this.renderer.click_target = null;
+            this.renderer.is_dragging = false;
+            this.renderer.removeRepresentationsOfType("editor");
+            if (this.renderer.isEditable()) {
+                this.source_representation.showNeighbors(false);
+            }
+        }
+    }).value();
+
+    /* NodeShowButton End */
+
+    return NodeShowButton;
+
+});
--- a/client/js/renderer/nodeshrinkbutton.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/nodeshrinkbutton.js	Fri May 22 17:50:10 2015 +0200
@@ -13,8 +13,8 @@
         _init: function() {
             this.type = "Node-shrink-button";
             this.lastSectorInner = 0;
-            this.startAngle = -180;
-            this.endAngle = -135;
+            this.startAngle = -170;
+            this.endAngle = -125;
             this.imageName = "shrink";
             this.text = "Shrink";
         },
--- a/client/js/renderer/scene.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/renderer/scene.js	Fri May 22 17:50:10 2015 +0200
@@ -14,13 +14,18 @@
         this.onStatusChange();
         this.canvas_$ = this.$.find(".Rk-Canvas");
         this.labels_$ = this.$.find(".Rk-Labels");
-        this.editor_$ = this.$.find(".Rk-Editor");
+        if (!_renkan.options.popup_editor){
+            this.editor_$ = $("#" + _renkan.options.editor_panel);
+        }else{
+            this.editor_$ = this.$.find(".Rk-Editor");
+        }
         this.notif_$ = this.$.find(".Rk-Notifications");
         paper.setup(this.canvas_$[0]);
         this.scale = 1;
         this.initialScale = 1;
         this.offset = paper.view.center;
         this.totalScroll = 0;
+        this.hiddenNodes = [];
         this.mouse_down = false;
         this.click_target = null;
         this.selected_target = null;
@@ -78,7 +83,7 @@
         this.image_cache = {};
         this.icon_cache = {};
 
-        ['edit', 'remove', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) {
+        ['edit', 'remove', 'hide', 'show', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) {
             var img = new Image();
             img.src = _renkan.options.static_url + 'img/' + imgname + '.png';
             _this.icon_cache[imgname] = img;
@@ -234,14 +239,26 @@
         bindClick(".Rk-ZoomFit", "autoScale");
         this.$.find(".Rk-ZoomSave").click( function() {
             // Save scale and offset point
-            _this.renkan.project.addView( { zoom_level:_this.scale, offset:_this.offset } );
+            _this.renkan.project.addView( { zoom_level:_this.scale, offset:_this.offset, hidden_nodes: _this.hiddenNodes } );
         });
         this.$.find(".Rk-ZoomSetSaved").click( function() {
             var view = _this.renkan.project.get("views").last();
             if(view){
                 _this.setScale(view.get("zoom_level"), new paper.Point(view.get("offset")));
+                _this.hiddenNodes = view.get("hidden_nodes") || [];
+                _this.hideNodes();
             }
         });
+        this.$.find(".Rk-ShowHiddenNodes").mouseenter( function() {
+            _this.showNodes(true);
+            _this.$.find(".Rk-ShowHiddenNodes").mouseleave( function() {
+                _this.hideNodes(false);
+            });
+        });
+        this.$.find(".Rk-ShowHiddenNodes").click( function() {
+            _this.showNodes(false);
+            _this.$.find(".Rk-ShowHiddenNodes").off( "mouseleave" ); 
+        });
         if(this.renkan.project.get("views").length > 0 && this.renkan.options.save_view){
             this.$.find(".Rk-ZoomSetSaved").show();
         }
@@ -725,7 +742,7 @@
         addRepresentations: function(_type, _collection) {
             var _this = this;
             _collection.forEach(function(_model) {
-                _this.addRepresentation(_type, _model);
+                //_this.addRepresentation(_type, _model);
             });
         },
         userTemplate: _.template(
@@ -829,6 +846,7 @@
             });
         },
         redraw: function() {
+            var _this = this;
             if(! this.redrawActive ) {
                 return;
             }
@@ -847,6 +865,38 @@
             _tmpEdge.redraw();
             this.click_target = _tmpEdge;
         },
+        addHiddenNode: function(_model){
+            this.hideNode(_model);
+            this.hiddenNodes.push(_model.id);
+        },
+        hideNode: function(_model){
+            var _this = this;
+            if (typeof _this.getRepresentationByModel(_model) !== 'undefined'){
+                _this.getRepresentationByModel(_model).hide();
+            }
+        },
+        hideNodes: function(){
+            var _this = this;
+            this.hiddenNodes.forEach(function(_id, index){
+                var node = _this.renkan.project.get("nodes").get(_id);
+                if (typeof node !== 'undefined'){
+                    return _this.hideNode(_this.renkan.project.get("nodes").get(_id));
+                }else{
+                    _this.hiddenNodes.splice(index, 1);
+                }
+            });
+            paper.view.draw();
+        },
+        showNodes: function(ghost){
+            var _this = this;
+            this.hiddenNodes.forEach(function(_id){
+                _this.getRepresentationByModel(_this.renkan.project.get("nodes").get(_id)).show(ghost);
+            });
+            if (!ghost){
+                this.hiddenNodes = [];
+            }
+            paper.view.draw();
+        },
         findTarget: function(_hitResult) {
             if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
                 var _newTarget = _hitResult.item.__representation;
@@ -977,15 +1027,21 @@
             }
         },
         onDoubleClick: function(_event) {
-            if (!this.isEditable()) {
-                return;
-            }
             var _off = this.canvas_$.offset(),
             _point = new paper.Point([
                                       _event.pageX - _off.left,
                                       _event.pageY - _off.top
                                       ]);
             var _hitResult = paper.project.hitTest(_point);
+            
+            if (!this.isEditable()) {
+                if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+                    if (_hitResult.item.__representation.model.get('uri')){
+                        window.open(_hitResult.item.__representation.model.get('uri'), '_blank');
+                    }
+                }
+                return;
+            }
             if (this.isEditable() && (!_hitResult || typeof _hitResult.item.__representation === "undefined")) {
                 var _coords = this.toModelCoords(_point),
                 _data = {
--- a/client/js/save-once.js	Wed May 13 10:02:04 2015 +0200
+++ b/client/js/save-once.js	Fri May 22 17:50:10 2015 +0200
@@ -20,13 +20,13 @@
             url: _opts.url,
             data: getdata,
             beforeSend: function(){
-            	_proj.set({loading_status:true});
+                _proj.set({loading_status:true});
             },
             success: function(_data) {
                 _proj.set(_data, {validate: true});
-            	_proj.set({loading_status:false});
+                _proj.set({loading_status:false});
                 _proj.set({save_status:0});
-            	_renkan.renderer.autoScale();
+                _renkan.renderer.autoScale();
             }
         });
     };
@@ -39,7 +39,7 @@
             contentType: "application/json",
             data: JSON.stringify(_data),
             beforeSend: function(){
-            	_proj.set({save_status:2});
+                _proj.set({save_status:2});
             },
             success: function(data, textStatus, jqXHR) {
                 $(window).off("beforeunload", _onLeave);
@@ -51,8 +51,8 @@
         });
     };
     var _checkLeave = function() {
-    	_proj.set({save_status:1});
-    	
+        _proj.set({save_status:1});
+        
         var title = _proj.get("title");
         if (title && _proj.get("nodes").length) {
             $(".Rk-Save-Button").removeClass("disabled");
@@ -69,14 +69,14 @@
     };
     _load();
     _proj.on("add:nodes add:edges add:users change", function(_model) {
-	    _model.on("change remove", function(_model) {
-	    	if(!(_model.changedAttributes.length === 1 && _model.hasChanged('save_status'))) {
-	    		_checkLeave();
-	    	}
-	    });
-		if(!(_proj.changedAttributes.length === 1 && _proj.hasChanged('save_status'))) {
-		    _checkLeave();
-    	}
+        _model.on("change remove", function(_model) {
+            if(!(_model.changedAttributes.length === 1 && _model.hasChanged('save_status'))) {
+                _checkLeave();
+            }
+        });
+        if(!(_proj.changedAttributes.length === 1 && _proj.hasChanged('save_status'))) {
+            _checkLeave();
+        }
     });
     _renkan.renderer.save = function() {
         if ($(".Rk-Save-Button").hasClass("disabled")) {
--- a/client/templates/scene.html	Wed May 13 10:02:04 2015 +0200
+++ b/client/templates/scene.html	Fri May 22 17:50:10 2015 +0200
@@ -145,6 +145,7 @@
                 <% } %>
                 <% if (options.save_view) { %>
                     <div class="Rk-ZoomSetSaved" title="<%-translate('View saved zoom')%>"></div>
+                	<div class="Rk-ShowHiddenNodes" title="<%-translate('Show hidden nodes')%>"></div>
                 <% } %>
             </div>
         <% } %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/test/test-readonly-div-editor-panel.html	Fri May 22 17:50:10 2015 +0200
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html lang="fr">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>RENKAN test in read-only mode : body 100%</title>
+        <meta name="description" content="" />
+        <meta name="author" content="Institut de Recherche et d'Innovation" />
+        <script src="../lib/jquery/jquery.js"></script>
+        <script src="../lib/jquery-mousewheel/jquery.mousewheel.js"></script>
+        <script src="../lib/lodash/lodash.js"></script>
+        <script src="../lib/backbone/backbone.js"></script>
+        <script src="../lib/backbone-relational/backbone-relational.js"></script>
+        <script src="../lib/paper/paper-full.js"></script>
+        <script src="../js/main.js"></script>
+        <script src="../js/defaults.js"></script>
+        <script src="../js/i18n.js"></script>
+        <script src="../dist/js/templates.js"></script>
+        <script src="../js/models.js"></script>
+        <script src="../js/full-json.js"></script>
+        <script src="../js/list-bin.js"></script>
+        <script src="../js/ldtjson-bin.js"></script>
+        <script src="../js/wikipedia-bin.js"></script>
+        <script data-main="../js/main-renderer.js" src="../lib/requirejs/require.js"></script>
+        <script type="text/javascript">
+            function startRenkan(){
+            	var _renkan = new Rkns.Renkan({
+                    editor_mode: false,
+                    show_bins: false,
+                    static_url: "../",
+                    default_view:0,
+                    popup_editor:false,
+                    editor_panel:'editor-panel'
+                });
+                Rkns.jsonIO(_renkan, {
+                    url: "../data/example-cinema-src.json"
+                });
+            };
+        </script>
+        <link rel="stylesheet" href="../css/renkan.css" />
+        <style type="text/css">
+        body{
+            margin: 0 auto;
+            width: 960px;
+        }
+        .header, .footer {
+            font-size: 14px;
+            height: 40px;
+            padding-top: 10px;
+        }
+        .header{
+            height: 100px;
+        }
+        .rnk-container{
+            height: 700px;
+            position: relative;
+            width: 800px;
+        }
+        </style>
+    </head>
+
+    <body>
+        <div class="header">
+        This is a header with no css override.
+        <ul>
+           <li>list item 1</li>
+           <li>list item 2</li>
+        </ul>
+        <p>This is a paragraphe. This is a <a href="#">link</a>.
+        </div>
+        <div id="editor-panel" style="float: right;">
+        </div>
+        <div class="rnk-container">
+            <div id="renkan"></div>
+        </div>
+        <div class="footer">
+        This is a footer
+        </div>
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/test/test-writable-simple-div-editor-panel.html	Fri May 22 17:50:10 2015 +0200
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="fr">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>Test de Rendu RENKAN</title>
+        <meta name="description" content="" />
+        <meta name="author" content="Institut de Recherche et d'Innovation" />
+        <script src="../lib/jquery/jquery.js"></script>
+        <script src="../lib/jquery-mousewheel/jquery.mousewheel.js"></script>
+        <script src="../lib/lodash/lodash.js"></script>
+        <script src="../lib/backbone/backbone.js"></script>
+        <script src="../lib/backbone-relational/backbone-relational.js"></script>
+        <script src="../lib/paper/paper-full.js"></script>
+        <script src="../js/main.js"></script>
+        <script src="../js/models.js"></script>
+        <script src="../js/defaults.js"></script>
+        <script src="../js/i18n.js"></script>
+        <script src="../dist/js/templates.js"></script>
+        <script src="../js/full-json.js"></script>
+        <script src="../js/ldtjson-bin.js"></script>
+        <script src="../js/list-bin.js"></script>
+        <script src="../js/wikipedia-bin.js"></script>
+        <script data-main="../js/main-renderer.js" src="../lib/requirejs/require.js"></script>
+        <script type="text/javascript">
+            function startRenkan(){
+            	var _renkan = new Rkns.Renkan({
+                    /*property_files: [ "data/properties.json" ],
+                    user_id: "u-iri",
+                    language: "fr",
+                    node_fill_color: false*/
+                    show_bins: false,
+                    static_url: "../",
+                    popup_editor:false,
+                    editor_panel:"editor-panel"
+                });
+                Rkns.jsonIO(_renkan, {
+                    url: "/simple-persist"
+                });
+            };
+        </script>
+        <link rel="stylesheet" href="../css/renkan.css" />
+        <style type="text/css">
+        body{
+            margin: 0 auto;
+            width: 960px;
+        }
+        .header, .footer {
+            font-size: 14px;
+            height: 40px;
+            padding-top: 10px;
+        }
+        .rnk-container{
+            height: 500px;
+            position: relative;
+            width: 600px;
+        }
+        </style>
+    </head>
+
+    <body>
+        <div class="header">
+        This is a header
+        </div>
+        <div id="editor-panel" style="float: right;">
+        </div>
+        <div class="rnk-container">
+            <div id="renkan"></div>
+        </div>
+        <div class="footer">
+        This is a footer
+        </div>
+    </body>
+</html>