diff --git a/css/infobar.css b/css/infobar.css
index eb8bc25d48a55c2ef64bb9749b99ef624ba273d0..f76268f0f0e27c014411af173f6c0fac455bddc6 100644
--- a/css/infobar.css
+++ b/css/infobar.css
@@ -81,7 +81,6 @@
     height: 100%;
     position: absolute;
     cursor: pointer;
-    
 }
 
 .infobar .infobutton svg {
@@ -95,16 +94,21 @@
 }
 
 .infobar .infobutton svg path {
-    fill:none;
+    fill: none;
     /*stroke: #000;*/
 }
 
+.navi.hide {
+    display: none;
+}
+
 .navi {
     z-index: 300;
     top: 30%;
     position: absolute;
-    left: 0;    
+    left: 0;
 }
+
 .navi .button {
     transition: all 0.3s;
     text-transform: uppercase;
@@ -131,6 +135,7 @@
     padding-right: 10px;
     /* border-right: 4px solid rgba(247, 239, 205, 0.18); */
 }
+
 .navi .button:hover:not(.active) {
     color: rgba(255, 255, 255, 0.75);
 }
@@ -164,7 +169,7 @@
     float: left;
     height: 100%;
     overflow-y: auto;
-    direction:rtl
+    direction: rtl
 }
 
 .infobar .outer::-webkit-scrollbar * {
@@ -177,10 +182,11 @@
     /* height: 100%; */
     /* overflow-y: scroll; */
     float: left;
-    direction:ltr;
+    direction: ltr;
     /*direction: ltr;*/
 }
-.infobar .inner > div {
+
+.infobar .inner>div {
     /* height: 100%; */
     position: relative;
     /*width: 360px;*/
@@ -262,7 +268,5 @@
     text-align: right;
     clear: both;
     opacity: 0.7;
-    padding-top: 30px; 
-}
-
-
+    padding-top: 30px;
+}
\ No newline at end of file
diff --git a/index.html b/index.html
index 870fe8c7b68500faa1fcacc221c71ab62d958b1a..50f0f0743299f87a2cb280e12d681a46c3a2cbf7 100644
--- a/index.html
+++ b/index.html
@@ -1,39 +1,41 @@
 <!DOCTYPE html>
 <html>
+
 <head>
-<meta charset="utf-8">
-<title>VikusViewer</title>
-<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" />
-<meta name="mobile-web-app-capable" content="yes" />
-<meta name="apple-mobile-web-app-capable" content="yes" />
-<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
-<meta name="format-detection" content="telephone=no" />
-<meta name="pinterest" content="nohover" />
-<base target="_blank">
-
-<link rel="stylesheet" href="css/style.css">
-<link rel="stylesheet" href="css/infobar.css">
-<link rel="stylesheet" href="css/timeline.css">
-
-<script src="js/d3.v3.min.js"></script>
-<script src="js/vue.min.js"></script>
-<script src="js/marked.min.js"></script>
-<script src="js/lodash.min.js"></script>
-<script src="js/pixi.min.js"></script>
-<script src="js/pixi-packer-parser.js"></script>
-<script src="js/loader.js"></script>
-<script src="js/canvas.js"></script>
-<script src="js/timeline.js"></script>
-<script src="js/search.js"></script>
-<script src="js/tags.js"></script>
-<script src="js/utils.js"></script>
-<script src="js/modernizr-custom.js"></script>
-<!--[if lt IE 9]>
+	<meta charset="utf-8">
+	<title>VikusViewer</title>
+	<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"
+	/>
+	<meta name="mobile-web-app-capable" content="yes" />
+	<meta name="apple-mobile-web-app-capable" content="yes" />
+	<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
+	<meta name="format-detection" content="telephone=no" />
+	<meta name="pinterest" content="nohover" />
+	<base target="_blank">
+
+	<link rel="stylesheet" href="css/style.css">
+	<link rel="stylesheet" href="css/infobar.css">
+	<link rel="stylesheet" href="css/timeline.css">
+
+	<script src="js/d3.v3.min.js"></script>
+	<script src="js/vue.min.js"></script>
+	<script src="js/marked.min.js"></script>
+	<script src="js/lodash.min.js"></script>
+	<script src="js/pixi.min.js"></script>
+	<script src="js/pixi-packer-parser.js"></script>
+	<script src="js/loader.js"></script>
+	<script src="js/canvas.js"></script>
+	<script src="js/timeline.js"></script>
+	<script src="js/search.js"></script>
+	<script src="js/tags.js"></script>
+	<script src="js/utils.js"></script>
+	<script src="js/modernizr-custom.js"></script>
+	<!--[if lt IE 9]>
 <script src='http://html5shiv.googlecode.com/svn/trunk/html5.js' type='text/javascript'></script>
 <![endif]-->
 
 
- <!-- 
+	<!-- 
 
                            ,--.                                     
                ,---,   ,--/  /|               .--.--.               
@@ -71,102 +73,95 @@ cpietsch@gmail.com
 
  -->
 </head>
+
 <body>
-<div id="hiddenreload"></div>
-
-<div class="browserInfo">
-<p>This visualization is not optimized for mobile phones and needs WebGL enabled.</p><p>Please come back on a Computer.</p><span>💡</span>
-</div>
-
-<div class="search"></div>
-
-<div class="page">
-
-	<div class="detailLoader"></div>
-	<div class="sideLoader"></div>
-
-	<div class="sidebar detail hide">
-		<div class="slidebutton"></div>
-
-		<div class="outer">
-			<div id="detail" class="inner">
-				<div class="entries" v-if="item">
-				  <div
-				    v-if="item._imagenum > 1"
-				    class="entry wide pages"
-				  >
-				    <div class="label">Seite</div>
-				    <div class="content">
-				      <span
-				        v-for="i in parseInt(item._imagenum)"
-				        v-bind:key="i"
-				        v-on:click="displayPage(i-1)"
-				        v-bind:class="{ active: i === page+1, keyword: true }"
-				      >
-				      {{ i }}
-				      </span>
-				    </div>
-				  </div>
-				  <div
-				    v-for="entry in structure"
-				    v-bind:key="entry.name"
-				    v-bind:class="entry.display"
-				    class="entry"
-				    v-if="hasData(entry)"
-				  >
-				    <div class="label">{{ entry.name }}</div>
-				    <div class="content">
-				      <span v-if="entry.type === 'keywords'">
-				         <span
-				            v-for="keyword in item[entry.source]"
-				            v-bind:key="keyword"
-				            class="keyword"
-				          >
-				          {{ keyword }}
-				         </span>
-				      </span>
-				      <span v-else-if="entry.type === 'link'">
-				         <a :href="item[entry.source]" target="_blank">Link</a>
-				      </span>
-				      <span v-else-if="entry.type === 'markdown'">
-				         <span v-html="getContent(entry)"></span>
-				      </span>
-				      <span v-else>
-				        {{ getContent(entry) }}
-				      </span>
-				    </div>
-				  </div>
-				</div>
-			</div> 
-		</div> 
+	<div id="hiddenreload"></div>
+
+	<div class="browserInfo">
+		<p>This visualization is not optimized for mobile phones and needs WebGL enabled.</p>
+		<p>Please come back on a Computer.</p>
+		<span>💡</span>
 	</div>
 
-	<div class="infobar sneaks">
-		<div class="infobutton">
-			<svg width="16px" height="24px" viewBox="0 0 16 24">
-		        <path d="M13.6824546,2 L3.7109392,11.9715154 L13.7394238,22" stroke="#FFF" stroke-width="5"></path>
-			</svg>
+	<div class="search"></div>
+
+	<div class="page">
+
+		<div class="detailLoader"></div>
+		<div class="sideLoader"></div>
+
+		<div class="sidebar detail hide">
+			<div class="slidebutton"></div>
+
+			<div class="outer">
+				<div id="detail" class="inner">
+					<div class="entries" v-if="item">
+						<div v-if="item._imagenum > 1" class="entry wide pages">
+							<div class="label">Seite</div>
+							<div class="content">
+								<span v-for="i in parseInt(item._imagenum)" v-bind:key="i" v-on:click="displayPage(i-1)" v-bind:class="{ active: i === page+1, keyword: true }">
+									{{ i }}
+								</span>
+							</div>
+						</div>
+						<div v-for="entry in structure" v-bind:key="entry.name" v-bind:class="entry.display" class="entry" v-if="hasData(entry)">
+							<div class="label">{{ entry.name }}</div>
+							<div class="content">
+								<span v-if="entry.type === 'keywords'">
+									<span v-for="keyword in item[entry.source]" v-bind:key="keyword" class="keyword">
+										{{ keyword }}
+									</span>
+								</span>
+								<span v-else-if="entry.type === 'link'">
+									<a :href="item[entry.source]" target="_blank">Link</a>
+								</span>
+								<span v-else-if="entry.type === 'markdown'">
+									<span v-html="getContent(entry)"></span>
+								</span>
+								<span v-else>
+									{{ getContent(entry) }}
+								</span>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+
+		<div class="navi hide">
+			<div class="time button active">time</div>
+			<div class="tsne button">tsne</div>
 		</div>
-		
-		<div class="outer">
-			<div class="inner">
-				<div id="infobar" class="infosidebar">
-					<span v-html="marked(info)"></span>
-					<div class="credit">Powered by <a href="https://vikusviewer.fh-potsdam.de/" target="_blank">VIKUS Viewer</a></div>
-				</div> 
+
+		<div class="infobar sneak">
+			<div class="infobutton">
+				<svg width="16px" height="24px" viewBox="0 0 16 24">
+					<path d="M13.6824546,2 L3.7109392,11.9715154 L13.7394238,22" stroke="#FFF" stroke-width="5"></path>
+				</svg>
+			</div>
+
+			<div class="outer">
+				<div class="inner">
+					<div id="infobar" class="infosidebar">
+						<span v-html="marked(info)"></span>
+						<div class="credit">Powered by
+							<a href="https://vikusviewer.fh-potsdam.de/" target="_blank">VIKUS Viewer</a>
+						</div>
+					</div>
+				</div>
 			</div>
 		</div>
-	</div>
-	<div class="searchbar">
-		<input type="input" name="suche">
-		<div class="button">
-			<div class="openbutton"></div>
+		<div class="searchbar">
+			<input type="input" name="suche">
+			<div class="button">
+				<div class="openbutton"></div>
+			</div>
 		</div>
 	</div>
-</div>
 
-<script src="js/sidebars.js"></script>
-<script src="js/viz.js"></script>
+	<script src="js/sidebars.js"></script>
+	<script src="js/viz.js"></script>
 
 </body>
+
 </html>
\ No newline at end of file
diff --git a/js/canvas.js b/js/canvas.js
index db6c5c1fab9ff887e34a7b448070009eefb19b6c..5a2f408ccf89646a980fc1ae7bd0dc7ab2e4ebf4 100644
--- a/js/canvas.js
+++ b/js/canvas.js
@@ -31,10 +31,10 @@ function Canvas() {
         .rangeBands([margin.left, width + margin.left], 0.2);
 
     var Quadtree = d3.geom.quadtree()
-        .x(function(d) {
+        .x(function (d) {
             return d.x;
         })
-        .y(function(d) {
+        .y(function (d) {
             return d.y;
         });
 
@@ -100,18 +100,30 @@ function Canvas() {
     var timelineData;
     var stage, stage1, stage2, stage3, stage4, stage5;
     var timelineHover = false;
+    var tsne = []
+    var tsneIndex = {}
 
     function canvas() {}
 
-    canvas.rangeBand = function() { return rangeBand }
-    canvas.width = function() { return width }
-    canvas.height = function() { return height }
-    canvas.rangeBandImage = function() { return rangeBandImage }
+    canvas.rangeBand = function () {
+        return rangeBand
+    }
+    canvas.width = function () {
+        return width
+    }
+    canvas.height = function () {
+        return height
+    }
+    canvas.rangeBandImage = function () {
+        return rangeBandImage
+    }
     canvas.zoom = zoom
-    canvas.selectedImage = function() { return selectedImage }
+    canvas.selectedImage = function () {
+        return selectedImage
+    }
     canvas.x = x
 
-    canvas.resize = function() {
+    canvas.resize = function () {
         if (!state.init) return;
         width = window.innerWidth - margin.left - margin.right;
         height = window.innerHeight < minHeight ? minHeight : window.innerHeight;
@@ -121,7 +133,7 @@ function Canvas() {
         canvas.project();
     }
 
-    canvas.makeScales = function() {
+    canvas.makeScales = function () {
         x.rangeBands([margin.left, width + margin.left], 0.2)
 
         rangeBand = x.rangeBand();
@@ -150,7 +162,7 @@ function Canvas() {
         zoomedToImageScale = 0.8 / (x.rangeBand() / collumns / width)
     }
 
-    canvas.init = function(_data, _timeline, _config) {
+    canvas.init = function (_data, _timeline, _config) {
         data = _data;
         config = _config;
 
@@ -188,20 +200,28 @@ function Canvas() {
         stage2.addChild(stage4);
         stage2.addChild(stage5);
 
-        _timeline.forEach(function(d) {
+        _timeline.forEach(function (d) {
             d.type = "timeline";
         });
 
         var canvasDomain = d3.nest()
-            .key(function(d) { return d.year; })
+            .key(function (d) {
+                return d.year;
+            })
             .entries(_data.concat(_timeline))
-            .sort(function(a, b) { return a.key - b.key; })
-            .map(function(d) { return d.key; })
+            .sort(function (a, b) {
+                return a.key - b.key;
+            })
+            .map(function (d) {
+                return d.key;
+            })
 
-        timeDomain = canvasDomain.map(function(d) {
+        timeDomain = canvasDomain.map(function (d) {
             return {
                 key: d,
-                values: _timeline.filter(function(e) { return d == e.year; })
+                values: _timeline.filter(function (e) {
+                    return d == e.year;
+                })
             }
         })
 
@@ -210,7 +230,7 @@ function Canvas() {
         canvas.makeScales();
 
         // add preview pics
-        data.forEach(function(d, i) {
+        data.forEach(function (d, i) {
             var sprite = new PIXI.Sprite(PIXI.Texture.WHITE);
 
             sprite.anchor.x = 0.5;
@@ -231,11 +251,11 @@ function Canvas() {
             .call(zoom)
             .on("mousemove", mousemove)
             .on("dblclick.zoom", null)
-            .on("touchstart", function(d) {
+            .on("touchstart", function (d) {
                 mousemove(d);
                 touchstart = new Date() * 1;
             })
-            .on("touchend", function(d) {
+            .on("touchend", function (d) {
                 var touchtime = (new Date() * 1) - touchstart;
                 if (touchtime > 250) return;
                 if (selectedImageDistance > 15) return;
@@ -245,9 +265,12 @@ function Canvas() {
 
                 zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale)))
             })
-            .on("click", function() {
+            .on("click", function () {
                 console.log("click");
-                if (spriteClick) { spriteClick = false; return; }
+                if (spriteClick) {
+                    spriteClick = false;
+                    return;
+                }
                 if (selectedImage && !selectedImage.id) return;
                 if (drag) return;
                 if (selectedImageDistance > 15) return;
@@ -271,6 +294,35 @@ function Canvas() {
         state.init = true;
     };
 
+    canvas.addTsneData = function (d) {
+        console.time("tsne")
+        var clean = d.map(function (d) {
+            return {
+                id: d.id,
+                x: parseFloat(d.x),
+                y: parseFloat(d.y)
+            }
+        })
+        var xExtent = d3.extent(clean, function (d) {
+            return d.x
+        })
+        var yExtent = d3.extent(clean, function (d) {
+            return d.y
+        })
+
+        var x = d3.scale.linear().range([0, 1]).domain(xExtent)
+        var y = d3.scale.linear().range([0, 1]).domain(yExtent)
+
+        d.forEach(function (d) {
+            tsneIndex[d.id] = [
+                x(d.x),
+                y(d.y)
+            ]
+        })
+
+        console.timeEnd("tsne")
+    }
+
 
     function mousemove(d) {
         if (timelineHover) return;
@@ -298,7 +350,7 @@ function Canvas() {
                 selectedImage = d;
             }
 
-            container.style("cursor", function() {
+            container.style("cursor", function () {
                 return ((best.d < 5) && selectedImage.active) ? "pointer" : "default";
             });
         }
@@ -309,19 +361,19 @@ function Canvas() {
     function stackLayout(data, invert) {
 
         var years = d3.nest()
-            .key(function(d) {
+            .key(function (d) {
                 return d.year;
             })
             .entries(data)
 
-        years.forEach(function(year) {
+        years.forEach(function (year) {
             var startX = x(year.key);
             var total = year.values.length;
-            year.values.sort(function(a, b) {
+            year.values.sort(function (a, b) {
                 return b.keywords.length - a.keywords.length;
             })
 
-            year.values.forEach(function(d, i) {
+            year.values.forEach(function (d, i) {
                 var row = (Math.floor(i / collumns) + 2);
                 d.ii = i;
 
@@ -346,7 +398,7 @@ function Canvas() {
         })
     }
 
-    canvas.distance = function(a, b) {
+    canvas.distance = function (a, b) {
         return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]));
     }
 
@@ -362,7 +414,7 @@ function Canvas() {
     function imageAnimation() {
         var sleep = true
 
-        data.forEach(function(d, i) {
+        data.forEach(function (d, i) {
             var diff;
             diff = (d.x1 - d.sprite.position.x);
             if (Math.abs(diff) > 0.1) {
@@ -398,8 +450,15 @@ function Canvas() {
         return sleep
     }
 
-    
-    canvas.wakeup = function() { sleep = false }
+
+    canvas.wakeup = function () {
+        sleep = false
+    }
+
+    canvas.setMode = function (mode) {
+        state.mode = mode
+        canvas.project()
+    }
 
     function animate(time) {
         requestAnimationFrame(animate);
@@ -434,7 +493,7 @@ function Canvas() {
 
         zoomedToImageScale = scale;
 
-        setTimeout(function() {
+        setTimeout(function () {
             hideTheRest(d);
         }, duration / 2);
 
@@ -442,7 +501,7 @@ function Canvas() {
             .call(zoom.translate(translate).event)
             .transition().duration(duration)
             .call(zoom.scale(scale).translate(translateNow).event)
-            .each("end", function() {
+            .each("end", function () {
                 zoomedToImage = true;
                 selectedImage = d;
                 hideTheRest(d);
@@ -479,7 +538,7 @@ function Canvas() {
 
     }
 
-    canvas.changePage = function(id, page) {
+    canvas.changePage = function (id, page) {
         console.log("changePage", id, page, selectedImage);
         selectedImage.page = page
         detailVue._data.page = page
@@ -489,7 +548,7 @@ function Canvas() {
 
 
     function hideTheRest(d) {
-        data.forEach(function(d2) {
+        data.forEach(function (d2) {
             if (d2.id !== d.id) {
                 d2.alpha = 0;
                 d2.alpha2 = 0;
@@ -499,7 +558,7 @@ function Canvas() {
     }
 
     function showAllImages() {
-        data.forEach(function(d) {
+        data.forEach(function (d) {
             d.alpha = d.active ? 1 : 0.2;;
             d.alpha2 = d.visible ? 1 : 0;
         })
@@ -583,23 +642,96 @@ function Canvas() {
         }
     }
 
-    canvas.highlight = function() {
-        data.forEach(function(d, i) {
+    canvas.highlight = function () {
+        data.forEach(function (d, i) {
             d.alpha = d.highlight ? 1 : 0.2;
         });
         canvas.wakeup();
     }
 
-    canvas.project = function() {
+    // canvas.project = function () {
+    //     sleep = false
+    //     canvas.split();
+    //     canvas.resetZoom();
+    // }
+
+    canvas.project = function () {
         sleep = false
-        canvas.split();
+        if (state.mode == "tsne") {
+            canvas.projectTSNE();
+        } else {
+            canvas.split();
+        }
         canvas.resetZoom();
     }
 
-    canvas.resetZoom = function() {
+    canvas.projectTSNE = function () {
+
+        var marginBottom = -height / 2.5;
+
+        var inactive = data.filter(function (d) {
+            return !d.active;
+        });
+        var inactiveSize = inactive.length;
+
+        var active = data.filter(function (d) {
+            return d.active;
+        });
+
+        // inactive.sort(function (a, b) {
+        //     return a.rTSNE - b.rTSNE
+        // });
+
+        var dimension = Math.min(width, height) * 0.8
+
+        inactive.forEach(function (d, i) {
+            var r = dimension / 1.9 + Math.random() * 40;
+            var a = -Math.PI / 2 + (i / inactiveSize) * 2 * Math.PI;
+
+            d.x = r * Math.cos(a) + width / 2 + margin.left;
+            d.y = r * Math.sin(a) + marginBottom;
+        });
+
+        active.forEach(function (d) {
+
+            var factor = height / 2;
+            var tsneEntry = tsneIndex[d.id]
+            // var tsneEntry = tsne.find(function (t) {
+            //     return t.id == d.id
+            // })
+            d.x = (tsneEntry[0] * dimension) + width / 2 - dimension / 2 + margin.left;
+            d.y = (tsneEntry[1] * dimension) - dimension / 2 + marginBottom;
+
+        })
+
+        data.forEach(function (d) {
+            d.x1 = d.x * scale1 + imageSize / 2;
+            d.y1 = d.y * scale1 + imageSize / 2;
+
+            if (d.sprite.position.x == 0) {
+                d.sprite.position.x = d.x1;
+                d.sprite.position.y = d.y1;
+            }
+
+            if (d.sprite2) {
+                d.sprite2.position.x = d.x * scale2 + imageSize2 / 2;
+                d.sprite2.position.y = d.y * scale2 + imageSize2 / 2;
+            }
+        });
+
+
+        quadtree = Quadtree(data);
+        //chart.resetZoom();
+
+
+    }
+
+    canvas.resetZoom = function () {
         var duration = 1400;
-        console.log(translate)
-        extent = d3.extent(data, function(d) { return d.y; });
+
+        extent = d3.extent(data, function (d) {
+            return d.y;
+        });
 
         var y = -extent[1] - bottomPadding;
         y = (extent[1] / -3) - bottomPadding
@@ -610,12 +742,12 @@ function Canvas() {
             .call(zoom.translate([0, y]).scale(1).event)
     }
 
-    canvas.split = function() {
-        var active = data.filter(function(d) {
+    canvas.split = function () {
+        var active = data.filter(function (d) {
             return d.active;
         })
         stackLayout(active, false);
-        var inactive = data.filter(function(d) {
+        var inactive = data.filter(function (d) {
             return !d.active;
         })
         stackLayout(inactive, true);
@@ -626,7 +758,7 @@ function Canvas() {
         var zoomScale = scale;
         if (zoomedToImage) return;
 
-        data.forEach(function(d, i) {
+        data.forEach(function (d, i) {
             var p = d.sprite.position;
             var x = (p.x / scale1) + translate[0] / zoomScale;
             var y = ((p.y / scale1) + (translate[1]) / zoomScale);
@@ -639,18 +771,18 @@ function Canvas() {
             }
         });
 
-        var visible = data.filter(function(d) {
+        var visible = data.filter(function (d) {
             return d.visible;
         });
 
         if (visible.length < 40) {
-            data.forEach(function(d) {
+            data.forEach(function (d) {
                 if (d.visible && d.loaded && d.active) d.alpha2 = 1;
                 else if (d.visible && !d.loaded && d.active) loadImagesCue.push(d);
                 else d.alpha2 = 0;
             })
         } else {
-            data.forEach(function(d) {
+            data.forEach(function (d) {
                 d.alpha2 = 0;
             })
         }
@@ -663,10 +795,11 @@ function Canvas() {
         }
 
         // console.log("load", d)
-        var texture = new PIXI.Texture.fromImage(config.loader.textures.detail.url + d.id + '.jpg', true)
+        var url = encodeURIComponent(config.loader.textures.detail.url + d.id + '.jpg')
+        var texture = new PIXI.Texture.fromImage(url, true)
         var sprite = new PIXI.Sprite(texture);
 
-        var update = function() {
+        var update = function () {
             sleep = false
         }
 
@@ -696,13 +829,13 @@ function Canvas() {
 
         state.lastZoomed = d.id;
         var page = d.page ? '_' + d.page : ''
-        var url = config.loader.textures.big.url + d.id + page + ".jpg";
+        var url = encodeURIComponent(config.loader.textures.big.url + d.id + page + ".jpg");
 
         var texture = new PIXI.Texture.fromImage(url, true)
         var sprite = new PIXI.Sprite(texture);
         var res = config.loader.textures.big.size
 
-        var updateSize = function() {
+        var updateSize = function () {
             var size = Math.max(texture.width, texture.height)
             sprite.scale.x = sprite.scale.y = (imageSize3 / size) * d.scaleFactor;
             sleep = false
@@ -712,11 +845,11 @@ function Canvas() {
         texture.once('update', updateSize)
 
         if (d.imagenum) {
-            sprite.on("mousemove", function(s) {
+            sprite.on("mousemove", function (s) {
                 var pos = s.data.getLocalPosition(s.currentTarget)
                 s.currentTarget.cursor = pos.x > 0 ? "e-resize" : "w-resize"
             })
-            sprite.on("click", function(s) {
+            sprite.on("click", function (s) {
                 if (drag) return
 
                 s.stopPropagation()
diff --git a/js/timeline.js b/js/timeline.js
index 580b9d850d1e87ed6b7a200fd1016f4ab6f23e73..194e9ad28f24023d5a409723bc6316e72d5b056f 100644
--- a/js/timeline.js
+++ b/js/timeline.js
@@ -1,149 +1,155 @@
-
 function Timeline() {
 
-  var fontScaleYear = d3.scale.linear()
-      .domain([1, 9])
-      .range([9, 20])
-      .clamp(true)
-
-  var timelineFontScale = d3.scale.linear()
-      .domain([40, 8])
-      .range([2, 10])
-      .clamp(true)
-
-  var timelineScale = d3.scale.threshold()
-      .domain([3, 10, 20])
-      .range(["none", "small", "middle", "large"])
-
-  var timelineHover = false;
-  var container
-  var timeDomain
-  var fontSize = 1
-
-  function timeline(){ }
-
-  timeline.init = function(_timeDomain) {
-    timeDomain = _timeDomain
-    container = d3.select(".viz").append("div").classed("timeline", true)
-    container.style("transform", "translate(" + 0 + "px," + (canvas.height() - 30) + "px)");
-  }
-
-  timeline.rescale = function(scale) {
-    timeDomain.forEach(function(d) {
-        d.x = canvas.x(d.key);
-    });
-    fontSize = timelineFontScale(scale)
-  }
-
-  timeline.update = function(x1, x2, scale, translate) {
-
-      timeDomain.forEach(function(d) {
-          d.pos = ((d.x - x1) * scale);
-          d.visible = (d.pos > (-canvas.rangeBand() * scale) && d.pos < canvas.width() + 100);
-      })
-
-      var timeY = ((canvas.height()) * scale - (-1 * translate[1]) - canvas.rangeBandImage() * scale);
-
-      container
-        .attr("class", "timeline " + timelineScale(scale * (fontSize/2)))
-        .style("font-size", function() {
-            return fontSize * scale + "px";
+    var fontScaleYear = d3.scale.linear()
+        .domain([1, 9])
+        .range([9, 20])
+        .clamp(true)
+
+    var timelineFontScale = d3.scale.linear()
+        .domain([40, 8])
+        .range([2, 10])
+        .clamp(true)
+
+    var timelineScale = d3.scale.threshold()
+        .domain([3, 10, 20])
+        .range(["none", "small", "middle", "large"])
+
+    var timelineHover = false;
+    var container
+    var timeDomain
+    var fontSize = 1
+    var disabled = false
+
+    function timeline() {}
+
+    timeline.init = function (_timeDomain) {
+        timeDomain = _timeDomain
+        container = d3.select(".viz").append("div").classed("timeline", true)
+        container.style("transform", "translate(" + 0 + "px," + (canvas.height() - 30) + "px)");
+    }
+
+    timeline.rescale = function (scale) {
+        timeDomain.forEach(function (d) {
+            d.x = canvas.x(d.key);
+        });
+        fontSize = timelineFontScale(scale)
+    }
+
+    timeline.setDisabled = function (d) {
+        disabled = d
+        container.style("display", disabled ? "none" : "block")
+    }
+
+    timeline.update = function (x1, x2, scale, translate) {
+        if (disabled) return
+
+        timeDomain.forEach(function (d) {
+            d.pos = ((d.x - x1) * scale);
+            d.visible = (d.pos > (-canvas.rangeBand() * scale) && d.pos < canvas.width() + 100);
         })
-        .style("transform", "translate3d(" + 0 + "px," + timeY + "px, 0px)");
-
-      var select = container.selectAll(".container")
-          .data(timeDomain)
-
-      var enter = select
-          .enter()
-          .append("div")
-          .classed("container", true)
-          .on("mouseenter", function(d){
-            timelineHover = true;
-            canvas.zoom.center(null);
-            // canvas.selectedImage() = null;
-          })
-          .on("mouseleave", function(d){
-            timelineHover = false;
-          })
-
-      enter.append("div")
-          .classed("year", true)
-          .text(function(d) {
-              return d.key;
-          })
-
-      var e = enter
-          .append("div")
-          .classed("entries", true)
-          .selectAll(".entry")
-          .data(function(d) {
-              return d.values;
-          })
-          .enter()
-          .append("div")
-          .classed("entry", true)
-
-      e
-          .append("div")
-          .classed("small", true)
-          .append("div")
-          .classed("title", true)
-          .text(function(d) {
-              return d.titel;
-          })
-
-      var m = e
-          .append("div")
-          .classed("middle", true)
-
-      m
-          .append("div")
-          .classed("title", true)
-          .text(function(d) {
-              return d.titel;
-          })
-
-      m
-          .append("div")
-          .classed("text", true)
-          .text(function(d) {
-              return d.text + ".";
-          }) //…
-
-      var l = e
-          .append("div")
-          .classed("large", true)
-
-      l
-          .append("div")
-          .classed("title", true)
-          .text(function(d) {
-              return d.titel;
-          })
-
-      l
-          .append("div")
-          .classed("text", true)
-          .html(function(d) {
-              return d.text + ".<br><br>" + d.extra;
-          })
-
-      select
-          .style("transform", function(d) {
-              return "translate3d(" + parseInt(d.pos) + "px,0px,0px)";
-          })
-          .style("height", canvas.rangeBand() * scale + "px")
-          .style("width", canvas.rangeBand() * scale + "px")
-          .style("display", function(d) {
-              return d.visible ? "block" : "none";
-          })
-
-      select
-          .select(".year")
-          .style("font-size", fontScaleYear(scale) + "px")
-  }
-
-  return timeline
+
+        var timeY = ((canvas.height()) * scale - (-1 * translate[1]) - canvas.rangeBandImage() * scale);
+
+        container
+            .attr("class", "timeline " + timelineScale(scale * (fontSize / 2)))
+            .style("font-size", function () {
+                return fontSize * scale + "px";
+            })
+            .style("transform", "translate3d(" + 0 + "px," + timeY + "px, 0px)");
+
+        var select = container.selectAll(".container")
+            .data(timeDomain)
+
+        var enter = select
+            .enter()
+            .append("div")
+            .classed("container", true)
+            .on("mouseenter", function (d) {
+                timelineHover = true;
+                canvas.zoom.center(null);
+                // canvas.selectedImage() = null;
+            })
+            .on("mouseleave", function (d) {
+                timelineHover = false;
+            })
+
+        enter.append("div")
+            .classed("year", true)
+            .text(function (d) {
+                return d.key;
+            })
+
+        var e = enter
+            .append("div")
+            .classed("entries", true)
+            .selectAll(".entry")
+            .data(function (d) {
+                return d.values;
+            })
+            .enter()
+            .append("div")
+            .classed("entry", true)
+
+        e
+            .append("div")
+            .classed("small", true)
+            .append("div")
+            .classed("title", true)
+            .text(function (d) {
+                return d.titel;
+            })
+
+        var m = e
+            .append("div")
+            .classed("middle", true)
+
+        m
+            .append("div")
+            .classed("title", true)
+            .text(function (d) {
+                return d.titel;
+            })
+
+        m
+            .append("div")
+            .classed("text", true)
+            .text(function (d) {
+                return d.text + ".";
+            }) //…
+
+        var l = e
+            .append("div")
+            .classed("large", true)
+
+        l
+            .append("div")
+            .classed("title", true)
+            .text(function (d) {
+                return d.titel;
+            })
+
+        l
+            .append("div")
+            .classed("text", true)
+            .html(function (d) {
+                return d.text + ".<br><br>" + d.extra;
+            })
+
+        select
+            .style("transform", function (d) {
+                return "translate3d(" + parseInt(d.pos) + "px,0px,0px)";
+            })
+            .style("height", canvas.rangeBand() * scale + "px")
+            .style("width", canvas.rangeBand() * scale + "px")
+            .style("display", function (d) {
+                return d.visible ? "block" : "none";
+            })
+
+        select
+            .select(".year")
+            .style("font-size", fontScaleYear(scale) + "px")
+    }
+
+    return timeline
 
 }
\ No newline at end of file
diff --git a/js/viz.js b/js/viz.js
index 26db6179fac9248351dee2d7d7a812b76eaddf1d..a745527c3ad02c7a42081a09873eea7ebcb613fc 100644
--- a/js/viz.js
+++ b/js/viz.js
@@ -41,75 +41,96 @@ var search;
 var ping;
 
 if (Modernizr.webgl && !utils.isMobile()) {
-		init();
+	init();
 }
 
-
 function init() {
 
-		tags = Tags();
-		canvas = Canvas();
-		search = Search();
-		timeline = Timeline()
-		ping = utils.ping();
-
-		d3.json("data/config.json", function(config) {
-
-				utils.initConfig(config)
-
-				d3.csv(config.loader.timeline, function(timeline) {
-						Loader(config.loader.items).finished(function(data) {
-
-								utils.clean(data);
-
-								tags.init(data, config);
-								search.init();
-								canvas.init(data, timeline, config);
-
-								LoaderSprites()
-										.progress(function(textures) {
-												Object.keys(textures).forEach(function(id) {
-														data
-																.filter(function(d) { return d.id === id })
-																.forEach(function(d) {
-																		d.sprite.texture = textures[id]
-																})
-												})
-												canvas.wakeup()
-										})
-										.load(config.loader.textures.medium.url)
-						});
-				});
+	tags = Tags();
+	canvas = Canvas();
+	search = Search();
+	timeline = Timeline()
+	ping = utils.ping();
+
+	d3.json("data/config.json", function (config) {
+
+		utils.initConfig(config)
+
+		Loader(config.loader.timeline).finished(function (timeline) {
+			Loader(config.loader.items).finished(function (data) {
+
+				utils.clean(data);
+
+				tags.init(data, config);
+				search.init();
+				canvas.init(data, timeline, config);
+
+				if (config.loader.tsne) {
+					d3.csv(config.loader.tsne, function (tsne) {
+						console.log(tsne)
+						d3.select(".navi").classed("hide", false)
+						canvas.addTsneData(tsne)
+					})
+				}
+
+				LoaderSprites()
+					.progress(function (textures) {
+						Object.keys(textures).forEach(function (id) {
+							data
+								.filter(function (d) {
+									return d.id === id
+								})
+								.forEach(function (d) {
+									d.sprite.texture = textures[id]
+								})
+						})
+						canvas.wakeup()
+					})
+					.load(config.loader.textures.medium.url)
+			});
 		});
-
-		d3.select(window)
-				.on("resize", function() {
-						if (canvas !== undefined && tags !== undefined) {
-								clearTimeout(window.resizedFinished);
-								window.resizedFinished = setTimeout(function() {
-										canvas.resize();
-										tags.resize();
-								}, 250);
-						}
-				})
-				.on("keydown", function(e) {
-						if (d3.event.keyCode != 27) return
-						search.reset();
-						tags.reset();
-						canvas.split();
-				})
-
-		d3.select(".slidebutton")
-				.on("click", function() {
-						var s = !d3.select(".sidebar").classed("sneak");
-						d3.select(".sidebar").classed("sneak", s);
-				})
-
-		d3.select(".infobutton")
-				.on("click", function() {
-						var s = !d3.select(".infobar").classed("sneak");
-						d3.select(".infobar").classed("sneak", s)
-				})
+	});
+
+	d3.select(window)
+		.on("resize", function () {
+			if (canvas !== undefined && tags !== undefined) {
+				clearTimeout(window.resizedFinished);
+				window.resizedFinished = setTimeout(function () {
+					canvas.resize();
+					tags.resize();
+				}, 250);
+			}
+		})
+		.on("keydown", function (e) {
+			if (d3.event.keyCode != 27) return
+			search.reset();
+			tags.reset();
+			canvas.split();
+		})
+
+	d3.select(".slidebutton")
+		.on("click", function () {
+			var s = !d3.select(".sidebar").classed("sneak");
+			d3.select(".sidebar").classed("sneak", s);
+		})
+
+	d3.select(".infobutton")
+		.on("click", function () {
+			var s = !d3.select(".infobar").classed("sneak");
+			d3.select(".infobar").classed("sneak", s)
+		})
+
+	d3.selectAll(".navi .button")
+		.on("click", function () {
+			var that = this
+			var mode = d3.select(this).text()
+			canvas.setMode(mode)
+			timeline.setDisabled(mode != "time")
+
+			d3.selectAll(".navi .button").classed("active", function () {
+				return that === this
+			});
+		})
 }
 
 d3.select(".browserInfo").classed("show", utils.isMobile());
\ No newline at end of file