Improve on remote failure handling

Change-Id: Ieeea4778612aa61cf4b3bfcf32b6909c5b671772
diff --git a/dev/js/src/api.js b/dev/js/src/api.js
index 5295b3c..5b30870 100644
--- a/dev/js/src/api.js
+++ b/dev/js/src/api.js
@@ -41,9 +41,9 @@
     if (param['spans'] == true) {
       url += '?spans=true';
       if (param['foundry'] !== undefined)
-	url += '&foundry=' + param['foundry'];
+	      url += '&foundry=' + param['foundry'];
       if (param['layer'] !== undefined)
-	url += '&layer=' + param['layer'];
+	      url += '&layer=' + param['layer'];
     }
     
     // { spans : false, layer: [Array of KorAP.InfoLayer] }
@@ -67,7 +67,6 @@
    */
   KorAP.API.getJSON = function (url, onload) {
     var req = new XMLHttpRequest();
-
     req.open("GET", url, true);
     req.setRequestHeader("Accept", "application/json");
     req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 
@@ -81,17 +80,23 @@
 	4 - done
       */
       if (this.readyState == 4) {
-	if (this.status === 200) {
-	  var json = JSON.parse(this.responseText);
-	  if (json["errors"] !== null) {
-	    for (var i in json["errors"]) {
-	      KorAP.log(json["errors"][i][0], json["errors"][i][1]);
-	    };
-	  };
-	  onload(json);
-	}
-	else
-	  KorAP.log(this.status, this.statusText);
+
+        var json = JSON.parse(this.responseText);
+	      if (json !== null && json["errors"] !== null) {
+	        for (var i in json["errors"]) {
+	          KorAP.log(json["errors"][i][0], json["errors"][i][1] || "Unknown");
+	        };
+	      }
+        else if (this.status !== 200) {
+        	KorAP.log(this.status, this.statusText);
+        };
+
+	      if (this.status === 200) {
+	        onload(json);
+	      }
+	      else {
+          onload(undefined);
+        };
       }
     };
     req.ontimeout = function () {
diff --git a/dev/js/src/match/info.js b/dev/js/src/match/info.js
index ab72778..743fa2c 100644
--- a/dev/js/src/match/info.js
+++ b/dev/js/src/match/info.js
@@ -114,6 +114,9 @@
 	      // Callback for retrieval
 	      function (matchResponse) {
 
+          if (matchResponse === undefined)
+            cb(null);
+
 	        // Get snippet from match info
 	        if (matchResponse["snippet"] !== undefined) {
 	          this._table = matchTableClass.create(matchResponse["snippet"]);
@@ -270,9 +273,9 @@
       this.getTable(undefined, function (table) {
 
 	      if (table !== null) {
-	        matchtable.classList.remove('loading');
           matchtable.appendChild(table.element());
 	      };
+	      matchtable.classList.remove('loading');
       });
 
       // Get spans
diff --git a/lib/Kalamar/API.pm b/lib/Kalamar/API.pm
index 763c124..2a8806c 100644
--- a/lib/Kalamar/API.pm
+++ b/lib/Kalamar/API.pm
@@ -32,6 +32,7 @@
 			 collection
 			 collection_jsonld/]);
   $index_class->attr(no_cache => 0);
+  $index_class->attr(status => 200);
 };
 
 
@@ -203,8 +204,8 @@
   $c->app->log->debug('Match info: ' . $url);
 
   # Create new user agent and set timeout to 30 seconds
-#  my $ua = $c->user->ua; # Mojo::UserAgent->new;
-#  $ua->inactivity_timeout(30);
+  #  my $ua = $c->user->ua; # Mojo::UserAgent->new;
+  #  $ua->inactivity_timeout(30);
 
   # non-blocking
   if ($cb) {
@@ -214,7 +215,7 @@
       $url => sub {
         my $tx = pop;
         $self->_process_response('match', $index, $tx);
-    weaken $index;
+        weaken $index;
         return $cb->($index);
       });
   }
@@ -222,7 +223,7 @@
   # Match info blocking
   else {
     my $tx = $c->user->auth_request(get => $url);
-#    my $tx = $ua->get($url);
+    # my $tx = $ua->get($url);
     return $self->_process_response('match', $index, $tx);
   };
 };
@@ -294,11 +295,16 @@
 
   # An error has occurded
   if (my $e = $tx->error) {
-    $c->notify(
-      error =>
-        ($e->{code} ? $e->{code} . ': ' : '') .
-        $e->{message} . ' for ' . $type . ' (remote)'
-      );
+
+    # Send error
+    $self->_notify_on_error($c, 0, $tx->res->json);
+
+    # $c->notify(
+    # error =>
+    # ($e->{code} ? $e->{code} . ': ' : '') .
+    # $e->{message} . ' for ' . $type . ' (remote)'
+    # );
+    $index->status($e->{code} // 0);
     return;
   };
 
@@ -309,6 +315,7 @@
     my $json;
     unless ($json = $res->json) {
       $c->notify(error => 'JSON response is invalid');
+      $index->status(0);
       return;
     };
 
@@ -337,6 +344,7 @@
 
   # Request failed
   else {
+    $index->status(0);
     $self->_notify_on_error($c, 1, $tx->res);
   };
   return 1;
@@ -476,7 +484,7 @@
         $c->notify(
           error =>
             ($_->[0] ? $_->[0] . ': ' : '') .
-            $_->[1]
+            ($_->[1] || 'Unknown')
           );
       };
     }
diff --git a/lib/Kalamar/Controller/Search.pm b/lib/Kalamar/Controller/Search.pm
index 2e55e87..5069996 100644
--- a/lib/Kalamar/Controller/Search.pm
+++ b/lib/Kalamar/Controller/Search.pm
@@ -18,7 +18,7 @@
 
   #my $tx = $ua->build_tx(TRACE => $url . 'search?cq=corpusAuthor+%3D+%22Baum%22');
   #{"@context":"http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld","errors":[[301,"You did not specify a query!"]],"collection":{"@type":"koral:doc","key":"corpusAuthor","value":"Baum","match":"match:eq"}}
-  
+
   my $query = $v->param('q');
 
   # No query
@@ -114,21 +114,24 @@
       my $index = shift;
       return $c->respond_to(
 
-	# Render json if requested
-	json => sub {
-	  # Add notifications to the matching json
-	  # TODO: There should be a special notification engine doing that!
-	  my $notes = $c->notifications(json => $index->results->[0]);
-	  $c->render(json => $notes);
-	},
+        # Render json if requested
+        json => sub {
+          # Add notifications to the matching json
+          # TODO: There should be a special notification engine doing that!
+          my $notes = $c->notifications(json => $index->results->[0]);
+          $c->render(
+            json => $notes,
+            status => $index->status
+          );
+        },
 
-	# Render html if requested
-	html => sub {
-	  return $c->render(
-	    layout   => 'default',
-	    template => 'match_info'
-	  )
-	}
+        # Render html if requested
+        html => sub {
+          return $c->render(
+            layout   => 'default',
+            template => 'match_info'
+          )
+        }
       );
     }
   );