diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
index 39547b83726e74fdc8681a0c7ab2b2dbf87afd6c..3fafdd4b752c4211196a323198be3356283055be 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
@@ -1,6 +1,7 @@
 package de.vipra.rest.resource;
 
 import java.io.IOException;
+import java.util.Date;
 import java.util.List;
 
 import javax.servlet.ServletContext;
@@ -67,7 +68,8 @@ public class ArticleResource {
 	public Response getArticles(@QueryParam("topicModel") final String topicModel, @QueryParam("skip") final Integer skip,
 			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("date") final String sortBy,
 			@QueryParam("fields") final String fields, @QueryParam("word") final String word, @QueryParam("entity") final String entity,
-			@QueryParam("excerpt") final String excerpt, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains) {
+			@QueryParam("excerpt") final String excerpt, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains,
+			@QueryParam("from") final Long fromDate, @QueryParam("to") final Long toDate) {
 		final ResponseWrapper<List<ArticleFull>> res = new ResponseWrapper<>();
 
 		if (topicModel == null || topicModel.trim().isEmpty()) {
@@ -104,6 +106,12 @@ public class ArticleResource {
 			if (contains != null && !contains.isEmpty())
 				query.contains("title", contains, true);
 
+			if (fromDate != null)
+				query.gte("date", new Date(fromDate));
+
+			if (toDate != null)
+				query.lte("date", new Date(toDate));
+
 			final List<ArticleFull> articles = dbArticles.getMultiple(query);
 
 			if ((skip != null && skip > 0) || (limit != null && limit > 0))
diff --git a/vipra-ui/app/html/articles/index.html b/vipra-ui/app/html/articles/index.html
index 2037f1dfd28452ecff1125f5f20dd54a8a79bef1..91193ff1220c473ace98dbf2935c35de8071e278 100644
--- a/vipra-ui/app/html/articles/index.html
+++ b/vipra-ui/app/html/articles/index.html
@@ -70,6 +70,21 @@
                 </span>
               </div>
             </div>
+            <div class="form-group">
+              <label>From/to date</label>
+              <div class="input-group date" id="fromDate" bs-datetimepicker ng-model="articlesIndexModels.fromDate">
+                <input type="text" class="form-control" placeholder="From date">
+                <span class="input-group-addon">
+                  <span class="glyphicon glyphicon-calendar"></span>
+                </span>
+              </div>
+              <div class="input-group date" id="toDate" bs-datetimepicker ng-model="articlesIndexModels.toDate">
+                <input type="text" class="form-control" placeholder="To date">
+                <span class="input-group-addon">
+                  <span class="glyphicon glyphicon-calendar"></span>
+                </span>
+              </div>
+            </div>
           </div>
         </div>
       </div>
diff --git a/vipra-ui/app/html/directives/article-link.html b/vipra-ui/app/html/directives/article-link.html
index e62bd916ba357df1b280283cfbaeca58b85710b7..952d2991b5e61401bdb68726e4220a81956b1758 100644
--- a/vipra-ui/app/html/directives/article-link.html
+++ b/vipra-ui/app/html/directives/article-link.html
@@ -1,6 +1,10 @@
 <div class="link-wrapper">
   <span class="menu-padding ellipsis">
     <div class="pull-right article-dropdown">
+      <div class="date-compact">
+        <small class="text-muted" ng-bind-template="{{::$root.Vipra.formatDate(article.date)}}"></small>
+        <small class="text-muted" ng-bind-template="{{::$root.Vipra.formatTime(article.date)}}"></small>
+      </div>
       <span class="badge" ng-bind="::article.topicsCount" ng-attr-title="{{::article.topicsCount}} topic(s)" ng-if="::showBadge"></span>
       <i class="fa text-muted pointer" ng-class="{'fa-chevron-down':!detailsShown,'fa-chevron-up':detailsShown}" ng-click="toggleDetails()" ng-if="::showDetails" analytics-on analytics-event="Article details" analytics-category="Article actions"></i>
     </div>
@@ -13,7 +17,9 @@
   <div ng-if="detailsShown" class="details">
     <span ng-bind="::articleDetails.text"></span>
     <div>
-      <a ui-sref="topics.show({id:topic.topic.id})" class="badge topic-badge text-outline" ng-bind="::topic.topic.name" ng-style="{'background':topic.topic.color}" ng-attr-title="{{::topic.topic.name}}" ng-repeat="topic in articleDetails.topics"></a>
+      <a class="badge topic-badge text-outline" ng-style="{'background':topic.topic.color}" ng-repeat="topic in articleDetails.topics">
+        <topic-link topic="::topic.topic" badge="false" />
+      </a>
     </div>
   </div>
 </div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/article-menu.html b/vipra-ui/app/html/directives/article-menu.html
index 1a2ed5613f9d460782d09d0d079cf39508f42f4c..09815f09a46b98ed3d312bb0bf6001545029f853 100644
--- a/vipra-ui/app/html/directives/article-menu.html
+++ b/vipra-ui/app/html/directives/article-menu.html
@@ -5,6 +5,6 @@
   <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="articles.show({id:article.id})">Show</a></li>
     <li role="separator" class="divider"></li>
-    <li><a ui-sref="network({type:'topics',id:article.id})">Network</a></li>
+    <li><a ui-sref="network({type:'articles',id:article.id})">Network</a></li>
   </ul>
 </div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/char-selector.html b/vipra-ui/app/html/directives/char-selector.html
index 7747f99edcecdf38489776e512b28db21bf7663b..0b173e190aa5864855efa13ad075b1e241bf9e84 100644
--- a/vipra-ui/app/html/directives/char-selector.html
+++ b/vipra-ui/app/html/directives/char-selector.html
@@ -1,29 +1,36 @@
-<select class="form-control">
-  <option value=""  analytics-on analytics-event="Char selector ()"  analytics-category="Filter actions">All</option>
-  <option value="A" analytics-on analytics-event="Char selector (A)" analytics-category="Filter actions">A</option>
-  <option value="B" analytics-on analytics-event="Char selector (B)" analytics-category="Filter actions">B</option>
-  <option value="C" analytics-on analytics-event="Char selector (C)" analytics-category="Filter actions">C</option>
-  <option value="D" analytics-on analytics-event="Char selector (D)" analytics-category="Filter actions">D</option>
-  <option value="E" analytics-on analytics-event="Char selector (E)" analytics-category="Filter actions">E</option>
-  <option value="F" analytics-on analytics-event="Char selector (F)" analytics-category="Filter actions">F</option>
-  <option value="G" analytics-on analytics-event="Char selector (G)" analytics-category="Filter actions">G</option>
-  <option value="H" analytics-on analytics-event="Char selector (H)" analytics-category="Filter actions">H</option>
-  <option value="I" analytics-on analytics-event="Char selector (I)" analytics-category="Filter actions">I</option>
-  <option value="J" analytics-on analytics-event="Char selector (J)" analytics-category="Filter actions">J</option>
-  <option value="K" analytics-on analytics-event="Char selector (K)" analytics-category="Filter actions">K</option>
-  <option value="L" analytics-on analytics-event="Char selector (L)" analytics-category="Filter actions">L</option>
-  <option value="M" analytics-on analytics-event="Char selector (M)" analytics-category="Filter actions">M</option>
-  <option value="N" analytics-on analytics-event="Char selector (N)" analytics-category="Filter actions">N</option>
-  <option value="O" analytics-on analytics-event="Char selector (O)" analytics-category="Filter actions">O</option>
-  <option value="P" analytics-on analytics-event="Char selector (P)" analytics-category="Filter actions">P</option>
-  <option value="Q" analytics-on analytics-event="Char selector (Q)" analytics-category="Filter actions">Q</option>
-  <option value="R" analytics-on analytics-event="Char selector (R)" analytics-category="Filter actions">R</option>
-  <option value="S" analytics-on analytics-event="Char selector (S)" analytics-category="Filter actions">S</option>
-  <option value="T" analytics-on analytics-event="Char selector (T)" analytics-category="Filter actions">T</option>
-  <option value="U" analytics-on analytics-event="Char selector (U)" analytics-category="Filter actions">U</option>
-  <option value="V" analytics-on analytics-event="Char selector (V)" analytics-category="Filter actions">V</option>
-  <option value="W" analytics-on analytics-event="Char selector (W)" analytics-category="Filter actions">W</option>
-  <option value="X" analytics-on analytics-event="Char selector (X)" analytics-category="Filter actions">X</option>
-  <option value="Y" analytics-on analytics-event="Char selector (Y)" analytics-category="Filter actions">Y</option>
-  <option value="Z" analytics-on analytics-event="Char selector (Z)" analytics-category="Filter actions">Z</option>
-</select>
\ No newline at end of file
+<div class="input-group">
+  <select class="form-control" ng-model="ngModel">
+    <option value=""  analytics-on analytics-event="Char selector ()"  analytics-category="Filter actions">All</option>
+    <option value="A" analytics-on analytics-event="Char selector (A)" analytics-category="Filter actions">A</option>
+    <option value="B" analytics-on analytics-event="Char selector (B)" analytics-category="Filter actions">B</option>
+    <option value="C" analytics-on analytics-event="Char selector (C)" analytics-category="Filter actions">C</option>
+    <option value="D" analytics-on analytics-event="Char selector (D)" analytics-category="Filter actions">D</option>
+    <option value="E" analytics-on analytics-event="Char selector (E)" analytics-category="Filter actions">E</option>
+    <option value="F" analytics-on analytics-event="Char selector (F)" analytics-category="Filter actions">F</option>
+    <option value="G" analytics-on analytics-event="Char selector (G)" analytics-category="Filter actions">G</option>
+    <option value="H" analytics-on analytics-event="Char selector (H)" analytics-category="Filter actions">H</option>
+    <option value="I" analytics-on analytics-event="Char selector (I)" analytics-category="Filter actions">I</option>
+    <option value="J" analytics-on analytics-event="Char selector (J)" analytics-category="Filter actions">J</option>
+    <option value="K" analytics-on analytics-event="Char selector (K)" analytics-category="Filter actions">K</option>
+    <option value="L" analytics-on analytics-event="Char selector (L)" analytics-category="Filter actions">L</option>
+    <option value="M" analytics-on analytics-event="Char selector (M)" analytics-category="Filter actions">M</option>
+    <option value="N" analytics-on analytics-event="Char selector (N)" analytics-category="Filter actions">N</option>
+    <option value="O" analytics-on analytics-event="Char selector (O)" analytics-category="Filter actions">O</option>
+    <option value="P" analytics-on analytics-event="Char selector (P)" analytics-category="Filter actions">P</option>
+    <option value="Q" analytics-on analytics-event="Char selector (Q)" analytics-category="Filter actions">Q</option>
+    <option value="R" analytics-on analytics-event="Char selector (R)" analytics-category="Filter actions">R</option>
+    <option value="S" analytics-on analytics-event="Char selector (S)" analytics-category="Filter actions">S</option>
+    <option value="T" analytics-on analytics-event="Char selector (T)" analytics-category="Filter actions">T</option>
+    <option value="U" analytics-on analytics-event="Char selector (U)" analytics-category="Filter actions">U</option>
+    <option value="V" analytics-on analytics-event="Char selector (V)" analytics-category="Filter actions">V</option>
+    <option value="W" analytics-on analytics-event="Char selector (W)" analytics-category="Filter actions">W</option>
+    <option value="X" analytics-on analytics-event="Char selector (X)" analytics-category="Filter actions">X</option>
+    <option value="Y" analytics-on analytics-event="Char selector (Y)" analytics-category="Filter actions">Y</option>
+    <option value="Z" analytics-on analytics-event="Char selector (Z)" analytics-category="Filter actions">Z</option>
+  </select>
+  <span class="input-group-btn">
+    <button class="btn btn-default" type="button" ng-click="ngModel=''">
+      <span class="glyphicon glyphicon-remove text-danger"></span>
+    </button>
+  </span>
+</div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/pagination-full.html b/vipra-ui/app/html/directives/pagination-full.html
index c206067bc1b9845808ffa04d42266adccc64547b..7564a87c025a491eaf2e554a3a882ba83cd4b220 100644
--- a/vipra-ui/app/html/directives/pagination-full.html
+++ b/vipra-ui/app/html/directives/pagination-full.html
@@ -27,9 +27,9 @@
     </div>
   </div>
 
-  <div class="btn-group btn-group-justified">
+  <div class="btn-group btn-group-justified button-pagination">
     <div class="btn-group" ng-repeat="p in pages">
-      <button class="btn btn-default" ng-class="{active:page==p}" ng-attr-title="{{'Page ' + p}}" ng-click="changePage(p)" ng-disabled="page==p" analytics-on analytics-event="Paginator (i)" analytics-category="Filter actions" ng-bind="p"></button>
+      <button class="btn btn-default" ng-class="{current:page==p}" ng-attr-title="{{'Page ' + p}}" ng-click="changePage(p)" analytics-on analytics-event="Paginator (i)" analytics-category="Filter actions" ng-bind="p"></button>
     </div>
   </div>
 </div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/network.html b/vipra-ui/app/html/network.html
index 79fab49ca641c8414241be772a63f5630139f978..d410777f47cd522ce4b3a0fe7245b00db93e4944 100644
--- a/vipra-ui/app/html/network.html
+++ b/vipra-ui/app/html/network.html
@@ -19,6 +19,11 @@
           <input type="checkbox" id="showWords" ng-model="shown.words">
           <label for="showWords" analytics-on analytics-event="Network Type (Words)" analytics-category="Filter actions">Words</label>
         </div>
+        <hr>
+        <div class="checkbox">
+          <input type="checkbox" id="highlightEnabled" ng-model="highlightEnabled">
+          <label for="highlightEnabled" analytics-on analytics-event="Network Highlight Enable" analytics-category="Network actions">Neighborhood highlight</label>
+        </div>
         <div style="display:none">
           Window
           <window-dropdown ng-model="selectedWindow" windows="windows" />
@@ -45,6 +50,17 @@
             </tr>
           </table>
         </div>
+        <div>
+          <table>
+            <tr>
+              <td>
+                <button class="btn btn-default" ng-click="togglePhysics()" analytics-on analytics-event="Network Physics Toggle" analytics-category="Network actions">
+                  <span class="fa" ng-class="{'fa-pause':physicsEnabled, 'fa-play':!physicsEnabled}"></span> Physics
+                </button>
+              </td>
+            </tr>
+          </table>
+        </div>
         <div>
           <button class="btn btn-default btn-block" ng-click="completeNetwork()" analytics-on analytics-event="Network Complete Network" analytics-category="Network actions">
             Load missing relations
diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js
index 1fc95a68654349207aed4a66e162111aa1335331..c73784eed3a9bc1763bbc267a04bfdb19f795957 100644
--- a/vipra-ui/app/js/app.js
+++ b/vipra-ui/app/js/app.js
@@ -16,14 +16,15 @@
     'nya.bootstrap.select',
     'angulartics',
     'angulartics.google.analytics',
+    'angular-loading-bar',
     'vipra.controllers',
     'vipra.directives',
     'vipra.factories',
     'vipra.templates'
   ]);
 
-  app.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', '$httpProvider',
-    function($locationProvider, $stateProvider, $urlRouterProvider, $httpProvider) {
+  app.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', '$httpProvider', 'cfpLoadingBarProvider',
+    function($locationProvider, $stateProvider, $urlRouterProvider, $httpProvider, cfpLoadingBarProvider) {
 
       $locationProvider.html5Mode(true);
       $urlRouterProvider.otherwise('/');
@@ -211,6 +212,8 @@
         fadeAfter: 10000
       });
 
+      // disable loading bar spinner
+      cfpLoadingBarProvider.includeSpinner = false;
     }
   ]);
 
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index 4c04181b15aea244cde5cc4dbaaeee47d877936d..1d6d78582108d11935e774ccbf6b8ebf2af61839 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -90,7 +90,6 @@
       };
 
       $scope.checkTopicModel = function(state, callback) {
-        if($state.current.name === 'index' || $state.current.name !== state) return;
         if($scope.rootModels.topicModel)
           callback();
         else {
@@ -289,10 +288,16 @@
   /**
    * Network controller
    */
-  app.controller('NetworkController', ['$scope', '$state', '$stateParams', '$timeout', 'ArticleFactory', 'TopicFactory', 'WordFactory',
-    function($scope, $state, $stateParams, $timeout, ArticleFactory, TopicFactory, WordFactory) {
+  app.controller('NetworkController', ['$scope', '$state', '$stateParams', '$q', '$window', '$timeout', 'ArticleFactory', 'TopicFactory', 'WordFactory',
+    function($scope, $state, $stateParams, $q, $window, $timeout, ArticleFactory, TopicFactory, WordFactory) {
       $scope.rootModels.title = 'Network';
 
+      $scope.physicsEnabled = true;
+      $scope.highlightEnabled = true;
+
+      var level2Color = 'rgba(130,130,130,0.8)';
+      var level3Color = 'rgba(220,220,220,0.4)';
+
       var id = 0,
         ids = {},
         edges = {};
@@ -330,6 +335,10 @@
           barnesHut: {
             springConstant: 0.008,
             gravitationalConstant: -3500
+          },
+          timestep: 0.4,
+          stabilization: {
+            iterations: 100
           }
         },
         interaction: {
@@ -349,8 +358,6 @@
         ids[dbid] = ++id;
         return {
           id: id,
-          x: x,
-          y: y,
           title: title,
           label: title.multiline(5).ellipsize(50),
           type: type,
@@ -360,6 +367,7 @@
           loader: loader,
           borderWidth: 1,
           origColor: {
+            border: '#000',
             background: color,
             highlight: {
               background: color,
@@ -460,12 +468,17 @@
       };
 
       // on node select
+      var nodeLoader = null;
       $scope.select = function(props) {
         var node = $scope.nodes.get(props.nodes[0]);
         if (node) {
-          node.loader(node, props);
-          node.loaded = true;
-          $scope.nodes.update(node);
+          nodeLoader = node.loader(node, props);
+          nodeLoader.then(function() {
+            node.loaded = true;
+            $scope.nodes.update(node);
+            if($scope.searchNodes)
+              $scope.search();
+          });
         }
       };
 
@@ -476,6 +489,7 @@
       };
 
       $scope.loadArticle = function(node, props) {
+        var defer = $q.defer();
         ArticleFactory.get({
           id: node.dbid,
           fields: '_all'
@@ -493,55 +507,91 @@
               articles.push(data.similarArticles[i].article);
             constructor(articles, articleNode, node, props);
           }
+          defer.resolve();
         });
+        return defer.promise;
       };
 
       $scope.loadTopic = function(node, props) {
+        var defers = [];
+        var d1 = $q.defer();
+        d1.resolve();
+        defers.push(d1.promise);
         if ($scope.shown.articles) {
+          var d2 = $q.defer();
+          defers.push(d2.promise);
           TopicFactory.articles({
             id: node.dbid,
             limit: 50
           }, function(data) {
             constructor(data, articleNode, node, props);
+            d2.resolve();
           });
         }
         if ($scope.shown.words) {
+          var d3 = $q.defer();
+          defers.push(d3.promise);
           TopicFactory.get({
             id: node.dbid,
             limit: 50
           }, function(data) {
             constructor(data.words, wordNode, node, props);
+            d3.resolve();
           });
         }
+        var defer = $q.defer();
+        $q.all([]).then(function() {
+          defer.resolve();
+        });
+        return defer.promise;
       };
 
       $scope.loadWord = function(node, props) {
+        var defers = [];
+        var d1 = $q.defer();
+        d1.resolve();
+        defers.push(d1.promise);
         if ($scope.shown.articles) {
+          var d2 = $q.defer();
+          defers.push(d2.promise);
           ArticleFactory.query({
             word: node.dbid,
             topicModel: $scope.rootModels.topicModel.id,
             limit: 50
           }, function(data) {
             constructor(data, articleNode, node, props);
+            d2.resolve();
           });
         }
         if ($scope.shown.topics) {
+          var d3 = $q.defer();
+          defers.push(d3.promise);
           TopicFactory.query({
             word: node.dbid,
             topicModel: $scope.rootModels.topicModel.id,
             limit: 50
           }, function(data) {
             constructor(data, topicNode, node, props);
+            d3.resolve();
           });
         }
+        var defer = $q.defer();
+        $q.all([]).then(function() {
+          defer.resolve();
+        });
+        return defer.promise;
       };
 
       // on node open
       $scope.open = function(props) {
+        if(!props.nodes.length) return;
         var node = $scope.nodes.get(props.nodes[0]);
-        $state.transitionTo(node.show, {
+
+        $window.open($state.href(node.show, {
           id: node.dbid
-        });
+        }, {
+          absolute: true
+        }), '_blank');
       };
 
       $scope.reset = function() {
@@ -569,6 +619,10 @@
       };
 
       $scope.$watch('searchNodes', function() {
+        $scope.search();
+      });
+
+      $scope.search = function() {
         var nodes = $scope.nodes.get();
         var i;
         var updates = [];
@@ -585,11 +639,9 @@
             } else {
               updates.push({
                 id: nodes[i].id,
-                color: {
-                  background: '#eee'
-                },
+                color: level3Color,
                 font: {
-                  color: '#ccc'
+                  color: level3Color
                 }
               });
             }
@@ -607,14 +659,126 @@
         }
 
         $scope.data.nodes.update(updates);
+      };
+
+      var highlightActive = false;
+      var lastParams = null;
+      $scope.neighbourhoodHighlight = function(params, force) {
+        if(typeof force === 'undefined' && !$scope.highlightEnabled) return;
+        if(!highlightActive && $scope.searchNodes) return;
+        var allNodes = $scope.nodes.get({returnType:"Object"});
+        var nodeId;
+
+        if (params && params.nodes.length > 0) {
+          // if something is selected
+          highlightActive = true;
+          var i, j;
+          var selectedNode = params.nodes[0];
+          var degrees = 2;
+
+          // mark all nodes as hard to read.
+          for (nodeId in allNodes) {
+            allNodes[nodeId].color = level3Color;
+            if (allNodes[nodeId].hiddenLabel === undefined) {
+              allNodes[nodeId].hiddenLabel = allNodes[nodeId].label;
+              allNodes[nodeId].label = undefined;
+            }
+          }
+          var connectedNodes = $scope.graph.getConnectedNodes(selectedNode);
+          var allConnectedNodes = [];
+
+          // get the second degree nodes
+          for (i = 1; i < degrees; i++)
+            for (j = 0; j < connectedNodes.length; j++)
+              allConnectedNodes = allConnectedNodes.concat($scope.graph.getConnectedNodes(connectedNodes[j]));
+
+          // all second degree nodes get a different color and their label back
+          for (i = 0; i < allConnectedNodes.length; i++) {
+            allNodes[allConnectedNodes[i]].color = level2Color;
+            if (allNodes[allConnectedNodes[i]].hiddenLabel !== undefined) {
+              allNodes[allConnectedNodes[i]].label = allNodes[allConnectedNodes[i]].hiddenLabel;
+              allNodes[allConnectedNodes[i]].hiddenLabel = undefined;
+            }
+          }
+
+          // all first degree nodes get their own color and their label back
+          for (i = 0; i < connectedNodes.length; i++) {
+            allNodes[connectedNodes[i]].color = allNodes[connectedNodes[i]].origColor;
+            if (allNodes[connectedNodes[i]].hiddenLabel !== undefined) {
+              allNodes[connectedNodes[i]].label = allNodes[connectedNodes[i]].hiddenLabel;
+              allNodes[connectedNodes[i]].hiddenLabel = undefined;
+            }
+          }
+
+          // the main node gets its own color and its label back.
+          allNodes[selectedNode].color = allNodes[selectedNode].origColor;
+          if (allNodes[selectedNode].hiddenLabel !== undefined) {
+            allNodes[selectedNode].label = allNodes[selectedNode].hiddenLabel;
+            allNodes[selectedNode].hiddenLabel = undefined;
+          }
+        } else {
+          // nothing is selected
+          highlightActive = false;
+          for (nodeId in allNodes) {
+            allNodes[nodeId].color = allNodes[nodeId].origColor;
+            if (allNodes[nodeId].hiddenLabel !== undefined) {
+              allNodes[nodeId].label = allNodes[nodeId].hiddenLabel;
+              allNodes[nodeId].hiddenLabel = undefined;
+            }
+          }
+        }
+
+        // transform the object into an array
+        var updateArray = [];
+        for (nodeId in allNodes)
+          if (allNodes.hasOwnProperty(nodeId))
+            updateArray.push(allNodes[nodeId]);
+        $scope.nodes.update(updateArray);
+
+        if(!highlightActive && $scope.searchNodes)
+          $scope.search();
+      };
+
+      $scope.$watch('highlightEnabled', function() {
+        if(!$scope.highlightEnabled && highlightActive) {
+          $scope.neighbourhoodHighlight(null, true);
+        } else if($scope.highlightEnabled && !highlightActive && lastParams) {
+          $scope.neighbourhoodHighlight(lastParams);
+        }
       });
 
+      $scope.togglePhysics = function(t) {
+        if((typeof t !== 'undefined' && !t) || $scope.physicsEnabled) {
+          $scope.graph.stopSimulation();
+        } else {
+          $scope.graph.startSimulation();
+        }
+        $scope.physicsEnabled = typeof t !== 'undefined' ? t : !$scope.physicsEnabled;
+      };
+
       // create graph
       var container = document.getElementById("visgraph");
       $scope.graph = new vis.Network(container, $scope.data, $scope.options);
       $scope.graph.on('selectNode', $scope.select);
       $scope.graph.on('deselectNode', $scope.deselect);
       $scope.graph.on('doubleClick', $scope.open);
+      $scope.graph.on('click', function(params) {
+        lastParams = params;
+        if(params.nodes.length > 0) {
+          nodeLoader.then(function() {
+            $scope.neighbourhoodHighlight(params);
+          });
+        } else {
+          $scope.neighbourhoodHighlight(params);
+        }
+      });
+      $scope.graph.on('dragging', function() {
+        if(!$scope.physicsEnabled) {
+          $scope.$apply(function() {
+            $scope.physicsEnabled = true;
+          });
+        }
+      });
 
       if($stateParams.type) {
         // if the topic model is not set, the page was refreshed
@@ -972,13 +1136,16 @@
 
         $scope.reloadArticles = function() {
           $scope.loadingArticles = true;
+
           ArticleFactory.query({
             skip: ($scope.articlesIndexModels.page - 1) * $scope.articlesIndexModels.limit,
             limit: $scope.articlesIndexModels.limit,
             sort: ($scope.articlesIndexModels.sortdir ? '' : '-') + $scope.articlesIndexModels.sortkey,
             topicModel: $scope.rootModels.topicModel.id,
             char: $scope.articlesIndexModels.startChar,
-            contains: $scope.articlesIndexModels.contains
+            contains: $scope.articlesIndexModels.contains,
+            from: $scope.articlesIndexModels.fromDate ? $scope.articlesIndexModels.fromDate.getTime() : null,
+            to: $scope.articlesIndexModels.toDate ? $scope.articlesIndexModels.toDate.getTime() : null
           }, function(data, headers) {
             $scope.articles = data;
             $scope.articlesTotal = headers("V-Total");
@@ -989,7 +1156,7 @@
           });
         };
 
-        $scope.$watchGroup(['articlesIndexModels.page', 'articlesIndexModels.sortkey', 'articlesIndexModels.sortdir'], function() {
+        $scope.$watchGroup(['articlesIndexModels.page', 'articlesIndexModels.sortkey', 'articlesIndexModels.sortdir', 'articlesIndexModels.fromDate', 'articlesIndexModels.toDate'], function() {
           $scope.reloadArticles();
         });
 
@@ -1021,6 +1188,7 @@
         id: $stateParams.id
       }, function(data) {
         $scope.article = data;
+        $scope.article.text = $scope.prepareText($scope.article.text);
         $scope.articleDate = Vipra.formatDate($scope.article.date);
         $scope.articleCreated = Vipra.formatDateTime($scope.article.created);
         $scope.articleModified = Vipra.formatDateTime($scope.article.modified);
@@ -1114,6 +1282,11 @@
         $scope.entities = $scope.allEntities;
       };
 
+      $scope.prepareText = function(text) {
+        var base = $state.href('entities', {}, {absolute: true});
+        return text.replace(/href="[^>]+>([^<]+)/g, 'href="' + base + '/$1">$1');
+      };
+
       var topicShareChartElement = $('#topic-share');
       $scope.highlightSlice = function(id, toggle) {
         var highcharts = topicShareChartElement.highcharts();
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index 1c1aec18a9b004241ff60123e1fe69ef20d62987..90613587bcc59b3b51eb037e3ac3c91d41779bff 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -258,7 +258,7 @@
         });
         $elem.on('dp.change', function(e) {
           $scope.$apply(function() {
-            $scope.ngModel = e.date.toDate();
+            $scope.ngModel = e.date ? e.date.toDate() : null;
           });
         });
       }
diff --git a/vipra-ui/app/js/helpers.js b/vipra-ui/app/js/helpers.js
index a3df6c4ee795a6d38710bea35d0eb77ba2a2dd4f..8a33c7a25a5712cae94c396a2824f492bf29f27a 100644
--- a/vipra-ui/app/js/helpers.js
+++ b/vipra-ui/app/js/helpers.js
@@ -17,6 +17,10 @@
     return new Date(date).toLocaleDateString();
   };
 
+  Vipra.formatTime = function(date) {
+    return new Date(date).toLocaleTimeString();
+  };
+
   Vipra.formatDateTime = function(date) {
     return new Date(date).toLocaleString();
   };
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index 3638b6066601bd9d5cd8e07fa3efd25870a6d46e..1adb2ddb803705549ab31f4aa2522a3b3096dbd8 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -84,11 +84,8 @@ a:hover {
 .graph-item {
   position: absolute;
   padding: @graph-spacing*2;
-  background: rgba(128, 128, 128, 0.1);
+  background: #f5f5f5;
   border-radius: 5px;
-  &:hover {
-    background: rgb(242, 242, 242);
-  }
   &.top-left {
     top: 10px;
     left: 10px;
@@ -139,6 +136,10 @@ a:hover {
     position: relative;
     z-index: 2;
   }
+  hr {
+    margin: 5px 0;
+    border-color: #ccc;
+  }
 }
 td {
   overflow: hidden;
@@ -796,6 +797,10 @@ entity-menu {
     padding: 0 10px;
     opacity: 0.8;
   }
+  label {
+    color: white;
+    font-weight: normal;
+  }
 }
 
 .latest-items {
@@ -966,10 +971,14 @@ entity-menu {
 
 .topic-badge {
   margin-right: 3px;
-}
-
-.text-outline {
-  text-shadow: 1px 1px 1px #888, 1px -1px 1px #888, -1px 1px 1px #888, -1px -1px 1px #888;
+  .topic-link {
+    color: white;
+    text-decoration: none;
+    text-shadow: 1px 1px 1px #888, 1px -1px 1px #888, -1px 1px 1px #888, -1px -1px 1px #888;
+    .title {
+      padding-right: 2px;
+    }
+  }
 }
 
 .sidebar-affix {
@@ -995,6 +1004,27 @@ entity-menu {
   text-decoration: underline;
 }
 
+.button-pagination {
+  margin: 5px 0 0 0;
+  .current,
+  .current:focus
+  .current:hover,
+  .current:active {
+    background-color: #337ab7;
+    border-color: #337ab7;
+    color: #fff;
+    cursor: default;
+  }
+}
+
+.date-compact {
+  display: inline-block;
+  line-height: .9;
+  vertical-align: middle;
+  text-align: right;
+  margin-top: -2px;
+}
+
 [ng\:cloak], [ng-cloak], .ng-cloak {
   display: none !important;
 }
@@ -1046,24 +1076,12 @@ entity-menu {
   }
 }
 
-@media (min-width: 1200px) {
-  .sidebar-affix {
-    width: 262.5px;
-  }
-}
-
-@media (max-width: 1050px) {
+@media screen and (max-width: 900px) {
   .search-form {
     display: none;
   }
 }
 
-@media (min-width: 992px) {
-  .sidebar-affix {
-    width: 212.5px;
-  }
-}
-
 @media (max-width: 920px) {
   .navbar-header {
     float: none;
@@ -1100,9 +1118,20 @@ entity-menu {
   .collapsing {
     overflow: hidden!important;
   }
+  .date-compact {
+    small {
+      display: block;
+    }
+  }
 }
 
-@media screen and (max-width: 900px) {
+@media (min-width: 992px) {
+  .sidebar-affix {
+    width: 212.5px;
+  }
+}
+
+@media (max-width: 1050px) {
   .search-form {
     display: none;
   }
diff --git a/vipra-ui/bower.json b/vipra-ui/bower.json
index ce397d0fa02cc04ae742c9cdbce2128922149401..a84e1b265555a9a383c0d6cc9791944615b32c15 100644
--- a/vipra-ui/bower.json
+++ b/vipra-ui/bower.json
@@ -34,6 +34,7 @@
     "bootbox.js": "bootbox#^4.x",
     "angular-hotkeys": "chieffancypants/angular-hotkeys#^1.x",
     "eonasdan-bootstrap-datetimepicker": "^4.x",
-    "angulartics-google-analytics": "^0.1.4"
+    "angulartics-google-analytics": "^0.1.4",
+    "angular-loading-bar": "^0.9.0"
   }
 }
diff --git a/vipra-ui/gulpfile.js b/vipra-ui/gulpfile.js
index db2b270609ec12149f367843095130a826452bc6..abee6c086adfaedaf43631473dd1184f7c5b8631 100644
--- a/vipra-ui/gulpfile.js
+++ b/vipra-ui/gulpfile.js
@@ -34,7 +34,8 @@ var assets = {
     'bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
     'bower_components/angulartics/dist/angulartics.min.js',
     'bower_components/angulartics-google-analytics/dist/angulartics-google-analytics.min.js',
-    'bower_components/jquery-layout/source/stable/jquery.layout.min.js'
+    'bower_components/jquery-layout/source/stable/jquery.layout.min.js',
+    'bower_components/angular-loading-bar/build/loading-bar.min.js'
   ],
   css: [
     'bower_components/bootstrap/dist/css/bootstrap.min.css',
@@ -43,7 +44,8 @@ var assets = {
     'bower_components/nya-bootstrap-select/dist/css/nya-bs-select.min.css',
     'bower_components/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css',
     'bower_components/angular-hotkeys/build/hotkeys.min.css',
-    'bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css'
+    'bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css',
+    'bower_components/angular-loading-bar/build/loading-bar.min.css'
   ],
   fonts: [
     'bower_components/bootstrap/dist/fonts/*',