Added Drag-and-add bookmarklet
authorveltr
Thu, 28 Feb 2013 19:13:08 +0100
changeset 69 f0873867143a
parent 68 803dbeb7c919
child 70 47b3125130a2
Added Drag-and-add bookmarklet
client/css/renkan.css
client/img/topbarbuttons.png
client/js/i18n.js
client/js/main.js
client/js/paper-renderer.js
--- a/client/css/renkan.css	Wed Feb 27 19:04:36 2013 +0100
+++ b/client/css/renkan.css	Thu Feb 28 19:13:08 2013 +0100
@@ -79,7 +79,7 @@
 }
 
 .Rk-PadTitle {
-    float: left; font-size: 14px; height: 16px; margin: 4px 5px; width: 200px; background: #666666; padding: 4px; border: 1px solid #333333;
+    float: left; font-size: 14px; height: 16px; margin: 4px 5px; width: 180px; background: #666666; padding: 4px; border: 1px solid #333333;
     border-radius: 3px; box-shadow: 0 1px 0 #505050; color: #ffffff; font-weight: bold;
 }
 
@@ -132,31 +132,31 @@
 }
 
 .Rk-AddNode-Button {
-    width: 34px;
+    width: 30px; background-position: -2px 0;
 }
 
 .Rk-AddNode-Button:hover {
-    background-position: 0 -35px;
+    background-position: -2px -35px;
 }
 
 .Rk-FullScreen-Button {
-    width: 34px; background-position: -34px 0;
+    width: 30px; background-position: -36px 0;
 }
 
 .Rk-FullScreen-Button:hover {
-    background-position: -34px -35px;
+    background-position: -36px -35px;
 }
 
 .Rk-AddEdge-Button {
-    width: 34px; background-position: -68px 0;
+    width: 30px; background-position: -70px 0;
 }
 
 .Rk-AddEdge-Button:hover {
-    background-position: -68px -35px;
+    background-position: -70px -35px;
 }
 
 .Rk-Save-Button {
-    width: 34px; background-position: -102px 0;
+    width: 30px; background-position: -104px 0;
 }
 
 .Rk-Save-Button.disabled {
@@ -164,12 +164,29 @@
 }
 
 .Rk-Save-Button:hover {
-    background-position: -102px -35px;
+    background-position: -104px -35px;
 }
 
 .Rk-Save-Button.disabled:hover {
-    opacity: 1; background-position: -102px 0;
+    opacity: 1; background-position: -104px 0;
+}
+
+.Rk-Bookmarklet-Button {
+    width: 30px; background-position: -138px 0;
+}
+
+.Rk-Bookmarklet-Button.disabled {
+    opacity: .5; cursor: default;
 }
+
+.Rk-Bookmarklet-Button:hover {
+    background-position: -138px -35px;
+}
+
+.Rk-Bookmarklet-Button.disabled:hover {
+    opacity: 1; background-position: -138px 0;
+}
+
 /* Canvas */
 
 .Rk-Canvas {
@@ -305,38 +322,23 @@
 
 /* Bins */
 
-.Rk-Title {
-    position: absolute; left: 0; top: 0; width: 300px; height: 35px;
-    background: #333333;
-    background: -moz-linear-gradient(top, #505050 5px, #1e1e1e 30px);
-    background: -webkit-linear-gradient(top, #505050 5px, #1e1e1e 30px);
-}
-
-.Rk-Title h1 {
-    font-size: 18px; color: #ffffff; margin: 5px;
+.Rk-Bins {
+    background: #ffffff; position: absolute; left: 0; top: 0; width: 299px; bottom: 0;
+    overflow: hidden; border-right: 1px solid #252525;
 }
 
-
-.Rk-Title:after {
-    background: #666666;
-    background: -moz-linear-gradient(top, #666666 20%, #333333 80%);
-    background: -webkit-linear-gradient(top, #666666 20%, #333333 80%);
-    content: ""; display: block; height: 35px;
-    left: 298px; position: absolute; top: 0; width: 1px; border-left: 1px solid #111111;
-}
-
-.Rk-Bins {
-    background: #ffffff; position: absolute; left: 0; top: 35px; width: 299px; bottom: 0;
-    overflow: hidden; border-right: 1px solid #252525;
+.Rk-Bins-Title {
+    width: 290px; height: 15px; line-height: 15px; padding: 15px 0 5px 10px;
+    background: #333333; font-size: 14px; color: #F0F0F0;
+    background: -moz-linear-gradient(top, #1e1e1e 5px, #606060 30px);
+    background: -webkit-linear-gradient(top, #1e1e1e 5px, #606060 30px);
 }
 
 /* Bin Search Field */
 
 .Rk-Search-Form {
-    padding: 5px 10px; height: 27px;
-    background: #666666;
-    background: -moz-linear-gradient(top, #606060 20%, #909090 80%);
-    background: -webkit-linear-gradient(top, #606060 20%, #909090 80%);
+    padding: 0 10px 8px; height: 27px;
+    background: #606060;
 }
 
 .Rk-Search-Input, .Rk-Search-Select {
Binary file client/img/topbarbuttons.png has changed
--- a/client/js/i18n.js	Wed Feb 27 19:04:36 2013 +0100
+++ b/client/js/i18n.js	Thu Feb 28 19:13:08 2013 +0100
@@ -38,6 +38,7 @@
         "Do you really wish to remove edge ": "Voulez-vous réellement supprimer le lien ",
         "This file is not an image": "Ce fichier n'est pas une image",
         "Image size must be under ": "L'image doit peser moins de ",
+        "Size:": "Taille :",
         "KB": "ko",
         "Choose from vocabulary:": "Choisir dans un vocabulaire :",
         "SKOS Documentation properties": "SKOS: Propriétés documentaires",
--- a/client/js/main.js	Wed Feb 27 19:04:36 2013 +0100
+++ b/client/js/main.js	Thu Feb 28 19:13:08 2013 +0100
@@ -28,7 +28,14 @@
 
 Rkns.VERSION = '0.2';
 
-Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc", "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc", "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc", "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc", "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe", "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe", "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe", "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"];
+Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc",
+    "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc",
+    "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc",
+    "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc",
+    "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe",
+    "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe",
+    "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe",
+    "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"];
 
 Rkns._BaseBin = function(_renkan, _opts) {
     if (typeof _renkan !== "undefined") {
@@ -122,12 +129,26 @@
     		});
     	});
     }
+    if (typeof _opts.bookmarklet_url !== "string") {
+        _opts.bookmarklet_url = "js/bookmarklet.js";
+    }
     this.project = new Rkns.Models.Project();
     this.language = _opts.language;
     this.static_url = _opts.static_url;
     this.show_bins = _opts.show_bins;
     this.read_only = _opts.read_only;
     this.properties = _opts.properties;
+    
+    function getAbsoluteURL(url) {
+        var tmp = document.createElement('img');
+        tmp.src = url;
+        var res = tmp.src;
+        tmp.src = null;
+        return res;
+    }
+    
+    this.bookmarklet_url = getAbsoluteURL(_opts.bookmarklet_url);
+    
     this.translate = function(_text) {
     	return (Rkns.i18n[_opts.language] || Rkns.i18n[_opts.language.substr(0,2)] || {})[_text] || _text;
     }
@@ -230,7 +251,7 @@
 }
 
 Rkns.Renkan.prototype.template = Rkns._.template(
-    '<% if (show_bins) { %><div class="Rk-Title"><h1><%- translate("Renkan") %></h1></div><div class="Rk-Bins">'
+    '<% if (show_bins) { %><div class="Rk-Bins"><h2 class="Rk-Bins-Title"><%- translate("Select contents:")%></h2>'
     + '<form class="Rk-Web-Search-Form Rk-Search-Form"><input class="Rk-Web-Search-Input Rk-Search-Input" type="search" placeholder="<%- translate("Search the Web") %>" />'
     + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>'
     + '<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" /></form>'
--- a/client/js/paper-renderer.js	Wed Feb 27 19:04:36 2013 +0100
+++ b/client/js/paper-renderer.js	Thu Feb 28 19:13:08 2013 +0100
@@ -1,6 +1,6 @@
 Rkns.Renderer = {
-    _MARGIN_X: 80,
-    _MARGIN_Y: 50,
+    _MINIMAP_MARGIN_X: 20,
+    _MINIMAP_MARGIN_Y: 20,
     _MIN_DRAG_DISTANCE: 2,
     _NODE_SIZE_BASE: 25,
     _NODE_BUTTON_WIDTH: 40,
@@ -22,6 +22,8 @@
     _CLICKMODE_ENDEDGE : 3,
     _IMAGE_MAX_KB : 500,
     _NODE_SIZE_STEP: Math.LN2/4,
+    _MINIMAP_WIDTH: 160,
+    _MINIMAP_HEIGHT: 120,
     _USER_PLACEHOLDER : {
         color: "#000000",
         title: "(unknown user)",
@@ -106,6 +108,7 @@
             _textX = Math.cos(_centerRads) * (_outR + 3),
             _textY = Math.sin(_centerRads) * (_outR + 3),
             _segments = [];
+    	_repr.renderer.buttons_layer.activate();
         var _path = new paper.Path();
         _path.add([_startXIn, _startYIn]);
         _path.arcTo([_centerXIn, _centerYIn], [_endXIn, _endYIn]);
@@ -261,14 +264,19 @@
     }
     this.last_circle_radius = 1;
     this.title.paragraphStyle.justification = 'center';
+    
+    this.renderer.minimap.node_layer.activate();
+    this.minimap_circle = new paper.Path.Circle([0, 0], 1);
+    this.renderer.minimap.node_group.addChild(this.minimap_circle);
 }
 
 Rkns.Renderer.Node.prototype.redraw = function() {
+    var _model_coords = new paper.Point(this.model.get("position")),
+    	_baseRadius = Rkns.Renderer._NODE_SIZE_BASE * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP);
     if (!this.paper_coords) {
-        var _model_coords = new paper.Point(this.model.get("position"));
         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
     }
-    this.circle_radius = Rkns.Renderer._NODE_SIZE_BASE * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP) * this.renderer.scale;
+    this.circle_radius = _baseRadius * this.renderer.scale;
     if (this.last_circle_radius !== this.circle_radius) {
     	if (!this.renderer.renkan.read_only) {
 	    	this.edit_button.setSectorSize();
@@ -292,7 +300,8 @@
     
     this.title.content = this.model.get("title") || this.renderer.renkan.translate("(untitled)");
     this.title.position = this.paper_coords.add([0, this.circle_radius + 1.5 *Rkns.Renderer._NODE_FONT_SIZE]);
-    this.circle.strokeColor = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color");
+    var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color");
+    this.circle.strokeColor = _color;
     this.edit_button.moveTo(this.paper_coords);
     this.remove_button.moveTo(this.paper_coords);
     this.link_button.moveTo(this.paper_coords);
@@ -330,6 +339,12 @@
         this.node_image.remove();
         delete this.node_image;
     }
+    
+    this.minimap_circle.fillColor = _color;
+    var minipos = this.renderer.toMinimapCoords(_model_coords),
+    	miniradius = this.renderer.minimap.scale * _baseRadius,
+    	minisize = new paper.Size([miniradius, miniradius]);
+    this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
         
     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);
@@ -366,6 +381,7 @@
     if (this.renderer.renkan.read_only) {
         this.openEditor();
     }
+    this.minimap_circle.fillColor = "#ff00fc";
 }
 
 Rkns.Renderer.Node.prototype.unselect = function(_newTarget) {
@@ -375,6 +391,7 @@
         this.link_button.hide();
         this.circle.strokeWidth = 2;
         Rkns.$('.Rk-Bin-Item').removeClass("selected");
+    	this.minimap_circle.fillColor = this.circle.strokeColor;
     }
 }
 
@@ -423,6 +440,7 @@
     this.link_button.destroy();
     this.circle.remove();
     this.title.remove();
+    this.minimap_circle.remove();
     if (this.node_image) {
         this.node_image.remove();
     }
@@ -918,7 +936,6 @@
 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
 
 Rkns.Renderer.NodeEditButton.prototype._init = function() {
-    this.renderer.buttons_layer.activate();
     this.type = "Node-edit-button";
     this.lastSectorInner = 0;
 }
@@ -972,7 +989,6 @@
 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
 
 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
-    this.renderer.buttons_layer.activate();
     this.type = "Node-remove-button";
     this.lastSectorInner = 0;
 }
@@ -1027,7 +1043,6 @@
 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
 
 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
-    this.renderer.buttons_layer.activate();
     this.type = "Node-link-button";
     this.lastSectorInner = 0;
 }
@@ -1075,7 +1090,6 @@
 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
 
 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
-    this.renderer.buttons_layer.activate();
     this.type = "Edge-edit-button";
     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 90, 90, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.translate("Edit"));
 }
@@ -1118,7 +1132,6 @@
 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
 
 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
-    this.renderer.buttons_layer.activate();
     this.type = "Edge-remove-button";
     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 270, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.translate("Remove"));
 }
@@ -1175,6 +1188,33 @@
     this.edge_layer = new paper.Layer();
     this.node_layer = new paper.Layer();
     this.buttons_layer = new paper.Layer();
+    
+    this.minimap = {
+    	background_layer: new paper.Layer(),
+    	node_layer: new paper.Layer(),
+    	node_group: new paper.Group(),
+    	size: new paper.Size( Rkns.Renderer._MINIMAP_WIDTH, Rkns.Renderer._MINIMAP_HEIGHT )
+    }
+    
+    this.minimap.background_layer.activate();
+    this.minimap.topleft = paper.view.bounds.bottomRight.subtract(this.minimap.size);
+    this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4]));
+    this.minimap.rectangle.fillColor = '#ffffff';
+    this.minimap.rectangle.strokeColor = '#cccccc';
+    this.minimap.rectangle.strokeWidth = 4;
+    this.minimap.offset = new paper.Point(this.minimap.size.divide(2));
+    this.minimap.scale = .25;
+    
+    this.node_layer.activate();
+    this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
+    this.minimap.node_group.addChild(this.minimap.cliprectangle);
+    this.minimap.node_group.clipped = true;
+    this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
+    this.minimap.node_group.addChild(this.minimap.miniframe);
+    this.minimap.miniframe.fillColor = '#f0f0ff';
+    this.minimap.miniframe.strokeColor = '#8080ff';
+    this.minimap.miniframe.strokeWidth = 2;
+    
     this.bundles = [];
     this.click_mode = false;
     var _tool = new paper.Tool(),
@@ -1205,29 +1245,38 @@
     this.canvas_$.on("drop", function(_event) {
     	_event.stopPropagation();
     	_event.preventDefault();
+    	if (_this.renkan.read_only) {
+    		return;
+    	}
     	var res = {}
     	Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
     		return res[t] = _event.originalEvent.dataTransfer.getData(t);
     	});
     	var newNode = {};
+    	if (res["text/x-iri-source-uri"]) {
+    		newNode.uri = res["text/x-iri-source-uri"];
+    	}
     	if (res["text/plain"]) {
     		newNode.description = res["text/plain"].replace(/[\s\n]+/gm,' ').trim();
     	}
     	if (res["text/html"]) {
     		var snippet = Rkns.$('<div>').html(res["text/html"]);
     		newNode.image = snippet.find("img").attr("src") || '';
-    		newNode.uri = snippet.find("a").attr("href");
+    		newNode.uri = snippet.find("a").attr("href") || newNode.uri;
     		newNode.title = snippet.find("[title]").attr("title");
     	}
     	if (res["text/uri-list"]) {
     		newNode.uri = res["text/uri-list"];
     	}
-    	if (res["text/x-moz-url"]) {
+    	if (res["text/x-moz-url"] && !newNode.title) {
     		newNode.title = (res["text/x-moz-url"].split("\n")[1] || "").trim();
     		if (newNode.title === newNode.uri) {
-    			newNode.title = "";
+    			newNode.title = false;
     		}
     	}
+    	if (res["text/x-iri-source-title"] && !newNode.title) {
+    		newNode.title = res["text/x-iri-source-title"];
+    	}
     	var fields = ["title", "description", "uri", "image"];
     	for (var i = 0; i < fields.length; i++) {
     		var f = fields[i];
@@ -1307,7 +1356,7 @@
             _this.notif_$.hide();
         } else {
             _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE;
-            _this.notif_$.html(_renkan.translate("Click on the background canvas to add a node")).fadeIn();
+            _this.notif_$.text(_renkan.translate("Click on the background canvas to add a node")).fadeIn();
         }
     });
     this.$.find(".Rk-AddEdge-Button").click(function() {
@@ -1316,9 +1365,17 @@
             _this.notif_$.hide();
         } else {
             _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
-            _this.notif_$.html(_renkan.translate("Click on a first node to start the edge")).fadeIn();
+            _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
         }
     });
+    this.$.find(".Rk-Bookmarklet-Button").click(function(){
+    	_this.notif_$
+    		.text(_renkan.translate("Drag this bookmarklet to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan."))
+    		.fadeIn()
+    		.delay(5000)
+    		.fadeOut();
+		return false;
+    });
     this.$.find(".Rk-TopBar-Button").mouseover(function() {
         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
     }).mouseout(function() {
@@ -1328,6 +1385,9 @@
     paper.view.onResize = function(_event) {
         _this.offset = _this.offset.add(_event.delta.divide(2));
         _this.resetCoords();
+        _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size)
+        _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4]));
+        _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
         _this.redraw();
     }
     
@@ -1372,6 +1432,9 @@
     });
     
     this.redraw();
+    window.setInterval(function() {
+    	_this.rescaleMinimap()
+    }, 2000);
 }
 
 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
@@ -1383,6 +1446,10 @@
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Archive Project")%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="javascript:(function(){a=document;'
+    + 'b=function(c){d=a.createElement(\'script\');d.type=\'text/javascript\';d.src=c;a.getElementsByTagName(\'head\')[0].appendChild(d);};'
+    + 'b(\'<%- bookmarklet_url %>\');})();"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents">'
+    + '<%-translate("Renkan \'Drag and Add\' bookmarklet")%></div></div></a>'
     + '<div class="Rk-TopBar-Separator"></div></div>'
     + '<% } %>'
     + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
@@ -1419,8 +1486,14 @@
     this.resetCoords();
     this.redraw();
 }
-/*
-Rkns.Renderer.Scene.prototype.autoScale = function() {
+
+Rkns.Renderer.Scene.prototype.redrawMiniframe = function() {
+	var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
+		bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
+	this.minimap.miniframe.fitBounds(topleft, bottomright);
+}
+
+Rkns.Renderer.Scene.prototype.rescaleMinimap = function() {
     var nodes = this.renkan.project.get("nodes")
     if (nodes.length > 1) {
         var _xx = nodes.map(function(_node) { return _node.get("position").x }),
@@ -1429,16 +1502,17 @@
             _miny = Math.min.apply(Math, _yy),
             _maxx = Math.max.apply(Math, _xx),
             _maxy = Math.max.apply(Math, _yy);
-        var _scale = Math.min((paper.view.size.width - 2 * Rkns.Renderer._MARGIN_X) / (_maxx - _minx), (paper.view.size.height - 2 * Rkns.Renderer._MARGIN_Y) / (_maxy - _miny));
-        this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
-        this.setScale(_scale);
+        var _scale = Math.min(this.scale * .8 * Rkns.Renderer._MINIMAP_WIDTH / paper.view.bounds.width, this.scale * .8 * Rkns.Renderer._MINIMAP_HEIGHT / paper.view.bounds.height, (Rkns.Renderer._MINIMAP_WIDTH - 2 * Rkns.Renderer._MINIMAP_MARGIN_X) / (_maxx - _minx), (Rkns.Renderer._MINIMAP_HEIGHT - 2 * Rkns.Renderer._MINIMAP_MARGIN_Y) / (_maxy - _miny));
+        this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
+        this.minimap.scale = _scale;
     }
     if (nodes.length === 1) {
-        this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
-        this.setScale(1);
+        this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
+        this.minimap.scale = .25;
     }
+    this.redraw();
 }
-*/
+
 Rkns.Renderer.Scene.prototype.resetCoords = function(_point) {
     _(this.representations).each(function(r) {
         r.resetCoords();
@@ -1449,6 +1523,9 @@
     return _point.multiply(this.scale).add(this.offset);
 }
 
+Rkns.Renderer.Scene.prototype.toMinimapCoords = function(_point) {
+    return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
+}
 
 Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
     return _point.subtract(this.offset).divide(this.scale);
@@ -1529,6 +1606,7 @@
     Rkns._(this.representations).each(function(_representation) {
         _representation.redraw();
     });
+    this.redrawMiniframe();
     paper.view.draw();
 }