From 791cf6478ce2f9db026b9f729df194f262617374 Mon Sep 17 00:00:00 2001
From: Jan Grewe <jan@faked.org>
Date: Sun, 17 May 2015 20:50:44 +0200
Subject: [PATCH] improve lazyloading try multiple filenames for artwork

---
 .gitignore                |  14 +-
 api.php                   | 505 +++++++++++++++++++----------------
 cache/fanart/_dummy       |   0
 cache/fanart/movie/_dummy |   0
 cache/fanart/show/_dummy  |   0
 cache/json/_dummy         |   0
 cache/logo/_dummy         |   0
 cache/logo/movie/_dummy   |   0
 cache/logo/show/_dummy    |   0
 cache/poster/_dummy       |   0
 cache/poster/movie/_dummy |   0
 cache/poster/show/_dummy  |   0
 css/mediarack.css         | 143 +++++-----
 index.php                 |  22 +-
 js/jquery.lazyload.min.js |   4 +-
 js/mediarack.js           | 547 ++++++++++++++++++--------------------
 16 files changed, 628 insertions(+), 607 deletions(-)
 create mode 100644 cache/fanart/_dummy
 create mode 100644 cache/fanart/movie/_dummy
 create mode 100644 cache/fanart/show/_dummy
 create mode 100644 cache/json/_dummy
 create mode 100644 cache/logo/_dummy
 create mode 100644 cache/logo/movie/_dummy
 create mode 100644 cache/logo/show/_dummy
 create mode 100644 cache/poster/_dummy
 create mode 100644 cache/poster/movie/_dummy
 create mode 100644 cache/poster/show/_dummy

diff --git a/.gitignore b/.gitignore
index b937733..a407e7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
 /config.php
-/cache/*.json
-/logo/show/*.png
-/logo/movie/*.png
-/fanart/show/*.jpg
-/fanart/movie/*.jpg
-/poster/show/*.jpg
-/poster/movie/*.jpg
+/cache/json/*.json
+/cache/logo/show/*.png
+/cache/logo/movie/*.png
+/cache/fanart/show/*.jpg
+/cache/fanart/movie/*.jpg
+/cache/poster/show/*.jpg
+/cache/poster/movie/*.jpg
diff --git a/api.php b/api.php
index aa609bf..2890757 100644
--- a/api.php
+++ b/api.php
@@ -3,282 +3,331 @@ include_once 'config.php';
 
 if ($_GET['get'] == 'shows' && $_GET['limit'] && isset($_GET['offset'])) {
 
-	$output = array();
-	$shows = querySB('shows');
-	uasort($shows, function($a, $b) {
-		return strcmp($a['show_name'], $b['show_name']);
-	});
-	$shows = array_slice($shows, $_GET['offset'], $_GET['limit'], true);
-	foreach($shows as $key => $show) {
-		$dataShow = querySB('show', $key);		
-		$dataSeasons = querySB('show.seasons', $key);
-		$seasons = array();
-		foreach($dataSeasons as $season => $episodes) {
-			array_push($seasons, array("season" => $season, "count" => count($episodes)));
-		}
-		array_push($output, array(
-			"id" => $key,
-			"name" => $show['show_name'],
-			"folder" => str_replace($showsPath.'/', '', $dataShow['location']),
-			"seasons" => $seasons
-		));
-		unset($seasons);
-	}
-	echo json_encode($output);
-	die;
+  $output = array();
+  $shows = querySB('shows');
+  uasort($shows, function($a, $b) {
+    return strcmp($a['show_name'], $b['show_name']);
+  });
+  $shows = array_slice($shows, $_GET['offset'], $_GET['limit'], true);
+  foreach($shows as $key => $show) {
+    $dataShow = querySB('show', $key);    
+    $dataSeasons = querySB('show.seasons', $key);
+    $seasons = array();
+    foreach($dataSeasons as $season => $episodes) {
+      array_push($seasons, array("season" => $season, "count" => count($episodes)));
+    }
+    array_push($output, array(
+      "id" => $key,
+      "name" => $show['show_name'],
+      "folder" => str_replace($showsPath.'/', '', $dataShow['location']),
+      "seasons" => $seasons
+    ));
+    unset($seasons);
+  }
+  echo json_encode($output);
+  die;
 
 }
 
 
 if ($_GET['get'] == 'movies' && $_GET['limit'] && isset($_GET['offset'])) {
 
-	$movies = queryCP('media.list', 'type=movie&status=done&release_status=done&status_or=1');
-	$movies = array_slice($movies, $_GET['offset'], $_GET['limit'], true);
-	$output = array();
-	foreach ($movies as $movie) {
-		array_push($output, array(
-			"imdb" => $movie['info']['imdb'],
-			"title" => $movie['title'],
-			"year" => $movie['info']['year'],
-			"tagline" => $movie['info']['tagline'],	
-			"plot" => $movie['info']['plot'],
-			"rating" => $movie['info']['rating']['imdb'][0].' ('.$movie['info']['rating']['imdb'][1].')',
-			"status" => $movie['status'],
-			"folder" => current(explode('/', current(str_replace($moviesPath.'/', '', $movie['releases'][release_with_file($movie['releases'])]['files']['movie']))))
-		));
-	}
-	echo json_encode($output);
-	die;
+  $movies = queryCP('media.list', 'type=movie&status=done&release_status=done&status_or=1');
+  $movies = array_slice($movies, $_GET['offset'], $_GET['limit'], true);
+  $output = array();
+  foreach ($movies as $movie) {
+    array_push($output, array(
+      "imdb" => $movie['info']['imdb'],
+      "title" => $movie['title'],
+      "year" => $movie['info']['year'],
+      "tagline" => $movie['info']['tagline'], 
+      "plot" => $movie['info']['plot'],
+      "rating" => $movie['info']['rating']['imdb'][0].' ('.$movie['info']['rating']['imdb'][1].')',
+      "status" => $movie['status'],
+      "folder" => current(explode('/', current(str_replace($moviesPath.'/', '', $movie['releases'][release_with_file($movie['releases'])]['files']['movie']))))
+    ));
+  }
+  echo json_encode($output);
+  die;
 
 }
 
 
 if ($_GET['get'] == 'poster' && (!empty($_GET['show']) || !empty($_GET['movie']))) {
 
-	if(isset($_GET['show'])) {
-		$type = 'show';
-	}else{
-		$type = 'movie';
-	}
-
-	if($_GET['show'] && $_GET['season'])
-		$poster = get_absolute_path('poster/'.$type.'/'.cleanName($_GET['show']).'-S'.$_GET['season'].'.jpg');
-	elseif($_GET['show'])
-		$poster = get_absolute_path('poster/'.$type.'/'.cleanName($_GET['show']).'.jpg');
-	else
-		$poster = get_absolute_path('poster/'.$type.'/'.cleanName($_GET['movie']).'.jpg');
-
-
-	if(!file_exists($poster)) {
-
-		if($_GET['show'] && $_GET['season'])
-			$source = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET['show'], false).'/season'.$_GET['season'].'-poster.jpg');
-		elseif($_GET['show'])
-			$source = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET['show'], false).'/poster.jpg');
-		else
-			$source = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET['movie'], false).'/'.cleanName($_GET['movie'], false).'-poster.jpg');
-
-		if(file_exists($source)) {
-			$img = new Imagick();
-			$img->setOption('jpeg:size', '800x532');
-			$img->readImage($source);
-			$img->thumbnailImage(0, 220);
-			$img->setImageCompression(Imagick::COMPRESSION_JPEG);
-			$img->setImageCompressionQuality(70);
-			$img->writeImage($poster);
-		}elseif($_GET['season'] != '') {
-			header("HTTP/1.0 404 Not Found");
-			die;
-		}else{
-			//$poster = 'img/no_poster.jpg';
-			header("Location: ../../img/no_poster.jpg");
-		}
-	}
-
-	header('Content-type: image/jpeg');
-	header('Content-length: '.filesize($poster));
-	readfile($poster);
-	die;
+  if(isset($_GET['show'])) {
+    $type = 'show';
+  }else{
+    $type = 'movie';
+  }
+
+  if($_GET['show'] && $_GET['season'])
+    $poster = get_absolute_path('cache/poster/'.$type.'/'.cleanName($_GET[$type]).'-S'.$_GET['season'].'.jpg');
+  else
+    $poster = get_absolute_path('cache/poster/'.$type.'/'.cleanName($_GET[$type]).'.jpg');
+
+  if(!file_exists($poster)) {
+
+    if ($_GET['show']) {
+      $path = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET[$type], false));
+      if($_GET['season']) {
+        $filenames = array(
+          'season'.$_GET['season'].'-poster.jpg'
+        );
+      }else {
+        $filenames = array(
+          'poster.jpg',
+        );
+      }
+    } else {
+      $path = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET[$type], false));
+      $filenames = array(
+        cleanName($_GET['movie'], false).'-poster.jpg',
+        'poster.jpg',
+      );
+    }
+
+    foreach($filenames as $filename) {
+      if(file_exists($path.'/'.$filename)) {
+        $source = $path.'/'.$filename;
+        break;
+      }
+    }
+
+    if($source) {
+      $img = new Imagick();
+      $img->setOption('jpeg:size', '800x532');
+      $img->readImage($source);
+      $img->thumbnailImage(0, 220);
+      $img->setImageCompression(Imagick::COMPRESSION_JPEG);
+      $img->setImageCompressionQuality(70);
+      $img->writeImage($poster);
+    }elseif($_GET['season'] != '') {
+      header("HTTP/1.0 404 Not Found");
+      die;
+    }else{
+      //$poster = 'img/no_poster.jpg';
+      header("Location: ../../img/no_poster.jpg");
+    }
+  }
+
+  header('Content-type: image/jpeg');
+  header('Content-length: '.filesize($poster));
+  readfile($poster);
+  die;
 }
 
 
 if ($_GET['get'] == 'fanart' && (!empty($_GET['show']) || !empty($_GET['movie']))) {
 
-	if(isset($_GET['show'])) {
-		$type = 'show';
-	}else{
-		$type = 'movie';
-	}
-	
-	$fanart = get_absolute_path('fanart/'.$type.'/'. cleanName($_GET[$type]).'.jpg');
-
-	if(!file_exists($fanart)) {
-
-		if($_GET['show'])
-			$source = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET['show'], false).'/fanart.jpg');
-		else
-			$source = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET['movie'], false).'/'.cleanName($_GET['movie'], false).'-fanart.jpg');
-
-		if(file_exists($source)) {
-			$img = new Imagick();
-			$img->setOption('jpeg:size', '1024x576');
-			$img->readImage($source);
-			$img->thumbnailImage(1024, 0);
-			$overlay = new Imagick();
-			$overlay->newImage(1024, 576, new ImagickPixel('black'));
-			$overlay->setOption('jpeg:size', '1024x576');
-			$overlay->setImageOpacity(0.50);
-			$img->compositeImage($overlay, imagick::COMPOSITE_OVER, 0, 0);
-			$img->setImageCompression(Imagick::COMPRESSION_JPEG);
-			$img->setImageCompressionQuality(50);
-			$img->writeImage($fanart);
-		}else{
-			//$fanart = 'img/no_fanart.jpg';
-			header("Location: ../../img/no_fanart.jpg");
-		}
-	}
-
-	header('Content-type: image/jpeg');
-	header('Content-length: '.filesize($fanart));
-	readfile($fanart);
-	die;
+  if(isset($_GET['show'])) {
+    $type = 'show';
+  }else{
+    $type = 'movie';
+  }
+  
+  $fanart = get_absolute_path('cache/fanart/'.$type.'/'. cleanName($_GET[$type]).'.jpg');
+
+  if(!file_exists($fanart)) {
+
+    if($_GET['show']) {
+      $path = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET[$type], false));
+      $filenames = array(
+      'fanart.jpg',
+      );
+    } else {
+      $path = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET[$type], false));
+      $filenames = array(
+        cleanName($_GET['movie'], false).'-fanart.jpg',
+        'fanart.jpg',
+      );
+    }
+
+    foreach($filenames as $filename) {
+      if(file_exists($path.'/'.$filename)) {
+        $source = $path.'/'.$filename;
+        break;
+      }
+    }
+
+    if($source) {
+      $img = new Imagick();
+      $img->setOption('jpeg:size', '1024x576');
+      $img->readImage($source);
+      $img->thumbnailImage(1024, 0);
+      $overlay = new Imagick();
+      $overlay->newImage(1024, 576, new ImagickPixel('black'));
+      $overlay->setOption('jpeg:size', '1024x576');
+      $overlay->setImageOpacity(0.50);
+      $img->compositeImage($overlay, imagick::COMPOSITE_OVER, 0, 0);
+      $img->setImageCompression(Imagick::COMPRESSION_JPEG);
+      $img->setImageCompressionQuality(50);
+      $img->writeImage($fanart);
+    }else{
+      //$fanart = 'img/no_fanart.jpg';
+      header("Location: ../../img/no_fanart.jpg");
+    }
+  }
+
+  header('Content-type: image/jpeg');
+  header('Content-length: '.filesize($fanart));
+  readfile($fanart);
+  die;
 }
 
 
 if ($_GET['get'] == 'logo' && (!empty($_GET['show']) || !empty($_GET['movie']))) {
 
-	if(isset($_GET['show'])) {
-		$type = 'show';
-	}else{
-		$type = 'movie';
-	}
-	
-	$logo = get_absolute_path('logo/'.$type.'/'.cleanName($_GET[$type]).'.png');
-
-	if(!file_exists($logo)) {
-
-		if($_GET['show'])
-			$source = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET['show'], false).'/clearlogo.png');
-		else
-			$source = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET['movie'], false).'/'.cleanName($_GET['movie'], false).'-clearlogo.png');
-
-		if(file_exists($source)) {
-			$img = new Imagick();
-			$img->readImage($source);
-			$img->thumbnailImage(0, 50);
-			$img->writeImage($logo);
-		}else{
-			header("HTTP/1.0 404 Not Found");
-			die;
-		}
-	}
-
-	header('Content-type: image/png');
-	header('Content-length: '.filesize($logo));
-	readfile($logo);
-	die;
+  if(isset($_GET['show'])) {
+    $type = 'show';
+  }else{
+    $type = 'movie';
+  }
+  
+  $logo = get_absolute_path('cache/logo/'.$type.'/'.cleanName($_GET[$type]).'.png');
+
+  if(!file_exists($logo)) {
+
+    if($_GET['show']) {
+      $path = '/'.get_absolute_path($showsPath.'/'.cleanName($_GET[$type], false));
+      $filenames = array(
+      'clearlogo.png',
+      'logo.png',
+      );
+    } else {
+      $path = '/'.get_absolute_path($moviesPath.'/'.cleanName($_GET[$type], false));
+      $filenames = array(
+        cleanName($_GET['movie'], false).'-clearlogo.png',
+        'clearlogo.png',
+        cleanName($_GET['movie'], false).'-logo.png',
+        'logo.png',
+      );
+    }
+
+    foreach($filenames as $filename) {
+      if(file_exists($path.'/'.$filename)) {
+        $source = $path.'/'.$filename;
+        break;
+      }
+    }
+
+    if($source) {
+      $img = new Imagick();
+      $img->readImage($source);
+      $img->thumbnailImage(0, 50);
+      $img->writeImage($logo);
+    }else{
+      header("HTTP/1.0 404 Not Found");
+      die;
+    }
+  }
+
+  header('Content-type: image/png');
+  header('Content-length: '.filesize($logo));
+  readfile($logo);
+  die;
 }
 
 
 if ($_GET['get'] == 'episodes' && !empty($_GET['show']) && isset($_GET['season'])) {
-	$output = array();
-	if($json = file_get_contents('http://'.$sb['host'].':'.$sb['port'].$sb['path'].'/api/'.$sb['key'].'/?cmd=show.seasons&tvdbid='.$_GET['show'].'&season='.$_GET['season'])) {
-		$data = current(json_decode($json, true));
-		foreach ($data as $key => $episode) {
-			array_push($output, array("episode" => $key, "name" => $episode['name'], "status" => $episode['status'], "airdate" => $episode['airdate']));
-		}
-	}
-	echo json_encode($output);
-	die;
+  $output = array();
+  if($json = file_get_contents('http://'.$sb['host'].':'.$sb['port'].$sb['path'].'/api/'.$sb['key'].'/?cmd=show.seasons&tvdbid='.$_GET['show'].'&season='.$_GET['season'])) {
+    $data = current(json_decode($json, true));
+    foreach ($data as $key => $episode) {
+      array_push($output, array("episode" => $key, "name" => $episode['name'], "status" => $episode['status'], "airdate" => $episode['airdate']));
+    }
+  }
+  echo json_encode($output);
+  die;
 }
 
 
 if ($_GET['get'] == 'latest' && $_GET['type'] == 'shows') {
-	
-	$eps = querySB('history');
-	$output = array();
-	foreach ($eps as $ep) {
-		if($ep['status'] == 'Downloaded') {
-			array_push($output, array("show" => $ep['show_name'], "episode" => "S".str_pad($ep['season'], 2, '0', STR_PAD_LEFT)."E".str_pad($ep['episode'], 2, '0', STR_PAD_LEFT), "airdate" => $ep['date']));
-		}
-	}
-	$output = array_slice($output, 0, 10);
-	echo json_encode($output);
-	die;
-	
+  
+  $eps = querySB('history');
+  $output = array();
+  foreach ($eps as $ep) {
+    if($ep['status'] == 'Downloaded') {
+      array_push($output, array("show" => $ep['show_name'], "episode" => "S".str_pad($ep['season'], 2, '0', STR_PAD_LEFT)."E".str_pad($ep['episode'], 2, '0', STR_PAD_LEFT), "airdate" => $ep['date']));
+    }
+  }
+  $output = array_slice($output, 0, 10);
+  echo json_encode($output);
+  die;
+  
 }
 
 if ($_GET['get'] == 'latest' && $_GET['type'] == 'movies') {
 
-	$movies = queryCP('media.list', 'type=movie&status=done&release_status=done&status_or=1');
-	uasort($movies, function($a, $b) {
-		return $b['releases'][0]['last_edit'] - $a['releases'][0]['last_edit'];
-	});
-	$output = array();
-	foreach ($movies as $movie) {
-		array_push($output, array("movie" => $movie['title'].' ('.$movie['info']['year'].')'));
-	}
-	$output = array_slice($output, 0, 10);
-	echo json_encode($output);
-	die;
-	
+  $movies = queryCP('media.list', 'type=movie&status=done&release_status=done&status_or=1');
+  uasort($movies, function($a, $b) {
+    return $b['releases'][0]['last_edit'] - $a['releases'][0]['last_edit'];
+  });
+  $output = array();
+  foreach ($movies as $movie) {
+    array_push($output, array("movie" => $movie['title'].' ('.$movie['info']['year'].')'));
+  }
+  $output = array_slice($output, 0, 10);
+  echo json_encode($output);
+  die;
+  
 }
 
 
 function cleanName($name, $strict = true) {
-	if($strict == true)
-		return preg_replace("/[^a-zA-Z0-9]/", "_", $name);
-	else
-		return preg_replace("/:/", "", $name);
+  if($strict == true)
+    return preg_replace("/[^a-zA-Z0-9]/", "_", $name);
+  else
+    return preg_replace("/:/", "", $name);
 }
 
 
 function get_absolute_path($path) {
-	$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
-	$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
-	$absolutes = array();
-	foreach ($parts as $part) {
-		if ('.' == $part) continue;
-		if ('..' == $part) {
-			array_pop($absolutes);
-		} else {
-			$absolutes[] = $part;
-		}
-	}
-	return implode(DIRECTORY_SEPARATOR, $absolutes);
+  $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
+  $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
+  $absolutes = array();
+  foreach ($parts as $part) {
+    if ('.' == $part) continue;
+    if ('..' == $part) {
+      array_pop($absolutes);
+    } else {
+      $absolutes[] = $part;
+    }
+  }
+  return implode(DIRECTORY_SEPARATOR, $absolutes);
 }
 
 function querySB($cmd, $id = '', $season = '') {
-	
-	global $sb, $cacheTTL;
-	if($id == '') {
-		$cache = './cache/'.$cmd.'.json';
-	}else{
-		$cache = './cache/'.$cmd.'-'.$id.'.json';
-	}
-	if (!file_exists($cache) || filemtime($cache) < time()-$cacheTTL) {
-		file_put_contents($cache, file_get_contents('http://'.$sb['host'].':'.$sb['port'].$sb['path'].'/api/'.$sb['key'].'/?cmd='.$cmd.'&tvdbid='.$id.'&season='.$season));
-	}
-	$json = file_get_contents($cache);
-	$data = current(json_decode($json, true));
-	return $data;
-	
+  
+  global $sb, $cacheTTL;
+  if($id == '') {
+    $cache = './cache/json/'.$cmd.'.json';
+  }else{
+    $cache = './cache/json/'.$cmd.'-'.$id.'.json';
+  }
+  if (!file_exists($cache) || filemtime($cache) < time()-$cacheTTL) {
+    file_put_contents($cache, file_get_contents('http://'.$sb['host'].':'.$sb['port'].$sb['path'].'/api/'.$sb['key'].'/?cmd='.$cmd.'&tvdbid='.$id.'&season='.$season));
+  }
+  $json = file_get_contents($cache);
+  $data = current(json_decode($json, true));
+  return $data;
+  
 }
 
 function queryCP($cmd, $params = '') {
-	
-	global $cp, $cacheTTL;
-	if($params != '') {
-		$params = '?'.$params;
-	}
-	$cache = './cache/'.$cmd.'.json';
-	if (!file_exists($cache) || filemtime($cache) < time()-$cacheTTL) {
-		file_put_contents($cache, file_get_contents('http://'.$cp['host'].':'.$cp['port'].$cp['path'].'/api/'.$cp['key'].'/'.$cmd.'/'.$params));
-	}
-	$json = file_get_contents($cache);
-	$data = current(json_decode($json, true));
-	return $data;
-	
+  
+  global $cp, $cacheTTL;
+  if($params != '') {
+    $params = '?'.$params;
+  }
+  $cache = './cache/json/'.$cmd.'.json';
+  if (!file_exists($cache) || filemtime($cache) < time()-$cacheTTL) {
+    file_put_contents($cache, file_get_contents('http://'.$cp['host'].':'.$cp['port'].$cp['path'].'/api/'.$cp['key'].'/'.$cmd.'/'.$params));
+  }
+  $json = file_get_contents($cache);
+  $data = current(json_decode($json, true));
+  return $data;
+  
 }
 
 function release_with_file($releases) {
diff --git a/cache/fanart/_dummy b/cache/fanart/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/fanart/movie/_dummy b/cache/fanart/movie/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/fanart/show/_dummy b/cache/fanart/show/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/json/_dummy b/cache/json/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/logo/_dummy b/cache/logo/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/logo/movie/_dummy b/cache/logo/movie/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/logo/show/_dummy b/cache/logo/show/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/poster/_dummy b/cache/poster/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/poster/movie/_dummy b/cache/poster/movie/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/cache/poster/show/_dummy b/cache/poster/show/_dummy
new file mode 100644
index 0000000..e69de29
diff --git a/css/mediarack.css b/css/mediarack.css
index 192042c..88c8fb1 100644
--- a/css/mediarack.css
+++ b/css/mediarack.css
@@ -1,156 +1,149 @@
 html { 
-	overflow: -moz-scrollbars-vertical; 
-	overflow: scroll; 
-	overflow-y: scroll;
+  overflow: -moz-scrollbars-vertical; 
+  overflow: scroll; 
+  overflow-y: scroll;
 }
 
 body {
-	padding-top: 70px;
+  padding-top: 70px;
 }
 
 .navbar-brand {
-	height: 50px;
-	padding-top: 0;
-    padding-bottom: 0;
+  height: 50px;
+  padding-top: 0;
+  padding-bottom: 0;
 }
 
 .show {
-	margin-bottom: 50px;
-	min-height: 200px;
+  margin-bottom: 50px;
+  min-height: 200px;
 }
 
 .showName.panel-heading,
 .movieName.panel-heading {
-	min-height: 71px;
-	height: 71px;
+  min-height: 71px;
+  height: 71px;
 }
 
 img.showLogo, 
-img.movieLogo {	
-	display: block;
-    margin-left: auto;
-    margin-right: auto;
-	min-height: 50px;
-	height: 50px;
+img.movieLogo { 
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  min-height: 50px;
+  height: 50px;
 }
 
-#shows .thumbnail {
-	min-height: 230px;
-	height: 230px;
-}
-
-a.thumbnail  img.showPoster,
-a.thumbnail  img.moviePoster {
-	min-height: 220px;
-	height: 220px;
+.posterContainer a.thumbnail {
+  height: 224px;
 }
 
 table.episodes {
-	margin-top: 10px;
+  margin-top: 10px;
 }
 
 table.episodes  tr td{
-	font-weight: bold;
+  font-weight: bold;
 }
 
 .panel-title {
-	font-weight: bold;
+  font-weight: bold;
 }
 
 div.panel-body {
-	background-size: 100% auto;
+  background-size: 100% auto;
 }
 
 div.moviePlot {
-	padding: 0;
+  padding: 0;
 }
 
 div.moviePlot div.panel-heading{
-	font-weight: bold;
+  font-weight: bold;
 }
 
 div#shows, div#movies {
-	display: none;
+  display: none;
 }
 
 ul#latestShows li,
 ul#latestMovies li {
-	text-align: center;
+  text-align: center;
 }
 
 div.epLabel {
-	max-width: 200px;
-	margin-top: 5px;
-	font-size: 8pt;
-	font-weight: bold;
-	line-height: 15px;
-	text-align: center;
+  max-width: 200px;
+  margin-top: 5px;
+  font-size: 8pt;
+  font-weight: bold;
+  line-height: 15px;
+  text-align: center;
 
 }
 
 #loading {
-	display: none;
+  display: none;
 }
 
 .jcarousel-wrapper {
-    margin: 20px auto;
-    position: relative;
+  margin: 20px auto;
+  position: relative;
 }
 
 /** Carousel **/
 
 .jcarousel {
-    position: relative;
-    overflow: hidden;
-    width: 100%;
+  position: relative;
+  overflow: hidden;
+  width: 100%;
 }
 
 .jcarousel ul {
-    width: 20000em;
-    position: relative;
-    list-style: none;
-    margin: 0;
-    padding: 0;
+  width: 20000em;
+  position: relative;
+  list-style: none;
+  margin: 0;
+  padding: 0;
 }
 
 .jcarousel li {
-    width: 200px;
-    float: left;
+  width: 200px;
+  float: left;
 }
 
 .jcarousel img {
-	margin: 0 10px;
-    max-width: 150px;
-    height: auto !important;
+  margin: 0 10px;
+  max-width: 150px;
+  height: auto !important;
 }
 
 /** Carousel Controls **/
 
 .jcarousel-control-prev,
 .jcarousel-control-next {
-    position: absolute;
-    top: 50%;
-    margin-top: -15px;
-    width: 30px;
-    height: 30px;
-    text-align: center;
-    background: #4E443C;
-    color: #fff;
-    text-decoration: none;
-    text-shadow: 0 0 1px #000;
-    font: 24px/27px Arial, sans-serif;
-    -webkit-border-radius: 30px;
-    -moz-border-radius: 30px;
-    border-radius: 30px;
-    -webkit-box-shadow: 0 0 4px #F0EFE7;
-    -moz-box-shadow: 0 0 4px #F0EFE7;
-    box-shadow: 0 0 4px #F0EFE7;
+  position: absolute;
+  top: 50%;
+  margin-top: -15px;
+  width: 30px;
+  height: 30px;
+  text-align: center;
+  background: #4E443C;
+  color: #fff;
+  text-decoration: none;
+  text-shadow: 0 0 1px #000;
+  font: 24px/27px Arial, sans-serif;
+  -webkit-border-radius: 30px;
+  -moz-border-radius: 30px;
+  border-radius: 30px;
+  -webkit-box-shadow: 0 0 4px #F0EFE7;
+  -moz-box-shadow: 0 0 4px #F0EFE7;
+  box-shadow: 0 0 4px #F0EFE7;
 }
 
 .jcarousel-control-prev {
-    left: 15px;
+  left: 15px;
 }
 
 .jcarousel-control-next {
-    right: 15px;
+  right: 15px;
 }
diff --git a/index.php b/index.php
index 1c6a8d4..6968f5f 100644
--- a/index.php
+++ b/index.php
@@ -17,18 +17,15 @@ include_once 'config.php';
 	<meta property="og:url" content="http://<?php echo $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; ?>" />
 	<meta property="og:image" content="http://<?php echo $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; ?>img/opengraph.jpg" />
 
-    <link href="css/bootstrap.min.css" rel="stylesheet">
-	<link href="css/bootstrap-slate.min.css" rel="stylesheet">
-    <link href="css/mediarack.css" rel="stylesheet">
+  <link href="css/bootstrap.min.css" rel="stylesheet">
+  <link href="css/bootstrap-slate.min.css" rel="stylesheet">
+  <link href="css/mediarack.css" rel="stylesheet">
 
-    <!-- Just for debugging purposes. Don't actually copy this line! -->
-    <!--[if lt IE 9]><script src="../../docs-assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
-
-    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
-    <!--[if lt IE 9]>
-      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
-      <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
-    <![endif]-->
+  <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+  <!--[if lt IE 9]>
+    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+    <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+  <![endif]-->
   </head>
 
   <body>
@@ -88,7 +85,7 @@ include_once 'config.php';
 			</div>
 		</div>
 
-		<div class="content" id="shows"></div>
+		<div class="content panel-group" id="shows" role="tablist"></div>
 
 		<div class="content" id="movies"></div>
 		
@@ -112,6 +109,7 @@ include_once 'config.php';
     <script src="js/bootstrap.min.js"></script>
 	<script src="js/jquery.jcarousel.min.js"></script>
 	<script src="js/jquery.lazyload.min.js"></script>
+  <script src="js/jquery.lazy.min.js"></script>
 	<script src="js/jquery.scrollstop.js"></script>
 	<script src="js/mediarack.js"></script>
 	
diff --git a/js/jquery.lazyload.min.js b/js/jquery.lazyload.min.js
index b94a83a..575abfb 100644
--- a/js/jquery.lazyload.min.js
+++ b/js/jquery.lazyload.min.js
@@ -1,2 +1,2 @@
-/*! Lazy Load 1.9.1 - MIT license - Copyright 2010-2013 Mika Tuupola */
-!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);
\ No newline at end of file
+/*! Lazy Load 1.9.5 - MIT license - Copyright 2010-2015 Mika Tuupola */
+!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!1,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);
\ No newline at end of file
diff --git a/js/mediarack.js b/js/mediarack.js
index a37e830..be78ebe 100644
--- a/js/mediarack.js
+++ b/js/mediarack.js
@@ -11,308 +11,289 @@ var seasonOpacity = 0.5;
 
 $(document).ready(function() {
 
-	getLatest('Shows');
-	getLatest('Movies');
-	getShows();
-	getMovies();
-	
-	$(".nav a").on('click',function(e) {
-		var page = $(this).attr('href');
-		e.preventDefault();
-		window.location.hash = page;
-		showPage(page);
-	});
-	
-	$(window).scroll(function(){
-		if  ($(window).scrollTop()+200 >= ($(document).height() - ($(window).height()))){
-			if ($("#shows").is(":visible") && loadShows == true) {
-				loadShows = false;
-				getShows();
-			}
-			if ($("#movies").is(":visible") && loadMovies == true) {
-				loadMovies = false;
-				getMovies();
-			}
-		}
-	});
-	
-	var url = document.location.toString();
-	if (url.match('#')) {
-		showPage('#'+url.split('#')[1]);
-	}
+  getLatest('Shows');
+  getLatest('Movies');
+  getShows();
+  getMovies();
+  
+  $(".nav a").on('click',function(e) {
+    var page = $(this).attr('href');
+    e.preventDefault();
+    window.location.hash = page;
+    showPage(page);
+  });
+  
+  $(window).scroll(function(){
+    if  ($(window).scrollTop()+1000 >= ($(document).height() - ($(window).height()))){
+      if ($("#shows").is(":visible") && loadShows == true) {
+        loadShows = false;
+        getShows();
+      }
+      if ($("#movies").is(":visible") && loadMovies == true) {
+        loadMovies = false;
+        getMovies();
+      }
+    }
+  });
+  
+  var url = document.location.toString();
+  if (url.match('#')) {
+    showPage('#'+url.split('#')[1]);
+  }
 
 });
 
 function showPage(page) {
-	$('.content').hide();
-	$(".nav li").removeClass('active');
-	$(".nav li:has(a[href="+page+"])").addClass('active');
-	window.scrollTo(0, 0);
-	$(page).show();
+  $('.content').hide();
+  $(".nav li").removeClass('active');
+  $(".nav li:has(a[href="+page+"])").addClass('active');
+  window.scrollTo(0, 0);
+  $(page).show();
 }
 
 function getLatest(type) {
-	$.getJSON('api.php', {
-		'type': type.toLowerCase(),
-		'get': 'latest'
-		}, function(data) {
-			$.each(data, function (key, ep) {
-				var ulLatestContainer = $("#latest"+type);
-				if(type == 'Shows') {
-					var liLatestItem =  $('<li><img src="'+cdn('show/'+escape(ep.show))+'/poster.jpg" /><div class="epLabel">'+ep.show+'<br />'+ep.episode+'<br />'+ep.airdate+'</div></li>');
-				}else{
-					var liLatestItem =  $('<li><img src="'+cdn('movie/'+escape(ep.movie))+'/poster.jpg" /><div class="epLabel">'+ep.movie+'</div></li>');
-				}
-				ulLatestContainer.append(liLatestItem);
-			});
-			$('.jcarousel.jc'+type)
-			.on('jcarousel:create jcarousel:reload', function() {
-				var element = $(this),
-					width = element.innerWidth();
-				
-				if (width > 1000) {
-					width = width / 5;
-				} else if (width > 800) {
-					width = width / 4;
-				} else if (width > 590) {
-					width = width / 3;
-				} else if (width < 590) {
-					width = width / 2;
-				}
-				element.jcarousel('items').css('width', width + 'px');
-			})
-			.jcarousel({
-				wrap: 'both'
-			});
-			$('.jcarousel-control-prev.jc'+type)
-				.on('jcarouselcontrol:active', function() {
-					$(this).removeClass('inactive');
-				})
-				.on('jcarouselcontrol:inactive', function() {
-					$(this).addClass('inactive');
-				})
-				.jcarouselControl({
-					target: '-=1'
-				});
+  $.getJSON('api.php', {
+    'type': type.toLowerCase(),
+    'get': 'latest'
+    }, function(data) {
+      $.each(data, function (key, ep) {
+        var ulLatestContainer = $("#latest"+type);
+        if(type == 'Shows') {
+          var liLatestItem =  $('<li><img src="'+cdn('show/'+escape(ep.show))+'/poster.jpg" /><div class="epLabel">'+ep.show+'<br />'+ep.episode+'<br />'+ep.airdate+'</div></li>');
+        }else{
+          var liLatestItem =  $('<li><img src="'+cdn('movie/'+escape(ep.movie))+'/poster.jpg" /><div class="epLabel">'+ep.movie+'</div></li>');
+        }
+        ulLatestContainer.append(liLatestItem);
+      });
+      $('.jcarousel.jc'+type)
+      .on('jcarousel:create jcarousel:reload', function() {
+        var element = $(this),
+          width = element.innerWidth();
+        
+        if (width > 1000) {
+          width = width / 5;
+        } else if (width > 800) {
+          width = width / 4;
+        } else if (width > 590) {
+          width = width / 3;
+        } else if (width < 590) {
+          width = width / 2;
+        }
+        element.jcarousel('items').css('width', width + 'px');
+      })
+      .jcarousel({
+        wrap: 'both'
+      });
+      $('.jcarousel-control-prev.jc'+type)
+        .on('jcarouselcontrol:active', function() {
+          $(this).removeClass('inactive');
+        })
+        .on('jcarouselcontrol:inactive', function() {
+          $(this).addClass('inactive');
+        })
+        .jcarouselControl({
+          target: '-=1'
+        });
 
-			$('.jcarousel-control-next.jc'+type)
-				.on('jcarouselcontrol:active', function() {
-					$(this).removeClass('inactive');
-				})
-				.on('jcarouselcontrol:inactive', function() {
-					$(this).addClass('inactive');
-				})
-				.jcarouselControl({
-					target: '+=1'
-				});
+      $('.jcarousel-control-next.jc'+type)
+        .on('jcarouselcontrol:active', function() {
+          $(this).removeClass('inactive');
+        })
+        .on('jcarouselcontrol:inactive', function() {
+          $(this).addClass('inactive');
+        })
+        .jcarouselControl({
+          target: '+=1'
+        });
 
-		}
-	);
+    }
+  );
 }
 
 function getShows() {
-	$("#loading").show();
-	$.getJSON('api.php', {
-		'get': 'shows',
-		'limit': showLimit.toString(),
-		'offset': showOffset.toString()
-		}, function(data) {
-			var divShows = $("#shows");
-			var i = 0;
-			$.each(data, function (key, show) {
-				
-				if(show.seasons.length == 0) {
-					return true;
-				}
-			
-				var divShowContainer = $('<div class="show panel panel-default" data-showid="'+show.id+'" id="show_'+show.id+'"></div>');
-				var divShowHeader = $('<div class="showName panel-heading"><h2 class="panel-title text-center"><img class="showLogo lazy" style="min-height: 50px; height: 50px;" alt="'+show.name+'" data-original="'+cdn('show/'+escape(show.folder)+'/logo.png')+'" /></h2></div>');
-				var divShowBody = $('<div class="panel-body lazy" data-original="'+cdn('show/'+escape(show.folder)+'/fanart.jpg')+'"></div>');
-				divShowBody.css('background-image', 'url('+cdn('img/no_fanart.jpg'));
-				
-				if(show.seasons[0].season == '0') {
-					var countSeasons = show.seasons.length-1;
-				} else {
-					var countSeasons = show.seasons.length;
-				}
-				var countEpisodes = 0;
-				$.each(show.seasons, function(i, season) {
-					countEpisodes = countEpisodes+season.count;
-				});
-				var divShowFooter =$('<div class="panel-footer"><strong>Seasons:</strong> '+countSeasons+', <strong>Episodes:</strong> '+countEpisodes+' </div>');
-				var divShowPoster = $('<div class="col-md-2 text-center"><a href="#" class="thumbnail"><img id="poster_'+show.id+'" class="showPoster lazy" data-original="'+cdn('show/'+escape(show.folder)+'/poster.jpg')+'" /></a></div>');
-				var ulSeasons = $('<ul class="seasons col-md-10 list-group"></ul>');
-				$.each(show.seasons, function(key, season) {
-					if (season.season == '0') {
-						var seasonTitle = 'Specials';
-					}else{
-						var seasonTitle = 'Season '+season.season;
-					}
-					var liSeason = $('<li class="season list-group-item" data-season="'+season.season+'"><strong>'+seasonTitle+'</strong><span class="badge">'+season.count+'</span></li>');
-					liSeason.bind('click', function() {
-						getEpisodes($(this).parent().parent().parent().data('showid'), $(this).data('season'));
-					});
-					liSeason.hover(function() {
-						$("#poster_"+show.id).error(function() {$(this).attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg'))});
-						$("#poster_"+show.id).attr('src', cdn('show/'+escape(show.folder)+'/'+season.season+'/poster.jpg'));
-					}, function() {
-						$("#poster_"+show.id).attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg'));
-					});
-					ulSeasons.append(liSeason);
-				});
-				ulSeasons.fadeTo(0, seasonOpacity);
-				divShowBody.hover(function() {
-					ulSeasons.fadeTo(300, 1);
-				}, function() {
-					ulSeasons.fadeTo(300, seasonOpacity);
-				});
-				divShowContainer.append(divShowHeader);
-				divShowContainer.append(divShowBody);
-				divShowBody.append(divShowPoster);
-				divShowBody.append(ulSeasons);
-				divShowContainer.append(divShowFooter);
-				$("#shows div.panel-body.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});		
-				$("#shows img.showPoster.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});
-				$("#shows img.showLogo.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});
-				divShows.append(divShowContainer);
-				if(i < 5) {
-					divShowHeader.find("img.showLogo").attr('src', cdn('show/'+escape(show.folder)+'/logo.png')).removeClass('lazy');
-					divShowBody.css('background-image', 'url('+cdn('show/'+escape(show.folder)+'/fanart.jpg')+')').removeClass('lazy');
-					divShowPoster.find("img.showPoster").attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg')).removeClass('lazy');
-				}
-				i++;
-			});
-			showOffset = showOffset+showLimit;
-			if(i > 0) {
-				loadShows = true;
-			}
-			$("#loading").hide();
-		}
-	);
+  $("#loading").show();
+  $.getJSON('api.php', {
+    'get': 'shows',
+    'limit': showLimit.toString(),
+    'offset': showOffset.toString()
+    }, function(data) {
+      var divShows = $("#shows");
+      var i = 0;
+      $("#shows div.panel-body.lazy, #shows img.showPoster.lazy, #shows img.showLogo.lazy").removeClass('lazy');
+      $.each(data, function (key, show) {
+        
+        if(show.seasons.length == 0) {
+          return true;
+        }
+      
+        var divShowContainer = $('<div class="show panel panel-default" data-showid="'+show.id+'" id="show_'+show.id+'"></div>');
+        var divShowHeader = $('<div class="showName panel-heading"><h2 class="panel-title text-center"><img class="showLogo lazy" style="min-height: 50px; height: 50px;" alt="'+show.name+'" data-original="'+cdn('show/'+escape(show.folder)+'/logo.png')+'" /></h2></div>');
+        var divShowBody = $('<div class="panel-body lazy" data-original="'+cdn('show/'+escape(show.folder)+'/fanart.jpg')+'"></div>');
+        
+        if(show.seasons[0].season == '0') {
+          var countSeasons = show.seasons.length-1;
+        } else {
+          var countSeasons = show.seasons.length;
+        }
+        var countEpisodes = 0;
+        $.each(show.seasons, function(i, season) {
+          countEpisodes = countEpisodes+season.count;
+        });
+        var divShowFooter =$('<div class="panel-footer"><strong>Seasons:</strong> '+countSeasons+', <strong>Episodes:</strong> '+countEpisodes+' </div>');
+        var divShowPoster = $('<div class="col-md-2 text-center posterContainer"><a href="#" class="thumbnail"><img id="poster_'+show.id+'" class="showPoster lazy" data-original="'+cdn('show/'+escape(show.folder)+'/poster.jpg')+'"/></a></div>');
+        var ulSeasons = $('<ul class="seasons col-md-10 list-group"></ul>');
+        $.each(show.seasons, function(key, season) {
+          if (season.season == '0') {
+            var seasonTitle = 'Specials';
+          }else{
+            var seasonTitle = 'Season '+season.season;
+          }
+          var liSeason = $('<li class="season list-group-item" data-season="'+season.season+'"><strong>'+seasonTitle+'</strong><span class="badge">'+season.count+'</span></li>');
+          liSeason.bind('click', function() {
+            getEpisodes($(this).parent().parent().parent().data('showid'), $(this).data('season'));
+          });
+          liSeason.hover(function() {
+            $("#poster_"+show.id).error(function() {$(this).attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg'))});
+            $("#poster_"+show.id).attr('src', cdn('show/'+escape(show.folder)+'/'+season.season+'/poster.jpg'));
+          }, function() {
+            $("#poster_"+show.id).attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg'));
+          });
+          ulSeasons.append(liSeason);
+        });
+        ulSeasons.fadeTo(0, seasonOpacity);
+        divShowBody.hover(function() {
+          ulSeasons.fadeTo(300, 1);
+        }, function() {
+          ulSeasons.fadeTo(300, seasonOpacity);
+        });
+        divShowBody.append(divShowPoster);
+        divShowBody.append(ulSeasons);
+        divShowContainer.append(divShowHeader);
+        divShowContainer.append(divShowBody);
+        divShowContainer.append(divShowFooter);
+        divShows.append(divShowContainer);
+        $("#shows div.panel-body.lazy, #shows img.showPoster.lazy, #shows img.showLogo.lazy").lazyload({
+          threshold: 1000
+        });
+        /*
+        if(showOffset < showLimit) {
+          divShowHeader.find("img.showLogo").attr('src', cdn('show/'+escape(show.folder)+'/logo.png')).removeClass('lazy');
+          divShowBody.css('background-image', 'url('+cdn('show/'+escape(show.folder)+'/fanart.jpg')+')').removeClass('lazy');
+          divShowPoster.find("img.showPoster").attr('src', cdn('show/'+escape(show.folder)+'/poster.jpg')).removeClass('lazy');
+        }
+        */
+        i++;
+      });
+      showOffset = showOffset+showLimit;
+      if(i >= showLimit) {
+        loadShows = true;
+      }
+      $("#loading").hide();
+    }
+  );
 }
 
 function getEpisodes(show, season) {
-	$.getJSON('api.php', {
-		'get': 'episodes',
-		'show': show,
-		'season': season
-		}, function(data) {
-			var liSeason = $("#shows").find('div[data-showid="'+show+'"] li[data-season="'+season+'"]');
-			liSeason.find("table.episodes").remove();
-			var olEpisodes = $('<table class="table table-bordered table-condensed episodes"></table>');
-			$.each(data, function (key, episode) {
-				var status;
-				switch(episode.status) {
-					case 'Ignored':
-						status = "info";
-						break;
-					case 'Downloaded':
-						status = "success";
-						break;
-					case 'Wanted':
-						status = "danger";
-						break;
-					case 'Snatched':
-						status = "warning";
-						break;
-					case 'Unaired':
-						status = "";
-						break;
-					default:
-						status = "text-default";
-					
-				}
-				var liEpisode = $('<tr class="episode text-'+status+'"><td>'+episode.episode+'</td><td>'+episode.name+'</td><td class="text-right">'+episode.airdate+'</td></tr>');
-				olEpisodes.append(liEpisode);
-			});
-			liSeason.append(olEpisodes);
-			liSeason.unbind('click').bind('click', function() {
-				$(this).find("table.episodes").remove();
-				$(this).unbind('click').bind('click', function() {
-					getEpisodes($(this).parent().parent().parent().data('showid'), $(this).data('season'));
-				});
-			});
-		}
-	);
+  $.getJSON('api.php', {
+    'get': 'episodes',
+    'show': show,
+    'season': season
+    }, function(data) {
+      var liSeason = $("#shows").find('div[data-showid="'+show+'"] li[data-season="'+season+'"]');
+      liSeason.find("table.episodes").remove();
+      var olEpisodes = $('<table class="table table-bordered table-condensed episodes"></table>');
+      $.each(data, function (key, episode) {
+        var status;
+        switch(episode.status) {
+          case 'Ignored':
+            status = "info";
+            break;
+          case 'Downloaded':
+            status = "success";
+            break;
+          case 'Wanted':
+            status = "danger";
+            break;
+          case 'Snatched':
+            status = "warning";
+            break;
+          case 'Unaired':
+            status = "";
+            break;
+          default:
+            status = "text-default";
+          
+        }
+        var liEpisode = $('<tr class="episode text-'+status+'"><td>'+episode.episode+'</td><td>'+episode.name+'</td><td class="text-right">'+episode.airdate+'</td></tr>');
+        olEpisodes.append(liEpisode);
+      });
+      liSeason.append(olEpisodes);
+      liSeason.unbind('click').bind('click', function() {
+        $(this).find("table.episodes").remove();
+        $(this).unbind('click').bind('click', function() {
+          getEpisodes($(this).parent().parent().parent().data('showid'), $(this).data('season'));
+        });
+      });
+    }
+  );
 }
 
 function getMovies() {
-	$("#loading").show();
-	$.getJSON('api.php', {
-		'get': 'movies',
-		'limit': movieLimit.toString(),
-		'offset': movieOffset.toString()
-		}, function(data) {
-			var divMovies = $("#movies");
-			var i = 0;
-			$.each(data, function (key, movie) {
-				var divMovieContainer = $('<div class="movie panel panel-default" data-imdb="'+movie.imdb+'" id="movie_'+movie.imdb+'"></div>');
-				var divMovieHeader = $('<div class="movieName panel-heading"><h2 class="panel-title text-center"><img class="movieLogo lazy" alt="'+movie.title+'" data-original="'+cdn('movie/'+escape(movie.folder)+'/logo.png')+'" /></h2></div>');
-				var divMovieBody = $('<div class="panel-body lazy" data-original="'+cdn('movie/'+escape(movie.folder)+'/fanart.jpg')+'"></div>');
-				divMovieBody.css('background-image', 'url('+cdn('img/no_fanart.jpg'));
-				var divMoviePoster = $('<div class="col-md-2 text-center"><a href="#" class="thumbnail"><img id="poster_'+movie.imdb+'" class="moviePoster lazy" data-original="'+cdn('movie/'+escape(movie.folder)+'/poster.jpg')+'" /></a></div>');
-				var divMoviePlot = $('<div class="moviePlot col-md-10 panel panel-default"><div class="panel-heading">'+movie.tagline+'</div><div class="panel-body">'+movie.plot+'</div></div>');
-				var divMovieFooter =$('<div class="panel-footer text-right">IMDB Rating: '+movie.rating+'</div>');
-				divMovieContainer.append(divMovieHeader);
-				divMovieContainer.append(divMovieBody);
-				divMovieBody.append(divMoviePoster);
-				divMoviePlot.fadeTo(0, seasonOpacity);
-				divMovieBody.hover(function() {
-					divMoviePlot.fadeTo(300, 1);
-				}, function() {
-					divMoviePlot.fadeTo(300, seasonOpacity);
-				});
-				divMovieBody.append(divMoviePlot);
-				divMovieContainer.append(divMovieFooter);
-				$("#movies div.panel-body.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});		
-				$("#movies img.moviePoster.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});
-				$("#movies img.movieLogo.lazy").lazyload({
-					//event: "scrollstop",
-					effect: "fadeIn",
-					//threshold: 100
-				});
-				divMovies.append(divMovieContainer);
-				if(i < 5) {
-					divMovieHeader.find("img.movieLogo").attr('src', cdn('movie/'+escape(movie.folder)+'/logo.png')).removeClass('lazy');
-					divMovieBody.css('background-image', 'url('+cdn('movie/'+escape(movie.folder)+'/fanart.jpg')+')').removeClass('lazy');
-					divMoviePoster.find("img.moviePoster").attr('src', cdn('movie/'+escape(movie.folder)+'/poster.jpg')).removeClass('lazy');
-				}
-				i++;
-			});
-			movieOffset = movieOffset+movieLimit;
-			if(i > 0) {
-				loadMovies = true;
-			}
-			$("#loading").hide();
-		}
-	);
+  $("#loading").show();
+  $.getJSON('api.php', {
+    'get': 'movies',
+    'limit': movieLimit.toString(),
+    'offset': movieOffset.toString()
+    }, function(data) {
+      var divMovies = $("#movies");
+      var i = 0;
+      $("#movies div.panel-body.lazy, #movies img.moviePoster.lazy, #movies img.movieLogo.lazy").removeClass('lazy');
+      $.each(data, function (key, movie) {
+        var divMovieContainer = $('<div class="movie panel panel-default" data-imdb="'+movie.imdb+'" id="movie_'+movie.imdb+'"></div>');
+        var divMovieHeader = $('<div class="movieName panel-heading"><h2 class="panel-title text-center"><img class="movieLogo lazy" alt="'+movie.title+'" data-original="'+cdn('movie/'+escape(movie.folder)+'/logo.png')+'" /></h2></div>');
+        var divMovieBody = $('<div class="panel-body lazy" data-original="'+cdn('movie/'+escape(movie.folder)+'/fanart.jpg')+'"></div>');
+        //divMovieBody.css('background-image', 'url('+cdn('img/no_fanart.jpg'));
+        var divMoviePoster = $('<div class="col-md-2 text-center"><a href="#" class="thumbnail"><img id="poster_'+movie.imdb+'" class="moviePoster lazy" data-original="'+cdn('movie/'+escape(movie.folder)+'/poster.jpg')+'" /></a></div>');
+        var divMoviePlot = $('<div class="moviePlot col-md-10 panel panel-default"><div class="panel-heading">'+movie.tagline+'</div><div class="panel-body">'+movie.plot+'</div></div>');
+        var divMovieFooter =$('<div class="panel-footer text-right">IMDB Rating: '+movie.rating+'</div>');
+        divMovieBody.append(divMoviePoster);
+        divMoviePlot.fadeTo(0, seasonOpacity);
+        divMovieBody.hover(function() {
+          divMoviePlot.fadeTo(300, 1);
+        }, function() {
+          divMoviePlot.fadeTo(300, seasonOpacity);
+        });
+        divMovieBody.append(divMoviePlot);
+        divMovieContainer.append(divMovieHeader);
+        divMovieContainer.append(divMovieBody);
+        divMovieContainer.append(divMovieFooter);
+        divMovies.append(divMovieContainer);
+        $("#movies div.panel-body.lazy, #movies img.moviePoster.lazy, #movies img.movieLogo.lazy").lazyload({
+          threshold: 1000
+        });   
+        /*
+        if(movieOffset < movieLimit) {
+          divMovieHeader.find("img.movieLogo").attr('src', cdn('movie/'+escape(movie.folder)+'/logo.png')).removeClass('lazy');
+          divMovieBody.css('background-image', 'url('+cdn('movie/'+escape(movie.folder)+'/fanart.jpg')+')').removeClass('lazy');
+          divMoviePoster.find("img.moviePoster").attr('src', cdn('movie/'+escape(movie.folder)+'/poster.jpg')).removeClass('lazy');
+        }
+        */
+        i++;
+      });
+      movieOffset = movieOffset+movieLimit;
+      if(i >= movieLimit) {
+        loadMovies = true;
+      }
+      $("#loading").hide();
+    }
+  );
 }
 
 function cdn(img) {
-	if(cdnEnabled == true) {
-		var cdnHost = cdnHostPattern.replace('#',  Math.floor((Math.random()*cdnHostCount)));
-		var base = window.location.href.replace(/https?:\/\//i, "").split('#')[0];
-		var img = window.location.protocol+'//'+cdnHost+'/'+base+img
-	}
-	return img;
+  if(cdnEnabled == true) {
+    var cdnHost = cdnHostPattern.replace('#',  Math.floor((Math.random()*cdnHostCount)));
+    var base = window.location.href.replace(/https?:\/\//i, "").split('#')[0];
+    var img = window.location.protocol+'//'+cdnHost+'/'+base+img
+  }
+  return img;
 }
-- 
GitLab