From 2272111458fe3e854e04988c0b65f6cce63c7498 Mon Sep 17 00:00:00 2001
From: TamaraGunkel <tamara.nrw@web.de>
Date: Tue, 6 Feb 2018 15:31:33 +0100
Subject: [PATCH] finished login and ajax requests

---
 amd/build/form.min.js                         |    1 +
 amd/src/form.js                               |   48 +
 classes/api.php                               |  229 -
 classes/rest.php                              |    8 +-
 filter.php                                    |   44 +-
 info/episode.json                             |   10 +-
 info/me.json                                  |   94 +-
 lang/en/filter_opencast.php                   |    4 +-
 lib.php                                       |   92 +-
 player/js/engage/models/meInfo.js             |   31 +-
 player/js/engage_init.js                      |    1 +
 player/plugin/controls/main.js                | 2984 +++++------
 .../collections/footprint.js                  |   12 +-
 player/plugin/custom-mhConnection/main.js     |   20 +-
 .../custom-mhConnection/models/infoMe.js      |   11 +-
 .../models/mediaPackage.js                    |   11 +-
 .../custom-mhConnection/models/views.js       |   12 +-
 player/plugin/list.json                       |    6 -
 .../plugin/timeline-statistics/lib/Chart.js   |   11 -
 player/plugin/timeline-statistics/main.js     |  381 --
 .../timeline-statistics/styles/desktop.css    |    9 -
 .../timeline-statistics/styles/embed.css      |    1 -
 .../timeline-statistics/styles/mobile.css     |    1 -
 .../templates/desktop.html                    |    6 -
 .../timeline-statistics/templates/embed.html  |    1 -
 .../timeline-statistics/templates/mobile.html |    1 -
 player/plugin/video-videojs/main.js           | 4532 ++++++++---------
 .../plugin/video-videojs/styles/desktop.css   |    4 +-
 player/templates/core_desktop_bottom.html     |    2 +-
 settings.php                                  |    2 +
 version.php                                   |    2 +-
 31 files changed, 4105 insertions(+), 4466 deletions(-)
 create mode 100644 amd/build/form.min.js
 create mode 100644 amd/src/form.js
 delete mode 100644 classes/api.php
 delete mode 100644 player/plugin/timeline-statistics/lib/Chart.js
 delete mode 100644 player/plugin/timeline-statistics/main.js
 delete mode 100644 player/plugin/timeline-statistics/styles/desktop.css
 delete mode 100644 player/plugin/timeline-statistics/styles/embed.css
 delete mode 100644 player/plugin/timeline-statistics/styles/mobile.css
 delete mode 100644 player/plugin/timeline-statistics/templates/desktop.html
 delete mode 100644 player/plugin/timeline-statistics/templates/embed.html
 delete mode 100644 player/plugin/timeline-statistics/templates/mobile.html

diff --git a/amd/build/form.min.js b/amd/build/form.min.js
new file mode 100644
index 0000000..62d5a20
--- /dev/null
+++ b/amd/build/form.min.js
@@ -0,0 +1 @@
+define(["jquery"],function(a){var b={init:function(){a("#ltiLaunchForm").submit(function(b){b.preventDefault(),alert("im submitted"),a.ajax({url:"http://localhost:8080/lti",crossDomain:!0,type:"post",xhrFields:{withCredentials:!0},data:a("#ltiLaunchForm").serialize(),complete:function(){a("iframe").each(function(){a(this).attr("src",a(this).data("framesrc"))})}})}),a("#ltiLaunchForm").submit()}};return b});
\ No newline at end of file
diff --git a/amd/src/form.js b/amd/src/form.js
new file mode 100644
index 0000000..487b445
--- /dev/null
+++ b/amd/src/form.js
@@ -0,0 +1,48 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Ajax functions for opencast
+ *
+ * @module     filter/opencast
+ * @package    filter_opencast
+ * @copyright  2018 Tamara Gunkel
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery'], function ($) {
+
+    var t = {
+        init: function () {
+            $('#ltiLaunchForm').submit(function (e) {
+                e.preventDefault();
+                $.ajax({
+                    url: 'http://localhost:8080/lti',
+                    crossDomain: true,
+                    type: 'post',
+                    xhrFields: {withCredentials: true},
+                    data: $('#ltiLaunchForm').serialize(),
+                    complete: function() {
+                        $("iframe").each(function() {
+                            $(this).attr('src', $(this).data('framesrc'));
+                        });
+                    }
+                });
+            });
+            $('#ltiLaunchForm').submit();
+        }
+    };
+
+    return t;
+});
diff --git a/classes/api.php b/classes/api.php
deleted file mode 100644
index 136a220..0000000
--- a/classes/api.php
+++ /dev/null
@@ -1,229 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-/**
- * API for opencast
- *
- * @package    repository_opencast
- * @copyright  2017 Andreas Wagner, SYNERGY LEARNING
- * @author     Andreas Wagner
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-require_once($CFG->dirroot . '/lib/filelib.php');
-class api extends \curl {
-    private $username;
-    private $password;
-    public static function get_sort_param($params) {
-        if (empty($params)) {
-            return '';
-        }
-        foreach ($params as $key => $sortorder) {
-            $sortdir = (SORT_ASC == $sortorder) ? 'ASC' : 'DESC';
-            return "&sort={$key}:" . $sortdir;
-        }
-    }
-
-    public function __construct($username, $password, $timeout = 30, $settings = array()) {
-        parent::__construct($settings);
-        $this->username = $username;
-        $this->password = $password;
-        $this->timeout = $timeout;
-    }
-
-    /**
-     * Get http status code
-     *
-     * @return int|boolean status code or false if not available.
-     */
-    public function get_http_code() {
-        $info = $this->get_info();
-        if (!isset($info['http_code'])) {
-            return false;
-        }
-        return $info['http_code'];
-    }
-
-    /**
-     * Get an digest authentication header.
-     *
-     * @param \curl $curl
-     * @param string $method
-     * @param string $url
-     * @param string $username
-     * @param string $password
-     * @param array $runwithroles
-     * @return array
-     * @throws \moodle_exception
-     */
-    private function get_authentication_header($method, $url, $runwithroles = array()) {
-        $options = array('CURLOPT_HEADER' => true);
-        $this->setopt($options);
-        $header = array();
-        $header[] = "X-Requested-Auth: Digest";
-        // Restrict to Roles.
-        if (!empty($runwithroles)) {
-            $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles);
-        }
-        $this->setHeader($header);
-        $this->setopt('CURLOPT_CONNECTTIMEOUT', $this->timeout);
-        $authresponse = $this->get($url);
-        $matches = [];
-        preg_match('/WWW-Authenticate: Digest (.*)/', $authresponse, $matches);
-        if (empty($matches)) {
-            throw new \moodle_exception('authenticationrequestfailed', 'repository_opencast');
-        }
-        $authheaders = explode(',', $matches[1]);
-        $parsed = array();
-        foreach ($authheaders as $pair) {
-            $vals = explode('=', $pair);
-            $parsed[trim($vals[0])] = trim($vals[1], '" ');
-        }
-        $realm = (isset($parsed['realm'])) ? $parsed['realm'] : "";
-        $nonce = (isset($parsed['nonce'])) ? $parsed['nonce'] : "";
-        $opaque = (isset($parsed['opaque'])) ? $parsed['opaque'] : "";
-        $authenticate1 = md5($this->username . ":" . $realm . ":" . $this->password);
-        $authenticate2 = md5($method . ":" . $url);
-        $response = md5($authenticate1 . ":" . $nonce . ":" . $authenticate2);
-        $header = array();
-        $header[] = sprintf(
-            'Authorization: Digest username="%s", realm="%s", nonce="%s", opaque="%s", uri="%s", response="%s"',
-            $this->username, $realm, $nonce, $opaque, $url, $response
-        );
-        return $header;
-    }
-
-    /**
-     * Do a GET call to opencast API.
-     *
-     * @param string $url
-     * @param array $runwithroles
-     * @return string JSON String of result.
-     */
-    public function oc_get($url, $runwithroles = array()) {
-        $header = $this->get_authentication_header('GET', $url, $runwithroles);
-        $header[] = 'Content-Type: application/json';
-        $this->setHeader($header);
-        $this->setopt(array('CURLOPT_HEADER' => false));
-        return $this->get($url);
-    }
-
-    /**
-     * Opencast needs a fileextension for uploaded file, so add a postname
-     * (which the core curl module does NOT) to curl_file.
-     *
-     * @param type $storedfile
-     * @param type $key
-     */
-    private function add_postname($storedfile, $key) {
-        $curlfile = $this->_tmp_file_post_params[$key];
-        // Ensure that file is uploaded a a curl file (PHP 5 > 5.5.0 is needed).
-        if (!$curlfile instanceof \CURLFile) {
-            throw new \moodle_exception('needphp55orhigher', 'block_opencast');
-        }
-        $filename = $storedfile->get_source();
-        $extension = pathinfo($filename, PATHINFO_EXTENSION);
-        // If extension is empty, add extension base on mimetype.
-        if (empty($extension)) {
-            $extension = mimeinfo_from_type('extension', $storedfile->get_mimetype());
-            $filename .= '.' . $extension;
-        }
-        // Check mimetype.
-        $mimetype = mimeinfo('type', $filename);
-        list($mediatype, $subtype) = explode('/', $mimetype);
-        if ($mediatype != 'video') {
-            $contextid = $storedfile->get_contextid();
-            $context = \context::instance_by_id($id);
-            list($context, $course, $cm) = get_context_info_array($context);
-            $info = new \stdClass();
-            $info->coursename = $course->fullname . "(ID: {$course->id})";
-            $info->filename = $filename;
-            throw new \moodle_exception('wrongmimetypedetected', 'block_opencast', $info);
-        }
-        $curlfile->postname = $filename;
-        $curlfile->mime = $mimetype;
-    }
-
-    /**
-     * Do a POST call to opencast API.
-     *
-     * @param string $url
-     * @param array $runwithroles
-     * @return string JSON String of result.
-     */
-    public function oc_post($url, $params = array(), $runwithroles = array()) {
-        $header = $this->get_authentication_header('POST', $url, $runwithroles);
-        $header[] = "Content-Type: multipart/form-data";
-        $this->setHeader($header);
-        $this->setopt(array('CURLOPT_HEADER' => false));
-        $options['CURLOPT_POST'] = 1;
-        if (is_array($params)) {
-            $this->_tmp_file_post_params = array();
-            foreach ($params as $key => $value) {
-                if ($value instanceof \stored_file) {
-                    $value->add_to_curl_request($this, $key);
-                    $this->add_postname($value, $key);
-                } else {
-                    $this->_tmp_file_post_params[$key] = $value;
-                }
-            }
-            $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params;
-            unset($this->_tmp_file_post_params);
-        } else {
-            // The raw post data.
-            $options['CURLOPT_POSTFIELDS'] = $params;
-        }
-        return $this->request($url, $options);
-    }
-
-    /**
-     * Do a PUT call to opencast API.
-     *
-     * @param string $url
-     * @param array $runwithroles
-     * @return string JSON String of result.
-     */
-    public function oc_put($url, $params = array(), $runwithroles = array()) {
-        $header = $this->get_authentication_header('PUT', $url, $runwithroles);
-        $this->setHeader($header);
-        $this->setopt(array('CURLOPT_HEADER' => false));
-        $options['CURLOPT_CUSTOMREQUEST'] = "PUT";
-        if (is_array($params)) {
-            $this->_tmp_file_post_params = array();
-            foreach ($params as $key => $value) {
-                $this->_tmp_file_post_params[$key] = $value;
-            }
-            $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params;
-            unset($this->_tmp_file_post_params);
-        } else {
-            // The raw post data.
-            $options['CURLOPT_POSTFIELDS'] = $params;
-        }
-        return $this->request($url, $options);
-    }
-
-    public function oc_only_get($url) {
-        $options = array('CURLOPT_HEADER' => true);
-        $this->setopt($options);
-        $header = array();
-        $header[] = "X-Requested-Auth: Digest";
-        // Restrict to Roles.
-        if (!empty($runwithroles)) {
-            $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles);
-        }
-        $this->setHeader($header);
-        $this->setopt('CURLOPT_CONNECTTIMEOUT', $this->timeout);
-        return $this->get($url);
-    }
-}
\ No newline at end of file
diff --git a/classes/rest.php b/classes/rest.php
index 52b1341..838dd50 100644
--- a/classes/rest.php
+++ b/classes/rest.php
@@ -11,15 +11,17 @@ class rest extends \core\oauth2\rest {
      *  [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
      */
     public function get_api_functions() {
+        $baseurl = get_config('filter_opencast', 'baseurlapi');
+
         return [
             'me' => [
-                'endpoint' => 'https://electures.uni-muenster.de/info/me.json',
+                'endpoint' => $baseurl . '/info/me.json',
                 'method' => 'get',
                 'args' => [],
                 'response' => 'raw'
             ],
             'episode' => [
-                'endpoint' => 'https://electures.uni-muenster.de/search/episode.json',
+                'endpoint' => $baseurl . '/search/episode.json',
                 'method' => 'get',
                 'args' => [
                     'id' => PARAM_RAW
@@ -27,7 +29,7 @@ class rest extends \core\oauth2\rest {
                 'response' => 'raw'
             ],
             'footprint' => [
-                'endpoint' => 'https://electures.uni-muenster.de/usertracking/footprint.json',
+                'endpoint' => $baseurl . '/usertracking/footprint.json',
                 'method' => 'get',
                 'args' => [
                     'id' => PARAM_RAW
diff --git a/filter.php b/filter.php
index 3794836..e61cf43 100644
--- a/filter.php
+++ b/filter.php
@@ -26,7 +26,8 @@
  */
 
 defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot.'/filter/opencast/lib.php');
+require_once($CFG->dirroot . '/filter/opencast/lib.php');
+require_once($CFG->libdir . '/oauthlib.php');
 
 /**
  * Automatic opencast videos filter class.
@@ -40,7 +41,7 @@ class filter_opencast extends moodle_text_filter {
 
 
     public function filter($text, array $options = array()) {
-        global $CFG;
+        global $CFG, $PAGE;
         //Checks momentarily only for videos embedded in <video> tag
 
         if (stripos($text, '</video>') === false) {
@@ -52,39 +53,32 @@ class filter_opencast extends moodle_text_filter {
         $matches = preg_split('/(<[^>]*>)/i', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
 
         if ($matches) {
-            $issuerid = get_config('filter_opencast', 'issuerid');
-            $issuer = \core\oauth2\api::get_issuer($issuerid);
-            // Get an OAuth client from the issuer.
-            // TODO return url
-            $returnurl = new moodle_url('/filter/opencastfilter/adminsettings.php');
-            $client = \core\oauth2\api::get_user_oauth_client($issuer, $returnurl);
-            $service = new \filter_opencast\rest($client);
-
             // Get me.json
-            $me = $service->call('me', []);
-            file_put_contents($CFG->dirroot . '\filter\opencast\info\me.json', $me);
+            filter_opencast_load_meInfo();
+
+            $video = false;
 
             foreach ($matches as $match) {
                 if (substr($match, 0, 6) === "<video") {
-                    // Replace it
-                    // TODO
-                    $id = substr($match, strpos($match, 'id=') + 4, 36);
-                    // Get episode.json
-                    $id = '0cc5a97c-82fd-4358-9266-351dc1b1b046';
-                    $params = ['id' => $id];
-                    $episode = $service->call('episode', $params);
-                    file_put_contents($CFG->dirroot . '\filter\opencast\info\episode.json', $episode);
+                    $video = true;
+                } else if ($video) {
+                    $video = false;
+                    if (substr($match, 0, 7) === "<source") {
+                        // Extract id
+                        $id = substr($match, strpos($match, 'api/') + 4, 36);
 
-                    $player = '<iframe src="'.$CFG->wwwroot.'/filter/opencast/player/core.html" width="100%" height="400px"></iframe>';
-		            $text = preg_replace('/<video.*<\/video>/', $player, $text, 1);
+                        $player = '<iframe src="" data-frameSrc="' . $CFG->wwwroot . '/filter/opencast/player/core.html?id='.$id.'" width="80%" height="450px" class="ocplayer"></iframe>';
+                        $link = get_config('filter_opencast', 'baseurlapi') . '/engage/theodul/ui/core.html?id=' . $id;
+                        $newtext = $player . '<a style="display:block;" href="' . $link . '">Zum Video</a>';
+                        $text = preg_replace('/<video.*<\/video>/', $newtext, $text, 1);
+
+                    }
                 }
             }
         }
 
-        $newtext = $text;
-
         // Return the same string except processed by the above.
-        return $newtext;
+        return $text;
     }
 
 
diff --git a/info/episode.json b/info/episode.json
index fecff37..555b7ef 100644
--- a/info/episode.json
+++ b/info/episode.json
@@ -1 +1,9 @@
-{"search-results":{"offset":"0","limit":"1","total":"1","searchTime":"0","query":"(id:0cc5a97c\\-82fd\\-4358\\-9266\\-351dc1b1b046) AND oc_organization:mh_default_org AND (oc_acl_read:ROLE_ANONYMOUS) AND -oc_mediatype:Series AND -oc_deleted:[* TO *]","result":{"id":"0cc5a97c-82fd-4358-9266-351dc1b1b046","org":"mh_default_org","mediapackage":{"duration":"4742080","id":"0cc5a97c-82fd-4358-9266-351dc1b1b046","start":"2017-10-25T20:22:43Z","title":"Theorie und Praxis der Sozialen Arbeit WiSe 2017\/18 22","series":"47013d7e-8e50-4ed5-927f-044e65c37ee1","seriestitle":"Theorie und Praxis der Sozialen Arbeit WiSe 2017\/18","creators":{"creator":"Prof. Dr. Jörn Dummann"},"license":"Alle Rechte vorbehalten","media":{"track":[{"id":"6a2627ec-17d4-493d-96cd-3eb6a5aaef42","type":"presenter\/delivery","ref":"track:74af8ad3-2a36-4bda-93ed-f44708616acf","mimetype":"audio\/mpeg","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/70bd1458-71ea-4bc5-a21c-bdf871dee9b9\/concat.mp3","checksum":{"type":"md5","$":"663002ea323c5a28324ec599f2787e3b"},"duration":4738168,"audio":{"id":"audio-1","device":"","encoder":{"type":"MP3 (MPEG audio layer 3)"},"channels":1,"samplingrate":44100,"bitrate":128000}},{"id":"0329c6e9-423e-4f4c-a5ad-8524cc9aefca","type":"presentation\/delivery","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","medium-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/3b657cc9-157e-42d0-816d-c83b40b85fb1\/concat.mp4","checksum":{"type":"md5","$":"c29cb36d73f719b20a61e568ba13b24d"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":97010},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":41176,"framerate":25,"resolution":"1280x720"}},{"id":"9cfb1cea-9acb-43cd-99a4-4990719a4f51","type":"presentation\/delivery","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"audio\/mpeg","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/2f8471af-d5cc-450a-846d-624ef8da9209\/concat.mp3","checksum":{"type":"md5","$":"663002ea323c5a28324ec599f2787e3b"},"duration":4738168,"audio":{"id":"audio-1","device":"","encoder":{"type":"MP3 (MPEG audio layer 3)"},"channels":1,"samplingrate":44100,"bitrate":128000}},{"id":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","type":"presentation\/delivery","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","high-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/292c9ae9-64b6-43a2-9d22-f2fd6e30e59d\/concat.mp4","checksum":{"type":"md5","$":"7f8bc85b73dc8bbd33a60bc9e36c18b3"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":69901},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":94777,"framerate":25,"resolution":"1920x1080"}},{"id":"f356f035-0cca-44ef-ac96-768642b63527","type":"presenter\/delivery","ref":"track:74af8ad3-2a36-4bda-93ed-f44708616acf","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","medium-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/9bc11163-3ee0-4e05-90fe-44c06e718096\/concat.mp4","checksum":{"type":"md5","$":"17cb7fc5a293e3c9b9c62e8bb7ebec25"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":97010},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":399075,"framerate":25,"resolution":"854x480"}},{"id":"decbc532-5cfe-43d1-ab0d-b9d2351ddf76","type":"presenter\/delivery","ref":"track:74af8ad3-2a36-4bda-93ed-f44708616acf","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","high-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/8eefd227-176b-4420-a1c0-f246584b772f\/concat.mp4","checksum":{"type":"md5","$":"d92878321b9bafc400b1e6ba0fadc770"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":69901},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":3707967,"framerate":25,"resolution":"1280x720"}},{"id":"ae510714-01da-4010-91eb-1cef37f2bdda","type":"presenter\/delivery","ref":"track:74af8ad3-2a36-4bda-93ed-f44708616acf","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","low-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/ffe324d5-7354-4648-81b7-dcbb6d9693c5\/concat.mp4","checksum":{"type":"md5","$":"b59ffea2d091d53e78034c890203eb07"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":97010},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":239105,"framerate":25,"resolution":"640x360"}},{"id":"e2e90a3b-d0b6-4d26-a8a1-9affb6f74c36","type":"presentation\/delivery","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"video\/mp4","tags":{"tag":["archive","engage-download","low-quality"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/de47f7a2-8495-4b01-8de5-81312e600163\/concat.mp4","checksum":{"type":"md5","$":"8d17b447e7c2392718844f71fe297d43"},"duration":4742080,"audio":{"id":"audio-1","device":"","encoder":{"type":"AAC (Advanced Audio Coding)"},"framecount":204055,"channels":1,"samplingrate":44100,"bitrate":97010},"video":{"id":"video-1","device":"","encoder":{"type":"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10"},"framecount":118552,"bitrate":26259,"framerate":25,"resolution":"854x480"}}]},"metadata":{"catalog":[{"id":"cde288f3-ca70-4652-ac7f-e083b23ca181","type":"mpeg-7\/text","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"text\/xml","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/437b2690-4665-4a5f-ab9c-d7d778c62678\/slidetext.xml"},{"id":"efcc63c8-64ae-4b21-a659-e3f6ece27dca","type":"dublincore\/series","mimetype":"text\/xml","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/79707801-d8cd-42e7-bc92-658cd271284f\/catalog.xml","checksum":{"type":"md5","$":"bf0bfa8788a321d5e2d4bd1f7a5c02a4"}},{"id":"468ca74b-ec5e-4408-92ac-17297bbf34b5","type":"dublincore\/episode","mimetype":"text\/xml","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/90f6b3d1-17e0-4dce-a43d-cf0e8d340b6a\/catalog.xml","checksum":{"type":"md5","$":"3635a489f56da1a369ad08c1541e9cb6"}}]},"attachments":{"attachment":[{"id":"6a339e05-96b5-474a-92df-81b0c91a7a28","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:05:42:40F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/a8f9abd4-42a0-4efd-aaea-dc14f7c72385\/concat.jpg","size":0},{"id":"636c6c86-8c89-44da-8f54-8dcc0c491da7","type":"security\/xacml+episode","mimetype":"text\/xml","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/security-policy-episode\/attachment.xml","size":0,"checksum":{"type":"md5","$":"3453b9534120b93ee45a5127ff8497ff"}},{"id":"fb0a888d-8ebf-4e30-b319-32abd66f4cc9","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:17:46:360F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/3af2df28-9458-47c6-a92f-dd187988f696\/concat.jpg","size":0},{"id":"3706ce3a-ea8d-4bd6-8a8d-6a8707b9f3e2","type":"security\/xacml+series","mimetype":"text\/xml","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/security-policy-series\/attachment.xml","size":0,"checksum":{"type":"md5","$":"3453b9534120b93ee45a5127ff8497ff"}},{"id":"be945fe6-f68a-45be-9f9d-62edcb1e7861","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:30:03:120F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/5154fe49-8ef9-4236-ad29-a91245035c8e\/concat.jpg","size":0},{"id":"cfedbb67-eedc-4b1e-a2bf-017cdaad7cdd","type":"presenter\/search+preview","ref":"track:74af8ad3-2a36-4bda-93ed-f44708616acf","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-5\/concat_6_000s_search.jpg","size":0},{"id":"277286c2-3025-4fa0-b0d2-a4959cbeb614","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:00:00:0F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/2ec4e8d9-a31e-44e2-943d-b8f44b30dc92\/concat.jpg","size":0},{"id":"13ac3c7b-5834-4d16-b94d-c3d9d6e9749b","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:01:28:600F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/1c751ea8-3497-4b27-8e33-2783ebb46c39\/concat.jpg","size":0},{"id":"4498a35a-2870-476b-82c2-041dce0975d4","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:03:09:440F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/749366b2-2e4f-4a16-a4b2-5add21fc56e5\/concat.jpg","size":0},{"id":"083ef381-6e70-4021-95a9-63c34739165a","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:18:36:0F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cff56dec-e14d-41a3-b687-e0439167580a\/concat.jpg","size":0},{"id":"b9101e8c-d70e-43be-9a56-ad4c7d99f466","type":"presentation\/player+preview","mimetype":"image\/png","tags":{"tag":["archive","engage-download"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/d6a2bed4-8ba7-4bb4-ba90-f9dfb2fd0f06\/coverimage.png","size":0},{"id":"82ac065b-9476-4ae4-b55d-5aa209943751","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:31:51:800F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/dc811079-42ee-47a6-bdb1-29e943bd7a6b\/concat.jpg","size":0},{"id":"5beaf8ce-5952-4610-8484-1798ae779eb8","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:02:51:640F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/f19e3a2d-373e-4ccd-86db-c557acc7f186\/concat.jpg","size":0},{"id":"5e84d874-2465-4d33-b0ab-66cba13eaaaa","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:01:26:280F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/43d9360e-70cf-4104-9a53-d90bde6f75f6\/concat.jpg","size":0},{"id":"a085d46e-6d5c-4f6a-89f5-6f5d4303f502","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:56:59:840F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/33765a2e-b145-4856-a452-f23dc917cda5\/concat.jpg","size":0},{"id":"750194f8-54b9-49f0-84b0-af91efe9b360","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:36:34:160F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/83ae744b-7929-4fde-8c33-417af9018819\/concat.jpg","size":0},{"id":"f6f5cdfa-583a-4772-b880-4dad04b4d6dd","type":"*\/feed+preview","ref":"attachment:b9101e8c-d70e-43be-9a56-ad4c7d99f466","mimetype":"image\/png","tags":{"tag":["archive","atom","engage-download","rss"]},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-7\/coverimage.png","size":0},{"id":"b7c26dfa-79ae-416f-91af-8eb1e47a95b7","type":"presentation\/search+preview","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-4\/concat_6_000s_search.jpg","size":0},{"id":"cce0fd25-1021-4222-a06f-675453373429","type":"presentation\/segment+preview","ref":"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:08:57:320F1000","mimetype":"image\/jpeg","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cad41e4d-014f-4df2-8e5a-399104fcf6cc\/concat.jpg","size":0},{"id":"8205f2a8-97e6-431a-9803-2c7964e9ae26","type":"presentation\/timeline+preview","ref":"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13","mimetype":"image\/png","tags":{"tag":"engage-download"},"url":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/17ef4081-0581-4303-913a-6ae12f2e0b9b\/concat_timelinepreviews.png","size":0,"additionalProperties":{"property":[{"key":"resolutionY","$":"-1"},{"key":"imageCount","$":"100"},{"key":"resolutionX","$":"160"},{"key":"imageSizeY","$":"10"},{"key":"imageSizeX","$":"10"}]}}]},"publications":""},"dcExtent":4742080,"dcTitle":"Theorie und Praxis der Sozialen Arbeit WiSe 2017\/18 22","dcCreator":"Prof. Dr. Jörn Dummann","dcCreated":"2018-01-08T08:05:00+01:00","dcSpatial":"AulaAasee","dcIsPartOf":"47013d7e-8e50-4ed5-927f-044e65c37ee1","dcLicense":"Alle Rechte vorbehalten","ocMediapackage":"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><mediapackage duration=\"4742080\" id=\"0cc5a97c-82fd-4358-9266-351dc1b1b046\" start=\"2017-10-25T20:22:43Z\" xmlns=\"http:\/\/mediapackage.opencastproject.org\"><title>Theorie und Praxis der Sozialen Arbeit WiSe 2017\/18 22<\/title><series>47013d7e-8e50-4ed5-927f-044e65c37ee1<\/series><seriestitle>Theorie und Praxis der Sozialen Arbeit WiSe 2017\/18<\/seriestitle><creators><creator>Prof. Dr. Jörn Dummann<\/creator><\/creators><license>Alle Rechte vorbehalten<\/license><media><track id=\"6a2627ec-17d4-493d-96cd-3eb6a5aaef42\" type=\"presenter\/delivery\" ref=\"track:74af8ad3-2a36-4bda-93ed-f44708616acf\"><mimetype>audio\/mpeg<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/70bd1458-71ea-4bc5-a21c-bdf871dee9b9\/concat.mp3<\/url><checksum type=\"md5\">663002ea323c5a28324ec599f2787e3b<\/checksum><duration>4738168<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"MP3 (MPEG audio layer 3)\"\/><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>128000.0<\/bitrate><\/audio><\/track><track id=\"0329c6e9-423e-4f4c-a5ad-8524cc9aefca\" type=\"presentation\/delivery\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>medium-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/3b657cc9-157e-42d0-816d-c83b40b85fb1\/concat.mp4<\/url><checksum type=\"md5\">c29cb36d73f719b20a61e568ba13b24d<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>97010.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>41176.0<\/bitrate><framerate>25.0<\/framerate><resolution>1280x720<\/resolution><\/video><\/track><track id=\"9cfb1cea-9acb-43cd-99a4-4990719a4f51\" type=\"presentation\/delivery\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>audio\/mpeg<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/2f8471af-d5cc-450a-846d-624ef8da9209\/concat.mp3<\/url><checksum type=\"md5\">663002ea323c5a28324ec599f2787e3b<\/checksum><duration>4738168<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"MP3 (MPEG audio layer 3)\"\/><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>128000.0<\/bitrate><\/audio><\/track><track id=\"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3\" type=\"presentation\/delivery\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>high-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/292c9ae9-64b6-43a2-9d22-f2fd6e30e59d\/concat.mp4<\/url><checksum type=\"md5\">7f8bc85b73dc8bbd33a60bc9e36c18b3<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>69901.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>94777.0<\/bitrate><framerate>25.0<\/framerate><resolution>1920x1080<\/resolution><\/video><\/track><track id=\"f356f035-0cca-44ef-ac96-768642b63527\" type=\"presenter\/delivery\" ref=\"track:74af8ad3-2a36-4bda-93ed-f44708616acf\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>medium-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/9bc11163-3ee0-4e05-90fe-44c06e718096\/concat.mp4<\/url><checksum type=\"md5\">17cb7fc5a293e3c9b9c62e8bb7ebec25<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>97010.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>399075.0<\/bitrate><framerate>25.0<\/framerate><resolution>854x480<\/resolution><\/video><\/track><track id=\"decbc532-5cfe-43d1-ab0d-b9d2351ddf76\" type=\"presenter\/delivery\" ref=\"track:74af8ad3-2a36-4bda-93ed-f44708616acf\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>high-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/8eefd227-176b-4420-a1c0-f246584b772f\/concat.mp4<\/url><checksum type=\"md5\">d92878321b9bafc400b1e6ba0fadc770<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>69901.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>3707967.0<\/bitrate><framerate>25.0<\/framerate><resolution>1280x720<\/resolution><\/video><\/track><track id=\"ae510714-01da-4010-91eb-1cef37f2bdda\" type=\"presenter\/delivery\" ref=\"track:74af8ad3-2a36-4bda-93ed-f44708616acf\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>low-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/ffe324d5-7354-4648-81b7-dcbb6d9693c5\/concat.mp4<\/url><checksum type=\"md5\">b59ffea2d091d53e78034c890203eb07<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>97010.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>239105.0<\/bitrate><framerate>25.0<\/framerate><resolution>640x360<\/resolution><\/video><\/track><track id=\"e2e90a3b-d0b6-4d26-a8a1-9affb6f74c36\" type=\"presentation\/delivery\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>video\/mp4<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><tag>low-quality<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/de47f7a2-8495-4b01-8de5-81312e600163\/concat.mp4<\/url><checksum type=\"md5\">8d17b447e7c2392718844f71fe297d43<\/checksum><duration>4742080<\/duration><audio id=\"audio-1\"><device\/><encoder type=\"AAC (Advanced Audio Coding)\"\/><framecount>204055<\/framecount><channels>1<\/channels><samplingrate>44100<\/samplingrate><bitrate>97010.0<\/bitrate><\/audio><video id=\"video-1\"><device\/><encoder type=\"H.264 \/ AVC \/ MPEG-4 AVC \/ MPEG-4 part 10\"\/><framecount>118552<\/framecount><bitrate>26259.0<\/bitrate><framerate>25.0<\/framerate><resolution>854x480<\/resolution><\/video><\/track><\/media><metadata><catalog id=\"cde288f3-ca70-4652-ac7f-e083b23ca181\" type=\"mpeg-7\/text\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>text\/xml<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/437b2690-4665-4a5f-ab9c-d7d778c62678\/slidetext.xml<\/url><\/catalog><catalog id=\"efcc63c8-64ae-4b21-a659-e3f6ece27dca\" type=\"dublincore\/series\"><mimetype>text\/xml<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/79707801-d8cd-42e7-bc92-658cd271284f\/catalog.xml<\/url><checksum type=\"md5\">bf0bfa8788a321d5e2d4bd1f7a5c02a4<\/checksum><\/catalog><catalog id=\"468ca74b-ec5e-4408-92ac-17297bbf34b5\" type=\"dublincore\/episode\"><mimetype>text\/xml<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/90f6b3d1-17e0-4dce-a43d-cf0e8d340b6a\/catalog.xml<\/url><checksum type=\"md5\">3635a489f56da1a369ad08c1541e9cb6<\/checksum><\/catalog><\/metadata><attachments><attachment id=\"6a339e05-96b5-474a-92df-81b0c91a7a28\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:05:42:40F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/a8f9abd4-42a0-4efd-aaea-dc14f7c72385\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"636c6c86-8c89-44da-8f54-8dcc0c491da7\" type=\"security\/xacml+episode\"><mimetype>text\/xml<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/security-policy-episode\/attachment.xml<\/url><size>0<\/size><checksum type=\"md5\">3453b9534120b93ee45a5127ff8497ff<\/checksum><\/attachment><attachment id=\"fb0a888d-8ebf-4e30-b319-32abd66f4cc9\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:17:46:360F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/3af2df28-9458-47c6-a92f-dd187988f696\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"3706ce3a-ea8d-4bd6-8a8d-6a8707b9f3e2\" type=\"security\/xacml+series\"><mimetype>text\/xml<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/security-policy-series\/attachment.xml<\/url><size>0<\/size><checksum type=\"md5\">3453b9534120b93ee45a5127ff8497ff<\/checksum><\/attachment><attachment id=\"be945fe6-f68a-45be-9f9d-62edcb1e7861\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:30:03:120F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/5154fe49-8ef9-4236-ad29-a91245035c8e\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"cfedbb67-eedc-4b1e-a2bf-017cdaad7cdd\" type=\"presenter\/search+preview\" ref=\"track:74af8ad3-2a36-4bda-93ed-f44708616acf\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-5\/concat_6_000s_search.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"277286c2-3025-4fa0-b0d2-a4959cbeb614\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:00:00:0F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/2ec4e8d9-a31e-44e2-943d-b8f44b30dc92\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"13ac3c7b-5834-4d16-b94d-c3d9d6e9749b\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:01:28:600F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/1c751ea8-3497-4b27-8e33-2783ebb46c39\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"4498a35a-2870-476b-82c2-041dce0975d4\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:03:09:440F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/749366b2-2e4f-4a16-a4b2-5add21fc56e5\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"083ef381-6e70-4021-95a9-63c34739165a\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:18:36:0F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cff56dec-e14d-41a3-b687-e0439167580a\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"b9101e8c-d70e-43be-9a56-ad4c7d99f466\" type=\"presentation\/player+preview\"><mimetype>image\/png<\/mimetype><tags><tag>archive<\/tag><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/d6a2bed4-8ba7-4bb4-ba90-f9dfb2fd0f06\/coverimage.png<\/url><size>0<\/size><\/attachment><attachment id=\"82ac065b-9476-4ae4-b55d-5aa209943751\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:31:51:800F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/dc811079-42ee-47a6-bdb1-29e943bd7a6b\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"5beaf8ce-5952-4610-8484-1798ae779eb8\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T01:02:51:640F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/f19e3a2d-373e-4ccd-86db-c557acc7f186\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"5e84d874-2465-4d33-b0ab-66cba13eaaaa\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:01:26:280F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/43d9360e-70cf-4104-9a53-d90bde6f75f6\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"a085d46e-6d5c-4f6a-89f5-6f5d4303f502\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:56:59:840F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/33765a2e-b145-4856-a452-f23dc917cda5\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"750194f8-54b9-49f0-84b0-af91efe9b360\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:36:34:160F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/83ae744b-7929-4fde-8c33-417af9018819\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"f6f5cdfa-583a-4772-b880-4dad04b4d6dd\" type=\"*\/feed+preview\" ref=\"attachment:b9101e8c-d70e-43be-9a56-ad4c7d99f466\"><mimetype>image\/png<\/mimetype><tags><tag>archive<\/tag><tag>atom<\/tag><tag>engage-download<\/tag><tag>rss<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-7\/coverimage.png<\/url><size>0<\/size><\/attachment><attachment id=\"b7c26dfa-79ae-416f-91af-8eb1e47a95b7\" type=\"presentation\/search+preview\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/attachment-4\/concat_6_000s_search.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"cce0fd25-1021-4222-a06f-675453373429\" type=\"presentation\/segment+preview\" ref=\"track:b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3;time=T00:08:57:320F1000\"><mimetype>image\/jpeg<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cad41e4d-014f-4df2-8e5a-399104fcf6cc\/concat.jpg<\/url><size>0<\/size><\/attachment><attachment id=\"8205f2a8-97e6-431a-9803-2c7964e9ae26\" type=\"presentation\/timeline+preview\" ref=\"track:6f7ace47-4ac5-48f7-9b25-9635e7a6aa13\"><mimetype>image\/png<\/mimetype><tags><tag>engage-download<\/tag><\/tags><url>https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/17ef4081-0581-4303-913a-6ae12f2e0b9b\/concat_timelinepreviews.png<\/url><size>0<\/size><additionalProperties><property key=\"resolutionY\">-1<\/property><property key=\"imageCount\">100<\/property><property key=\"resolutionX\">160<\/property><property key=\"imageSizeY\">10<\/property><property key=\"imageSizeX\">10<\/property><\/additionalProperties><\/attachment><\/attachments><publications\/><\/mediapackage>","mediaType":"AudioVisual","keywords":{"keywords":""},"modified":"2018-01-09T00:36:51.038+01:00","score":7.3735256,"segments":{"segment":[{"index":"0","time":"0","duration":"86280","relevance":"-1","hit":"false","text":"","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/2ec4e8d9-a31e-44e2-943d-b8f44b30dc92\/concat.jpg"}}},{"index":"1","time":"86280","duration":"103160","relevance":"-1","hit":"false","text":"Gruppenarbeit 08. 01. 18 Herleitung Kompetenzen exemplarisch: Gruppenphasenmodell Gruppenarbeit in der Praxis Einzelfall- oder Gruppenarbeit Fazit kritische Betrachtung Infos zur Klausur mündl. Prüfung Dummarnvonn mnn Enmnvunq stzom una Pthsson Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/43d9360e-70cf-4104-9a53-d90bde6f75f6\/concat.jpg"}}},{"index":"2","time":"189440","duration":"152600","relevance":"-1","hit":"false","text":"Herleitu ng Konzept Haltung, Lebensweltorientierung Methoden Handlungsmethoden Forschungsmethoden Einzelfallarbeit Beobachtung Gruppenarbeit Analyse Gemeinwesenarbeit Sozial- Diagnose EIanung Durchführung Interventionen Uberprüfung Evaluation Verfahren Techniken Konkretisierung der Methoden Dummar- vom mnn Enmnvung stzom una Preussen oe! Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/749366b2-2e4f-4a16-a4b2-5add21fc56e5\/concat.jpg"}}},{"index":"3","time":"342040","duration":"195280","relevance":"-1","hit":"false","text":"Die Gruppe als Einheit wird anerkannt mit ihren Gruppenregeln etc. Ressourcen von Gruppen werden anerkannt Ressourcen werden im Interesse der Veränderung von Klientlnnen aktiviert. Soziale Gruppenarbeit wirkt sich auch auf das Verhalten Einzelner aus. Dummarnvonn mnn Enmnmnq stzom una Professur in! Scum Amon Gmnoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/a8f9abd4-42a0-4efd-aaea-dc14f7c72385\/concat.jpg"}}},{"index":"4","time":"537320","duration":"578680","relevance":"-1","hit":"false","text":"Kompetenzen Durch Kompetenzen erfolgt Unterscheidung zu Selbsthilfegruppen. Erkenntnisse aus der Klein- Gruppenforschung Gruppendynamik und Soziometrie Soziogramm Handlungsprinzipien individualisieren, sich entbehrlich machen Rolle und das Verhalten der Gruppenpädagoglnnen Techniken und Verfahrensweisen Interaktionsspiele, Techniken der Selbst- und Fremdwahrnehmung, Gesprächsleitung Gruppenphasenmodell Dummar- vom mnn Enmnvung stzom una Pthsson oe! Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cad41e4d-014f-4df2-8e5a-399104fcf6cc\/concat.jpg"}}},{"index":"5","time":"1116000","duration":"687120","relevance":"-1","hit":"false","text":"Kompetenzen tz exemplarisch: Gruppenphasenmodell nderung Prozentsatz der Dummar- vom mnn Enmnvung stzom una Pthsson oe! Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/cff56dec-e14d-41a3-b687-e0439167580a\/concat.jpg"}}},{"index":"6","time":"1803120","duration":"108680","relevance":"-1","hit":"false","text":"Gruppenarbeit in der Praxis, Teil- offene Angebote Sen.- Tagesstätten, OKJA nach 11 SGB VIII, KiTa,... Dummar vonn mnn Enmnvung stzom una Proftsson oe! Scum Amon Grumman","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/5154fe49-8ef9-4236-ad29-a91245035c8e\/concat.jpg"}}},{"index":"7","time":"1911800","duration":"282360","relevance":"-1","hit":"false","text":"Gruppenarbeit in der Praxis, Teil- offene Angebote Sen.- Tagesstätten, OKJA nach 11 SGB VIII, KiTa,... HzE 27 Abs. SGB VIII Sozialpädagogische Gruppenarbeit für Kinder und Jugendliche im schulfähigen Alter. TechnikenNerfahren: Kurse, fortlaufende Gruppen inkl. HP HzE 27 Abs. SGB VIII bzw. JGG Ältere Jugendliche und junge Volljährige bis 27 in schwierigen Lebenssituationen, nach Drogen- abhängigkeit. Gefängnisaufentha Prinzip der Freiwilligkeit eingeschränkt durch Anordnung von Maßregel im JGG für 14- 21 Dummarnivonn mnn Enmmung stzom una Proftsson oe! Scum Amon Grumman","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/dc811079-42ee-47a6-bdb1-29e943bd7a6b\/concat.jpg"}}},{"index":"8","time":"2194160","duration":"1225680","relevance":"-1","hit":"false","text":"IV. Einzelfall- und oder Gruppenarbeit? ov Any- So- Anwendung Zielgruppe: wo sich Menschen in einer vergleichbaren problematischen Situation be nden häu De zitorientierung Die Problemlage bestimmt den Inhalt der Sozialen Gruppenarbeit Konformität Dummar- vom mnn Enmnvung stzom una Pthsson oe! Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/83ae744b-7929-4fde-8c33-417af9018819\/concat.jpg"}}},{"index":"9","time":"3419840","duration":"268760","relevance":"-1","hit":"false","text":"ID Fazit kritische Betrachtung ov Any- So- Jedes Arbeitsfeld bedient sich mindestens einer der drei Methoden Einzelfallarbeit, Gruppenarbeit, Gemeinwesenarbeit Die Methoden sind nicht trennscharf in ihren Verfahren Techniken. Handeln in fachlicher Autonomie erforderlich. Kann Rechte, Iegitime Wünsche, Bedarfe Einzelner beschneiden. Dummar- vom mnn Enmnvung stzom una Pthsson oe! Scum Amon Gmaoonamn","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/33765a2e-b145-4856-a452-f23dc917cda5\/concat.jpg"}}},{"index":"10","time":"3688600","duration":"83040","relevance":"-1","hit":"false","text":"","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/1c751ea8-3497-4b27-8e33-2783ebb46c39\/concat.jpg"}}},{"index":"11","time":"3771640","duration":"894720","relevance":"-1","hit":"false","text":"Infos zur Klausur mündl. Prüfung ov Any- So- Klausur am Fr., 02. 02., Aula am Aasee Start der Schreibzeit: 08: 00 Uhr vorher da sein und Ausweis mitbringen Inhalt: De nitionsarbeit Wissen 90 Minuten, 40 Fragen multiple Choice älhreAuswahl hreAuswah 4Punkte 1i 2Punkte Mündliche Prüfung 12.- 16. 02. Voraussetzung: Klausur im selben Semester bestanden Inhalt: Wenig De nitionsarbeit, primär Vernetzungsarbeit Können Terminauswahl über DoodIe- Onlineabfrage: Terminwünsche werden nur berücksichtigt, wenn Angaben zu beiden Studierenden Tandemprüfung mit Einzelbewertung korrekt und vollständig in die DoodIe- Umfrage eingetragen wurden. Ansonsten wird Tandempartnerln Zeit zugeteilt. Infos Link zu der Doodle- Umfrage kommen in der Klausurwoche per Rundmail Infomail bitte ordentlich lesen! Dummam von mnn Enmnmng stzom una Pthsson oe! Scum Amon Grumman","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/f19e3a2d-373e-4ccd-86db-c557acc7f186\/concat.jpg"}}},{"index":"12","time":"4666360","duration":"75720","relevance":"-1","hit":"false","text":"","previews":{"preview":{"ref":"b7e0b22b-cb99-4dc5-b1e3-5abc395e6eb3","$":"https:\/\/electures.uni-muenster.de\/static\/mh_default_org\/engage-player\/0cc5a97c-82fd-4358-9266-351dc1b1b046\/3af2df28-9458-47c6-a92f-dd187988f696\/concat.jpg"}}}]}}}}
\ No newline at end of file
+{
+  "search-results": {
+    "offset": "0",
+    "limit": "0",
+    "total": "0",
+    "searchTime": "7",
+    "query": "(id:caffc928\\-255b\\-4a8d\\-8302\\-d91d55c2a126) AND oc_organization:mh_default_org AND (oc_acl_read:ROLE_ANONYMOUS) AND -oc_mediatype:Series AND -oc_deleted:[* TO *]"
+  }
+}
\ No newline at end of file
diff --git a/info/me.json b/info/me.json
index 42f2cc6..09fd356 100644
--- a/info/me.json
+++ b/info/me.json
@@ -1 +1,93 @@
-{"org":{"anonymousRole":"ROLE_ANONYMOUS","name":"Opencast Project","adminRole":"ROLE_ADMIN","id":"mh_default_org","properties":{"admin.shortcut.general.series_view":"s","org.opencastproject.admin.ui.url":"https:\/\/electures-admin.uni-muenster.de","admin.shortcut.editor.split_at_current_time":"v","player.shortcut.controls.nextChapter":"pageup","engageui.annotations.enable":"true","player.shortcut.controls.jumpToBegin":"backspace","admin.shortcut.general.select_previous_dashboard_filter":"F","admin.shortcut.player.mute":"m","admin.shortcut.editor.play_ending_of_current_segment":"n","player.piwik.heartbeat":"30","player.mastervideotype":"presenter\/delivery","player.shortcut.layout.focusPrev":"<","org.opencastproject.admin.help.documentation.url":"http:\/\/docs.opencast.org","player.shortcut.controls.prevChapter":"pagedown","player.positioncontrols":"bottom","player.shortcut.zoom.moveLeft":"a","admin.shortcut.general.event_view":"e","admin.shortcut.editor.clear_list":"ctrl+backspace","adminui.user.external_role_display":"false","admin.shortcut.general.help":"?","logo_mediamodule":"https:\/\/electures.uni-muenster.de\/images\/electures-icon.svg","org.opencastproject.admin.help.restdocs.url":"\/rest_docs.html","admin.event.new.interval":"60","admin.shortcut.general.new_series":"N","engageui.link_mobile_redirect.description":"For more information have a look at the official site.","player.shortcut.zoom.moveRight":"d","player.shortcut.layout.movePiP":"p","player.hide_video_context_menu":"true","player.piwik.site_id":"53","player.shortcut.playbackrate.decrease":"T","admin.event.new.start_time":"08:05","admin.shortcut.general.select_next_dashboard_filter":"f","player.shortcut.zoom.in":"+","admin.shortcut.player.next_segment":"down","player.piwik.track_events":"play, pause, seek, ended, playbackrate, volume, quality, fullscreen, focus, layout_reset, zoom","admin.shortcut.general.new_event":"n","player.shortcut.controls.playPause":"space","admin.event.new.duration":"110","admin.shortcut.player.next_frame":"right","player.shortcut.fullscreen.cancel":"escape","org.opencastproject.admin.mediamodule.url":"https:\/\/electures.uni-muenster.de\/engage\/ui","player.focusedflavor":"presentation","player.allowedtags":"engage-download,engage-streaming","player.shortcut.zoom.moveUp":"w","player.shortcut.zoom.out":"-","player.shortcut.layout.focusNext":">","player.shortcut-sequence":"controls,volume,playbackrate,layout,zoom,fullscreen","player.shortcut.controls.seekLeft":"left","player.shortcut.playbackrate.increase":"t","admin.event.new.end_time":"19:55","admin.shortcut.editor.play_current_segment_with_pre-roll":"C","player.shortcut.volume.up":"9","org.opencastproject.engage.ui.url":"https:\/\/electures.uni-muenster.de","adminui.chunksize":"2048","admin.shortcut.player.step_backward":"ctrl+left","admin.shortcut.editor.cut_selected_segment":"backspace","player.shortcut.controls.seekRight":"right","admin.shortcut.editor.play_current_segment":"c","logo_player":"https:\/\/electures.uni-muenster.de\/images\/electures-logo.svg","admin.shortcut.general.remove_filters":"r","player":"\/engage\/theodul\/ui\/core.html","player.piwik.server":"https:\/\/piwik.uni-muenster.de","player.shortcut.volume.down":"8","admin.shortcut.general.main_menu":"m","engageui.link_download.enable":"false","engageui.links_media_module.enable":"true","engageui.link_mobile_redirect.enable":"false","login.display_defaults":"false","show_embed_links":"false","admin.shortcut.player.volume_up":"+","player.layout":"beside","link_mediamodule":"true","player.shortcut.fullscreen.enable":"mod+enter","admin.shortcut.player.previous_frame":"left","admin.shortcut.player.play_pause":"space","player.shortcut.volume.muteToggle":"m","admin.shortcut.player.volume_down":"-","engageui.link_mobile_redirect.url":"http:\/\/opencast.org\/","admin.shortcut.player.previous_segment":"up","org.opencastproject.oaipmh.server.hosturl":"https:\/\/electures.uni-muenster.de","player.shortcut.zoom.moveDown":"s","player.shortcut.layout.togglePiP":"o","admin.shortcut.player.step_forward":"ctrl+right"}},"roles":["ROLE_ANONYMOUS"],"userRole":"ROLE_USER_ANONYMOUS","user":{"provider":null,"name":null,"email":null,"username":"anonymous"}}
\ No newline at end of file
+{
+  "org": {
+    "anonymousRole": "ROLE_ANONYMOUS",
+    "name": "Opencast Project",
+    "adminRole": "ROLE_ADMIN",
+    "id": "mh_default_org",
+    "properties": {
+      "admin.shortcut.general.series_view": "s",
+      "admin.shortcut.editor.split_at_current_time": "v",
+      "player.shortcut.controls.nextChapter": "pageup",
+      "engageui.annotations.enable": "true",
+      "player.shortcut.controls.jumpToBegin": "backspace",
+      "admin.shortcut.general.select_previous_dashboard_filter": "F",
+      "admin.shortcut.player.mute": "m",
+      "admin.shortcut.editor.play_ending_of_current_segment": "n",
+      "player.mastervideotype": "presenter\/delivery",
+      "player.shortcut.layout.focusPrev": "<",
+      "org.opencastproject.admin.help.documentation.url": "http:\/\/docs.opencast.org",
+      "player.shortcut.controls.prevChapter": "pagedown",
+      "player.positioncontrols": "bottom",
+      "player.shortcut.zoom.moveLeft": "a",
+      "admin.shortcut.general.event_view": "e",
+      "admin.shortcut.editor.clear_list": "ctrl+backspace",
+      "adminui.user.external_role_display": "false",
+      "admin.shortcut.general.help": "?",
+      "logo_mediamodule": "\/engage\/ui\/img\/logo\/opencast-icon.svg",
+      "org.opencastproject.admin.help.restdocs.url": "\/rest_docs.html",
+      "admin.shortcut.general.new_series": "N",
+      "engageui.link_mobile_redirect.description": "For more information have a look at the official site.",
+      "player.shortcut.zoom.moveRight": "d",
+      "player.hide_video_context_menu": "false",
+      "player.shortcut.layout.movePiP": "p",
+      "player.shortcut.playbackrate.decrease": "T",
+      "admin.shortcut.general.select_next_dashboard_filter": "f",
+      "player.shortcut.zoom.in": "+",
+      "admin.shortcut.player.next_segment": "down",
+      "admin.shortcut.general.new_event": "n",
+      "player.shortcut.controls.playPause": "space",
+      "admin.shortcut.player.next_frame": "right",
+      "player.shortcut.fullscreen.cancel": "escape",
+      "org.opencastproject.admin.mediamodule.url": "\/engage\/ui",
+      "player.focusedflavor": "presentation",
+      "player.allowedtags": "engage-download,engage-streaming",
+      "player.shortcut.zoom.moveUp": "w",
+      "player.shortcut.zoom.out": "-",
+      "player.shortcut.layout.focusNext": ">",
+      "player.shortcut-sequence": "controls,volume,playbackrate,layout,zoom,fullscreen",
+      "player.shortcut.controls.seekLeft": "left",
+      "player.shortcut.playbackrate.increase": "t",
+      "admin.shortcut.editor.play_current_segment_with_pre-roll": "C",
+      "player.shortcut.volume.up": "9",
+      "adminui.chunksize": "2048",
+      "admin.shortcut.editor.cut_selected_segment": "backspace",
+      "admin.shortcut.player.step_backward": "ctrl+left",
+      "player.shortcut.controls.seekRight": "right",
+      "admin.shortcut.editor.play_current_segment": "c",
+      "logo_player": "\/engage\/theodul\/ui\/img\/opencast.svg",
+      "admin.shortcut.general.remove_filters": "r",
+      "player": "\/engage\/theodul\/ui\/core.html",
+      "player.shortcut.volume.down": "8",
+      "admin.shortcut.general.main_menu": "m",
+      "engageui.link_download.enable": "false",
+      "engageui.links_media_module.enable": "true",
+      "engageui.link_mobile_redirect.enable": "false",
+      "login.display_defaults": "true",
+      "show_embed_links": "true",
+      "admin.shortcut.player.volume_up": "+",
+      "player.layout": "off",
+      "link_mediamodule": "true",
+      "admin.shortcut.player.previous_frame": "left",
+      "player.shortcut.fullscreen.enable": "mod+enter",
+      "admin.shortcut.player.play_pause": "space",
+      "player.shortcut.volume.muteToggle": "m",
+      "admin.shortcut.player.volume_down": "-",
+      "admin.shortcut.player.previous_segment": "up",
+      "engageui.link_mobile_redirect.url": "http:\/\/opencast.org\/",
+      "org.opencastproject.oaipmh.server.hosturl": "",
+      "player.shortcut.layout.togglePiP": "o",
+      "admin.shortcut.player.step_forward": "ctrl+right",
+      "player.shortcut.zoom.moveDown": "s"
+    }
+  },
+  "roles": [
+    "ROLE_ANONYMOUS"
+  ],
+  "userRole": "ROLE_USER_ANONYMOUS",
+  "user": {
+    "provider": null,
+    "name": null,
+    "email": null,
+    "username": "anonymous"
+  }
+}
\ No newline at end of file
diff --git a/lang/en/filter_opencast.php b/lang/en/filter_opencast.php
index 423691e..c1b263b 100644
--- a/lang/en/filter_opencast.php
+++ b/lang/en/filter_opencast.php
@@ -26,4 +26,6 @@ defined('MOODLE_INTERNAL') || die();
 $string['filtername'] = 'Opencast';
 $string['pluginname'] = 'Opencast Filter';
 $string['setting_issuer'] = 'Issuer';
-$string['setting_issuer_desc'] = 'Issuer Desc';
\ No newline at end of file
+$string['setting_issuer_desc'] = 'Issuer Desc';
+$string['setting_baseurlapi'] = 'Opencast API url';
+$string['setting_baseurlapi_desc'] = 'Setup the base url of the Opencast system, for example: opencast.example.com';
\ No newline at end of file
diff --git a/lib.php b/lib.php
index 19fd05e..a02bb57 100644
--- a/lib.php
+++ b/lib.php
@@ -14,6 +14,8 @@
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
+require_once($CFG->dirroot.'/mod/lti/locallib.php');
+
 /**
  * Opencast library functions.
  *
@@ -25,7 +27,93 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-function filter_opencast_load_player() {
+function filter_opencast_load_meInfo() {
+    global $CFG, $PAGE;
+
+    $urlparts = parse_url($CFG->wwwroot);
+    $orgid = $urlparts['host'];
+
+    $endpoint = 'http://localhost:8080/lti';
+
+    $instance = new stdClass();
+    $instance->course = 2;
+    $instance->typeid = 2;
+    $instance->launchcontainer = 1;
+    $instance->id = 101;
+    $instance->name = 'Opencast';
+    $instance->servicesalt = '5a685957417926.81276553';
+
+    $typeid = 2;
+    $tool = new stdClass();
+    $tool->baseurl = 'http://localhost:8080/lti';
+    $tool->tooldomain = 'localhost:8080';
+    $tool->state = 1;
+    $tool->course = 2;
+    $tool->coursevisible = 1;
+
+    $typeconfig = array();
+    $typeconfig['resourcekey'] = 'myconsumerkey';
+    $typeconfig['password'] = 'myconsumersecret';
+    $typeconfig['sendname'] = 1;
+    $typeconfig['sendemailaddr'] = 1;
+    $typeconfig['acceptgrades'] = 1;
+
+    $urlparts = parse_url($CFG->wwwroot);
+    $typeconfig['organizationid'] = $urlparts['host'];
+
+    $key = $typeconfig['resourcekey'];
+    $secret = $typeconfig['password'];
+    $endpoint = $tool->baseurl;
+    $orgid = $typeconfig['organizationid'];
+    $course = $PAGE->course;
+    $islti2 = isset($tool->toolproxyid);
+
+    $requestparams = lti_build_request($instance, $typeconfig, $course);
+    $requestparams = array_merge($requestparams, lti_build_standard_request($instance, $orgid, $islti2));
+    $launchcontainer = lti_get_launch_container($instance, $typeconfig);
+
+    $target = '';
+    switch($launchcontainer) {
+        case LTI_LAUNCH_CONTAINER_EMBED:
+        case LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS:
+            $target = 'iframe';
+            break;
+        case LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW:
+            $target = 'frame';
+            break;
+        case LTI_LAUNCH_CONTAINER_WINDOW:
+            $target = 'window';
+            break;
+    }
+    if (!empty($target)) {
+        $requestparams['launch_presentation_document_target'] = $target;
+    }
+
+    $requestparams['launch_presentation_return_url'] = $PAGE->url->out();
+    $parms = lti_sign_parameters($requestparams, $endpoint, "POST", $key, $secret);
+
+    $content = "<form action=\"" . $endpoint .
+        "\" name=\"ltiLaunchForm\" id=\"ltiLaunchForm\" method=\"post\" encType=\"application/x-www-form-urlencoded\">\n";
+
+    // Contruct html for the launch parameters.
+    foreach ($parms as $key => $value) {
+        $key = htmlspecialchars($key);
+        $value = htmlspecialchars($value);
+        $content .= "<input type=\"hidden\" name=\"{$key}\"";
+        $content .= " value=\"";
+        $content .= $value;
+        $content .= "\"/>\n";
+    }
+    $content .= "</form>\n";
+
+    echo $content;
+    $PAGE->requires->js_call_amd('filter_opencast/form','init');
+}
+
+function filter_opencast_load_episode($service, $id) {
     global $CFG;
-    return '<iframe src="'.$CFG->wwwroot.'/filter/opencast/player/core.html"></iframe>';
+    // Get episode.json
+    $params = ['id' => $id];
+    $episode = $service->call('episode', $params);
+    file_put_contents($CFG->dirroot . '\filter\opencast\info\episode.json', $episode);
 }
\ No newline at end of file
diff --git a/player/js/engage/models/meInfo.js b/player/js/engage/models/meInfo.js
index 73aa6bc..bb90222 100644
--- a/player/js/engage/models/meInfo.js
+++ b/player/js/engage/models/meInfo.js
@@ -20,7 +20,7 @@
  */
 /*jslint browser: true, nomen: true*/
 /*global define, CustomEvent*/
-define(['jquery', 'backbone'], function($, Backbone) {
+define(['jquery', 'backbone'], function ($, Backbone) {
     "use strict";
 
     var prop_shortcut = "player.shortcut.",
@@ -47,8 +47,17 @@ define(['jquery', 'backbone'], function($, Backbone) {
      * Model with information about the current user and the current MH configuration
      */
     var MeInfoModel = Backbone.Model.extend({
-        urlRoot: "../info/me.json",
-        initialize: function() {
+        urlRoot: opencastlink+"/info/me.json",
+        sync: function(method, model, options) {
+            options ||(options = {});
+
+            options.type = 'get';
+            options.crossDomain = true;
+            options.xhrFields = {withCredentials:true};
+
+            return Backbone.sync(method, model, options);
+        },
+        initialize: function () {
             this.fetch({
                 success: function(me) {
                     var shortcuts = new Array(),
@@ -69,7 +78,7 @@ define(['jquery', 'backbone'], function($, Backbone) {
                         piwik_track_events;
                     if (me && me.attributes && me.attributes.org && me.attributes.org.properties) {
                         // extract shortcuts
-                        $.each(me.attributes.org.properties, function(key, value) {
+                        $.each(me.attributes.org.properties, function (key, value) {
                             var name = key.substring(prop_shortcut.length, key.length);
                             // shortcuts
                             if ((key.indexOf(prop_shortcut) != -1) && (name.length > 0) && value) {
@@ -124,20 +133,20 @@ define(['jquery', 'backbone'], function($, Backbone) {
                             }
                             // hide video context menu
                             else if ((key == prop_hide_video_context_menu) && value) {
-                              if (value.trim() == "true") hide_video_context_menu = true;
+                                if (value.trim() == "true") hide_video_context_menu = true;
                             }
                             // Piwik-Settings
                             else if ((key == prop_piwik_server) && value) {
-                              piwik_server = value;
+                                piwik_server = value;
                             }
                             else if ((key == prop_piwik_site_id) && value) {
-                              piwik_site_id = value;
+                                piwik_site_id = value;
                             }
                             else if ((key == prop_piwik_heartbeat) && value) {
-                              piwik_heartbeat = value;
+                                piwik_heartbeat = value;
                             }
                             else if ((key == prop_piwik_track_events) && value) {
-                              piwik_track_events = value;
+                                piwik_track_events = value;
                             }
                         });
                     }
@@ -161,10 +170,10 @@ define(['jquery', 'backbone'], function($, Backbone) {
                 }
             });
         },
-        ready: function() {
+        ready: function () {
             return ready;
         },
-        getPositionControls: function() {
+        getPositionControls: function () {
             return positioncontrols;
         }
     });
diff --git a/player/js/engage_init.js b/player/js/engage_init.js
index 9280d50..368a184 100644
--- a/player/js/engage_init.js
+++ b/player/js/engage_init.js
@@ -38,5 +38,6 @@ requirejs.config({
 });
 
 var PLUGIN_PATH = "../../plugin/";
+var opencastlink = "http://localhost:8080";
 // start core logic
 require(["engage/core"]);
diff --git a/player/plugin/controls/main.js b/player/plugin/controls/main.js
index 32e95a5..911ea88 100644
--- a/player/plugin/controls/main.js
+++ b/player/plugin/controls/main.js
@@ -21,1573 +21,1577 @@
 /*jslint browser: true, nomen: true*/
 /*global define*/
 define(['require', 'jquery', 'underscore', 'backbone', 'basil', 'bootbox', 'engage/core'], function (require, $, _, Backbone, Basil, Bootbox, Engage) {
-  'use strict';
-
-  var insertIntoDOM = true;
-  var PLUGIN_NAME = 'Engage Controls';
-  var PLUGIN_TYPE = 'engage_controls';
-  var PLUGIN_VERSION = '1.0';
-  var PLUGIN_TEMPLATE_DESKTOP = Engage.controls_top ? 'templates/desktop_top.html' : 'templates/desktop_bottom.html';
-  // provide this additional template if the controls are below the video to have content above the video
-  var PLUGIN_TEMPLATE_DESKTOP_TOP_IFBOTTOM = Engage.controls_top ? 'none' : 'templates/desktop_top_ifbottom.html';
-  var PLUGIN_TEMPLATE_EMBED = 'templates/embed.html';
-  var PLUGIN_TEMPLATE_MOBILE = 'templates/mobile.html';
-  var PLUGIN_STYLES_DESKTOP = [
-    Engage.controls_top ? 'styles/desktop_top.css' : 'styles/desktop_bottom.css',
-    'lib/jqueryui/jquery-ui.min.css'
-  ];
-  var PLUGIN_STYLES_EMBED = [
-    'styles/embed.css',
-    'lib/jqueryui/jquery-ui.min.css'
-  ];
-  var PLUGIN_STYLES_MOBILE = [
-    'styles/mobile.css',
-    'lib/jqueryui/jquery-ui.min.css'
-  ];
-
-  var basilOptions = {
-    namespace: 'mhStorage'
-  };
-  Basil = new window.Basil(basilOptions);
-
-  var plugin;
-  var events = {
-    play: new Engage.Event('Video:play', 'plays the video', 'both'),
-    pause: new Engage.Event('Video:pause', 'pauses the video', 'both'),
-    playPause: new Engage.Event('Video:playPause', '', 'trigger'),
-    fullscreenEnable: new Engage.Event('Video:fullscreenEnable', '', 'both'),
-    mute: new Engage.Event('Video:mute', '', 'both'),
-    unmute: new Engage.Event('Video:unmute', '', 'both'),
-    muteToggle: new Engage.Event('Video:muteToggle', '', 'both'),
-    segmentMouseover: new Engage.Event('Segment:mouseOver', 'the mouse is over a segment', 'both'),
-    segmentMouseout: new Engage.Event('Segment:mouseOut', 'the mouse is off a segment', 'both'),
-    volumeSet: new Engage.Event('Video:volumeSet', '', 'both'),
-    playbackRateChanged: new Engage.Event('Video:playbackRateChanged', 'The video playback rate changed', 'both'),
-    fullscreenCancel: new Engage.Event('Video:fullscreenCancel', '', 'both'),
-    sliderStart: new Engage.Event('Slider:start', '', 'trigger'),
-    sliderStop: new Engage.Event('Slider:stop', '', 'trigger'),
-    sliderMousein: new Engage.Event('Slider:mouseIn', 'the mouse entered the slider', 'trigger'),
-    sliderMouseout: new Engage.Event('Slider:mouseOut', 'the mouse is off the slider', 'trigger'),
-    sliderMousemove: new Engage.Event('Slider:mouseMoved', 'the mouse is moving over the slider', 'trigger'),
-    seek: new Engage.Event('Video:seek', 'seek video to a given position in seconds', 'trigger'),
-    seekLeft: new Engage.Event('Video:seekLeft', '', 'trigger'),
-    seekRight: new Engage.Event('Video:seekRight', '', 'trigger'),
-    nextChapter: new Engage.Event('Video:nextChapter', '', 'trigger'),
-    previousChapter: new Engage.Event('Video:previousChapter', '', 'trigger'),
-    customOKMessage: new Engage.Event('Notification:customOKMessage', 'a custom message with an OK button', 'trigger'),
-    customSuccess: new Engage.Event('Notification:customSuccess', 'a custom success message', 'trigger'),
-    customError: new Engage.Event('Notification:customError', 'an error occurred', 'trigger'),
-    qualitySet: new Engage.Event('Video:qualitySet', '', 'trigger'),
-    volumeUp: new Engage.Event('Video:volumeUp', '', 'handler'),
-    volumeDown: new Engage.Event('Video:volumeDown', '', 'handler'),
-    plugin_load_done: new Engage.Event('Core:plugin_load_done', '', 'handler'),
-    fullscreenChange: new Engage.Event('Video:fullscreenChange', 'notices a fullscreen change', 'handler'),
-    ready: new Engage.Event('Video:ready', 'all videos loaded successfully', 'both'),
-    timeupdate: new Engage.Event('Video:timeupdate', 'notices a timeupdate', 'handler'),
-    ended: new Engage.Event('Video:ended', 'end of the video', 'handler'),
-    usingFlash: new Engage.Event('Video:usingFlash', 'flash is being used', 'handler'),
-    mediaPackageModelError: new Engage.Event('MhConnection:mediaPackageModelError', '', 'handler'),
-    aspectRatioSet: new Engage.Event('Video:aspectRatioSet', 'the aspect ratio has been calculated', 'handler'),
-    isAudioOnly: new Engage.Event('Video:isAudioOnly', 'whether it`s audio only or not', 'handler'),
-    videoFormatsFound: new Engage.Event('Video:videoFormatsFound', '', 'both'),
-    numberOfVideodisplaysSet: new Engage.Event('Video:numberOfVideodisplaysSet', 'the number of videodisplays has been set', 'trigger'),
-    focusVideo: new Engage.Event('Video:focusVideo', 'increases the size of one video', 'handler'),
-    resetLayout: new Engage.Event('Video:resetLayout', 'resets the layout of the videodisplays', 'handler'),
-    movePiP: new Engage.Event('Video:movePiP', 'moves the smaller picture over the larger to the different corners', 'handler'),
-    togglePiP: new Engage.Event('Video:togglePiP', 'switches between PiP and next to each other layout', 'both'),
-    setZoomLevel: new Engage.Event('Video:setZoomLevel', 'sets the zoom level', 'trigger'),
-    zoomReset: new Engage.Event('Video:resetZoom', 'resets position and zoom level', 'trigger'),
-    zoomChange: new Engage.Event('Video:zoomChange', 'zoom level has changed', 'handler'),
-    toggleCaptions: new Engage.Event('Video:toggleCaptions', 'toggle captions', 'trigger'),
-    captionsFound: new Engage.Event('Video:captionsFound', 'captions found', 'handler'),
-    // events for mobile view
-    switchVideo: new Engage.Event('Video:switch', 'switch the video', 'trigger'),
-    showControls: new Engage.Event('Controls:show', 'show the controls', 'both'),
-    hideControls: new Engage.Event('Controls:hide', 'hide the controls', 'both')
-  };
-
-  var isDesktopMode = false;
-  var isEmbedMode = false;
-  var isMobileMode = false;
-
-  // desktop, embed and mobile logic
-  switch (Engage.model.get('mode')) {
-    case 'embed':
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_EMBED,
-        template: PLUGIN_TEMPLATE_EMBED,
-        events: events
-      };
-      isEmbedMode = true;
-      break;
-    case 'mobile':
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_MOBILE,
-        template: PLUGIN_TEMPLATE_MOBILE,
-        events: events
-      };
-      isMobileMode = true;
-      break;
-    case 'desktop':
-    default:
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_DESKTOP,
-        template: PLUGIN_TEMPLATE_DESKTOP,
-        template_topIfBottom: PLUGIN_TEMPLATE_DESKTOP_TOP_IFBOTTOM,
-        events: events
-      };
-      isDesktopMode = true;
-      break;
-  }
-
-  /* change these variables */
-  var embedHeightOne = 280;
-  var embedHeightTwo = 315;
-  var embedHeightThree = 360;
-  var embedHeightFour = 480;
-  var embedHeightFive = 720;
-  var min_segment_duration = 5000;
-  var logoLink = false;
-  var plugin_path = 'plugin/controls/';
-  var logo = plugin_path + 'images/logo.png';
-  var showEmbed = true;
-  // mobile mode: time after controls are hidden again in seconds
-  var hideTimeout = 4;
-
-
-  /* don't change these variables */
-  var Utils;
-  var volUpDown = 5.0;
-  var storage_volume = 'volume';
-  var storage_lastvolume = 'lastvolume';
-  var storage_muted = 'muted';
-  var storage_pip = 'pictureinpicture';
-  var storage_pip_pos = 'pictureinpictureposition';
-  var storage_focus_video = 'focusvideo';
-  var jQueryUIPath = 'lib/jqueryui/jquery-ui';
-  var id_zoomLevelIndicator = 'zoomLevelIndicator';
-  var id_zoomReset = 'resetZoom';
-  var id_zoomLevel1 = 'zoomLevel1';
-  var id_zoomLevel2 = 'zoomLevel2';
-  var id_zoomLevel3 = 'zoomLevel3';
-  var id_captions_button = 'captions_button';
-  var id_engage_controls = 'engage_controls';
-  var id_engage_controls_topIfBottom = 'engage_controls_second';
-  var id_slider = 'slider';
-  var id_volumeSlider = 'volumeSlider';
-  var id_volumeIcon = 'volumeIcon';
-  var id_dropdownMenuPlaybackRate = 'dropdownMenuPlaybackRate';
-  var id_playbackRate075 = 'playback075';
-  var id_playbackRate100 = 'playback100';
-  var id_playbackRate125 = 'playback125';
-  var id_playbackRate150 = 'playback150';
-  var id_playbackRate200 = 'playback200';
-  var id_playbackRate300 = 'playback300';
-  var id_pipIndicator = 'pipIndicator';
-  var id_pipLeft = 'pipLeft';
-  var id_pipRight = 'pipRight';
-  var id_pipBeside = 'pipBeside';
-  var id_pipOff = 'pipOff';
-  var id_qualityIndicator = 'qualityIndicator';
-  var id_playpause_controls = 'playpause_controls';
-  var id_fullscreen_button = 'fullscreen_button';
-  var id_embed_button = 'embed_button';
-  var id_backward_button = 'backward_button';
-  var id_forward_button = 'forward_button';
-  var id_navigation_time = 'navigation_time';
-  var id_navigation_time_current = 'navigation_time_current';
-  var id_big_play_button = 'big_play_button';
-  var id_play_button = 'play_button';
-  var id_pause_button = 'pause_button';
-  var id_unmute_button = 'unmute_button';
-  var id_mute_button = 'mute_button';
-  var id_segmentNo = 'segment_';
-  var id_embed0 = 'embed0';
-  var id_embed1 = 'embed1';
-  var id_embed2 = 'embed2';
-  var id_embed3 = 'embed3';
-  var id_embed4 = 'embed4';
-  var id_playbackRateIndicator = 'playbackRateIndicator';
-  var id_playbackRemTime075 = 'playbackRemTime075';
-  var id_playbackRemTime100 = 'playbackRemTime100';
-  var id_playbackRemTime125 = 'playbackRemTime125';
-  var id_playbackRemTime150 = 'playbackRemTime150';
-  var id_playbackRemTime200 = 'playbackRemTime200';
-  var id_playbackRemTime300 = 'playbackRemTime300';
-  var id_loggedInNotLoggedIn = 'loggedInNotLoggedIn';
-  var id_loginlogout = 'loginlogout';
-  var id_str_loginlogout = 'str_loginlogout';
-  var id_dropdownMenuLoginInfo = 'dropdownMenuLoginInfo';
-  var class_dropdown = 'dropdown-toggle';
-  var videosReady = false;
-  var enableFullscreenButton = false;
-  var currentTime = 0;
-  var videoDataModelChange = 'change:videoDataModel';
-  var infoMeChange = 'change:infoMe';
-  var mediapackageChange = 'change:mediaPackage';
-  var event_slidestart = 'slidestart';
-  var event_slidestop = 'slidestop';
-  var event_slide = 'slide';
-  var plugin_path = '';
-  var initCount = 5;
-  if (isMobileMode) {
-    initCount += 3;          // increase initCount, because mobile version loads 3 more libs
-  }
-  var inited = false;
-  var isPlaying = false;
-  var isSliding = false;
-  var duration;
-  var usingFlash = false;
-  var isAudioOnly = false;
-  var segments = {};
-  var mediapackageError = false;
-  var aspectRatioTriggered = false;
-  var aspectRatioWidth;
-  var aspectRatioHeight;
-  var aspectRatio;
-  var embedWidthOne;
-  var embedWidthTwo;
-  var embedWidthThree;
-  var embedWidthFour;
-  var embedWidthFive;
-  var loggedIn = false;
-  var username = 'Anonymous';
-  var translations = new Array();
-  var askedForLogin = false;
-  var springSecurityLoginURL = '/j_spring_security_check';
-  var springSecurityLogoutURL = '/j_spring_security_logout';
-  var springLoggedInStrCheck = '<title>Opencast – Login Page</title>';
-  var controlsViewTopIfBottom = undefined;
-  var controlsView = undefined;
-  var resolutions = undefined;
-  var pipPos = 'left';
-  var pipStatus = true;
-  var numberVideos = 1;
-  var currentFocusFlavor = 'focus.none';
-  var videosInitialReadyness = true;
-  // for mobile view
-  var id_videoWrapper = 'video_wrapper';
-  var id_gestureContainer = 'engage_video';
-  var controlsVisible = true;
-  var controlsTimer = null;
-  var carousel = null;
-  var captionsOn = false;
-
-  function initTranslate(language, funcSuccess, funcError) {
-    var path = Engage.getPluginPath('EngagePluginControls').replace(/(\.\.\/)/g, '');
-    var jsonstr = path; // this solution is really bad, fix it...
-
-    Engage.log('Controls: selecting language ' + language);
-    jsonstr += 'language/' + language + '.json';
-
-    $.ajax({
-      url: jsonstr,
-      dataType: 'json',
-      success: function (data) {
-        if (data) {
-          data.value_locale = language;
-          translations = data;
-          if (funcSuccess) {
-            funcSuccess(translations);
-          }
-        } else if (funcError) {
-          funcError();
-        }
-      },
-      error: function () {
-        if (funcError) {
-          funcError();
-        }
-      }
-    });
-  }
-
-  function translate(str, strIfNotFound) {
-    return (translations[str] != undefined) ? translations[str] : strIfNotFound;
-  }
-
-  function login() {
-    if (!askedForLogin) {
-      askedForLogin = true;
-      var username = 'User';
-      var password = 'Password';
-
-      Bootbox.dialog({
-        title: translate('loginInformation', 'Log in'),
-        message: '<form class="form-signin">' +
-        '<h2 class="form-signin-heading">' + translate('enterUsernamePassword', 'Please enter your username and password') + '</h2>' +
-        '<input id="username" type="text" class="form-control form-control-custom" name="username" placeholder="' + translate('username', 'Username') + '" required="true" autofocus="" />' +
-        '<input id="password" type="password" class="form-control form-control-custom" name="password" placeholder="' + translate('password', 'Password') + '" required="true" />' +
-        '<label class="checkbox">' +
-        '<input type="checkbox" value="' + translate('rememberMe', 'Remember me') + '" id="rememberMe" name="rememberMe" checked> ' + translate('rememberMe', 'Remember me') +
-        '</label>' +
-        '</form>',
-        buttons: {
-          cancel: {
-            label: translate('cancel', 'Cancel'),
-            className: 'btn-default',
-            callback: function () {
-              askedForLogin = false;
-            }
-          },
-          login: {
-            label: translate('login', 'Log in'),
-            className: 'btn-success',
-            callback: function () {
-              var username = $('#username').val().trim();
-              var password = $('#password').val().trim();
-              if ((username !== null) && (username.length > 0) && (password !== null) && (password.length > 0)) {
-                $.ajax({
-                  type: 'POST',
-                  url: springSecurityLoginURL,
-                  data: {
-                    'j_username': username,
-                    'j_password': password,
-                    '_spring_security_remember_me': $('#rememberMe').is(':checked')
-                  }
-                }).done(function (msg) {
-                  password = '';
-                  if (msg.indexOf(springLoggedInStrCheck) == -1) {
-                    Engage.trigger(events.customSuccess.getName(), translate('loginSuccessful', 'Successfully logged in. Please reload the page if the page does not reload automatically.'));
-                    location.reload();
-                  } else {
-                    Engage.trigger(events.customSuccess.getName(), translate('loginFailed', 'Failed to log in.'));
-                  }
-                  askedForLogin = false;
-                }).fail(function (msg) {
-                  password = '';
-                  Engage.trigger(events.customSuccess.getName(), translate('loginFailed', 'Failed to log in.'));
-                  askedForLogin = false;
-                });
-              } else {
-                askedForLogin = false;
-              }
+    'use strict';
+
+    var insertIntoDOM = true;
+    var PLUGIN_NAME = 'Engage Controls';
+    var PLUGIN_TYPE = 'engage_controls';
+    var PLUGIN_VERSION = '1.0';
+    var PLUGIN_TEMPLATE_DESKTOP = Engage.controls_top ? 'templates/desktop_top.html' : 'templates/desktop_bottom.html';
+    // provide this additional template if the controls are below the video to have content above the video
+    // var PLUGIN_TEMPLATE_DESKTOP_TOP_IFBOTTOM = Engage.controls_top ? 'none' : 'templates/desktop_top_ifbottom.html';
+    // Delete content above the video
+    var PLUGIN_TEMPLATE_DESKTOP_TOP_IFBOTTOM = 'none';
+    var PLUGIN_TEMPLATE_EMBED = 'templates/embed.html';
+    var PLUGIN_TEMPLATE_MOBILE = 'templates/mobile.html';
+    var PLUGIN_STYLES_DESKTOP = [
+        Engage.controls_top ? 'styles/desktop_top.css' : 'styles/desktop_bottom.css',
+        'lib/jqueryui/jquery-ui.min.css'
+    ];
+    var PLUGIN_STYLES_EMBED = [
+        'styles/embed.css',
+        'lib/jqueryui/jquery-ui.min.css'
+    ];
+    var PLUGIN_STYLES_MOBILE = [
+        'styles/mobile.css',
+        'lib/jqueryui/jquery-ui.min.css'
+    ];
+
+    var basilOptions = {
+        namespace: 'mhStorage'
+    };
+    Basil = new window.Basil(basilOptions);
+
+    var plugin;
+    var events = {
+        play: new Engage.Event('Video:play', 'plays the video', 'both'),
+        pause: new Engage.Event('Video:pause', 'pauses the video', 'both'),
+        playPause: new Engage.Event('Video:playPause', '', 'trigger'),
+        fullscreenEnable: new Engage.Event('Video:fullscreenEnable', '', 'both'),
+        mute: new Engage.Event('Video:mute', '', 'both'),
+        unmute: new Engage.Event('Video:unmute', '', 'both'),
+        muteToggle: new Engage.Event('Video:muteToggle', '', 'both'),
+        segmentMouseover: new Engage.Event('Segment:mouseOver', 'the mouse is over a segment', 'both'),
+        segmentMouseout: new Engage.Event('Segment:mouseOut', 'the mouse is off a segment', 'both'),
+        volumeSet: new Engage.Event('Video:volumeSet', '', 'both'),
+        playbackRateChanged: new Engage.Event('Video:playbackRateChanged', 'The video playback rate changed', 'both'),
+        fullscreenCancel: new Engage.Event('Video:fullscreenCancel', '', 'both'),
+        sliderStart: new Engage.Event('Slider:start', '', 'trigger'),
+        sliderStop: new Engage.Event('Slider:stop', '', 'trigger'),
+        sliderMousein: new Engage.Event('Slider:mouseIn', 'the mouse entered the slider', 'trigger'),
+        sliderMouseout: new Engage.Event('Slider:mouseOut', 'the mouse is off the slider', 'trigger'),
+        sliderMousemove: new Engage.Event('Slider:mouseMoved', 'the mouse is moving over the slider', 'trigger'),
+        seek: new Engage.Event('Video:seek', 'seek video to a given position in seconds', 'trigger'),
+        seekLeft: new Engage.Event('Video:seekLeft', '', 'trigger'),
+        seekRight: new Engage.Event('Video:seekRight', '', 'trigger'),
+        nextChapter: new Engage.Event('Video:nextChapter', '', 'trigger'),
+        previousChapter: new Engage.Event('Video:previousChapter', '', 'trigger'),
+        customOKMessage: new Engage.Event('Notification:customOKMessage', 'a custom message with an OK button', 'trigger'),
+        customSuccess: new Engage.Event('Notification:customSuccess', 'a custom success message', 'trigger'),
+        customError: new Engage.Event('Notification:customError', 'an error occurred', 'trigger'),
+        qualitySet: new Engage.Event('Video:qualitySet', '', 'trigger'),
+        volumeUp: new Engage.Event('Video:volumeUp', '', 'handler'),
+        volumeDown: new Engage.Event('Video:volumeDown', '', 'handler'),
+        plugin_load_done: new Engage.Event('Core:plugin_load_done', '', 'handler'),
+        fullscreenChange: new Engage.Event('Video:fullscreenChange', 'notices a fullscreen change', 'handler'),
+        ready: new Engage.Event('Video:ready', 'all videos loaded successfully', 'both'),
+        timeupdate: new Engage.Event('Video:timeupdate', 'notices a timeupdate', 'handler'),
+        ended: new Engage.Event('Video:ended', 'end of the video', 'handler'),
+        usingFlash: new Engage.Event('Video:usingFlash', 'flash is being used', 'handler'),
+        mediaPackageModelError: new Engage.Event('MhConnection:mediaPackageModelError', '', 'handler'),
+        aspectRatioSet: new Engage.Event('Video:aspectRatioSet', 'the aspect ratio has been calculated', 'handler'),
+        isAudioOnly: new Engage.Event('Video:isAudioOnly', 'whether it`s audio only or not', 'handler'),
+        videoFormatsFound: new Engage.Event('Video:videoFormatsFound', '', 'both'),
+        numberOfVideodisplaysSet: new Engage.Event('Video:numberOfVideodisplaysSet', 'the number of videodisplays has been set', 'trigger'),
+        focusVideo: new Engage.Event('Video:focusVideo', 'increases the size of one video', 'handler'),
+        resetLayout: new Engage.Event('Video:resetLayout', 'resets the layout of the videodisplays', 'handler'),
+        movePiP: new Engage.Event('Video:movePiP', 'moves the smaller picture over the larger to the different corners', 'handler'),
+        togglePiP: new Engage.Event('Video:togglePiP', 'switches between PiP and next to each other layout', 'both'),
+        setZoomLevel: new Engage.Event('Video:setZoomLevel', 'sets the zoom level', 'trigger'),
+        zoomReset: new Engage.Event('Video:resetZoom', 'resets position and zoom level', 'trigger'),
+        zoomChange: new Engage.Event('Video:zoomChange', 'zoom level has changed', 'handler'),
+        toggleCaptions: new Engage.Event('Video:toggleCaptions', 'toggle captions', 'trigger'),
+        captionsFound: new Engage.Event('Video:captionsFound', 'captions found', 'handler'),
+        // events for mobile view
+        switchVideo: new Engage.Event('Video:switch', 'switch the video', 'trigger'),
+        showControls: new Engage.Event('Controls:show', 'show the controls', 'both'),
+        hideControls: new Engage.Event('Controls:hide', 'hide the controls', 'both')
+    };
+
+    var isDesktopMode = false;
+    var isEmbedMode = false;
+    var isMobileMode = false;
+
+    // desktop, embed and mobile logic
+    switch (Engage.model.get('mode')) {
+        case 'embed':
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_EMBED,
+                template: PLUGIN_TEMPLATE_EMBED,
+                events: events
+            };
+            isEmbedMode = true;
+            break;
+        case 'mobile':
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_MOBILE,
+                template: PLUGIN_TEMPLATE_MOBILE,
+                events: events
+            };
+            isMobileMode = true;
+            break;
+        case 'desktop':
+        default:
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_DESKTOP,
+                template: PLUGIN_TEMPLATE_DESKTOP,
+                template_topIfBottom: PLUGIN_TEMPLATE_DESKTOP_TOP_IFBOTTOM,
+                events: events
+            };
+            isDesktopMode = true;
+            break;
+    }
+
+    /* change these variables */
+    var embedHeightOne = 280;
+    var embedHeightTwo = 315;
+    var embedHeightThree = 360;
+    var embedHeightFour = 480;
+    var embedHeightFive = 720;
+    var min_segment_duration = 5000;
+    var logoLink = false;
+    var plugin_path = 'plugin/controls/';
+    var logo = plugin_path + 'images/logo.png';
+    var showEmbed = true;
+    // mobile mode: time after controls are hidden again in seconds
+    var hideTimeout = 4;
+
+
+    /* don't change these variables */
+    var Utils;
+    var volUpDown = 5.0;
+    var storage_volume = 'volume';
+    var storage_lastvolume = 'lastvolume';
+    var storage_muted = 'muted';
+    var storage_pip = 'pictureinpicture';
+    var storage_pip_pos = 'pictureinpictureposition';
+    var storage_focus_video = 'focusvideo';
+    var jQueryUIPath = 'lib/jqueryui/jquery-ui';
+    var id_zoomLevelIndicator = 'zoomLevelIndicator';
+    var id_zoomReset = 'resetZoom';
+    var id_zoomLevel1 = 'zoomLevel1';
+    var id_zoomLevel2 = 'zoomLevel2';
+    var id_zoomLevel3 = 'zoomLevel3';
+    var id_captions_button = 'captions_button';
+    var id_engage_controls = 'engage_controls';
+    var id_engage_controls_topIfBottom = 'engage_controls_second';
+    var id_slider = 'slider';
+    var id_volumeSlider = 'volumeSlider';
+    var id_volumeIcon = 'volumeIcon';
+    var id_dropdownMenuPlaybackRate = 'dropdownMenuPlaybackRate';
+    var id_playbackRate075 = 'playback075';
+    var id_playbackRate100 = 'playback100';
+    var id_playbackRate125 = 'playback125';
+    var id_playbackRate150 = 'playback150';
+    var id_playbackRate200 = 'playback200';
+    var id_playbackRate300 = 'playback300';
+    var id_pipIndicator = 'pipIndicator';
+    var id_pipLeft = 'pipLeft';
+    var id_pipRight = 'pipRight';
+    var id_pipBeside = 'pipBeside';
+    var id_pipOff = 'pipOff';
+    var id_qualityIndicator = 'qualityIndicator';
+    var id_playpause_controls = 'playpause_controls';
+    var id_fullscreen_button = 'fullscreen_button';
+    var id_embed_button = 'embed_button';
+    var id_backward_button = 'backward_button';
+    var id_forward_button = 'forward_button';
+    var id_navigation_time = 'navigation_time';
+    var id_navigation_time_current = 'navigation_time_current';
+    var id_big_play_button = 'big_play_button';
+    var id_play_button = 'play_button';
+    var id_pause_button = 'pause_button';
+    var id_unmute_button = 'unmute_button';
+    var id_mute_button = 'mute_button';
+    var id_segmentNo = 'segment_';
+    var id_embed0 = 'embed0';
+    var id_embed1 = 'embed1';
+    var id_embed2 = 'embed2';
+    var id_embed3 = 'embed3';
+    var id_embed4 = 'embed4';
+    var id_playbackRateIndicator = 'playbackRateIndicator';
+    var id_playbackRemTime075 = 'playbackRemTime075';
+    var id_playbackRemTime100 = 'playbackRemTime100';
+    var id_playbackRemTime125 = 'playbackRemTime125';
+    var id_playbackRemTime150 = 'playbackRemTime150';
+    var id_playbackRemTime200 = 'playbackRemTime200';
+    var id_playbackRemTime300 = 'playbackRemTime300';
+    var id_loggedInNotLoggedIn = 'loggedInNotLoggedIn';
+    var id_loginlogout = 'loginlogout';
+    var id_str_loginlogout = 'str_loginlogout';
+    var id_dropdownMenuLoginInfo = 'dropdownMenuLoginInfo';
+    var class_dropdown = 'dropdown-toggle';
+    var videosReady = false;
+    var enableFullscreenButton = false;
+    var currentTime = 0;
+    var videoDataModelChange = 'change:videoDataModel';
+    var infoMeChange = 'change:infoMe';
+    var mediapackageChange = 'change:mediaPackage';
+    var event_slidestart = 'slidestart';
+    var event_slidestop = 'slidestop';
+    var event_slide = 'slide';
+    var plugin_path = '';
+    var initCount = 5;
+    if (isMobileMode) {
+        initCount += 3;          // increase initCount, because mobile version loads 3 more libs
+    }
+    var inited = false;
+    var isPlaying = false;
+    var isSliding = false;
+    var duration;
+    var usingFlash = false;
+    var isAudioOnly = false;
+    var segments = {};
+    var mediapackageError = false;
+    var aspectRatioTriggered = false;
+    var aspectRatioWidth;
+    var aspectRatioHeight;
+    var aspectRatio;
+    var embedWidthOne;
+    var embedWidthTwo;
+    var embedWidthThree;
+    var embedWidthFour;
+    var embedWidthFive;
+    var loggedIn = false;
+    var username = 'Anonymous';
+    var translations = new Array();
+    var askedForLogin = false;
+    var springSecurityLoginURL = '/j_spring_security_check';
+    var springSecurityLogoutURL = '/j_spring_security_logout';
+    var springLoggedInStrCheck = '<title>Opencast – Login Page</title>';
+    var controlsViewTopIfBottom = undefined;
+    var controlsView = undefined;
+    var resolutions = undefined;
+    var pipPos = 'left';
+    var pipStatus = true;
+    var numberVideos = 1;
+    var currentFocusFlavor = 'focus.none';
+    var videosInitialReadyness = true;
+    // for mobile view
+    var id_videoWrapper = 'video_wrapper';
+    var id_gestureContainer = 'engage_video';
+    var controlsVisible = true;
+    var controlsTimer = null;
+    var carousel = null;
+    var captionsOn = false;
+
+    function initTranslate(language, funcSuccess, funcError) {
+        var path = Engage.getPluginPath('EngagePluginControls').replace(/(\.\.\/)/g, '');
+        var jsonstr = path; // this solution is really bad, fix it...
+
+        Engage.log('Controls: selecting language ' + language);
+        jsonstr += 'language/' + language + '.json';
+
+        $.ajax({
+            url: jsonstr,
+            dataType: 'json',
+            success: function (data) {
+                if (data) {
+                    data.value_locale = language;
+                    translations = data;
+                    if (funcSuccess) {
+                        funcSuccess(translations);
+                    }
+                } else if (funcError) {
+                    funcError();
+                }
+            },
+            error: function () {
+                if (funcError) {
+                    funcError();
+                }
             }
-          }
-        },
-        className: 'usernamePassword-modal',
-        onEscape: function () {
-          askedForLogin = false;
-        },
-        closeButton: false
-      });
+        });
     }
-  }
-
-  function logout() {
-    Engage.trigger(events.customSuccess.getName(), translate('loggingOut', 'You are being logged out, please wait a moment.'));
-    $.ajax({
-      type: 'GET',
-      url: springSecurityLogoutURL,
-    }).complete(function (msg) {
-      location.reload();
-      Engage.trigger(events.customSuccess.getName(), translate('logoutSuccessful', 'Successfully logged out. Please reload the page if the page does not reload automatically.'));
-    });
-  }
-
-  function checkLoginStatus() {
-    $('#' + id_loginlogout).unbind('click');
-    if (Engage.model.get('infoMe').loggedIn) {
-      loggedIn = true;
-      username = Engage.model.get('infoMe').username;
-      $('#' + id_loggedInNotLoggedIn).html(username);
-      $('#' + id_str_loginlogout).html(translate('logout', 'Log out'));
-      $('#' + id_loginlogout).click(logout);
-    } else {
-      loggedIn = false;
-      username = 'Anonymous';
-      $('#' + id_loggedInNotLoggedIn).html(translate('loggedOut', 'Logged out'));
-      $('#' + id_str_loginlogout).html(translate('login', 'Log in'));
-      $('#' + id_loginlogout).click(login);
+
+    function translate(str, strIfNotFound) {
+        return (translations[str] != undefined) ? translations[str] : strIfNotFound;
     }
-    $('#' + id_dropdownMenuLoginInfo).removeClass('disabled');
-  }
-
-  var ControlsView = Backbone.View.extend({
-    el: $('#' + id_engage_controls), // every view has an element associated with it
-    initialize: function (videoDataModel, template, plugin_path) {
-      this.setElement($(plugin.container));
-      this.model = videoDataModel;
-      this.template = template;
-      this.pluginPath = plugin_path;
-
-      // bind the render function always to the view
-      _.bindAll(this, 'render');
-      // listen for changes of the model and bind the render function to this
-      this.model.bind('change', this.render);
-      this.render();
-    },
-    render: function () {
-      if (!mediapackageError) {
-        duration = parseInt(this.model.get('duration'));
-        segments = Engage.model.get('mediaPackage').get('segments');
-
-        var pipPosition = pipPos;
-        if (!pipStatus) {
-          pipPosition = 'beside';
-        }
 
-        segments = Utils.repairSegmentLength(segments, duration, min_segment_duration);
-
-        if (Engage.model.get('meInfo')) {
-          if (Engage.model.get('meInfo').get('logo_player')) {
-            logo = Engage.model.get('meInfo').get('logo_player');
-          }
-          if (Engage.model.get('meInfo').get('link_mediamodule')) {
-            logoLink = window.location.protocol + '//' + window.location.host + '/engage/ui/index.html'; // link to the media module
-          }
-          if (!Engage.model.get('meInfo').get('show_embed_links')) {
-            showEmbed = false;
-          }
-        }
-        var translatedQualities = new Array();
-        if (resolutions) {
-          for (var i = 0; i < resolutions.length; i++) {
-            translatedQualities[resolutions[i]] = translate(resolutions[i], resolutions[i]);
-          }
+    function login() {
+        if (!askedForLogin) {
+            askedForLogin = true;
+            var username = 'User';
+            var password = 'Password';
+
+            Bootbox.dialog({
+                title: translate('loginInformation', 'Log in'),
+                message: '<form class="form-signin">' +
+                '<h2 class="form-signin-heading">' + translate('enterUsernamePassword', 'Please enter your username and password') + '</h2>' +
+                '<input id="username" type="text" class="form-control form-control-custom" name="username" placeholder="' + translate('username', 'Username') + '" required="true" autofocus="" />' +
+                '<input id="password" type="password" class="form-control form-control-custom" name="password" placeholder="' + translate('password', 'Password') + '" required="true" />' +
+                '<label class="checkbox">' +
+                '<input type="checkbox" value="' + translate('rememberMe', 'Remember me') + '" id="rememberMe" name="rememberMe" checked> ' + translate('rememberMe', 'Remember me') +
+                '</label>' +
+                '</form>',
+                buttons: {
+                    cancel: {
+                        label: translate('cancel', 'Cancel'),
+                        className: 'btn-default',
+                        callback: function () {
+                            askedForLogin = false;
+                        }
+                    },
+                    login: {
+                        label: translate('login', 'Log in'),
+                        className: 'btn-success',
+                        callback: function () {
+                            var username = $('#username').val().trim();
+                            var password = $('#password').val().trim();
+                            if ((username !== null) && (username.length > 0) && (password !== null) && (password.length > 0)) {
+                                $.ajax({
+                                    type: 'POST',
+                                    url: springSecurityLoginURL,
+                                    data: {
+                                        'j_username': username,
+                                        'j_password': password,
+                                        '_spring_security_remember_me': $('#rememberMe').is(':checked')
+                                    }
+                                }).done(function (msg) {
+                                    password = '';
+                                    if (msg.indexOf(springLoggedInStrCheck) == -1) {
+                                        Engage.trigger(events.customSuccess.getName(), translate('loginSuccessful', 'Successfully logged in. Please reload the page if the page does not reload automatically.'));
+                                        location.reload();
+                                    } else {
+                                        Engage.trigger(events.customSuccess.getName(), translate('loginFailed', 'Failed to log in.'));
+                                    }
+                                    askedForLogin = false;
+                                }).fail(function (msg) {
+                                    password = '';
+                                    Engage.trigger(events.customSuccess.getName(), translate('loginFailed', 'Failed to log in.'));
+                                    askedForLogin = false;
+                                });
+                            } else {
+                                askedForLogin = false;
+                            }
+                        }
+                    }
+                },
+                className: 'usernamePassword-modal',
+                onEscape: function () {
+                    askedForLogin = false;
+                },
+                closeButton: false
+            });
         }
+    }
 
-        var tempVars = {
-          plugin_path: this.pluginPath,
-          startTime: Utils.formatSeconds(0),
-          durationMS: (duration && (duration > 0)) ? duration : 1, // duration in ms
-          duration: (duration ? Utils.formatSeconds(duration / 1000) : Utils.formatSeconds(0)), // formatted duration
-          logoLink: logoLink,
-          segments: segments,
-          str_prevChapter: translate('prevChapter', 'Go to previous chapter'),
-          str_nextChapter: translate('nextChapter', 'Go to next chapter'),
-          str_playPauseVideo: translate('playPauseVideo', 'Play or pause the video'),
-          str_playVideo: translate('playVideo', 'Play the video'),
-          str_pauseVideo: translate('pauseVideo', 'Pause the video'),
-          str_volumeSlider: translate('volumeSlider', 'Volume slider'),
-          str_muteVolume: translate('muteVolume', 'Mute volume'),
-          str_unmuteVolume: translate('unmuteVolume', 'Unmute Volume'),
-          str_message_inputField: translate('message_inputField', 'Input field shows current video time. Can be edited.'),
-          str_totalVideoLength: translate('totalVideoLength', 'Total length of the video:'),
-          str_openMediaModule: translate('openMediaModule', 'Go to Media Module'),
-          str_playbackRateButton: translate('playbackRateButton', 'Playback rate button. Select playback rate from dropdown.'),
-          str_playbackRate: translate('playbackRate', 'Playback rate'),
-          str_remainingTime: translate('remainingTime', 'remaining time'),
-          str_embedButton: translate('embedButton', 'Embed Button. Select embed size from dropdown.'),
-          loggedIn: false,
-          str_checkingStatus: translate('checkingLoginStatus', 'Checking login status...'),
-          str_loginLogout: translate('loginLogout', 'Login/Logout'),
-          str_fullscreen: translate('fullscreen', 'Fullscreen'),
-          str_qualityButton: translate('quality', 'Quality'),
-          str_quality: translate('quality', 'Quality'),
-          str_layoutButton: translate('layout', 'Layout'),
-          str_pictureInPicture: translate('pictureInPicture', 'Picture in Picture'),
-          str_left: translate('left', 'left'),
-          str_right: translate('right', 'right'),
-          str_beside: translate('beside', 'beside'),
-          str_off: translate('off', 'off'),
-          qualities: resolutions,
-          pip_position: translate(pipPosition, pipPosition),
-          translatedqualities: translatedQualities,
-          hasqualities: resolutions !== undefined,
-          hasmultiplevideos: (Engage.model.get('videoDataModel').get('ids').length > 1),
-          controlsTop: Engage.controls_top,
-          logo: logo,
-          show_embed: showEmbed,
-          str_zoomlevel: '100%',
-          flash: usingFlash,
-          // for mobile view
-          numberofvideos: Engage.model.get('videoDataModel').get('ids').length,
-          str_video: translate('video', 'Video'),
-          str_of: translate('of', 'of'),
-          str_showVolumeBar: translate('showVolumeBar', 'Show volume bar'),
-          str_swipeHint: translate('swipeHint', 'Swipe for additional view')
-        };
-
-        // compile template and load it
-        var template = _.template(this.template);
-        this.$el.html(template(tempVars));
-
-        initControlsEvents();
-
-        if (isDesktopMode) {
-          if (!aspectRatioTriggered) {
-            aspectRatioWidth = 0;
-            aspectRatioHeight = 0;
-            aspectRatio = 0;
-            Engage.trigger(plugin.events.aspectRatioSet.getName());
-          }
-          calculateEmbedAspectRatios();
-          addEmbedRatioEvents();
-        }
-        if (!isMobileMode) {
-          if (tempVars.hasmultiplevideos) {
-            addLayoutEvents();
-          }
-        }
+    function logout() {
+        Engage.trigger(events.customSuccess.getName(), translate('loggingOut', 'You are being logged out, please wait a moment.'));
+        $.ajax({
+            type: 'GET',
+            url: springSecurityLogoutURL,
+        }).complete(function (msg) {
+            location.reload();
+            Engage.trigger(events.customSuccess.getName(), translate('logoutSuccessful', 'Successfully logged out. Please reload the page if the page does not reload automatically.'));
+        });
+    }
 
-        if (tempVars.hasqualities) {
-          addQualityChangeEvents();
+    function checkLoginStatus() {
+        $('#' + id_loginlogout).unbind('click');
+        if (Engage.model.get('infoMe').loggedIn) {
+            loggedIn = true;
+            username = Engage.model.get('infoMe').username;
+            $('#' + id_loggedInNotLoggedIn).html(username);
+            $('#' + id_str_loginlogout).html(translate('logout', 'Log out'));
+            $('#' + id_loginlogout).click(logout);
+        } else {
+            loggedIn = false;
+            username = 'Anonymous';
+            $('#' + id_loggedInNotLoggedIn).html(translate('loggedOut', 'Logged out'));
+            $('#' + id_str_loginlogout).html(translate('login', 'Log in'));
+            $('#' + id_loginlogout).click(login);
         }
+        $('#' + id_dropdownMenuLoginInfo).removeClass('disabled');
+    }
 
-        // query ready state of video, in case the ready event from
-        // the video plugin was fired before the controls plugin was initialized
-        Engage.trigger(plugin.events.ready.getName(), true);
+    var ControlsView = Backbone.View.extend({
+        el: $('#' + id_engage_controls), // every view has an element associated with it
+        initialize: function (videoDataModel, template, plugin_path) {
+            this.setElement($(plugin.container));
+            this.model = videoDataModel;
+            this.template = template;
+            this.pluginPath = plugin_path;
+
+            // bind the render function always to the view
+            _.bindAll(this, 'render');
+            // listen for changes of the model and bind the render function to this
+            this.model.bind('change', this.render);
+            this.render();
+        },
+        render: function () {
+            if (!mediapackageError) {
+                duration = parseInt(this.model.get('duration'));
+                segments = Engage.model.get('mediaPackage').get('segments');
+
+                var pipPosition = pipPos;
+                if (!pipStatus) {
+                    pipPosition = 'beside';
+                }
 
-        // init dropdown menus
-        $('.' + class_dropdown).dropdown();
+                segments = Utils.repairSegmentLength(segments, duration, min_segment_duration);
+
+                if (Engage.model.get('meInfo')) {
+                    if (Engage.model.get('meInfo').get('logo_player')) {
+                        logo = Engage.model.get('meInfo').get('logo_player');
+                    }
+                    if (Engage.model.get('meInfo').get('link_mediamodule')) {
+                        logoLink = window.location.protocol + '//' + window.location.host + '/engage/ui/index.html'; // link to the media module
+                    }
+                    if (!Engage.model.get('meInfo').get('show_embed_links')) {
+                        showEmbed = false;
+                    }
+                }
+                var translatedQualities = new Array();
+                if (resolutions) {
+                    for (var i = 0; i < resolutions.length; i++) {
+                        translatedQualities[resolutions[i]] = translate(resolutions[i], resolutions[i]);
+                    }
+                }
 
-        ready();
-        playPause();
-        timeUpdate();
-        addNonFlashEvents();
-        checkLoginStatus();
-      }
-    }
-  });
-
-  // provide this additional view if the controls are below the video to have content above the video
-  var ControlsViewTop_ifBottom = Backbone.View.extend({
-    el: $('#' + id_engage_controls_topIfBottom), // every view has an element associated with it
-    initialize: function (videoDataModel, template, plugin_path) {
-      this.setElement($(plugin.containerSecondIfBottom));
-      this.model = videoDataModel;
-      this.template = template;
-      this.pluginPath = plugin_path;
-
-      // bind the render function always to the view
-      _.bindAll(this, 'render');
-      // listen for changes of the model and bind the render function to this
-      this.model.bind('change', this.render);
-      this.render();
-    },
-    render: function () {
-      if (!mediapackageError) {
-        if (Engage.model.get('meInfo')) {
-          if (Engage.model.get('meInfo').get('logo_player')) {
-            logo = Engage.model.get('meInfo').get('logo_player');
-          }
-          if (Engage.model.get('meInfo').get('link_mediamodule')) {
-            logoLink = window.location.protocol + '//' + window.location.host + '/engage/ui/index.html'; // link to the media module
-          }
-          if (!Engage.model.get('meInfo').get('show_embed_links')) {
-            showEmbed = false;
-          }
-        }
-        var tempVars = {
-          plugin_path: this.pluginPath,
-          logoLink: logoLink,
-          str_openMediaModule: translate('openMediaModule', 'Go to Media Module'),
-          str_embedButton: translate('embedButton', 'Embed Button. Select embed size from dropdown.'),
-          str_fullscreen: translate('fullscreen', 'Fullscreen'),
-          loggedIn: false,
-          str_checkingStatus: translate('checkingLoginStatus', 'Checking login status...'),
-          str_loginLogout: translate('loginLogout', 'Login/Logout'),
-          logo: logo,
-          show_embed: showEmbed
-        };
-
-        // compile template and load into the html
-        var template = _.template(this.template);
-        this.$el.html(template(tempVars));
-      }
-    }
-  });
-
-  function addNonFlashEvents() {
-    if (!mediapackageError && !usingFlash && !isAudioOnly) {
-      // setup listeners for the playback rate
-      $('#' + id_playbackRate075).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(0.75));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 0.75);
-      });
-      $('#' + id_playbackRate100).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.0));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.0);
-      });
-      $('#' + id_playbackRate125).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.25));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.25);
-      });
-      $('#' + id_playbackRate150).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.5));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.5);
-      });
-      $('#' + id_playbackRate200).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(2.0));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 2.0);
-      });
-      $('#' + id_playbackRate300).click(function (e) {
-        e.preventDefault();
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(3.0));
-        Engage.trigger(plugin.events.playbackRateChanged.getName(), 3.0);
-      });
-    }
-  }
-
-  function addQualityChangeEvents() {
-    if (!mediapackageError) {
-      for (var i = 0; i < resolutions.length; i++) {
-        var quality = resolutions[i];
-        addQualityListener(quality);
-      }
-      var q = Engage.model.get('quality');
-      $('#' + id_qualityIndicator).html(q.charAt(0).toUpperCase() + q.substring(1));
-    }
-  }
+                var tempVars = {
+                    plugin_path: this.pluginPath,
+                    startTime: Utils.formatSeconds(0),
+                    durationMS: (duration && (duration > 0)) ? duration : 1, // duration in ms
+                    duration: (duration ? Utils.formatSeconds(duration / 1000) : Utils.formatSeconds(0)), // formatted duration
+                    logoLink: logoLink,
+                    segments: segments,
+                    str_prevChapter: translate('prevChapter', 'Go to previous chapter'),
+                    str_nextChapter: translate('nextChapter', 'Go to next chapter'),
+                    str_playPauseVideo: translate('playPauseVideo', 'Play or pause the video'),
+                    str_playVideo: translate('playVideo', 'Play the video'),
+                    str_pauseVideo: translate('pauseVideo', 'Pause the video'),
+                    str_volumeSlider: translate('volumeSlider', 'Volume slider'),
+                    str_muteVolume: translate('muteVolume', 'Mute volume'),
+                    str_unmuteVolume: translate('unmuteVolume', 'Unmute Volume'),
+                    str_message_inputField: translate('message_inputField', 'Input field shows current video time. Can be edited.'),
+                    str_totalVideoLength: translate('totalVideoLength', 'Total length of the video:'),
+                    str_openMediaModule: translate('openMediaModule', 'Go to Media Module'),
+                    str_playbackRateButton: translate('playbackRateButton', 'Playback rate button. Select playback rate from dropdown.'),
+                    str_playbackRate: translate('playbackRate', 'Playback rate'),
+                    str_remainingTime: translate('remainingTime', 'remaining time'),
+                    str_embedButton: translate('embedButton', 'Embed Button. Select embed size from dropdown.'),
+                    loggedIn: false,
+                    str_checkingStatus: translate('checkingLoginStatus', 'Checking login status...'),
+                    str_loginLogout: translate('loginLogout', 'Login/Logout'),
+                    str_fullscreen: translate('fullscreen', 'Fullscreen'),
+                    str_qualityButton: translate('quality', 'Quality'),
+                    str_quality: translate('quality', 'Quality'),
+                    str_layoutButton: translate('layout', 'Layout'),
+                    str_pictureInPicture: translate('pictureInPicture', 'Picture in Picture'),
+                    str_left: translate('left', 'left'),
+                    str_right: translate('right', 'right'),
+                    str_beside: translate('beside', 'beside'),
+                    str_off: translate('off', 'off'),
+                    qualities: resolutions,
+                    pip_position: translate(pipPosition, pipPosition),
+                    translatedqualities: translatedQualities,
+                    hasqualities: resolutions !== undefined,
+                    hasmultiplevideos: (Engage.model.get('videoDataModel').get('ids').length > 1),
+                    controlsTop: Engage.controls_top,
+                    logo: logo,
+                    show_embed: showEmbed,
+                    str_zoomlevel: '100%',
+                    flash: usingFlash,
+                    // for mobile view
+                    numberofvideos: Engage.model.get('videoDataModel').get('ids').length,
+                    str_video: translate('video', 'Video'),
+                    str_of: translate('of', 'of'),
+                    str_showVolumeBar: translate('showVolumeBar', 'Show volume bar'),
+                    str_swipeHint: translate('swipeHint', 'Swipe for additional view')
+                };
+
+                // compile template and load it
+                var template = _.template(this.template);
+                this.$el.html(template(tempVars));
+
+                initControlsEvents();
+
+                if (isDesktopMode) {
+                    if (!aspectRatioTriggered) {
+                        aspectRatioWidth = 0;
+                        aspectRatioHeight = 0;
+                        aspectRatio = 0;
+                        Engage.trigger(plugin.events.aspectRatioSet.getName());
+                    }
+                    calculateEmbedAspectRatios();
+                    addEmbedRatioEvents();
+                }
+                if (!isMobileMode) {
+                    if (tempVars.hasmultiplevideos) {
+                        addLayoutEvents();
+                    }
+                }
 
-  function addQualityListener(quality) {
-    $('#quality' + quality).click(function (element) {
-      element.preventDefault();
-      $('#' + id_qualityIndicator).html(translate(quality, quality));
-      Engage.trigger(plugin.events.qualitySet.getName(), quality);
-    });
-  }
-
-  function addLayoutEvents() {
-    $('#' + id_pipLeft).click(function (e) {
-      e.preventDefault();
-      $('.videoDisplay').trigger('click');
-      $('#' + id_pipIndicator).html(translate('left', 'left'));
-      Engage.trigger(plugin.events.movePiP.getName(), 'left');
-      Engage.trigger(plugin.events.togglePiP.getName(), true);
-    });
-    $('#' + id_pipRight).click(function (e) {
-      e.preventDefault();
-      $('.videoDisplay').trigger('click');
-      $('#' + id_pipIndicator).html(translate('right', 'right'));
-      Engage.trigger(plugin.events.movePiP.getName(), 'right');
-      Engage.trigger(plugin.events.togglePiP.getName(), true);
-    });
-    $('#' + id_pipBeside).click(function (e) {
-      e.preventDefault();
-      $('.videoDisplay').trigger('click');
-      $('#' + id_pipIndicator).html(translate('beside', 'beside'));
-      Engage.trigger(plugin.events.togglePiP.getName(), false);
+                if (tempVars.hasqualities) {
+                    addQualityChangeEvents();
+                }
+
+                // query ready state of video, in case the ready event from
+                // the video plugin was fired before the controls plugin was initialized
+                Engage.trigger(plugin.events.ready.getName(), true);
+
+                // init dropdown menus
+                $('.' + class_dropdown).dropdown();
+
+                ready();
+                playPause();
+                timeUpdate();
+                addNonFlashEvents();
+                checkLoginStatus();
+            }
+        }
     });
-    $('#' + id_pipOff).click(function (e) {
-      e.preventDefault();
-      $('.videoDisplay').trigger('click');
-      $('#' + id_pipIndicator).html(translate('off', 'off'));
-      Engage.trigger(plugin.events.resetLayout.getName());
+
+    // provide this additional view if the controls are below the video to have content above the video
+    var ControlsViewTop_ifBottom = Backbone.View.extend({
+        el: $('#' + id_engage_controls_topIfBottom), // every view has an element associated with it
+        initialize: function (videoDataModel, template, plugin_path) {
+            this.setElement($(plugin.containerSecondIfBottom));
+            this.model = videoDataModel;
+            this.template = template;
+            this.pluginPath = plugin_path;
+
+            // bind the render function always to the view
+            _.bindAll(this, 'render');
+            // listen for changes of the model and bind the render function to this
+            this.model.bind('change', this.render);
+            this.render();
+        },
+        render: function () {
+            if (!mediapackageError) {
+                if (Engage.model.get('meInfo')) {
+                    if (Engage.model.get('meInfo').get('logo_player')) {
+                        logo = Engage.model.get('meInfo').get('logo_player');
+                    }
+                    if (Engage.model.get('meInfo').get('link_mediamodule')) {
+                        logoLink = window.location.protocol + '//' + window.location.host + '/engage/ui/index.html'; // link to the media module
+                    }
+                    if (!Engage.model.get('meInfo').get('show_embed_links')) {
+                        showEmbed = false;
+                    }
+                }
+                var tempVars = {
+                    plugin_path: this.pluginPath,
+                    logoLink: logoLink,
+                    str_openMediaModule: translate('openMediaModule', 'Go to Media Module'),
+                    str_embedButton: translate('embedButton', 'Embed Button. Select embed size from dropdown.'),
+                    str_fullscreen: translate('fullscreen', 'Fullscreen'),
+                    loggedIn: false,
+                    str_checkingStatus: translate('checkingLoginStatus', 'Checking login status...'),
+                    str_loginLogout: translate('loginLogout', 'Login/Logout'),
+                    logo: logo,
+                    show_embed: showEmbed
+                };
+
+                // compile template and load into the html
+                var template = _.template(this.template);
+                this.$el.html(template(tempVars));
+            }
+        }
     });
-  }
-
-  function addZoomEvents() {
-    if(!usingFlash) {
-      $('#' + id_zoomLevelIndicator).html('100%');
-
-      /* Events for Button */
-      $('#' + id_zoomLevel1).click(function (event) {
-        event.preventDefault();
-        Engage.trigger(plugin.events.setZoomLevel.getName(), [1.5, true]);
-      });
-
-      $('#' + id_zoomLevel2).click(function (event) {
-        event.preventDefault();
-        Engage.trigger(plugin.events.setZoomLevel.getName(), [2.0, true]);
-      });
-
-      $('#' + id_zoomLevel3).click(function (event) {
-        event.preventDefault();
-        Engage.trigger(plugin.events.setZoomLevel.getName(), [2.5, true]);
-      });
-
-      $('#' + id_zoomReset).click(function (event) {
-        event.preventDefault();
-        Engage.trigger(plugin.events.zoomReset.getName(), true);
-      });
-
-      Engage.on(plugin.events.zoomChange.getName(), function (level) {
-        level = Number(level).toFixed(2);
-        level = (level * 100).toFixed(0);
-        $('#' + id_zoomLevelIndicator).html(String(level) + '%');
-      });
-    }
-  }
-
-  function triggerEmbedMessage(ratioWidth, ratioHeight) {
-    var str = window.location.href;
-    if (str.indexOf('mode=desktop') == -1) {
-      str += '&mode=embed';
-    } else {
-      str = Utils.replaceAll(str, 'mode=desktop', 'mode=embed');
-    }
-    var code = '<iframe src=\'' + str + '\' style=\'border:0px #FFFFFF none;\' name=\'Opencast media player\' scrolling=\'no\' frameborder=\'0\' marginheight=\'0px\' marginwidth=\'0px\' width=\'' + ratioWidth + '\' height=\'' + ratioHeight + '\' allowfullscreen=\'true\' webkitallowfullscreen=\'true\' mozallowfullscreen=\'true\'></iframe>';
-    code = Utils.escapeHtml(code);
-    Engage.trigger(plugin.events.customOKMessage.getName(), 'Copy the following code and paste it to the body of your html page: <div class=\'well well-sm well-alert\'>' + code + '</div>');
-  }
-
-  function addEmbedRatioEvents() {
-    if (!mediapackageError) {
-      // setup listeners for the embed buttons
-      $('#' + id_embed0).click(function (e) {
-        e.preventDefault();
-        triggerEmbedMessage(embedWidthOne, embedHeightOne);
-      });
-      $('#' + id_embed1).click(function (e) {
-        e.preventDefault();
-        triggerEmbedMessage(embedWidthTwo, embedHeightTwo);
-      });
-      $('#' + id_embed2).click(function (e) {
-        e.preventDefault();
-        triggerEmbedMessage(embedWidthThree, embedHeightThree);
-      });
-      $('#' + id_embed3).click(function (e) {
-        e.preventDefault();
-        triggerEmbedMessage(embedWidthFour, embedHeightFour);
-      });
-      $('#' + id_embed4).click(function (e) {
-        e.preventDefault();
-        triggerEmbedMessage(embedWidthFive, embedHeightFive);
-      });
+
+    function addNonFlashEvents() {
+        if (!mediapackageError && !usingFlash && !isAudioOnly) {
+            // setup listeners for the playback rate
+            $('#' + id_playbackRate075).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(0.75));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 0.75);
+            });
+            $('#' + id_playbackRate100).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.0));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.0);
+            });
+            $('#' + id_playbackRate125).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.25));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.25);
+            });
+            $('#' + id_playbackRate150).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(1.5));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 1.5);
+            });
+            $('#' + id_playbackRate200).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(2.0));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 2.0);
+            });
+            $('#' + id_playbackRate300).click(function (e) {
+                e.preventDefault();
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(3.0));
+                Engage.trigger(plugin.events.playbackRateChanged.getName(), 3.0);
+            });
+        }
     }
-  }
 
-  function loadStoredInitialValues() {
-    var vol = Basil.get(storage_volume);
-    if (vol) {
-      Basil.set(storage_lastvolume, vol);
-      Engage.trigger(plugin.events.volumeSet.getName(), vol / 100);
+    function addQualityChangeEvents() {
+        if (!mediapackageError) {
+            for (var i = 0; i < resolutions.length; i++) {
+                var quality = resolutions[i];
+                addQualityListener(quality);
+            }
+            var q = Engage.model.get('quality');
+            $('#' + id_qualityIndicator).html(q.charAt(0).toUpperCase() + q.substring(1));
+        }
     }
 
-    var muted = Basil.get(storage_muted);
-    if (muted == 'true') {
-      Engage.trigger(plugin.events.mute.getName());
-    } else {
-      Engage.trigger(plugin.events.unmute.getName());
+    function addQualityListener(quality) {
+        $('#quality' + quality).click(function (element) {
+            element.preventDefault();
+            $('#' + id_qualityIndicator).html(translate(quality, quality));
+            Engage.trigger(plugin.events.qualitySet.getName(), quality);
+        });
     }
 
-    if (Basil.get(storage_pip_pos) !== undefined && Basil.get(storage_pip_pos) !== null) {
-      var pipPos = Basil.get(storage_pip_pos);
-      Engage.trigger(plugin.events.movePiP.getName(), pipPos);
-    } else {
-      if (Engage.model.get('meInfo').get('layout') !== 'off') {
-        var pipPos = Engage.model.get('meInfo').get('layout');
-        Engage.trigger(plugin.events.movePiP.getName(), pipPos);
-      }
+    function addLayoutEvents() {
+        $('#' + id_pipLeft).click(function (e) {
+            e.preventDefault();
+            $('.videoDisplay').trigger('click');
+            $('#' + id_pipIndicator).html(translate('left', 'left'));
+            Engage.trigger(plugin.events.movePiP.getName(), 'left');
+            Engage.trigger(plugin.events.togglePiP.getName(), true);
+        });
+        $('#' + id_pipRight).click(function (e) {
+            e.preventDefault();
+            $('.videoDisplay').trigger('click');
+            $('#' + id_pipIndicator).html(translate('right', 'right'));
+            Engage.trigger(plugin.events.movePiP.getName(), 'right');
+            Engage.trigger(plugin.events.togglePiP.getName(), true);
+        });
+        $('#' + id_pipBeside).click(function (e) {
+            e.preventDefault();
+            $('.videoDisplay').trigger('click');
+            $('#' + id_pipIndicator).html(translate('beside', 'beside'));
+            Engage.trigger(plugin.events.togglePiP.getName(), false);
+        });
+        $('#' + id_pipOff).click(function (e) {
+            e.preventDefault();
+            $('.videoDisplay').trigger('click');
+            $('#' + id_pipIndicator).html(translate('off', 'off'));
+            Engage.trigger(plugin.events.resetLayout.getName());
+        });
     }
-    if (Basil.get(storage_pip) !== undefined && Basil.get(storage_pip) !== null) {
-      var pip = Basil.get(storage_pip);
-      if (pip === false) {
-        Engage.trigger(plugin.events.togglePiP.getName(), pip);
-      }
-    } else {
-      if (Engage.model.get('meInfo').get('layout') === 'off' ||
-        Engage.model.get('meInfo').get('layout') === 'beside') {
-        Engage.trigger(plugin.events.togglePiP.getName(), false);
-      } else {
-        Engage.trigger(plugin.events.togglePiP.getName(), true);
-      }
+
+    function addZoomEvents() {
+        if (!usingFlash) {
+            $('#' + id_zoomLevelIndicator).html('100%');
+
+            /* Events for Button */
+            $('#' + id_zoomLevel1).click(function (event) {
+                event.preventDefault();
+                Engage.trigger(plugin.events.setZoomLevel.getName(), [1.5, true]);
+            });
+
+            $('#' + id_zoomLevel2).click(function (event) {
+                event.preventDefault();
+                Engage.trigger(plugin.events.setZoomLevel.getName(), [2.0, true]);
+            });
+
+            $('#' + id_zoomLevel3).click(function (event) {
+                event.preventDefault();
+                Engage.trigger(plugin.events.setZoomLevel.getName(), [2.5, true]);
+            });
+
+            $('#' + id_zoomReset).click(function (event) {
+                event.preventDefault();
+                Engage.trigger(plugin.events.zoomReset.getName(), true);
+            });
+
+            Engage.on(plugin.events.zoomChange.getName(), function (level) {
+                level = Number(level).toFixed(2);
+                level = (level * 100).toFixed(0);
+                $('#' + id_zoomLevelIndicator).html(String(level) + '%');
+            });
+        }
     }
-    if (Basil.get(storage_focus_video) !== undefined && Basil.get(storage_focus_video) !== null) {
-      var focusVideo = Basil.get(storage_focus_video);
-      currentFocusFlavor = focusVideo;
-    } else {
-      if (Engage.model.get('meInfo').get('layout') !== 'off') {
-        currentFocusFlavor = Engage.model.get('meInfo').get('focusedflavor');
-      }
+
+    function triggerEmbedMessage(ratioWidth, ratioHeight) {
+        var str = window.location.href;
+        if (str.indexOf('mode=desktop') == -1) {
+            str += '&mode=embed';
+        } else {
+            str = Utils.replaceAll(str, 'mode=desktop', 'mode=embed');
+        }
+        var code = '<iframe src=\'' + str + '\' style=\'border:0px #FFFFFF none;\' name=\'Opencast media player\' scrolling=\'no\' frameborder=\'0\' marginheight=\'0px\' marginwidth=\'0px\' width=\'' + ratioWidth + '\' height=\'' + ratioHeight + '\' allowfullscreen=\'true\' webkitallowfullscreen=\'true\' mozallowfullscreen=\'true\'></iframe>';
+        code = Utils.escapeHtml(code);
+        Engage.trigger(plugin.events.customOKMessage.getName(), 'Copy the following code and paste it to the body of your html page: <div class=\'well well-sm well-alert\'>' + code + '</div>');
     }
-  }
-
-  function initControlsEvents() {
-    if (!mediapackageError) {
-      // disable not used buttons
-      Utils.disable(id_backward_button);
-      Utils.disable(id_forward_button);
-      Utils.disable(id_play_button);
-      Utils.greyOut(id_backward_button);
-      Utils.greyOut(id_forward_button);
-      Utils.greyOut(id_play_button);
-      Utils.disable(id_navigation_time);
-      $('#' + id_navigation_time_current).keyup(function (e) {
-        e.preventDefault();
-        // enter
-        if (e.keyCode === 13) {
-          $(this).blur();
-          try {
-            var time = Utils.getTimeInMilliseconds($(this).val());
-            if (!isNaN(time)) {
-              Engage.trigger(plugin.events.seek.getName(), time / 1000);
-            }
-          } catch (e) {
-            Engage.trigger(plugin.events.seek.getName(), 0);
-          }
+
+    function addEmbedRatioEvents() {
+        if (!mediapackageError) {
+            // setup listeners for the embed buttons
+            $('#' + id_embed0).click(function (e) {
+                e.preventDefault();
+                triggerEmbedMessage(embedWidthOne, embedHeightOne);
+            });
+            $('#' + id_embed1).click(function (e) {
+                e.preventDefault();
+                triggerEmbedMessage(embedWidthTwo, embedHeightTwo);
+            });
+            $('#' + id_embed2).click(function (e) {
+                e.preventDefault();
+                triggerEmbedMessage(embedWidthThree, embedHeightThree);
+            });
+            $('#' + id_embed3).click(function (e) {
+                e.preventDefault();
+                triggerEmbedMessage(embedWidthFour, embedHeightFour);
+            });
+            $('#' + id_embed4).click(function (e) {
+                e.preventDefault();
+                triggerEmbedMessage(embedWidthFive, embedHeightFive);
+            });
         }
-      });
-
-      $('#' + id_slider).slider({
-        range: 'min',
-        min: 0,
-        max: 1000,
-        value: 0
-      });
-
-      $('#' + id_volumeSlider).slider({
-        range: 'min',
-        min: 0,
-        max: 100,
-        value: 100,
-        change: function (event, ui) {}
-      });
-
-      // use as mute button in desktop mode
-      if (!isMobileMode) {
-        $('#' + id_volumeIcon).click(function () {
-          var isMute = Basil.get(storage_muted);
-          if (isMute == 'true') {
-            Engage.trigger(plugin.events.unmute.getName());
-            Basil.set(storage_muted, 'false');
-          } else {
-            Engage.trigger(plugin.events.mute.getName());
-            Basil.set(storage_muted, 'true');
-          }
-        });
-      }
+    }
 
-      $('#' + id_playpause_controls).click(function (e) {
-        e.stopPropagation();
-        Engage.trigger(plugin.events.playPause.getName());
-      });
+    function loadStoredInitialValues() {
+        var vol = Basil.get(storage_volume);
+        if (vol) {
+            Basil.set(storage_lastvolume, vol);
+            Engage.trigger(plugin.events.volumeSet.getName(), vol / 100);
+        }
 
-      $('#' + id_forward_button).click(function () {
-        if (segments && (segments.length > 0)) {
-          Engage.trigger(plugin.events.nextChapter.getName());
+        var muted = Basil.get(storage_muted);
+        if (muted == 'true') {
+            Engage.trigger(plugin.events.mute.getName());
         } else {
-          Engage.trigger(plugin.events.seekRight.getName());
+            Engage.trigger(plugin.events.unmute.getName());
         }
-      });
 
-      $('#' + id_backward_button).click(function () {
-        if (segments && (segments.length > 0)) {
-          Engage.trigger(plugin.events.previousChapter.getName());
+        if (Basil.get(storage_pip_pos) !== undefined && Basil.get(storage_pip_pos) !== null) {
+            var pipPos = Basil.get(storage_pip_pos);
+            Engage.trigger(plugin.events.movePiP.getName(), pipPos);
         } else {
-          Engage.trigger(plugin.events.seekLeft.getName());
+            if (Engage.model.get('meInfo').get('layout') !== 'off') {
+                var pipPos = Engage.model.get('meInfo').get('layout');
+                Engage.trigger(plugin.events.movePiP.getName(), pipPos);
+            }
         }
-      });
-
-      $('#' + id_fullscreen_button).click(function (e) {
-        e.preventDefault();
-
-        $(this).toggleClass('active');
-        var isInFullScreen = document.fullScreen ||
-        document.mozFullScreen ||
-        document.webkitIsFullScreen;
-        if (!isInFullScreen) {
-          Engage.trigger(plugin.events.fullscreenEnable.getName());
-        } else if (isMobileMode) {
-          Engage.trigger(plugin.events.fullscreenCancel.getName());
+        if (Basil.get(storage_pip) !== undefined && Basil.get(storage_pip) !== null) {
+            var pip = Basil.get(storage_pip);
+            if (pip === false) {
+                Engage.trigger(plugin.events.togglePiP.getName(), pip);
+            }
+        } else {
+            if (Engage.model.get('meInfo').get('layout') === 'off' ||
+                Engage.model.get('meInfo').get('layout') === 'beside') {
+                Engage.trigger(plugin.events.togglePiP.getName(), false);
+            } else {
+                Engage.trigger(plugin.events.togglePiP.getName(), true);
+            }
         }
-      });
-
-      $('#' + id_captions_button).click(function (e) {
-        e.preventDefault();
-
-        $(this).toggleClass('active');
-        captionsOn  = !captionsOn;
-        Engage.trigger(plugin.events.toggleCaptions.getName(), captionsOn);
-      })
-      // slider events
-      $('#' + id_slider).on(event_slidestart, function (event, ui) {
-        isSliding = true;
-        Engage.trigger(plugin.events.sliderStart.getName(), ui.value);
-      });
-      $('#' + id_slider).on(event_slidestop, function (event, ui) {
-        isSliding = false;
-        Engage.trigger(plugin.events.sliderStop.getName(), ui.value);
-      });
-      $('#' + id_slider).mouseover(function (e) {
-        e.preventDefault();
-        Engage.trigger(plugin.events.sliderMousein.getName());
-      }).mouseout(function (e) {
-        e.preventDefault();
-        Engage.trigger(plugin.events.sliderMouseout.getName());
-      }).mousemove(function (e) {
-        e.preventDefault();
-        var currPos = e.clientX / ($('#' + id_slider).width() + $('#' + id_slider).offset().left);
-        var dur = (duration && (duration > 0)) ? duration : 1;
-        currPos = (currPos < 0) ? 0 : ((currPos > 1) ? 1 : currPos);
-        Engage.trigger(plugin.events.sliderMousemove.getName(), currPos * dur);
-      });
-      // volume event
-      $('#' + id_volumeSlider).on(event_slide, function (event, ui) {
-        Engage.trigger(plugin.events.volumeSet.getName(), ui.value / 100);
-        if (!isMobileMode) {
-          if (ui.value === 0) {
-            showMuteButton();
-          } else {
-            showUnmuteButton();
-          }
+        if (Basil.get(storage_focus_video) !== undefined && Basil.get(storage_focus_video) !== null) {
+            var focusVideo = Basil.get(storage_focus_video);
+            currentFocusFlavor = focusVideo;
+        } else {
+            if (Engage.model.get('meInfo').get('layout') !== 'off') {
+                currentFocusFlavor = Engage.model.get('meInfo').get('focusedflavor');
+            }
         }
-      });
-      // check segments
-      if (segments && (segments.length > 0)) {
-        Engage.log('Controls: ' + segments.length + ' segments are available.');
-        $.each(segments, function (i, v) {
-          $('#' + id_segmentNo + i).click(function (e) {
-            e.preventDefault();
-            var time = parseInt($(this).children().html());
-            if (!isNaN(time)) {
-              Engage.trigger(plugin.events.seek.getName(), time / 1000);
+    }
+
+    function initControlsEvents() {
+        if (!mediapackageError) {
+            // disable not used buttons
+            Utils.disable(id_backward_button);
+            Utils.disable(id_forward_button);
+            Utils.disable(id_play_button);
+            Utils.greyOut(id_backward_button);
+            Utils.greyOut(id_forward_button);
+            Utils.greyOut(id_play_button);
+            Utils.disable(id_navigation_time);
+            $('#' + id_navigation_time_current).keyup(function (e) {
+                e.preventDefault();
+                // enter
+                if (e.keyCode === 13) {
+                    $(this).blur();
+                    try {
+                        var time = Utils.getTimeInMilliseconds($(this).val());
+                        if (!isNaN(time)) {
+                            Engage.trigger(plugin.events.seek.getName(), time / 1000);
+                        }
+                    } catch (e) {
+                        Engage.trigger(plugin.events.seek.getName(), 0);
+                    }
+                }
+            });
+
+            $('#' + id_slider).slider({
+                range: 'min',
+                min: 0,
+                max: 1000,
+                value: 0
+            });
+
+            $('#' + id_volumeSlider).slider({
+                range: 'min',
+                min: 0,
+                max: 100,
+                value: 100,
+                change: function (event, ui) {
+                }
+            });
+
+            // use as mute button in desktop mode
+            if (!isMobileMode) {
+                $('#' + id_volumeIcon).click(function () {
+                    var isMute = Basil.get(storage_muted);
+                    if (isMute == 'true') {
+                        Engage.trigger(plugin.events.unmute.getName());
+                        Basil.set(storage_muted, 'false');
+                    } else {
+                        Engage.trigger(plugin.events.mute.getName());
+                        Basil.set(storage_muted, 'true');
+                    }
+                });
             }
-          });
-          $('#' + id_segmentNo + i).mouseover(function (e) {
-            e.preventDefault();
-            Engage.trigger(plugin.events.segmentMouseover.getName(), i);
-          }).mouseout(function (e) {
-            e.preventDefault();
-            Engage.trigger(plugin.events.segmentMouseout.getName(), i);
-          });
-        });
-      }
 
-      // register special events for mobile template
-      if (isMobileMode) {
-        $('#' + id_videoWrapper).hammer().bind('tap', function () {
-          Engage.trigger(plugin.events.showControls.getName());
-        });
+            $('#' + id_playpause_controls).click(function (e) {
+                e.stopPropagation();
+                Engage.trigger(plugin.events.playPause.getName());
+            });
 
-        $('.videoDisplay').hammer().bind('tap', function () {
-          if (!$(this).hasClass('active')) {
-            var id = (+this.id.replace('videoDisplay','')) - 1;
-            carousel.show(id);
-          }
-        });
+            $('#' + id_forward_button).click(function () {
+                if (segments && (segments.length > 0)) {
+                    Engage.trigger(plugin.events.nextChapter.getName());
+                } else {
+                    Engage.trigger(plugin.events.seekRight.getName());
+                }
+            });
 
-        $('#' + id_big_play_button).click(function (e) {
-          e.stopPropagation();
-          Engage.trigger(plugin.events.play.getName(), false);
-        });
+            $('#' + id_backward_button).click(function () {
+                if (segments && (segments.length > 0)) {
+                    Engage.trigger(plugin.events.previousChapter.getName());
+                } else {
+                    Engage.trigger(plugin.events.seekLeft.getName());
+                }
+            });
+
+            $('#' + id_fullscreen_button).click(function (e) {
+                e.preventDefault();
+
+                $(this).toggleClass('active');
+                var isInFullScreen = document.fullScreen ||
+                    document.mozFullScreen ||
+                    document.webkitIsFullScreen;
+                if (!isInFullScreen) {
+                    Engage.trigger(plugin.events.fullscreenEnable.getName());
+                } else if (isMobileMode) {
+                    Engage.trigger(plugin.events.fullscreenCancel.getName());
+                }
+            });
+
+            $('#' + id_captions_button).click(function (e) {
+                e.preventDefault();
+
+                $(this).toggleClass('active');
+                captionsOn = !captionsOn;
+                Engage.trigger(plugin.events.toggleCaptions.getName(), captionsOn);
+            })
+            // slider events
+            $('#' + id_slider).on(event_slidestart, function (event, ui) {
+                isSliding = true;
+                Engage.trigger(plugin.events.sliderStart.getName(), ui.value);
+            });
+            $('#' + id_slider).on(event_slidestop, function (event, ui) {
+                isSliding = false;
+                Engage.trigger(plugin.events.sliderStop.getName(), ui.value);
+            });
+            $('#' + id_slider).mouseover(function (e) {
+                e.preventDefault();
+                Engage.trigger(plugin.events.sliderMousein.getName());
+            }).mouseout(function (e) {
+                e.preventDefault();
+                Engage.trigger(plugin.events.sliderMouseout.getName());
+            }).mousemove(function (e) {
+                e.preventDefault();
+                var currPos = e.clientX / ($('#' + id_slider).width() + $('#' + id_slider).offset().left);
+                var dur = (duration && (duration > 0)) ? duration : 1;
+                currPos = (currPos < 0) ? 0 : ((currPos > 1) ? 1 : currPos);
+                Engage.trigger(plugin.events.sliderMousemove.getName(), currPos * dur);
+            });
+            // volume event
+            $('#' + id_volumeSlider).on(event_slide, function (event, ui) {
+                Engage.trigger(plugin.events.volumeSet.getName(), ui.value / 100);
+                if (!isMobileMode) {
+                    if (ui.value === 0) {
+                        showMuteButton();
+                    } else {
+                        showUnmuteButton();
+                    }
+                }
+            });
+            // check segments
+            if (segments && (segments.length > 0)) {
+                Engage.log('Controls: ' + segments.length + ' segments are available.');
+                $.each(segments, function (i, v) {
+                    $('#' + id_segmentNo + i).click(function (e) {
+                        e.preventDefault();
+                        var time = parseInt($(this).children().html());
+                        if (!isNaN(time)) {
+                            Engage.trigger(plugin.events.seek.getName(), time / 1000);
+                        }
+                    });
+                    $('#' + id_segmentNo + i).mouseover(function (e) {
+                        e.preventDefault();
+                        Engage.trigger(plugin.events.segmentMouseover.getName(), i);
+                    }).mouseout(function (e) {
+                        e.preventDefault();
+                        Engage.trigger(plugin.events.segmentMouseout.getName(), i);
+                    });
+                });
+            }
 
-        $('#' + id_volumeIcon).hammer().bind('tap', function () {
-          // toggle volume slider in mobile/embed mode
-          $(this).parent().toggleClass('active');
-        });
+            // register special events for mobile template
+            if (isMobileMode) {
+                $('#' + id_videoWrapper).hammer().bind('tap', function () {
+                    Engage.trigger(plugin.events.showControls.getName());
+                });
 
-        // create a VideoCarousel hammer.js instance for touch gesture support
-        carousel = new VideoCarousel($('#' + id_gestureContainer));
-      }
-    }
-  }
-
-  function getVolume() {
-    var isMute = Basil.get(storage_muted);
-    if (isMute == 'true') {
-      return 0;
-    } else {
-      var vol = $('#' + id_volumeSlider).slider('option', 'value');
-      return vol;
-    }
-  }
+                $('.videoDisplay').hammer().bind('tap', function () {
+                    if (!$(this).hasClass('active')) {
+                        var id = (+this.id.replace('videoDisplay', '')) - 1;
+                        carousel.show(id);
+                    }
+                });
 
-  function calculateEmbedAspectRatios() {
-    if ((aspectRatioWidth <= 0) && (aspectRatioHeight <= 0)) {
-      aspectRatioWidth = 1280;
-      aspectRatioHeight = 720;
-    }
-    embedWidthOne = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightOne);
-    embedWidthTwo = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightTwo);
-    embedWidthThree = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightThree);
-    embedWidthFour = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightFour);
-    embedWidthFive = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightFive);
-
-    $('#' + id_embed0).html('Embed ' + embedWidthOne + 'x' + embedHeightOne);
-    $('#' + id_embed1).html('Embed ' + embedWidthTwo + 'x' + embedHeightTwo);
-    $('#' + id_embed2).html('Embed ' + embedWidthThree + 'x' + embedHeightThree);
-    $('#' + id_embed3).html('Embed ' + embedWidthFour + 'x' + embedHeightFour);
-    $('#' + id_embed4).html('Embed ' + embedWidthFive + 'x' + embedHeightFive);
-
-    $('#' + id_embed_button).removeClass('disabled');
-  }
-
-  function ready() {
-    if (videosReady) {
-      loadStoredInitialValues();
-      Utils.greyIn(id_play_button);
-      Utils.enable(id_play_button);
-      Utils.greyIn(id_forward_button);
-      Utils.enable(id_forward_button);
-      Utils.greyIn(id_backward_button);
-      Utils.enable(id_backward_button);
-      if (!isAudioOnly) {
-        enableFullscreenButton = true;
-        $('#' + id_fullscreen_button).removeClass('disabled');
-      }
-
-      if (isDesktopMode) {
-        $('#' + id_pipIndicator).html(translate('off', 'off'));
-        Engage.trigger(plugin.events.movePiP.getName(), pipPos);
-        Engage.trigger(plugin.events.togglePiP.getName(), pipStatus);
-      }
-
-      if (videosInitialReadyness) {
-        Engage.trigger(plugin.events.focusVideo.getName(), currentFocusFlavor);
-        videosInitialReadyness = false;
-      }
-      if (Engage.model.get("captions")) {
-        $("#" + id_captions_button).removeClass("disabled");
-      }
-    }
-  }
-
-  function playPause() {
-    if (isPlaying) {
-      if (isMobileMode) {
-        $('#' + id_big_play_button).fadeOut();
-      }
-      $('#' + id_play_button).hide();
-      $('#' + id_pause_button).show();
-      if (!usingFlash && !isAudioOnly) {
-        $('#' + id_dropdownMenuPlaybackRate).removeClass('disabled');
-      }
-    } else {
-      if (isMobileMode) {
-        $('#' + id_big_play_button).fadeIn();
-      }
-      $('#' + id_play_button).show();
-      $('#' + id_pause_button).hide();
-    }
-  }
-
-  function mute() {
-    showMuteButton();
-    Engage.trigger(plugin.events.volumeSet.getName(), 0);
-  }
-
-  function unmute() {
-    showUnmuteButton();
-    var vol = Basil.get(storage_lastvolume);
-    if (vol) {
-      Engage.trigger(plugin.events.volumeSet.getName(), vol / 100);
-    } else {
-      Engage.trigger(plugin.events.volumeSet.getName(), 1);
-    }
-  }
-
-  function showUnmuteButton () {
-    $('#' + id_unmute_button).show();
-    $('#' + id_mute_button).hide();
-  }
-
-  function showMuteButton () {
-    $('#' + id_unmute_button).hide();
-    $('#' + id_mute_button).show();
-  }
-
-  function timeUpdate() {
-    if (videosReady) {
-      // set slider
-      var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
-      if (!isSliding && duration) {
-        var normTime = (currentTime / (duration / 1000)) * 1000;
-        $('#' + id_slider).slider('option', 'value', normTime);
-        if (!$('#' + id_navigation_time_current).is(':focus')) {
-          // distinguish between desktop and mobile, because in desktop mode
-          // an input field is used
-          if (isDesktopMode)
-            $('#' + id_navigation_time_current).val(Utils.formatSeconds(currentTime));
-          else
-            $('#' + id_navigation_time_current).text(Utils.formatSeconds(currentTime));
+                $('#' + id_big_play_button).click(function (e) {
+                    e.stopPropagation();
+                    Engage.trigger(plugin.events.play.getName(), false);
+                });
+
+                $('#' + id_volumeIcon).hammer().bind('tap', function () {
+                    // toggle volume slider in mobile/embed mode
+                    $(this).parent().toggleClass('active');
+                });
+
+                // create a VideoCarousel hammer.js instance for touch gesture support
+                carousel = new VideoCarousel($('#' + id_gestureContainer));
+            }
         }
-      }
-      var val = Math.round((duration / 1000) - currentTime);
-      val = ((val >= 0) && (val <= (duration / 1000))) ? val : '-';
-      $('#' + id_playbackRemTime075).html(Utils.formatSeconds(!isNaN(val) ? (val / 0.75) : val));
-      $('#' + id_playbackRemTime100).html(Utils.formatSeconds(!isNaN(val) ? (val) : val));
-      $('#' + id_playbackRemTime125).html(Utils.formatSeconds(!isNaN(val) ? (val / 1.25) : val));
-      $('#' + id_playbackRemTime150).html(Utils.formatSeconds(!isNaN(val) ? (val / 1.5) : val));
-      $('#' + id_playbackRemTime200).html(Utils.formatSeconds(!isNaN(val) ? (val / 2.0) : val));
-      $('#' + id_playbackRemTime300).html(Utils.formatSeconds(!isNaN(val) ? (val / 3.0) : val));
-    } else {
-      $('#' + id_slider).slider('option', 'value', 0);
     }
-  }
-
-  function VideoCarousel(container) {
-    this.container = container;
-    this.width = container.width();
-
-    this.currentIndex = 0;
-    this.length = Engage.model.get('videoDataModel').get('ids').length;
-
-    this.hammer = new Hammer.Manager(this.container.get(0));
-    this.hammer.add(new Hammer.Pan({ direction: Hammer.DIRECTION_HORIZONTAL, threshold: 10 }));
-    this.hammer.on('panstart panmove panend pancancel', Hammer.bindFn(this.onPan, this));
-  }
-
-  VideoCarousel.prototype = {
-    onPan: function (ev) {
-      // remove animation class to stop css transitions from interfering with user input
-      if (ev.type === 'panstart') {
-        this.container.removeClass('animate');
-      }
-
-      // stick to the finger
-      var delta = ev.deltaX;
-
-      // slow down at the first and last pane
-      if((this.currentIndex === 0 && ev.offsetDirection === Hammer.DIRECTION_RIGHT) ||
-       (this.currentIndex === this.length - 1 && ev.offsetDirection === Hammer.DIRECTION_LEFT)) {
-        delta *= 0.3;
-      }
-
-      this.width = this.container.width();
-      var percent = (100 / this.width) * delta;
-      var showIndex = this.currentIndex;
-
-      if (ev.type === 'panend' || ev.type === 'pancancel') {
-        if (Math.abs(percent) > 20 && ev.type === 'panend') {
-          Engage.log('Switch video by pan');
-          showIndex += (percent < 0) ? 1 : -1;
+
+    function getVolume() {
+        var isMute = Basil.get(storage_muted);
+        if (isMute == 'true') {
+            return 0;
+        } else {
+            var vol = $('#' + id_volumeSlider).slider('option', 'value');
+            return vol;
         }
-        percent = 0;
-        this.container.addClass('animate');
-      }
-
-      this.show(showIndex, percent);
-    },
-
-    show: function (showIndex, percent) {
-      showIndex = Math.max(0, Math.min(showIndex, this.length - 1));
-      percent = percent || 0;
-
-      var pos = -(showIndex * 100) + percent;
-      this.container.css({'transform': 'translateX(' + pos + '%)'});
-
-      // if the pane should actually be switched
-      if (showIndex !== this.currentIndex) {
-        // remove old classes
-        $('#' + id_engage_controls).removeClass('first last');
-        // add 'first' or 'last' class to wrapper if it's the first or last video showing
-        if (showIndex === 0 || showIndex === (this.length - 1)) {
-          $('#' + id_engage_controls).addClass((showIndex === 0) ? 'first' : 'last');
+    }
+
+    function calculateEmbedAspectRatios() {
+        if ((aspectRatioWidth <= 0) && (aspectRatioHeight <= 0)) {
+            aspectRatioWidth = 1280;
+            aspectRatioHeight = 720;
         }
+        embedWidthOne = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightOne);
+        embedWidthTwo = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightTwo);
+        embedWidthThree = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightThree);
+        embedWidthFour = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightFour);
+        embedWidthFive = Utils.getAspectRatioWidth(aspectRatioWidth, aspectRatioHeight, embedHeightFive);
+
+        $('#' + id_embed0).html('Embed ' + embedWidthOne + 'x' + embedHeightOne);
+        $('#' + id_embed1).html('Embed ' + embedWidthTwo + 'x' + embedHeightTwo);
+        $('#' + id_embed2).html('Embed ' + embedWidthThree + 'x' + embedHeightThree);
+        $('#' + id_embed3).html('Embed ' + embedWidthFour + 'x' + embedHeightFour);
+        $('#' + id_embed4).html('Embed ' + embedWidthFive + 'x' + embedHeightFive);
+
+        $('#' + id_embed_button).removeClass('disabled');
+    }
 
-        $('#current_video_id').text(showIndex + 1);
+    function ready() {
+        if (videosReady) {
+            loadStoredInitialValues();
+            Utils.greyIn(id_play_button);
+            Utils.enable(id_play_button);
+            Utils.greyIn(id_forward_button);
+            Utils.enable(id_forward_button);
+            Utils.greyIn(id_backward_button);
+            Utils.enable(id_backward_button);
+            if (!isAudioOnly) {
+                enableFullscreenButton = true;
+                $('#' + id_fullscreen_button).removeClass('disabled');
+            }
 
-        Engage.trigger(plugin.events.switchVideo.getName(), showIndex);
-      }
+            if (isDesktopMode) {
+                $('#' + id_pipIndicator).html(translate('off', 'off'));
+                Engage.trigger(plugin.events.movePiP.getName(), pipPos);
+                Engage.trigger(plugin.events.togglePiP.getName(), pipStatus);
+            }
 
-      this.currentIndex = showIndex;
-    }
-  };
-
-  /**
-   * Initializes the plugin
-   */
-  function initPlugin() {
-    // Check that the videoDataModel is available.
-    if (! Engage.model.get('videoDataModel')) {
-      Engage.on(videoDataModelChange, function() {
-        Engage.log("Controls: videoDataModel available.");
-        initPlugin();
-      });
-      window.setTimeout(function() {
-        if (Engage.model.get('videoDataModel') && ! inited) {
-          initPlugin();
+            if (videosInitialReadyness) {
+                Engage.trigger(plugin.events.focusVideo.getName(), currentFocusFlavor);
+                videosInitialReadyness = false;
+            }
+            if (Engage.model.get("captions")) {
+                $("#" + id_captions_button).removeClass("disabled");
+            }
         }
-      }, 2000);
-      Engage.log("Controls: videoDataModel not available at start.");
-      return;
     }
-    // only init if plugin template was inserted into the DOM
-    if (plugin.inserted && ! inited) {
-      inited = true;
-      Engage.on(plugin.events.videoFormatsFound.getName(), function (formatarr) {
-        if (Array.isArray(formatarr)) {
-          resolutions = formatarr;
-          if (controlsViewTopIfBottom) {
-            controlsViewTopIfBottom.render();
-          }
-          if (controlsView) {
-            controlsView.render();
-          }
-          addQualityChangeEvents();
-        }
-      });
-
-      // retrigger the event in case the videoFormatsFound event from the video plugin
-      // was fired before the controls plugin was initialized
-      // to make sure the quality dropdown menu is shown
-      Engage.trigger(plugin.events.videoFormatsFound.getName(), true);
-
-      Engage.on(plugin.events.numberOfVideodisplaysSet.getName(), function (number) {
-        numberVideos = number;
-
-        if (number > 1) {
-          if (controlsViewTopIfBottom) {
-            controlsViewTopIfBottom.render();
-          }
-          if (controlsView) {
-            controlsView.render();
-          }
-          if (isDesktopMode) {
-            addLayoutEvents();
-          }
-        }
-      });
-      Engage.on(plugin.events.aspectRatioSet.getName(), function (as) {
-        if (as) {
-          aspectRatioWidth = as[0] || 0;
-          aspectRatioHeight = as[1] || 0;
-          aspectRatio = as[2] || 0;
-          aspectRatioTriggered = true;
-          if (isDesktopMode) {
-            calculateEmbedAspectRatios();
-            addEmbedRatioEvents();
-          }
-        }
-      });
-      Engage.on(plugin.events.mediaPackageModelError.getName(), function (msg) {
-        mediapackageError = true;
-      });
-      Engage.on(plugin.events.usingFlash.getName(), function (flash) {
-        usingFlash = flash;
-        addNonFlashEvents();
-      });
-      Engage.on(plugin.events.isAudioOnly.getName(), function (audio) {
-        isAudioOnly = audio;
-      });
-      Engage.on(plugin.events.playbackRateChanged.getName(), function (pbr) {
-        $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(pbr));
-      });
-      Engage.on(plugin.events.volumeSet.getName(), function (volume) {
-        $('#' + id_volumeSlider).slider('value', volume * 100);
-        if ((volume * 100) > 1) {
-          Basil.set(storage_lastvolume, volume * 100);
-        }
-        Basil.set(storage_volume, volume * 100);
-        if (volume > 0) {
-          Basil.set(storage_muted, 'false');
-        } else {
-          Basil.set(storage_muted, 'true');
-        }
 
-        // ui feedback in mobile mode
-        if (isMobileMode) {
-          var $el = $('#' + id_volumeIcon + ' span');
-          if (volume === 0) {
-            $el.removeClass('low');
-            $el.addClass('muted');
-          } else if (volume < 0.6) {
-            $el.removeClass('muted');
-            $el.addClass('low');
-          } else {
-            $el.removeClass('low muted');
-          }
-        }
-      });
-      Engage.on(plugin.events.volumeUp.getName(), function () {
-        var vol = getVolume();
-        if ((vol + volUpDown) <= 100) {
-          Engage.trigger(plugin.events.volumeSet.getName(), (vol + volUpDown) / 100);
+    function playPause() {
+        if (isPlaying) {
+            if (isMobileMode) {
+                $('#' + id_big_play_button).fadeOut();
+            }
+            $('#' + id_play_button).hide();
+            $('#' + id_pause_button).show();
+            if (!usingFlash && !isAudioOnly) {
+                $('#' + id_dropdownMenuPlaybackRate).removeClass('disabled');
+            }
         } else {
-          Engage.trigger(plugin.events.volumeSet.getName(), 1);
+            if (isMobileMode) {
+                $('#' + id_big_play_button).fadeIn();
+            }
+            $('#' + id_play_button).show();
+            $('#' + id_pause_button).hide();
         }
-        unmute();
-      });
-      Engage.on(plugin.events.volumeDown.getName(), function () {
-        var vol = getVolume();
-        if ((vol - volUpDown) > 0) {
-          Engage.trigger(plugin.events.volumeSet.getName(), (vol - volUpDown) / 100);
-          unmute();
+    }
+
+    function mute() {
+        showMuteButton();
+        Engage.trigger(plugin.events.volumeSet.getName(), 0);
+    }
+
+    function unmute() {
+        showUnmuteButton();
+        var vol = Basil.get(storage_lastvolume);
+        if (vol) {
+            Engage.trigger(plugin.events.volumeSet.getName(), vol / 100);
         } else {
-          Engage.trigger(plugin.events.mute.getName());
-        }
-      });
-      Engage.on(plugin.events.ready.getName(), function (query) {
-        if (query === true || videosReady === true) {
-          return;
-        }
-        addZoomEvents();
-        if (!mediapackageError) {
-          videosReady = true;
-          ready();
-        }
-      });
-      Engage.on(plugin.events.play.getName(), function () {
-        if (!mediapackageError && videosReady) {
-          isPlaying = true;
-          playPause();
-
-          if (isMobileMode) {
-            Engage.trigger(plugin.events.fullscreenEnable.getName());
-            Engage.trigger(plugin.events.hideControls.getName());
-            $('#swipe_hint').fadeOut();
-          }
-        }
-      });
-      Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
-        if (!mediapackageError && videosReady) {
-          isPlaying = false;
-          playPause();
-        }
-      });
-      Engage.on(plugin.events.mute.getName(), function () {
-        if (!mediapackageError) {
-          mute();
-        }
-      });
-      Engage.on(plugin.events.unmute.getName(), function () {
-        if (!mediapackageError) {
-          unmute();
+            Engage.trigger(plugin.events.volumeSet.getName(), 1);
         }
-      });
-      Engage.on(plugin.events.muteToggle.getName(), function () {
-        if (!mediapackageError) {
-          var muted = Basil.get(storage_muted);
-          if (muted == 'true') {
-            Engage.trigger(plugin.events.unmute.getName());
-          } else {
-            Engage.trigger(plugin.events.mute.getName());
-          }
-        }
-      });
-      Engage.on(plugin.events.fullscreenCancel.getName(), function () {
-        if (isMobileMode && isPlaying) {
-          Engage.trigger(plugin.events.pause.getName());
-          Engage.trigger(plugin.events.showControls.getName());
-        }
-      });
-      Engage.on(plugin.events.fullscreenChange.getName(), function () {
-        var isInFullScreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
-        if (!isInFullScreen) {
-          Engage.trigger(plugin.events.fullscreenCancel.getName());
-        }
-      });
-      Engage.on(plugin.events.timeupdate.getName(), function (_currentTime) {
-        if (!mediapackageError) {
-          currentTime = _currentTime;
-          timeUpdate();
-        }
-      });
-      Engage.on(plugin.events.ended.getName(), function () {
-        if (!mediapackageError && videosReady) {
-          Engage.trigger(plugin.events.pause);
-          if (isMobileMode) {
-            Engage.trigger(plugin.events.showControls.getName());
-          }
-        }
-      });
-      Engage.on(plugin.events.segmentMouseover.getName(), function (no) {
-        if (!mediapackageError) {
-          $('#' + id_segmentNo + no).addClass('segmentHover');
-        }
-      });
-      Engage.on(plugin.events.segmentMouseout.getName(), function (no) {
-        if (!mediapackageError) {
-          $('#' + id_segmentNo + no).removeClass('segmentHover');
-        }
-      });
-
-      // no pip in mobile mode
-      if (!isMobileMode) {
-        Engage.on(plugin.events.togglePiP.getName(), function (pip) {
-          if (pip !== undefined) {
-            Basil.set(storage_pip, pip);
-            pipStatus = pip;
-            if (currentFocusFlavor !== 'focus.none') {
-              if (! pip) {
-                $('#' + id_pipIndicator).html(translate('beside', 'beside'));
-              } else {
-                if (pipPos === 'left') {
-                  $('#' + id_pipIndicator).html(translate('left', 'left'));
-                } else {
-                  $('#' + id_pipIndicator).html(translate('right', 'right'));
+    }
+
+    function showUnmuteButton() {
+        $('#' + id_unmute_button).show();
+        $('#' + id_mute_button).hide();
+    }
+
+    function showMuteButton() {
+        $('#' + id_unmute_button).hide();
+        $('#' + id_mute_button).show();
+    }
+
+    function timeUpdate() {
+        if (videosReady) {
+            // set slider
+            var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
+            if (!isSliding && duration) {
+                var normTime = (currentTime / (duration / 1000)) * 1000;
+                $('#' + id_slider).slider('option', 'value', normTime);
+                if (!$('#' + id_navigation_time_current).is(':focus')) {
+                    // distinguish between desktop and mobile, because in desktop mode
+                    // an input field is used
+                    if (isDesktopMode)
+                        $('#' + id_navigation_time_current).val(Utils.formatSeconds(currentTime));
+                    else
+                        $('#' + id_navigation_time_current).text(Utils.formatSeconds(currentTime));
                 }
-              }
             }
-          }
-        });
-        Engage.on(plugin.events.focusVideo.getName(), function (flavor) {
-          if (flavor !== undefined && flavor !== null && flavor.indexOf('focus.') < 1) {
-            Basil.set(storage_focus_video, flavor);
-            var pip = Basil.get(storage_pip);
-            currentFocusFlavor = flavor;
-            if (pip === undefined || ! pip) {
-              $('#' + id_pipIndicator).html(translate('beside', 'beside'));
-            } else {
-              if (pipPos === 'left') {
-                $('#' + id_pipIndicator).html(translate('left', 'left'));
-              } else {
-                $('#' + id_pipIndicator).html(translate('right', 'right'));
-              }
+            var val = Math.round((duration / 1000) - currentTime);
+            val = ((val >= 0) && (val <= (duration / 1000))) ? val : '-';
+            $('#' + id_playbackRemTime075).html(Utils.formatSeconds(!isNaN(val) ? (val / 0.75) : val));
+            $('#' + id_playbackRemTime100).html(Utils.formatSeconds(!isNaN(val) ? (val) : val));
+            $('#' + id_playbackRemTime125).html(Utils.formatSeconds(!isNaN(val) ? (val / 1.25) : val));
+            $('#' + id_playbackRemTime150).html(Utils.formatSeconds(!isNaN(val) ? (val / 1.5) : val));
+            $('#' + id_playbackRemTime200).html(Utils.formatSeconds(!isNaN(val) ? (val / 2.0) : val));
+            $('#' + id_playbackRemTime300).html(Utils.formatSeconds(!isNaN(val) ? (val / 3.0) : val));
+        } else {
+            $('#' + id_slider).slider('option', 'value', 0);
+        }
+    }
+
+    function VideoCarousel(container) {
+        this.container = container;
+        this.width = container.width();
+
+        this.currentIndex = 0;
+        this.length = Engage.model.get('videoDataModel').get('ids').length;
+
+        this.hammer = new Hammer.Manager(this.container.get(0));
+        this.hammer.add(new Hammer.Pan({direction: Hammer.DIRECTION_HORIZONTAL, threshold: 10}));
+        this.hammer.on('panstart panmove panend pancancel', Hammer.bindFn(this.onPan, this));
+    }
+
+    VideoCarousel.prototype = {
+        onPan: function (ev) {
+            // remove animation class to stop css transitions from interfering with user input
+            if (ev.type === 'panstart') {
+                this.container.removeClass('animate');
             }
-          }
-        });
-        Engage.on(plugin.events.resetLayout.getName(), function () {
-          Basil.set(storage_focus_video, 'focus.none');
-          currentFocusFlavor = 'focus.none';
-          $('#' + id_pipIndicator).html(translate('off', 'off'));
-        });
-        Engage.on(plugin.events.movePiP.getName(), function (pos) {
-          if (pos !== undefined) {
-            Basil.set(storage_pip_pos, pos);
-            pipPos = pos;
-            if (currentFocusFlavor !== 'focus.none') {
-              if (pos === 'left') {
-                $('#' + id_pipIndicator).html(translate('left', 'left'));
-              } else {
-                $('#' + id_pipIndicator).html(translate('right', 'right'));
-              }
+
+            // stick to the finger
+            var delta = ev.deltaX;
+
+            // slow down at the first and last pane
+            if ((this.currentIndex === 0 && ev.offsetDirection === Hammer.DIRECTION_RIGHT) ||
+                (this.currentIndex === this.length - 1 && ev.offsetDirection === Hammer.DIRECTION_LEFT)) {
+                delta *= 0.3;
             }
-          }
-        });
-        Engage.on(plugin.events.captionsFound.getName(), function () {
-            $("#" + id_captions_button).removeClass("disabled");
-        });
-      }
-
-      if (isMobileMode) {
-        // register show- and hideControls event in mobile mode
-        Engage.on(plugin.events.showControls.getName(), function () {
-          if (!controlsVisible) {
-            controlsVisible = true;
-            $('#' + id_engage_controls).fadeIn();
-            controlsTimer = Utils.timer.setup(function () {
-              Engage.trigger(plugin.events.hideControls.getName());
-            }, hideTimeout * 1000);
-          } else {                            // when controls are visible
-            if (controlsTimer) {
-              controlsTimer.renew();
+
+            this.width = this.container.width();
+            var percent = (100 / this.width) * delta;
+            var showIndex = this.currentIndex;
+
+            if (ev.type === 'panend' || ev.type === 'pancancel') {
+                if (Math.abs(percent) > 20 && ev.type === 'panend') {
+                    Engage.log('Switch video by pan');
+                    showIndex += (percent < 0) ? 1 : -1;
+                }
+                percent = 0;
+                this.container.addClass('animate');
             }
-          }
-        });
-        Engage.on(plugin.events.hideControls.getName(), function () {
-          if (controlsVisible && isPlaying) {
-            $('#' + id_engage_controls).fadeOut();
-            controlsVisible = false;
-          }
-        });
 
-        // add first class to video wrapper
-        $('#' + id_engage_controls).addClass('first');
-      }
+            this.show(showIndex, percent);
+        },
+
+        show: function (showIndex, percent) {
+            showIndex = Math.max(0, Math.min(showIndex, this.length - 1));
+            percent = percent || 0;
 
-      Engage.on(plugin.events.nextChapter.getName(), function () {
-        if (segments && (segments.length > 0)) {
-          var seekTime = Utils.nextSegmentStart(segments, currentTime);
-          if (!isNaN(seekTime)) {
-            Engage.trigger(plugin.events.seek.getName(), seekTime / 1000);
-          }
+            var pos = -(showIndex * 100) + percent;
+            this.container.css({'transform': 'translateX(' + pos + '%)'});
+
+            // if the pane should actually be switched
+            if (showIndex !== this.currentIndex) {
+                // remove old classes
+                $('#' + id_engage_controls).removeClass('first last');
+                // add 'first' or 'last' class to wrapper if it's the first or last video showing
+                if (showIndex === 0 || showIndex === (this.length - 1)) {
+                    $('#' + id_engage_controls).addClass((showIndex === 0) ? 'first' : 'last');
+                }
+
+                $('#current_video_id').text(showIndex + 1);
+
+                Engage.trigger(plugin.events.switchVideo.getName(), showIndex);
+            }
+
+            this.currentIndex = showIndex;
         }
-      });
-      Engage.on(plugin.events.previousChapter.getName(), function () {
-        if (segments && (segments.length > 0)) {
-          var seekTime = Utils.previousSegmentStart(segments, currentTime);
-          if (!isNaN(seekTime)) {
-            Engage.trigger(plugin.events.seek.getName(), seekTime / 1000);
-          }
+    };
+
+    /**
+     * Initializes the plugin
+     */
+    function initPlugin() {
+        // Check that the videoDataModel is available.
+        if (!Engage.model.get('videoDataModel')) {
+            Engage.on(videoDataModelChange, function () {
+                Engage.log("Controls: videoDataModel available.");
+                initPlugin();
+            });
+            window.setTimeout(function () {
+                if (Engage.model.get('videoDataModel') && !inited) {
+                    initPlugin();
+                }
+            }, 2000);
+            Engage.log("Controls: videoDataModel not available at start.");
+            return;
         }
-      });
+        // only init if plugin template was inserted into the DOM
+        if (plugin.inserted && !inited) {
+            inited = true;
+            Engage.on(plugin.events.videoFormatsFound.getName(), function (formatarr) {
+                if (Array.isArray(formatarr)) {
+                    resolutions = formatarr;
+                    if (controlsViewTopIfBottom) {
+                        controlsViewTopIfBottom.render();
+                    }
+                    if (controlsView) {
+                        controlsView.render();
+                    }
+                    addQualityChangeEvents();
+                }
+            });
+
+            // retrigger the event in case the videoFormatsFound event from the video plugin
+            // was fired before the controls plugin was initialized
+            // to make sure the quality dropdown menu is shown
+            Engage.trigger(plugin.events.videoFormatsFound.getName(), true);
+
+            Engage.on(plugin.events.numberOfVideodisplaysSet.getName(), function (number) {
+                numberVideos = number;
+
+                if (number > 1) {
+                    if (controlsViewTopIfBottom) {
+                        controlsViewTopIfBottom.render();
+                    }
+                    if (controlsView) {
+                        controlsView.render();
+                    }
+                    if (isDesktopMode) {
+                        addLayoutEvents();
+                    }
+                }
+            });
+            Engage.on(plugin.events.aspectRatioSet.getName(), function (as) {
+                if (as) {
+                    aspectRatioWidth = as[0] || 0;
+                    aspectRatioHeight = as[1] || 0;
+                    aspectRatio = as[2] || 0;
+                    aspectRatioTriggered = true;
+                    if (isDesktopMode) {
+                        calculateEmbedAspectRatios();
+                        addEmbedRatioEvents();
+                    }
+                }
+            });
+            Engage.on(plugin.events.mediaPackageModelError.getName(), function (msg) {
+                mediapackageError = true;
+            });
+            Engage.on(plugin.events.usingFlash.getName(), function (flash) {
+                usingFlash = flash;
+                addNonFlashEvents();
+            });
+            Engage.on(plugin.events.isAudioOnly.getName(), function (audio) {
+                isAudioOnly = audio;
+            });
+            Engage.on(plugin.events.playbackRateChanged.getName(), function (pbr) {
+                $('#' + id_playbackRateIndicator).html(Utils.getFormattedPlaybackRate(pbr));
+            });
+            Engage.on(plugin.events.volumeSet.getName(), function (volume) {
+                $('#' + id_volumeSlider).slider('value', volume * 100);
+                if ((volume * 100) > 1) {
+                    Basil.set(storage_lastvolume, volume * 100);
+                }
+                Basil.set(storage_volume, volume * 100);
+                if (volume > 0) {
+                    Basil.set(storage_muted, 'false');
+                } else {
+                    Basil.set(storage_muted, 'true');
+                }
 
-      if (!Engage.controls_top && plugin.template_topIfBottom && (plugin.template_topIfBottom != 'none')) {
-        controlsViewTopIfBottom = new ControlsViewTop_ifBottom(Engage.model.get('videoDataModel'), plugin.template_topIfBottom, plugin.pluginPath_topIfBottom);
-      }
-      controlsView = new ControlsView(Engage.model.get('videoDataModel'), plugin.template, plugin.pluginPath);
+                // ui feedback in mobile mode
+                if (isMobileMode) {
+                    var $el = $('#' + id_volumeIcon + ' span');
+                    if (volume === 0) {
+                        $el.removeClass('low');
+                        $el.addClass('muted');
+                    } else if (volume < 0.6) {
+                        $el.removeClass('muted');
+                        $el.addClass('low');
+                    } else {
+                        $el.removeClass('low muted');
+                    }
+                }
+            });
+            Engage.on(plugin.events.volumeUp.getName(), function () {
+                var vol = getVolume();
+                if ((vol + volUpDown) <= 100) {
+                    Engage.trigger(plugin.events.volumeSet.getName(), (vol + volUpDown) / 100);
+                } else {
+                    Engage.trigger(plugin.events.volumeSet.getName(), 1);
+                }
+                unmute();
+            });
+            Engage.on(plugin.events.volumeDown.getName(), function () {
+                var vol = getVolume();
+                if ((vol - volUpDown) > 0) {
+                    Engage.trigger(plugin.events.volumeSet.getName(), (vol - volUpDown) / 100);
+                    unmute();
+                } else {
+                    Engage.trigger(plugin.events.mute.getName());
+                }
+            });
+            Engage.on(plugin.events.ready.getName(), function (query) {
+                if (query === true || videosReady === true) {
+                    return;
+                }
+                addZoomEvents();
+                if (!mediapackageError) {
+                    videosReady = true;
+                    ready();
+                }
+            });
+            Engage.on(plugin.events.play.getName(), function () {
+                if (!mediapackageError && videosReady) {
+                    isPlaying = true;
+                    playPause();
+
+                    if (isMobileMode) {
+                        Engage.trigger(plugin.events.fullscreenEnable.getName());
+                        Engage.trigger(plugin.events.hideControls.getName());
+                        $('#swipe_hint').fadeOut();
+                    }
+                }
+            });
+            Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
+                if (!mediapackageError && videosReady) {
+                    isPlaying = false;
+                    playPause();
+                }
+            });
+            Engage.on(plugin.events.mute.getName(), function () {
+                if (!mediapackageError) {
+                    mute();
+                }
+            });
+            Engage.on(plugin.events.unmute.getName(), function () {
+                if (!mediapackageError) {
+                    unmute();
+                }
+            });
+            Engage.on(plugin.events.muteToggle.getName(), function () {
+                if (!mediapackageError) {
+                    var muted = Basil.get(storage_muted);
+                    if (muted == 'true') {
+                        Engage.trigger(plugin.events.unmute.getName());
+                    } else {
+                        Engage.trigger(plugin.events.mute.getName());
+                    }
+                }
+            });
+            Engage.on(plugin.events.fullscreenCancel.getName(), function () {
+                if (isMobileMode && isPlaying) {
+                    Engage.trigger(plugin.events.pause.getName());
+                    Engage.trigger(plugin.events.showControls.getName());
+                }
+            });
+            Engage.on(plugin.events.fullscreenChange.getName(), function () {
+                var isInFullScreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
+                if (!isInFullScreen) {
+                    Engage.trigger(plugin.events.fullscreenCancel.getName());
+                }
+            });
+            Engage.on(plugin.events.timeupdate.getName(), function (_currentTime) {
+                if (!mediapackageError) {
+                    currentTime = _currentTime;
+                    timeUpdate();
+                }
+            });
+            Engage.on(plugin.events.ended.getName(), function () {
+                if (!mediapackageError && videosReady) {
+                    Engage.trigger(plugin.events.pause);
+                    if (isMobileMode) {
+                        Engage.trigger(plugin.events.showControls.getName());
+                    }
+                }
+            });
+            Engage.on(plugin.events.segmentMouseover.getName(), function (no) {
+                if (!mediapackageError) {
+                    $('#' + id_segmentNo + no).addClass('segmentHover');
+                }
+            });
+            Engage.on(plugin.events.segmentMouseout.getName(), function (no) {
+                if (!mediapackageError) {
+                    $('#' + id_segmentNo + no).removeClass('segmentHover');
+                }
+            });
+
+            // no pip in mobile mode
+            if (!isMobileMode) {
+                Engage.on(plugin.events.togglePiP.getName(), function (pip) {
+                    if (pip !== undefined) {
+                        Basil.set(storage_pip, pip);
+                        pipStatus = pip;
+                        if (currentFocusFlavor !== 'focus.none') {
+                            if (!pip) {
+                                $('#' + id_pipIndicator).html(translate('beside', 'beside'));
+                            } else {
+                                if (pipPos === 'left') {
+                                    $('#' + id_pipIndicator).html(translate('left', 'left'));
+                                } else {
+                                    $('#' + id_pipIndicator).html(translate('right', 'right'));
+                                }
+                            }
+                        }
+                    }
+                });
+                Engage.on(plugin.events.focusVideo.getName(), function (flavor) {
+                    if (flavor !== undefined && flavor !== null && flavor.indexOf('focus.') < 1) {
+                        Basil.set(storage_focus_video, flavor);
+                        var pip = Basil.get(storage_pip);
+                        currentFocusFlavor = flavor;
+                        if (pip === undefined || !pip) {
+                            $('#' + id_pipIndicator).html(translate('beside', 'beside'));
+                        } else {
+                            if (pipPos === 'left') {
+                                $('#' + id_pipIndicator).html(translate('left', 'left'));
+                            } else {
+                                $('#' + id_pipIndicator).html(translate('right', 'right'));
+                            }
+                        }
+                    }
+                });
+                Engage.on(plugin.events.resetLayout.getName(), function () {
+                    Basil.set(storage_focus_video, 'focus.none');
+                    currentFocusFlavor = 'focus.none';
+                    $('#' + id_pipIndicator).html(translate('off', 'off'));
+                });
+                Engage.on(plugin.events.movePiP.getName(), function (pos) {
+                    if (pos !== undefined) {
+                        Basil.set(storage_pip_pos, pos);
+                        pipPos = pos;
+                        if (currentFocusFlavor !== 'focus.none') {
+                            if (pos === 'left') {
+                                $('#' + id_pipIndicator).html(translate('left', 'left'));
+                            } else {
+                                $('#' + id_pipIndicator).html(translate('right', 'right'));
+                            }
+                        }
+                    }
+                });
+                Engage.on(plugin.events.captionsFound.getName(), function () {
+                    $("#" + id_captions_button).removeClass("disabled");
+                });
+            }
 
-      loadStoredInitialValues();
-    }
-  }
+            if (isMobileMode) {
+                // register show- and hideControls event in mobile mode
+                Engage.on(plugin.events.showControls.getName(), function () {
+                    if (!controlsVisible) {
+                        controlsVisible = true;
+                        $('#' + id_engage_controls).fadeIn();
+                        controlsTimer = Utils.timer.setup(function () {
+                            Engage.trigger(plugin.events.hideControls.getName());
+                        }, hideTimeout * 1000);
+                    } else {                            // when controls are visible
+                        if (controlsTimer) {
+                            controlsTimer.renew();
+                        }
+                    }
+                });
+                Engage.on(plugin.events.hideControls.getName(), function () {
+                    if (controlsVisible && isPlaying) {
+                        $('#' + id_engage_controls).fadeOut();
+                        controlsVisible = false;
+                    }
+                });
 
-  // init event
-  Engage.log('Controls: Init');
-  var relative_plugin_path = Engage.getPluginPath('EngagePluginControls');
+                // add first class to video wrapper
+                $('#' + id_engage_controls).addClass('first');
+            }
 
-  // listen on a change/set of the InfoMe model
-  Engage.model.on(infoMeChange, function () {
-    initCount -= 1;
-    if (initCount == 0) {
-      initPlugin();
-    }
-  });
+            Engage.on(plugin.events.nextChapter.getName(), function () {
+                if (segments && (segments.length > 0)) {
+                    var seekTime = Utils.nextSegmentStart(segments, currentTime);
+                    if (!isNaN(seekTime)) {
+                        Engage.trigger(plugin.events.seek.getName(), seekTime / 1000);
+                    }
+                }
+            });
+            Engage.on(plugin.events.previousChapter.getName(), function () {
+                if (segments && (segments.length > 0)) {
+                    var seekTime = Utils.previousSegmentStart(segments, currentTime);
+                    if (!isNaN(seekTime)) {
+                        Engage.trigger(plugin.events.seek.getName(), seekTime / 1000);
+                    }
+                }
+            });
 
-  // listen on a change/set of the mediaPackage model
-  Engage.model.on(mediapackageChange, function () {
-    initCount -= 1;
-    if (initCount == 0) {
-      initPlugin();
-    }
-  });
-
-  // all plugins loaded
-  Engage.on(plugin.events.plugin_load_done.getName(), function () {
-    Engage.log('Controls: Plugin load done');
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
+            if (!Engage.controls_top && plugin.template_topIfBottom && (plugin.template_topIfBottom != 'none')) {
+                // Don't show controls above video
+                // controlsViewTopIfBottom = new ControlsViewTop_ifBottom(Engage.model.get('videoDataModel'), plugin.template_topIfBottom, plugin.pluginPath_topIfBottom);
+            }
+            controlsView = new ControlsView(Engage.model.get('videoDataModel'), plugin.template, plugin.pluginPath);
+
+            loadStoredInitialValues();
+        }
     }
-  });
 
-  // load jquery-ui lib
-  require([relative_plugin_path + jQueryUIPath], function () {
-    Engage.log('Controls: Lib jQuery UI loaded');
+    // init event
+    Engage.log('Controls: Init');
+    var relative_plugin_path = Engage.getPluginPath('EngagePluginControls');
 
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
-    }
+    // listen on a change/set of the InfoMe model
+    Engage.model.on(infoMeChange, function () {
+        initCount -= 1;
+        if (initCount == 0) {
+            initPlugin();
+        }
+    });
 
-    // load jquery-ui touch-punch lib in mobile mode
-    if (isMobileMode) {
-      require([relative_plugin_path + 'lib/jquery.ui.touch-punch.min'], function () {
-        Engage.log('Controls: Lib jQuery UI Touch Punch loaded');
+    // listen on a change/set of the mediaPackage model
+    Engage.model.on(mediapackageChange, function () {
+        initCount -= 1;
+        if (initCount == 0) {
+            initPlugin();
+        }
+    });
+
+    // all plugins loaded
+    Engage.on(plugin.events.plugin_load_done.getName(), function () {
+        Engage.log('Controls: Plugin load done');
         initCount -= 1;
         if (initCount <= 0) {
-          initPlugin();
+            initPlugin();
         }
-      });
-    }
-  });
-
-  // load hammer.js lib for gestures on mobile (touch enabled) devices
-  if (isMobileMode) {
-    require([relative_plugin_path + 'lib/hammer.min'], function () {
-      Engage.log('Controls: Lib hammer.js loaded');
-      initCount -= 1;
-      if (initCount <= 0) {
-        initPlugin();
-      }
-
-      require([relative_plugin_path + 'lib/jquery.hammer'], function () {
+    });
+
+    // load jquery-ui lib
+    require([relative_plugin_path + jQueryUIPath], function () {
+        Engage.log('Controls: Lib jQuery UI loaded');
+
         initCount -= 1;
         if (initCount <= 0) {
-          initPlugin();
+            initPlugin();
+        }
+
+        // load jquery-ui touch-punch lib in mobile mode
+        if (isMobileMode) {
+            require([relative_plugin_path + 'lib/jquery.ui.touch-punch.min'], function () {
+                Engage.log('Controls: Lib jQuery UI Touch Punch loaded');
+                initCount -= 1;
+                if (initCount <= 0) {
+                    initPlugin();
+                }
+            });
         }
-      });
     });
-  }
-
-  // load utils class
-  require([relative_plugin_path + "utils"], function(utils) {
-      Engage.log("Controls: Utils class loaded");
-      Utils = new utils();
-      initTranslate(Engage.model.get("language"), function() {
-          Engage.log("Controls: Successfully translated.");
-          initCount -= 1;
-          if (initCount <= 0) {
-              initPlugin();
-          }
-      }, function() {
-          Engage.log("Controls: Error translating...");
-          initCount -= 1;
-          if (initCount <= 0) {
-              initPlugin();
-          }
-      });
-  });
-
-  return plugin;
+
+    // load hammer.js lib for gestures on mobile (touch enabled) devices
+    if (isMobileMode) {
+        require([relative_plugin_path + 'lib/hammer.min'], function () {
+            Engage.log('Controls: Lib hammer.js loaded');
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+
+            require([relative_plugin_path + 'lib/jquery.hammer'], function () {
+                initCount -= 1;
+                if (initCount <= 0) {
+                    initPlugin();
+                }
+            });
+        });
+    }
+
+    // load utils class
+    require([relative_plugin_path + "utils"], function (utils) {
+        Engage.log("Controls: Utils class loaded");
+        Utils = new utils();
+        initTranslate(Engage.model.get("language"), function () {
+            Engage.log("Controls: Successfully translated.");
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        }, function () {
+            Engage.log("Controls: Error translating...");
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        });
+    });
+
+    return plugin;
 });
diff --git a/player/plugin/custom-mhConnection/collections/footprint.js b/player/plugin/custom-mhConnection/collections/footprint.js
index 4069139..2bc8fa9 100644
--- a/player/plugin/custom-mhConnection/collections/footprint.js
+++ b/player/plugin/custom-mhConnection/collections/footprint.js
@@ -23,8 +23,8 @@
 define(["jquery", "backbone", "engage/core", "../models/footprint"], function($, Backbone, Engage, FootprintModel) {
     "use strict";
 
-    var USERTRACKING_ENDPOINT = "/usertracking";
-    var USERTRACKING_ENDPOINT_FOOTPRINTS = "../info/footprint.json";
+    var USERTRACKING_ENDPOINT = opencastlink+"/usertracking";
+    var USERTRACKING_ENDPOINT_FOOTPRINTS = opencastlink+"/info/footprint.json";
 
     var mediaPackageID = Engage.model.get("urlParameters").id;
     if (!mediaPackageID) {
@@ -34,6 +34,14 @@ define(["jquery", "backbone", "engage/core", "../models/footprint"], function($,
     var FootprintCollection = Backbone.Collection.extend({
         model: FootprintModel,
         url: USERTRACKING_ENDPOINT_FOOTPRINTS,
+        sync: function(method, model, options) {
+            options ||(options = {});
+
+            options.crossDomain = true;
+            options.xhrFields = {withCredentials:true};
+
+            return Backbone.sync(method, model, options);
+        },
         initialize: function() {
             this.update();
         },
diff --git a/player/plugin/custom-mhConnection/main.js b/player/plugin/custom-mhConnection/main.js
index 651d4d0..2651211 100644
--- a/player/plugin/custom-mhConnection/main.js
+++ b/player/plugin/custom-mhConnection/main.js
@@ -95,14 +95,14 @@ define(["require", "jquery", "backbone", "engage/core"], function(require, $, Ba
     }
 
     /* change these variables */
-    var SEARCH_ENDPOINT = "/search/episode.json";
+    var SEARCH_ENDPOINT = opencastlink+"/search/episode.json";
 
     /* don't change these variables */
-    var initCount = 5;
+    var initCount = 3; // decreased init count due to disabling footprint, viewsmodel
     var InfoMeModel;
     var MediaPackageModel;
-    var ViewsModel;
-    var FootprintCollection;
+ //   var ViewsModel;
+   // var FootprintCollection;
     var mediaPackageID = "";
     var mediaPackage; // mediaPackage data
     var mediaInfo; // media info like video tracks and attachments
@@ -179,8 +179,8 @@ define(["require", "jquery", "backbone", "engage/core"], function(require, $, Ba
             initTranslate(Engage.model.get("language"));
             Engage.model.set("infoMe", new InfoMeModel());
             Engage.model.set("mediaPackage", new MediaPackageModel());
-            Engage.model.set("views", new ViewsModel());
-            Engage.model.set("footprints", new FootprintCollection());
+       //     Engage.model.set("views", new ViewsModel());
+          //  Engage.model.set("footprints", new FootprintCollection());
         }
     }
 
@@ -256,16 +256,16 @@ define(["require", "jquery", "backbone", "engage/core"], function(require, $, Ba
     });
 
     // load views model
-    require([relative_plugin_path + "models/views"], function(model) {
+/*    require([relative_plugin_path + "models/views"], function(model) {
         Engage.log("MhConnection: ViewsModel loaded");
         ViewsModel = model;
         initCount -= 1;
         if (initCount <= 0) {
             initPlugin();
         }
-    });
+    });*/
 
-    // load footprint collection
+/*    // load footprint collection, disable footprint
     require([relative_plugin_path + "collections/footprint"], function(collection) {
         Engage.log("MhConnection: FootprintCollection loaded");
         FootprintCollection = collection;
@@ -273,7 +273,7 @@ define(["require", "jquery", "backbone", "engage/core"], function(require, $, Ba
         if (initCount <= 0) {
             initPlugin();
         }
-    });
+    });*/
 
     return plugin;
 });
diff --git a/player/plugin/custom-mhConnection/models/infoMe.js b/player/plugin/custom-mhConnection/models/infoMe.js
index 1ec16ac..46194db 100644
--- a/player/plugin/custom-mhConnection/models/infoMe.js
+++ b/player/plugin/custom-mhConnection/models/infoMe.js
@@ -23,10 +23,19 @@
 define(["backbone", "engage/core"], function(Backbone, Engage) {
     "use strict";
 
-    var INFO_ME_ENDPOINT = "../info/me.json";
+    var INFO_ME_ENDPOINT = opencastlink+"/info/me.json";
 
     var InfoMeModel = Backbone.Model.extend({
         urlRoot: INFO_ME_ENDPOINT,
+        sync: function(method, model, options) {
+            options ||(options = {});
+
+            options.type = 'get';
+            options.crossDomain = true;
+            options.xhrFields = {withCredentials:true};
+
+            return Backbone.sync(method, model, options);
+        },
         initialize: function() {
             Engage.log("MhConnection: Init InfoMe model");
             this.update();
diff --git a/player/plugin/custom-mhConnection/models/mediaPackage.js b/player/plugin/custom-mhConnection/models/mediaPackage.js
index 5a03141..18a2bf6 100644
--- a/player/plugin/custom-mhConnection/models/mediaPackage.js
+++ b/player/plugin/custom-mhConnection/models/mediaPackage.js
@@ -28,7 +28,7 @@ define(["backbone", "engage/core"], function(Backbone, Engage) {
         mediaPackageLoaded: new Engage.Event("MhConnection:mediaPackageLoaded", "A mediapackage has been loaded", "trigger")
     };
 
-    var SEARCH_ENDPOINT = "../info/episode.json";
+    var SEARCH_ENDPOINT = opencastlink+"/search/episode.json";
 
     var mediaPackageID = Engage.model.get("urlParameters").id;
     if (!mediaPackageID) {
@@ -37,6 +37,15 @@ define(["backbone", "engage/core"], function(Backbone, Engage) {
 
     var MediaPackageModel = Backbone.Model.extend({
         urlRoot: SEARCH_ENDPOINT,
+        sync: function(method, model, options) {
+            options ||(options = {});
+
+            options.type = 'get';
+            options.crossDomain = true;
+            options.xhrFields = {withCredentials:true};
+
+            return Backbone.sync(method, model, options);
+        },
         initialize: function() {
             Engage.log("MhConnection: Init MediaPackage model");
             this.update();
diff --git a/player/plugin/custom-mhConnection/models/views.js b/player/plugin/custom-mhConnection/models/views.js
index 0b556d5..3ffc399 100644
--- a/player/plugin/custom-mhConnection/models/views.js
+++ b/player/plugin/custom-mhConnection/models/views.js
@@ -34,8 +34,8 @@ define(["jquery", "backbone", "engage/core"], function($, Backbone, Engage) {
         }
     });
 
-    var USERTRACKING_ENDPOINT = "/usertracking";
-    var USERTRACKING_ENDPOINT_STATS = "/stats.json";
+    var USERTRACKING_ENDPOINT = opencastlink+"/usertracking";
+    var USERTRACKING_ENDPOINT_STATS = opencastlink+"/stats.json";
 
     var mediaPackageID = Engage.model.get("urlParameters").id;
     if (!mediaPackageID) {
@@ -44,6 +44,14 @@ define(["jquery", "backbone", "engage/core"], function($, Backbone, Engage) {
 
     var ViewsModel = Backbone.Model.extend({
         urlRoot: USERTRACKING_ENDPOINT + USERTRACKING_ENDPOINT_STATS,
+        sync: function(method, model, options) {
+            options ||(options = {});
+
+            options.crossDomain = true;
+            options.xhrFields = {withCredentials:true};
+
+            return Backbone.sync(method, model, options);
+        },
         initialize: function() {
             Engage.log("MhConnection: Init Views model");
             this.put();
diff --git a/player/plugin/list.json b/player/plugin/list.json
index 248b2cf..91fed4a 100644
--- a/player/plugin/list.json
+++ b/player/plugin/list.json
@@ -19,12 +19,6 @@
         "description":"Connection",
         "static-path":"custom-mhConnection"
       },
-      {
-        "name":"EngagePluginTimelineStatistics",
-        "id":"2",
-        "description":"Implementation timeline plugin to view usertracking stats",
-        "static-path":"timeline-statistics"
-      },
       {
         "name":"EngagePluginControls",
         "id":"1",
diff --git a/player/plugin/timeline-statistics/lib/Chart.js b/player/plugin/timeline-statistics/lib/Chart.js
deleted file mode 100644
index 626e6c3..0000000
--- a/player/plugin/timeline-statistics/lib/Chart.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*!
- * Chart.js
- * http://chartjs.org/
- * Version: 1.0.1-beta.4
- *
- * Copyright 2014 Nick Downie
- * Released under the MIT license
- * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
- */
-(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;this.width=t.canvas.width,this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof t.define&&t.define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),x=s.radians=function(t){return t*(Math.PI/180)},S=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),x=Math.round(f/v);(x>a||a>2*x)&&!h;)if(x>a)v*=2,x=Math.round(f/v),x%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,x=Math.round(f/v)}else v/=2,x=Math.round(f/v);return h&&(x=o,v=f/x),{steps:x,stepValue:v,min:p,max:p+x*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join("	").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("	").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),b=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-b.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*b.easeInBounce(2*t):.5*b.easeOutBounce(2*t-1)+.5}}),w=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=(s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),s.animationLoop=function(t,i,e,s,n,o){var a=0,h=b[e]||b.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=w(l):n.apply(o)};w(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),L=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},k=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},P(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){L(t.chart.canvas,e,i)})}),F=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),T=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},M=s.fontString=function(t,i,e){return i+" "+t+"px "+e},W=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},z=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return T(this.chart),this},stop:function(){return s.cancelAnimFrame.call(t,this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=F(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),k(this,this.events),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;switch(t.fillStyle=this.fillColor,this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}z(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=M(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=W(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){z(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?W(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=W(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(x(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(x(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/(this.valuesCount-(this.offsetGridLines?0:1)),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a);t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+S(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+S(this.lineWidth),o=this.xLabelRotation>0;t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*x(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(C(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};
-i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(t/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this);
\ No newline at end of file
diff --git a/player/plugin/timeline-statistics/main.js b/player/plugin/timeline-statistics/main.js
deleted file mode 100644
index 25b601e..0000000
--- a/player/plugin/timeline-statistics/main.js
+++ /dev/null
@@ -1,381 +0,0 @@
-/**
- * Licensed to The Apereo Foundation under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional
- * information regarding copyright ownership.
- *
- *
- * The Apereo Foundation licenses this file to you under the Educational
- * Community License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License
- * at:
- *
- *   http://opensource.org/licenses/ecl2.txt
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-/*jslint browser: true, nomen: true*/
-/*global define*/
-define(["require", "jquery", "underscore", "backbone", "engage/core"], function(require, $, _, Backbone, Engage) {
-    "use strict";
-
-    var insertIntoDOM = false;
-    var PLUGIN_NAME = "Timeline Usertracking Statistics";
-    var PLUGIN_TYPE = "engage_timeline";
-    var PLUGIN_VERSION = "1.0";
-    var PLUGIN_TEMPLATE_DESKTOP = "templates/desktop.html";
-    var PLUGIN_TEMPLATE_MOBILE = "templates/mobile.html";
-    var PLUGIN_TEMPLATE_EMBED = "templates/embed.html";
-    var PLUGIN_STYLES_DESKTOP = [
-        "styles/desktop.css"
-    ];
-    var PLUGIN_STYLES_EMBED = [
-        "styles/embed.css"
-    ];
-    var PLUGIN_STYLES_MOBILE = [
-        "styles/mobile.css"
-    ];
-
-    var plugin;
-    var events = {
-        plugin_load_done: new Engage.Event("Core:plugin_load_done", "", "handler"),
-        mediaPackageModelError: new Engage.Event("MhConnection:mediaPackageModelError", "", "handler")
-    };
-
-    var isDesktopMode = false;
-    var isEmbedMode = false;
-    var isMobileMode = false;
-
-    // desktop, embed and mobile logic
-    switch (Engage.model.get("mode")) {
-        case "embed":
-            plugin = {
-                insertIntoDOM: insertIntoDOM,
-                name: PLUGIN_NAME,
-                type: PLUGIN_TYPE,
-                version: PLUGIN_VERSION,
-                styles: PLUGIN_STYLES_EMBED,
-                template: PLUGIN_TEMPLATE_EMBED,
-                events: events
-            };
-            isEmbedMode = true;
-            break;
-        case "mobile":
-            plugin = {
-                insertIntoDOM: insertIntoDOM,
-                name: PLUGIN_NAME,
-                type: PLUGIN_TYPE,
-                version: PLUGIN_VERSION,
-                styles: PLUGIN_STYLES_MOBILE,
-                template: PLUGIN_TEMPLATE_MOBILE,
-                events: events
-            };
-            isMobileMode = true;
-            break;
-        case "desktop":
-        default:
-            plugin = {
-                insertIntoDOM: insertIntoDOM,
-                name: PLUGIN_NAME,
-                type: PLUGIN_TYPE,
-                version: PLUGIN_VERSION,
-                styles: PLUGIN_STYLES_DESKTOP,
-                template: PLUGIN_TEMPLATE_DESKTOP,
-                events: events
-            };
-            isDesktopMode = true;
-            break;
-    }
-
-    /* change these variables */
-    var renderEveryTimes = 10;
-    var chartPath = "lib/Chart";
-    var timelineplugin_opened = "Engage:timelineplugin_opened";
-    
-    // TODO: Wait for the new usertracking service...
-    
-    /*
-    var chartOptions = {
-        // Boolean - Whether to animate the chart
-        animation: false,
-        // Number - Number of animation steps
-        animationSteps: 60,
-        // String - Animation easing effect
-        animationEasing: "easeOutQuart",
-        // Boolean - If we should show the scale at all
-        showScale: false,
-        // Boolean - If we want to override with a hard coded scale
-        scaleOverride: false,
-        // ** Required if scaleOverride is true **
-        // Number - The number of steps in a hard coded scale
-        scaleSteps: 1,
-        // Number - The value jump in the hard coded scale
-        scaleStepWidth: null,
-        // Number - The scale starting value
-        scaleStartValue: 0,
-        // String - Colour of the scale line
-        scaleLineColor: "rgba(0,0,0,.1)",
-        // Number - Pixel width of the scale line
-        scaleLineWidth: 1,
-        // Boolean - Whether to show labels on the scale
-        scaleShowLabels: false,
-        // Interpolated JS string - can access value
-        scaleLabel: "<%=value%>",
-        // Boolean - Whether the scale should stick to integers, not floats even if drawing space is there
-        scaleIntegersOnly: true,
-        // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
-        scaleBeginAtZero: true,
-        // String - Scale label font declaration for the scale label
-        scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
-        // Number - Scale label font size in pixels
-        scaleFontSize: 12,
-        // String - Scale label font weight style
-        scaleFontStyle: "normal",
-        // String - Scale label font colour
-        scaleFontColor: "#666",
-        // Boolean - whether or not the chart should be responsive and resize when the browser does.
-        responsive: false,
-        // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
-        maintainAspectRatio: false,
-        // Boolean - Determines whether to draw tooltips on the canvas or not
-        showTooltips: false,
-        // Array - Array of string names to attach tooltip events
-        tooltipEvents: ["mousemove", "touchstart", "touchmove"],
-        // String - Tooltip background colour
-        tooltipFillColor: "rgba(0,0,0,0.8)",
-        // String - Tooltip label font declaration for the scale label
-        tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
-        // Number - Tooltip label font size in pixels
-        tooltipFontSize: 14,
-        // String - Tooltip font weight style
-        tooltipFontStyle: "normal",
-        // String - Tooltip label font colour
-        tooltipFontColor: "#fff",
-        // String - Tooltip title font declaration for the scale label
-        tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
-        // Number - Tooltip title font size in pixels
-        tooltipTitleFontSize: 14,
-        // String - Tooltip title font weight style
-        tooltipTitleFontStyle: "bold",
-        // String - Tooltip title font colour
-        tooltipTitleFontColor: "#fff",
-        // Number - pixel width of padding around tooltip text
-        tooltipYPadding: 6,
-        // Number - pixel width of padding around tooltip text
-        tooltipXPadding: 6,
-        // Number - Size of the caret on the tooltip
-        tooltipCaretSize: 8,
-        // Number - Pixel radius of the tooltip border
-        tooltipCornerRadius: 6,
-        // Number - Pixel offset from point x to tooltip edge
-        tooltipXOffset: 10,
-        // String - Template string for single tooltips
-        tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
-        // String - Template string for single tooltips
-        multiTooltipTemplate: "<%= value %>",
-        // Function - Will fire on animation progression.
-        onAnimationProgress: function() {},
-        // Function - Will fire on animation completion.
-        onAnimationComplete: function() {}
-    }
-    var chartLineOptions = {
-        // Boolean - Whether grid lines are shown across the chart
-        scaleShowGridLines: false,
-        // String - Colour of the grid lines
-        scaleGridLineColor: "rgba(0,0,0,.05)",
-        // Number - Width of the grid lines
-        scaleGridLineWidth: 1,
-        // Boolean - Whether the line is curved between points
-        bezierCurve: true,
-        // Number - Tension of the bezier curve between points
-        bezierCurveTension: 0.4,
-        // Boolean - Whether to show a dot for each point
-        pointDot: false,
-        // Number - Radius of each point dot in pixels
-        pointDotRadius: 4,
-        // Number - Pixel width of point dot stroke
-        pointDotStrokeWidth: 1,
-        // Number - amount extra to add to the radius to cater for hit detection outside the drawn point
-        pointHitDetectionRadius: 20,
-        // Boolean - Whether to show a stroke for datasets
-        datasetStroke: false,
-        // Number - Pixel width of dataset stroke
-        datasetStrokeWidth: 2,
-        // Boolean - Whether to fill the dataset with a colour
-        datasetFill: true,
-    }
-    */
-
-    /* don't change these variables */
-    /*
-    var mediapackageChange = "change:mediaPackage";
-    var footprintChange = "change:footprints";
-    var videoDataModelChange = "change:videoDataModel";
-    var initCount = 5;
-    var intLen = 500;
-    var statisticsTimelineView;
-    var renderEveryTimes_count = 0;
-    var data; // chart data array
-    var lineChartData;
-    var mediapackageError = false;
-
-    function setSize() {
-        $("#engage_timeline_statistics_chart").attr("width", $(window).width() - 40).attr("height", 60).css({
-            "width": $(window).width() - 40,
-            "height": 60
-        });
-    }
-
-    function rerender() {
-        setSize();
-        if (!mediapackageError && statisticsTimelineView && statisticsTimelineView.videoData) {
-            var duration = parseInt(statisticsTimelineView.videoData.get("duration"));
-
-            if (duration && (duration > 0)) {
-                --renderEveryTimes_count;
-                if (renderEveryTimes_count <= 0) {
-                    renderEveryTimes_count = renderEveryTimes;
-
-                    duration /= 1000;
-                    data = new Array();
-                    var labels = new Array(); // chart label array
-                    var tmpViews = 0; // views per interval
-                    var tmpViewsCount = 0; // view entry count per interval
-                    for (var cTime = 0; cTime <= duration; ++cTime) {
-                        tmpViews = 0;
-                        _.each(statisticsTimelineView.footprints, function(value, key, list) {
-                            value = list.at(key);
-                            if (value.get("position") == cTime) {
-                                tmpViews += value.get("views");
-                                return false; // break the foreach-loop
-                            }
-                        });
-                        // push chart data each point
-                        labels.push("");
-                        data.push(tmpViews);
-
-                        lineChartData = {
-                            labels: labels,
-                            datasets: [{
-                                fillColor: "rgba(151,187,205,0.5)",
-                                strokeColor: "rgba(151,187,205,1)",
-                                pointColor: "rgba(151,187,205,1)",
-                                pointStrokeColor: "#FFFFFF",
-                                data: data
-                            }]
-                        }
-                    }
-                }
-
-                if (lineChartData) {
-                    statisticsTimelineView.chart = new Chart(document.getElementById("engage_timeline_statistics_chart").getContext("2d")).Line(lineChartData, chartLineOptions);
-                    statisticsTimelineView.chart.update();
-                }
-            }
-        }
-    }
-
-    var StatisticsTimelineView = Backbone.View.extend({
-        initialize: function() {
-            this.setElement($(plugin.container)); // every plugin view has it"s own container associated with it
-            this.videoData = Engage.model.get("videoDataModel");
-            this.footprints = Engage.model.get("footprints");
-            this.template = plugin.template;
-            // bind the render function always to the view
-            _.bindAll(this, "render");
-            // listen for changes of the model and bind the render function to this
-            this.videoData.bind("change", this.render);
-            this.footprints.bind("change", this.render);
-            this.render();
-            $(window).resize(function() {
-                rerender();
-            });
-        },
-        render: function() {
-            if (!mediapackageError && this.videoData && this.footprints) {
-                var tempVars = {
-                    width: $(window).width() - 40,
-                    height: "60"
-                };
-
-                // compile template and load into the html
-                var template = _.template(this.template);
-                this.$el.html(template(tempVars));
-
-                rerender();
-                if (this.chart && this.chart.update) {
-                    this.chart.update();
-                }
-            }
-        }
-    });
-
-    function initPlugin() {
-        // only init if plugin template was inserted into the DOM
-        if (isDesktopMode && plugin.inserted) {
-            Chart.defaults.global = chartOptions;
-            statisticsTimelineView = new StatisticsTimelineView("");
-
-            Engage.on(timelineplugin_opened, function() {
-                rerender();
-            });
-
-            Engage.on(plugin.events.mediaPackageModelError.getName(), function(msg) {
-                mediapackageError = true;
-            });
-        }
-    }
-
-    // init event
-    Engage.log("Timeline:Statistics: Init");
-    var relative_plugin_path = Engage.getPluginPath("EngagePluginTimelineStatistics");
-
-    if (isDesktopMode) {
-        Engage.model.on(footprintChange, function() {
-            initCount -= 1;
-            if (initCount == 0) {
-                initPlugin();
-            }
-        });
-
-        // listen on a change/set of the mediaPackage model
-        Engage.model.on(mediapackageChange, function() {
-            initCount -= 1;
-            if (initCount == 0) {
-                initPlugin();
-            }
-        });
-
-        Engage.model.on(videoDataModelChange, function() {
-            initCount -= 1;
-            if (initCount == 0) {
-                initPlugin();
-            }
-        });
-
-        // all plugins loaded
-        Engage.on(plugin.events.plugin_load_done.getName(), function() {
-            Engage.log("Timeline:Statistics: Plugin load done");
-            initCount -= 1;
-            if (initCount == 0) {
-                initPlugin();
-            }
-        });
-
-        // load highchart lib
-        require([relative_plugin_path + chartPath], function(videojs) {
-            Engage.log("Timeline:Statistics: Lib chart loaded");
-            initCount -= 1;
-            if (initCount == 0) {
-                initPlugin();
-            }
-        });
-    }
-    */
-
-    return plugin;
-});
diff --git a/player/plugin/timeline-statistics/styles/desktop.css b/player/plugin/timeline-statistics/styles/desktop.css
deleted file mode 100644
index 9193c74..0000000
--- a/player/plugin/timeline-statistics/styles/desktop.css
+++ /dev/null
@@ -1,9 +0,0 @@
-#engage_timeline_statistics_chart {
-    width: 99%; 
-    height: 120px; 
-    min-width: 750px;
-}
-
-#engage_timeline_statistics_content {
-    min-width: 758px;
-}
\ No newline at end of file
diff --git a/player/plugin/timeline-statistics/styles/embed.css b/player/plugin/timeline-statistics/styles/embed.css
deleted file mode 100644
index 9b2e328..0000000
--- a/player/plugin/timeline-statistics/styles/embed.css
+++ /dev/null
@@ -1 +0,0 @@
-/*theodul timeline statistics plugin, embed mode styles*/
diff --git a/player/plugin/timeline-statistics/styles/mobile.css b/player/plugin/timeline-statistics/styles/mobile.css
deleted file mode 100644
index 63d9194..0000000
--- a/player/plugin/timeline-statistics/styles/mobile.css
+++ /dev/null
@@ -1 +0,0 @@
-/*theodul timeline statistics plugin, mobile mode styles*/
diff --git a/player/plugin/timeline-statistics/templates/desktop.html b/player/plugin/timeline-statistics/templates/desktop.html
deleted file mode 100644
index 4ff9734..0000000
--- a/player/plugin/timeline-statistics/templates/desktop.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- theodul timeline statistics plugin embed mode -->
-<div id="engage_timeline_statistics_content">
-    <% if(typeof width !== "undefined" && typeof height !== "undefined" ){ %>		
-    <canvas height="<%= height %>" width="<%= width %>" id="engage_timeline_statistics_chart"></canvas>
-    <% } %>
-</div>
diff --git a/player/plugin/timeline-statistics/templates/embed.html b/player/plugin/timeline-statistics/templates/embed.html
deleted file mode 100644
index 7a55ded..0000000
--- a/player/plugin/timeline-statistics/templates/embed.html
+++ /dev/null
@@ -1 +0,0 @@
-<!-- theodul timeline statistics plugin embed mode -->
diff --git a/player/plugin/timeline-statistics/templates/mobile.html b/player/plugin/timeline-statistics/templates/mobile.html
deleted file mode 100644
index b184c77..0000000
--- a/player/plugin/timeline-statistics/templates/mobile.html
+++ /dev/null
@@ -1 +0,0 @@
-<!-- theodul timeline statistics plugin mobile mode -->
diff --git a/player/plugin/video-videojs/main.js b/player/plugin/video-videojs/main.js
index 9eb5aa2..6a08e7a 100644
--- a/player/plugin/video-videojs/main.js
+++ b/player/plugin/video-videojs/main.js
@@ -21,2502 +21,2502 @@
 /*jslint browser: true, nomen: true*/
 /*global define*/
 define(['require', 'jquery', 'underscore', 'backbone', 'basil', 'bowser', 'engage/core'], function (require, $, _, Backbone, Basil, Bowser, Engage) {
-  'use strict';
-
-  var insertIntoDOM = true;
-  var PLUGIN_NAME = 'Engage VideoJS Videodisplay';
-  var PLUGIN_TYPE = 'engage_video';
-  var PLUGIN_VERSION = '1.0';
-  var PLUGIN_TEMPLATE_DESKTOP = 'templates/desktop.html';
-  var PLUGIN_TEMPLATE_EMBED = 'templates/embed.html';
-  var PLUGIN_TEMPLATE_MOBILE = 'templates/mobile.html';
-  var PLUGIN_STYLES_DESKTOP = [
-    'styles/desktop.css',
-    'lib/video-js/video-js.min.css'
-  ];
-  var PLUGIN_STYLES_EMBED = [
-    'styles/embed.css',
-    'lib/video-js/video-js.min.css'
-  ];
-  var PLUGIN_STYLES_MOBILE = [
-    'styles/mobile.css',
-    'lib/video-js/video-js.min.css'
-  ];
-
-  var plugin;
-  var events = {
-    play: new Engage.Event('Video:play', 'plays the video', 'both'),
-    pause: new Engage.Event('Video:pause', 'pauses the video', 'both'),
-    seek: new Engage.Event('Video:seek', 'seek video to a given position in seconds', 'both'),
-    ready: new Engage.Event('Video:ready', 'all videos loaded successfully', 'both'),
-    ended: new Engage.Event('Video:ended', 'end of the video', 'trigger'),
-    playerLoaded: new Engage.Event('Video:playerLoaded', 'player loaded successfully', 'trigger'),
-    synchronizing: new Engage.Event('Video:synchronizing', 'synchronizing videos with the master video', 'trigger'),
-    buffering: new Engage.Event('Video:buffering', 'video is buffering', 'trigger'),
-    bufferedAndAutoplaying: new Engage.Event('Video:bufferedAndAutoplaying', 'buffering successful, was playing, autoplaying now', 'trigger'),
-    customNotification: new Engage.Event('Notification:customNotification', 'a custom message', 'trigger'),
-    customError: new Engage.Event('Notification:customError', 'an error occured', 'trigger'),
-    bufferedButNotAutoplaying: new Engage.Event('Video:bufferedButNotAutoplaying', 'buffering successful, was not playing, not autoplaying now', 'trigger'),
-    timeupdate: new Engage.Event('Video:timeupdate', 'timeupdate happened', 'trigger'),
-    volumechange: new Engage.Event('Video:volumechange', 'volume change happened', 'trigger'),
-    fullscreenChange: new Engage.Event('Video:fullscreenChange', 'fullscreen change happened', 'trigger'),
-    usingFlash: new Engage.Event('Video:usingFlash', 'flash is being used', 'trigger'),
-    numberOfVideodisplaysSet: new Engage.Event('Video:numberOfVideodisplaysSet', 'the number of videodisplays has been set', 'trigger'),
-    aspectRatioSet: new Engage.Event('Video:aspectRatioSet', 'the aspect ratio has been calculated', 'both'),
-    isAudioOnly: new Engage.Event('Video:isAudioOnly', 'whether it´s audio only or not', 'trigger'),
-    audioCodecNotSupported: new Engage.Event('Video:audioCodecNotSupported', 'when the audio codec seems not to be supported by the browser', 'trigger'),
-    videoFormatsFound: new Engage.Event('Video:videoFormatsFound', '', 'both'),
-    playPause: new Engage.Event('Video:playPause', '', 'handler'),
-    plugin_load_done: new Engage.Event('Core:plugin_load_done', '', 'handler'),
-    fullscreenEnable: new Engage.Event('Video:fullscreenEnable', 'go to fullscreen', 'handler'),
-    fullscreenCancel: new Engage.Event('Video:fullscreenCancel', 'cancel fullscreen', 'handler'),
-    volumeSet: new Engage.Event('Video:volumeSet', 'set the volume', 'handler'),
-    volumeGet: new Engage.Event('Video:volumeGet', 'get the volume', 'handler'),
-    sliderStop: new Engage.Event('Slider:stop', 'slider stopped', 'handler'),
-    playbackRateChanged: new Engage.Event('Video:playbackRateChanged', 'The video playback rate changed', 'handler'),
-    playbackRateIncrease: new Engage.Event('Video:playbackRateIncrease', '', 'handler'),
-    playbackRateDecrease: new Engage.Event('Video:playbackRateDecrease', '', 'handler'),
-    mediaPackageModelError: new Engage.Event('MhConnection:mediaPackageModelError', '', 'handler'),
-    seekLeft: new Engage.Event('Video:seekLeft', '', 'handler'),
-    seekRight: new Engage.Event('Video:seekRight', '', 'handler'),
-    autoplay: new Engage.Event('Video:autoplay', '', 'handler'),
-    initialSeek: new Engage.Event('Video:initialSeek', '', 'handler'),
-    qualitySet: new Engage.Event('Video:qualitySet', '', 'handler'),
-    focusVideo: new Engage.Event('Video:focusVideo', 'increases the size of one video', 'handler'),
-    resetLayout: new Engage.Event('Video:resetLayout', 'resets the layout of the videodisplays', 'handler'),
-    movePiP: new Engage.Event('Video:movePiP', 'moves the smaller picture over the larger to the different corners', 'handler'),
-    togglePiP: new Engage.Event('Video:togglePiP', 'switches between PiP and next to each other layout', 'handler'),
-    closeVideo: new Engage.Event('Video:closeVideo', 'closes one videostream', 'handler'),
-    openVideo: new Engage.Event('Video:openVideo', 'opens a new videostream', 'handler'),
-    moveUp: new Engage.Event('Video:moveUp', 'moves video up', 'handler'),
-    moveDown: new Engage.Event('Video:moveDown', 'moves video down', 'handler'),
-    moveLeft: new Engage.Event('Video:moveLeft', 'moves video left', 'handler'),
-    moveRight: new Engage.Event('Video:moveRight', 'moves video right', 'handler'),
-    setZoomLevel: new Engage.Event('Video:setZoomLevel', 'sets the zoom level', 'both'),
-    zoomReset: new Engage.Event('Video:resetZoom', 'resets position and zoom level', 'handler'),
-    moveHorizontal: new Engage.Event('Video:moveHorizontal', 'move video horizontal', 'handler'),
-    moveVertical: new Engage.Event('Video:moveVertical', 'move video vertical', 'handler'),
-    zoomIn: new Engage.Event('Video:zoomIn', 'zooms in video', 'handler'),
-    zoomOut: new Engage.Event('Video:zoomOut', 'zooms out video', 'handler'),
-    zoomChange: new Engage.Event('Video:zoomChange', 'zoom level has changed', 'trigger'),
-    switchVideo: new Engage.Event('Video:switch', 'switch the video', 'handler'),
-    toggleCaptions: new Engage.Event('Video:toggleCaptions', 'toggle captions', 'handler'),
-    captionsFound: new Engage.Event('Video:captionsFound', 'captions found', 'handler')
-  };
-
-  var isDesktopMode = false;
-  var isEmbedMode = false;
-  var isMobileMode = false;
-
-  // desktop, embed and mobile logic
-  switch (Engage.model.get('mode')) {
-    case 'embed':
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_EMBED,
-        template: PLUGIN_TEMPLATE_EMBED,
-        events: events
-      };
-      isEmbedMode = true;
-      break;
-    case 'mobile':
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_MOBILE,
-        template: PLUGIN_TEMPLATE_MOBILE,
-        events: events
-      };
-      isMobileMode = true;
-      break;
-    case 'desktop':
-    default:
-      plugin = {
-        insertIntoDOM: insertIntoDOM,
-        name: PLUGIN_NAME,
-        type: PLUGIN_TYPE,
-        version: PLUGIN_VERSION,
-        styles: PLUGIN_STYLES_DESKTOP,
-        template: PLUGIN_TEMPLATE_DESKTOP,
-        events: events
-      };
-      isDesktopMode = true;
-      break;
-  }
-
-  /* change these variables */
-  var videoPath = 'lib/video-js/video.min';
-  /* https://github.com/videojs/video.js/releases */
-  var videojs_swf_path = 'lib/video-js/video-js.swf';
-  var synchronizePath = 'lib/synchronize-min';
-  /* https://github.com/CallToPower/Synchronize.js */
-  var mediaSourcesPath = 'lib/video-js/videojs-media-sources.min';
-  /* https://github.com/videojs/videojs-contrib-media-sources */
-  var hlsPath = 'lib/video-js/videojs.hls.min';
-  /* https://github.com/videojs/videojs-contrib-hls */
-  var videoAreaAspectRatio;
-  var checkVideoDisplaySizeTimeout = 1500;
-  var audioLoadTimeoutCheckDelay = 5000;
-  var seekSeconds = 5;
-  var interval_autoplay_ms = 1000;
-  var interval_initialSeek_ms = 1000;
-  var timeout_initialSeek_ms = 250;
-  var timer_qualitychange = 1000;
-  var zoom_step_size = 0.05;
-  var decimal_places = 3;
-
-  /* don't change these variables */
-  var currentTime = 0;
-  var Utils;
-  var parsedSeconds = 0;
-  var interval_autoplay;
-  var interval_initialSeek;
-  var VideoDataModel;
-  var isAudioOnly = false;
-  var isUsingFlash = false;
-  var mastervideotype = '';
-  var aspectRatio = null;
-  var singleVideoPaddingTop = '56.25%';
-  var initCount = 7;
-  var infoMeChange = 'change:infoMe';
-  var mediapackageError = false;
-  var videoDisplayNamePrefix = 'videojs_videodisplay_';
-  var id_video_wrapper = 'video_wrapper';
-  var id_engage_video = 'engage_video';
-  var id_videojs_wrapper = 'videojs_wrapper';
-  var id_videoDisplayClass = 'videoDisplay';
-  var id_engageControls = 'engage_controls';
-  var id_resize_container = 'engage_resize_container';
-  var id_engage_video_fullsceen_wrapper = 'fullscreen_video_wrapper';
-  var id_page_cover = 'page-cover';
-  var id_btn_fullscreenCancel = 'btn_fullscreenCancel';
-  var id_generated_videojs_flash_component = 'videojs_videodisplay_0_flash_api';
-  var id_btn_openInPlayer = 'btn_openInPlayer';
-  var id_btn_switchPlayer = 'btn_switchPlayer';
-  var id_switchPlayer_value = 'switchPlayer-value';
-  var id_audioDisplay = 'audioDisplay';
-  var class_vjs_switchPlayer = 'vjs-switchPlayer';
-  var class_btn_video = 'btn-video';
-  var class_vjs_switchPlayer_value = 'vjs-switchPlayer-value';
-  var class_vjs_menu_content = 'vjs-menu-content';
-  var class_vjs_menu_item = 'vjs-menu-item';
-  var class_vjsposter = 'vjs-poster';
-  var class_vjs_openInPlayer = 'vjs-openInPlayer';
-  var class_vjs_control_text = 'vjs-control-text';
-  var class_vjs_remaining_time = 'vjs-remaining-time';
-  var class_audioDisplay = 'audioDisplay';
-  var class_audioDisplayError = 'audioDisplayError';
-  var videosReady = false;
-  var pressedPlayOnce = false;
-  var mediapackageChange = 'change:mediaPackage';
-  var videoDataModelChange = 'change:videoDataModel';
-  var event_html5player_volumechange = 'volumechange';
-  var event_html5player_fullscreenchange = 'fullscreenchange';
-  var event_sjs_allPlayersReady = 'sjs:allPlayersReady';
-  var event_sjs_playerLoaded = 'sjs:playerLoaded';
-  var event_sjs_masterPlay = 'sjs:masterPlay';
-  var event_sjs_masterPause = 'sjs:masterPause';
-  var event_sjs_masterEnded = 'sjs:masterEnded';
-  var event_sjs_masterTimeupdate = 'sjs:masterTimeupdate';
-  var event_sjs_synchronizing = 'sjs:synchronizing';
-  var event_sjs_buffering = 'sjs:buffering';
-  var event_sjs_bufferedAndAutoplaying = 'sjs:bufferedAndAutoplaying';
-  var event_sjs_bufferedButNotAutoplaying = 'sjs:bufferedButNotAutoplaying';
-  var event_sjs_debug = 'sjs:debug';
-  var event_sjs_stopBufferChecker = 'sjs:stopBufferChecker';
-  var currentlySelectedVideodisplay = 0;
-  var globalVideoSource = [];
-  var videoResultions = [];
-  var loadHls = false;
-  var flavors = '';
-  var mimetypes = '';
-  var translations = [];
-  var videoDataView = undefined;
-  var fullscreen = false;
-  var videoDisplayClass = 'videoDisplay';
-  var qualities = null;
-  var videodisplayMaster = null;
-  var videoDefaultLayoutClass = 'videoDefaultLayout';
-  var videoUnfocusedClass = 'videoUnfocusedPiP';
-  var videoFocusedClass = 'videoFocusedPiP';
-  var unfocusedPiPClass = 'videoUnfocusedPiP';
-  var focusedPiPClass = 'videoFocusedPiP';
-  var unfocusedClass = 'videoUnfocused';
-  var focusedClass = 'videoFocused';
-  var isPiP = true;
-  var pipPos = 'left';
-  var activeCaption = undefined;
-
-  var foundQualities = undefined;
-  var zoomTimeout = 500;
-
-  function initTranslate(language, funcSuccess, funcError) {
-    var path = Engage.getPluginPath('EngagePluginVideoVideoJS').replace(/(\.\.\/)/g, '');
-    /* this solution is really bad, fix it... */
-    var jsonstr = path;
-
-    Engage.log('Controls: selecting language ' + language);
-    jsonstr += 'language/' + language + '.json';
-    $.ajax({
-      url: jsonstr,
-      dataType: 'json',
-      success: function (data) {
-        if (data) {
-          data.value_locale = language;
-          translations = data;
-          if (funcSuccess) {
-            funcSuccess(translations);
-          }
-        } else if (funcError) {
-          funcError();
-        }
-      },
-      error: function () {
-        if (funcError) {
-          funcError();
-        }
-      }
-    });
-  }
-
-  function translate(str, strIfNotFound) {
-    return (translations[str] != undefined) ? translations[str] : strIfNotFound;
-  }
-
-  var basilOptions = {
-    namespace: 'mhStorage'
-  };
-  Basil = new window.Basil(basilOptions);
-
-  function acceptFormat(track) {
-    var preferredFormat = Basil.get('preferredFormat');
-    if (preferredFormat && (preferredFormat != null)) {
-      var preferredFormat_checked = Utils.preferredFormat(preferredFormat);
-      // preferred format is not available
-      if ((preferredFormat_checked == null) || (mimetypes.indexOf(preferredFormat_checked) == -1)) {
-        return true; // accept all
-      }
-      return track.mimetype == preferredFormat_checked;
-    }
-    return true;
-  }
+    'use strict';
+
+    var insertIntoDOM = true;
+    var PLUGIN_NAME = 'Engage VideoJS Videodisplay';
+    var PLUGIN_TYPE = 'engage_video';
+    var PLUGIN_VERSION = '1.0';
+    var PLUGIN_TEMPLATE_DESKTOP = 'templates/desktop.html';
+    var PLUGIN_TEMPLATE_EMBED = 'templates/embed.html';
+    var PLUGIN_TEMPLATE_MOBILE = 'templates/mobile.html';
+    var PLUGIN_STYLES_DESKTOP = [
+        'styles/desktop.css',
+        'lib/video-js/video-js.min.css'
+    ];
+    var PLUGIN_STYLES_EMBED = [
+        'styles/embed.css',
+        'lib/video-js/video-js.min.css'
+    ];
+    var PLUGIN_STYLES_MOBILE = [
+        'styles/mobile.css',
+        'lib/video-js/video-js.min.css'
+    ];
+
+    var plugin;
+    var events = {
+        play: new Engage.Event('Video:play', 'plays the video', 'both'),
+        pause: new Engage.Event('Video:pause', 'pauses the video', 'both'),
+        seek: new Engage.Event('Video:seek', 'seek video to a given position in seconds', 'both'),
+        ready: new Engage.Event('Video:ready', 'all videos loaded successfully', 'both'),
+        ended: new Engage.Event('Video:ended', 'end of the video', 'trigger'),
+        playerLoaded: new Engage.Event('Video:playerLoaded', 'player loaded successfully', 'trigger'),
+        synchronizing: new Engage.Event('Video:synchronizing', 'synchronizing videos with the master video', 'trigger'),
+        buffering: new Engage.Event('Video:buffering', 'video is buffering', 'trigger'),
+        bufferedAndAutoplaying: new Engage.Event('Video:bufferedAndAutoplaying', 'buffering successful, was playing, autoplaying now', 'trigger'),
+        customNotification: new Engage.Event('Notification:customNotification', 'a custom message', 'trigger'),
+        customError: new Engage.Event('Notification:customError', 'an error occured', 'trigger'),
+        bufferedButNotAutoplaying: new Engage.Event('Video:bufferedButNotAutoplaying', 'buffering successful, was not playing, not autoplaying now', 'trigger'),
+        timeupdate: new Engage.Event('Video:timeupdate', 'timeupdate happened', 'trigger'),
+        volumechange: new Engage.Event('Video:volumechange', 'volume change happened', 'trigger'),
+        fullscreenChange: new Engage.Event('Video:fullscreenChange', 'fullscreen change happened', 'trigger'),
+        usingFlash: new Engage.Event('Video:usingFlash', 'flash is being used', 'trigger'),
+        numberOfVideodisplaysSet: new Engage.Event('Video:numberOfVideodisplaysSet', 'the number of videodisplays has been set', 'trigger'),
+        aspectRatioSet: new Engage.Event('Video:aspectRatioSet', 'the aspect ratio has been calculated', 'both'),
+        isAudioOnly: new Engage.Event('Video:isAudioOnly', 'whether it´s audio only or not', 'trigger'),
+        audioCodecNotSupported: new Engage.Event('Video:audioCodecNotSupported', 'when the audio codec seems not to be supported by the browser', 'trigger'),
+        videoFormatsFound: new Engage.Event('Video:videoFormatsFound', '', 'both'),
+        playPause: new Engage.Event('Video:playPause', '', 'handler'),
+        plugin_load_done: new Engage.Event('Core:plugin_load_done', '', 'handler'),
+        fullscreenEnable: new Engage.Event('Video:fullscreenEnable', 'go to fullscreen', 'handler'),
+        fullscreenCancel: new Engage.Event('Video:fullscreenCancel', 'cancel fullscreen', 'handler'),
+        volumeSet: new Engage.Event('Video:volumeSet', 'set the volume', 'handler'),
+        volumeGet: new Engage.Event('Video:volumeGet', 'get the volume', 'handler'),
+        sliderStop: new Engage.Event('Slider:stop', 'slider stopped', 'handler'),
+        playbackRateChanged: new Engage.Event('Video:playbackRateChanged', 'The video playback rate changed', 'handler'),
+        playbackRateIncrease: new Engage.Event('Video:playbackRateIncrease', '', 'handler'),
+        playbackRateDecrease: new Engage.Event('Video:playbackRateDecrease', '', 'handler'),
+        mediaPackageModelError: new Engage.Event('MhConnection:mediaPackageModelError', '', 'handler'),
+        seekLeft: new Engage.Event('Video:seekLeft', '', 'handler'),
+        seekRight: new Engage.Event('Video:seekRight', '', 'handler'),
+        autoplay: new Engage.Event('Video:autoplay', '', 'handler'),
+        initialSeek: new Engage.Event('Video:initialSeek', '', 'handler'),
+        qualitySet: new Engage.Event('Video:qualitySet', '', 'handler'),
+        focusVideo: new Engage.Event('Video:focusVideo', 'increases the size of one video', 'handler'),
+        resetLayout: new Engage.Event('Video:resetLayout', 'resets the layout of the videodisplays', 'handler'),
+        movePiP: new Engage.Event('Video:movePiP', 'moves the smaller picture over the larger to the different corners', 'handler'),
+        togglePiP: new Engage.Event('Video:togglePiP', 'switches between PiP and next to each other layout', 'handler'),
+        closeVideo: new Engage.Event('Video:closeVideo', 'closes one videostream', 'handler'),
+        openVideo: new Engage.Event('Video:openVideo', 'opens a new videostream', 'handler'),
+        moveUp: new Engage.Event('Video:moveUp', 'moves video up', 'handler'),
+        moveDown: new Engage.Event('Video:moveDown', 'moves video down', 'handler'),
+        moveLeft: new Engage.Event('Video:moveLeft', 'moves video left', 'handler'),
+        moveRight: new Engage.Event('Video:moveRight', 'moves video right', 'handler'),
+        setZoomLevel: new Engage.Event('Video:setZoomLevel', 'sets the zoom level', 'both'),
+        zoomReset: new Engage.Event('Video:resetZoom', 'resets position and zoom level', 'handler'),
+        moveHorizontal: new Engage.Event('Video:moveHorizontal', 'move video horizontal', 'handler'),
+        moveVertical: new Engage.Event('Video:moveVertical', 'move video vertical', 'handler'),
+        zoomIn: new Engage.Event('Video:zoomIn', 'zooms in video', 'handler'),
+        zoomOut: new Engage.Event('Video:zoomOut', 'zooms out video', 'handler'),
+        zoomChange: new Engage.Event('Video:zoomChange', 'zoom level has changed', 'trigger'),
+        switchVideo: new Engage.Event('Video:switch', 'switch the video', 'handler'),
+        toggleCaptions: new Engage.Event('Video:toggleCaptions', 'toggle captions', 'handler'),
+        captionsFound: new Engage.Event('Video:captionsFound', 'captions found', 'handler')
+    };
 
-  function filterTracksByTag(tracks, filterTags) {
-    if (filterTags == undefined) {
-      return tracks;
-    }
-    var filterTagsArray = filterTags.split(',');
-    var newTracksArray = [];
-
-    for (var i = 0; i < tracks.length; i++) {
-      var found = false;
-      for (var j = 0; j < tracks[i].tags.tag.length; j++) {
-        for (var k = 0; k < filterTagsArray.length; k++) {
-          if (tracks[i].tags.tag[j] == filterTagsArray[k].trim()) {
-            found = true;
-            newTracksArray.push(tracks[i]);
+    var isDesktopMode = false;
+    var isEmbedMode = false;
+    var isMobileMode = false;
+
+    // desktop, embed and mobile logic
+    switch (Engage.model.get('mode')) {
+        case 'embed':
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_EMBED,
+                template: PLUGIN_TEMPLATE_EMBED,
+                events: events
+            };
+            isEmbedMode = true;
+            break;
+        case 'mobile':
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_MOBILE,
+                template: PLUGIN_TEMPLATE_MOBILE,
+                events: events
+            };
+            isMobileMode = true;
+            break;
+        case 'desktop':
+        default:
+            plugin = {
+                insertIntoDOM: insertIntoDOM,
+                name: PLUGIN_NAME,
+                type: PLUGIN_TYPE,
+                version: PLUGIN_VERSION,
+                styles: PLUGIN_STYLES_DESKTOP,
+                template: PLUGIN_TEMPLATE_DESKTOP,
+                events: events
+            };
+            isDesktopMode = true;
             break;
-          }
-        }
-        if (found) break;
-      }
     }
 
-    // avoid filtering to an empty list, better play something than nothing
-    if (newTracksArray.length < 1) {
-      return tracks;
+    /* change these variables */
+    var videoPath = 'lib/video-js/video.min';
+    /* https://github.com/videojs/video.js/releases */
+    var videojs_swf_path = 'lib/video-js/video-js.swf';
+    var synchronizePath = 'lib/synchronize-min';
+    /* https://github.com/CallToPower/Synchronize.js */
+    var mediaSourcesPath = 'lib/video-js/videojs-media-sources.min';
+    /* https://github.com/videojs/videojs-contrib-media-sources */
+    var hlsPath = 'lib/video-js/videojs.hls.min';
+    /* https://github.com/videojs/videojs-contrib-hls */
+    var videoAreaAspectRatio;
+    var checkVideoDisplaySizeTimeout = 1500;
+    var audioLoadTimeoutCheckDelay = 5000;
+    var seekSeconds = 5;
+    var interval_autoplay_ms = 1000;
+    var interval_initialSeek_ms = 1000;
+    var timeout_initialSeek_ms = 250;
+    var timer_qualitychange = 1000;
+    var zoom_step_size = 0.05;
+    var decimal_places = 3;
+
+    /* don't change these variables */
+    var currentTime = 0;
+    var Utils;
+    var parsedSeconds = 0;
+    var interval_autoplay;
+    var interval_initialSeek;
+    var VideoDataModel;
+    var isAudioOnly = false;
+    var isUsingFlash = false;
+    var mastervideotype = '';
+    var aspectRatio = null;
+    var singleVideoPaddingTop = '56.25%';
+    var initCount = 7;
+    var infoMeChange = 'change:infoMe';
+    var mediapackageError = false;
+    var videoDisplayNamePrefix = 'videojs_videodisplay_';
+    var id_video_wrapper = 'video_wrapper';
+    var id_engage_video = 'engage_video';
+    var id_videojs_wrapper = 'videojs_wrapper';
+    var id_videoDisplayClass = 'videoDisplay';
+    var id_engageControls = 'engage_controls';
+    var id_resize_container = 'engage_resize_container';
+    var id_engage_video_fullsceen_wrapper = 'fullscreen_video_wrapper';
+    var id_page_cover = 'page-cover';
+    var id_btn_fullscreenCancel = 'btn_fullscreenCancel';
+    var id_generated_videojs_flash_component = 'videojs_videodisplay_0_flash_api';
+    var id_btn_openInPlayer = 'btn_openInPlayer';
+    var id_btn_switchPlayer = 'btn_switchPlayer';
+    var id_switchPlayer_value = 'switchPlayer-value';
+    var id_audioDisplay = 'audioDisplay';
+    var class_vjs_switchPlayer = 'vjs-switchPlayer';
+    var class_btn_video = 'btn-video';
+    var class_vjs_switchPlayer_value = 'vjs-switchPlayer-value';
+    var class_vjs_menu_content = 'vjs-menu-content';
+    var class_vjs_menu_item = 'vjs-menu-item';
+    var class_vjsposter = 'vjs-poster';
+    var class_vjs_openInPlayer = 'vjs-openInPlayer';
+    var class_vjs_control_text = 'vjs-control-text';
+    var class_vjs_remaining_time = 'vjs-remaining-time';
+    var class_audioDisplay = 'audioDisplay';
+    var class_audioDisplayError = 'audioDisplayError';
+    var videosReady = false;
+    var pressedPlayOnce = false;
+    var mediapackageChange = 'change:mediaPackage';
+    var videoDataModelChange = 'change:videoDataModel';
+    var event_html5player_volumechange = 'volumechange';
+    var event_html5player_fullscreenchange = 'fullscreenchange';
+    var event_sjs_allPlayersReady = 'sjs:allPlayersReady';
+    var event_sjs_playerLoaded = 'sjs:playerLoaded';
+    var event_sjs_masterPlay = 'sjs:masterPlay';
+    var event_sjs_masterPause = 'sjs:masterPause';
+    var event_sjs_masterEnded = 'sjs:masterEnded';
+    var event_sjs_masterTimeupdate = 'sjs:masterTimeupdate';
+    var event_sjs_synchronizing = 'sjs:synchronizing';
+    var event_sjs_buffering = 'sjs:buffering';
+    var event_sjs_bufferedAndAutoplaying = 'sjs:bufferedAndAutoplaying';
+    var event_sjs_bufferedButNotAutoplaying = 'sjs:bufferedButNotAutoplaying';
+    var event_sjs_debug = 'sjs:debug';
+    var event_sjs_stopBufferChecker = 'sjs:stopBufferChecker';
+    var currentlySelectedVideodisplay = 0;
+    var globalVideoSource = [];
+    var videoResultions = [];
+    var loadHls = false;
+    var flavors = '';
+    var mimetypes = '';
+    var translations = [];
+    var videoDataView = undefined;
+    var fullscreen = false;
+    var videoDisplayClass = 'videoDisplay';
+    var qualities = null;
+    var videodisplayMaster = null;
+    var videoDefaultLayoutClass = 'videoDefaultLayout';
+    var videoUnfocusedClass = 'videoUnfocusedPiP';
+    var videoFocusedClass = 'videoFocusedPiP';
+    var unfocusedPiPClass = 'videoUnfocusedPiP';
+    var focusedPiPClass = 'videoFocusedPiP';
+    var unfocusedClass = 'videoUnfocused';
+    var focusedClass = 'videoFocused';
+    var isPiP = true;
+    var pipPos = 'left';
+    var activeCaption = undefined;
+
+    var foundQualities = undefined;
+    var zoomTimeout = 500;
+
+    function initTranslate(language, funcSuccess, funcError) {
+        var path = Engage.getPluginPath('EngagePluginVideoVideoJS').replace(/(\.\.\/)/g, '');
+        /* this solution is really bad, fix it... */
+        var jsonstr = path;
+
+        Engage.log('Controls: selecting language ' + language);
+        jsonstr += 'language/' + language + '.json';
+        $.ajax({
+            url: jsonstr,
+            dataType: 'json',
+            success: function (data) {
+                if (data) {
+                    data.value_locale = language;
+                    translations = data;
+                    if (funcSuccess) {
+                        funcSuccess(translations);
+                    }
+                } else if (funcError) {
+                    funcError();
+                }
+            },
+            error: function () {
+                if (funcError) {
+                    funcError();
+                }
+            }
+        });
     }
-    return newTracksArray;
-  }
-
-  /**
-   * Lookup all tags that are in use
-   * @param {type} videoSources, List of still used tracks
-   * @param {type} keyword, substing that should be included in the tag
-   * @returns {Array}
-   */
-  function getTags(videoSources, keyword) {
-    if (videoSources === undefined) {
-      return;
+
+    function translate(str, strIfNotFound) {
+        return (translations[str] != undefined) ? translations[str] : strIfNotFound;
     }
-    var tagList = [];
 
-    for (var v in videoSources) {
-      for (var i = 0; i < videoSources[v].length; i++) {
-        for (var j = 0; j < videoSources[v][i].tags.tag.length; j++) {
-          if (keyword !== undefined) {
-            if (videoSources[v][i].tags.tag[j].indexOf(keyword) > 0) {
-              tagList.push(videoSources[v][i].tags.tag[j]);
+    var basilOptions = {
+        namespace: 'mhStorage'
+    };
+    Basil = new window.Basil(basilOptions);
+
+    function acceptFormat(track) {
+        var preferredFormat = Basil.get('preferredFormat');
+        if (preferredFormat && (preferredFormat != null)) {
+            var preferredFormat_checked = Utils.preferredFormat(preferredFormat);
+            // preferred format is not available
+            if ((preferredFormat_checked == null) || (mimetypes.indexOf(preferredFormat_checked) == -1)) {
+                return true; // accept all
             }
-          } else {
-            tagList.push(videoSources[v][i].tags.tag[j]);
-          }
+            return track.mimetype == preferredFormat_checked;
         }
-      }
+        return true;
     }
 
-    return _.uniq(tagList);
-  }
-
-  /**
-   * Find the different video qualities
-   * @param {type} videoSources videoSources that are still in use
-   * @returns {undefined}
-   *
-   */
-  function getQualities(videoSources) {
-    // using a cache for qualities, as they probably do not change
-    if (foundQualities) {
-      return foundQualities;
+    function filterTracksByTag(tracks, filterTags) {
+        if (filterTags == undefined) {
+            return tracks;
+        }
+        var filterTagsArray = filterTags.split(',');
+        var newTracksArray = [];
+
+        for (var i = 0; i < tracks.length; i++) {
+            var found = false;
+            for (var j = 0; j < tracks[i].tags.tag.length; j++) {
+                for (var k = 0; k < filterTagsArray.length; k++) {
+                    if (tracks[i].tags.tag[j] == filterTagsArray[k].trim()) {
+                        found = true;
+                        newTracksArray.push(tracks[i]);
+                        break;
+                    }
+                }
+                if (found) break;
+            }
+        }
+
+        // avoid filtering to an empty list, better play something than nothing
+        if (newTracksArray.length < 1) {
+            return tracks;
+        }
+        return newTracksArray;
     }
-    var tagsList = getTags(videoSources, '-quality');
-    var qualitiesList = [];
-    tagsList.forEach(function(quality) {
-      qualitiesList.push(quality.substring(0, quality.indexOf('-quality')));
-    });
-    var tracks;
-    for (var source in videoSources) {
-      if (videoSources[source] !== undefined) {
-        tracks = videoSources[source];
-        break;
-      }
+
+    /**
+     * Lookup all tags that are in use
+     * @param {type} videoSources, List of still used tracks
+     * @param {type} keyword, substing that should be included in the tag
+     * @returns {Array}
+     */
+    function getTags(videoSources, keyword) {
+        if (videoSources === undefined) {
+            return;
+        }
+        var tagList = [];
+
+        for (var v in videoSources) {
+            for (var i = 0; i < videoSources[v].length; i++) {
+                for (var j = 0; j < videoSources[v][i].tags.tag.length; j++) {
+                    if (keyword !== undefined) {
+                        if (videoSources[v][i].tags.tag[j].indexOf(keyword) > 0) {
+                            tagList.push(videoSources[v][i].tags.tag[j]);
+                        }
+                    } else {
+                        tagList.push(videoSources[v][i].tags.tag[j]);
+                    }
+                }
+            }
+        }
+
+        return _.uniq(tagList);
     }
-    var sortedResolutionsList = [];
-    sortedResolutionsList = _.map(qualitiesList, function(quality) {
-      var currentTrack = filterTracksByTag(tracks, quality + '-quality')[0];
-      return [quality, currentTrack.resolution.substring(0, currentTrack.resolution.indexOf('x'))];
-    });
-    sortedResolutionsList.sort(compareQuality);
-    foundQualities = [];
-    for (var i = 0; i < sortedResolutionsList.length; ++i) {
-      foundQualities.push(sortedResolutionsList[i][0]);
+
+    /**
+     * Find the different video qualities
+     * @param {type} videoSources videoSources that are still in use
+     * @returns {undefined}
+     *
+     */
+    function getQualities(videoSources) {
+        // using a cache for qualities, as they probably do not change
+        if (foundQualities) {
+            return foundQualities;
+        }
+        var tagsList = getTags(videoSources, '-quality');
+        var qualitiesList = [];
+        tagsList.forEach(function (quality) {
+            qualitiesList.push(quality.substring(0, quality.indexOf('-quality')));
+        });
+        var tracks;
+        for (var source in videoSources) {
+            if (videoSources[source] !== undefined) {
+                tracks = videoSources[source];
+                break;
+            }
+        }
+        var sortedResolutionsList = [];
+        sortedResolutionsList = _.map(qualitiesList, function (quality) {
+            var currentTrack = filterTracksByTag(tracks, quality + '-quality')[0];
+            return [quality, currentTrack.resolution.substring(0, currentTrack.resolution.indexOf('x'))];
+        });
+        sortedResolutionsList.sort(compareQuality);
+        foundQualities = [];
+        for (var i = 0; i < sortedResolutionsList.length; ++i) {
+            foundQualities.push(sortedResolutionsList[i][0]);
+        }
+        return foundQualities;
     }
-    return foundQualities;
-  }
 
-  function compareQuality(a, b) {
-    if (a && b) {
-      if (parseInt(a[1]) == parseInt(b[1])) {
+    function compareQuality(a, b) {
+        if (a && b) {
+            if (parseInt(a[1]) == parseInt(b[1])) {
+                return 0;
+            }
+            return parseInt(a[1]) > parseInt(b[1]) ? 1 : -1;
+        }
         return 0;
-      }
-      return parseInt(a[1]) > parseInt(b[1]) ? 1 : -1;
     }
-    return 0;
-  }
 
-  function filterTracksByFormat(tracks, filterFormats) {
-    if (filterFormats == undefined) {
-      return tracks;
-    }
-    var filterFormatsArray = filterFormats.split(',');
-    var newTracksArray = [];
-
-    for (var i = 0; i < tracks.length; i++) {
-      for (var j = 0; j < filterFormatsArray.length; j++) {
-        var formatMimeType = Utils.preferredFormat(filterFormatsArray[j].trim());
-        if (formatMimeType == undefined) return tracks; // if illegal mimetypes are configured ignore config
-        if (tracks[i].mimetype == formatMimeType) {
-          newTracksArray.push(tracks[i]);
-          break;
-        }
-      }
-    }
+    function filterTracksByFormat(tracks, filterFormats) {
+        if (filterFormats == undefined) {
+            return tracks;
+        }
+        var filterFormatsArray = filterFormats.split(',');
+        var newTracksArray = [];
 
-    return newTracksArray;
-  }
-
-  function registerSynchronizeEvents() {
-    // throw some important synchronize.js-events for other plugins
-    $(document)
-      .on(event_sjs_allPlayersReady, function () {
-        videosReady = true;
-        Engage.trigger(plugin.events.ready.getName());
-      })
-      .on(event_sjs_playerLoaded, function () {
-        Engage.trigger(plugin.events.playerLoaded.getName());
-      })
-      .on(event_sjs_masterPlay, function () {
-        Engage.trigger(plugin.events.play.getName(), true);
-        pressedPlayOnce = true;
-      })
-      .on(event_sjs_masterPause, function () {
-        Engage.trigger(plugin.events.pause.getName(), true);
-      })
-      .on(event_sjs_masterEnded, function () {
-        Engage.trigger(plugin.events.ended.getName(), true);
-      })
-      .on(event_sjs_masterTimeupdate, function (event, time) {
-        Engage.trigger(plugin.events.timeupdate.getName(), time, true);
-      })
-      .on(event_sjs_synchronizing, function () {
-        Engage.trigger(plugin.events.synchronizing.getName());
-      })
-      .on(event_sjs_buffering, function () {
-        Engage.trigger(plugin.events.buffering.getName());
-      })
-      .on(event_sjs_bufferedAndAutoplaying, function () {
-        Engage.trigger(plugin.events.bufferedAndAutoplaying.getName());
-      })
-      .on(event_sjs_bufferedButNotAutoplaying, function () {
-        Engage.trigger(plugin.events.bufferedButNotAutoplaying.getName());
-      });
-  }
-
-  function initSynchronize() {
-    $(document)
-      .trigger(event_sjs_debug, Engage.model.get('isDebug'))
-      .trigger(event_sjs_stopBufferChecker);
-  }
-
-  function initQualities(videoDataView) {
-    qualities = getQualities(videoDataView.model.get('videoSources'));
-
-    if (qualities.length > 1) {
-      Engage.on(plugin.events.qualitySet.getName(), function (q) {
-        changeQuality(q);
-      });
-      Engage.trigger(plugin.events.videoFormatsFound.getName(), qualities);
-      if (isMobileMode) {
-        Engage.model.set('quality', 'low');
-      }
-      changeQuality(Engage.model.get('quality'));
-    }
-  }
-
-  function changeQuality(q) {
-    if (q) {
-      var isPaused = videodisplayMaster.paused();
-      Engage.trigger(plugin.events.pause.getName(), false);
-      var quality = q + '-quality';
-      Engage.model.set('quality', q);
-      Engage.log('Video: Setting quality to: ' + q);
-      var tuples = getSortedVideosourcesArray(globalVideoSource);
-      for (var i = 0; i < tuples.length; ++i) {
-        var value = tuples[i][1];
-        if (value[1][0]) {
-          var track = filterTracksByTag(value[1], quality);
-          if (track && track.length > 0) {
-            videojs(value[0]).src(track[0].src);
-          }
-        }
-      }
-      if (pressedPlayOnce && (currentTime > 0)) {
-        window.setTimeout(function () {
-          initSynchronize(false);
-          Engage.trigger(plugin.events.seek.getName(), currentTime);
-          if (!isPaused) {
-            Engage.trigger(plugin.events.play.getName());
-          }
-        }, timer_qualitychange);
-      }
-    }
-  }
+        for (var i = 0; i < tracks.length; i++) {
+            for (var j = 0; j < filterFormatsArray.length; j++) {
+                var formatMimeType = Utils.preferredFormat(filterFormatsArray[j].trim());
+                if (formatMimeType == undefined) return tracks; // if illegal mimetypes are configured ignore config
+                if (tracks[i].mimetype == formatMimeType) {
+                    newTracksArray.push(tracks[i]);
+                    break;
+                }
+            }
+        }
 
-  function registerZoomLevelEvents() {
-    if (isUsingFlash) {
-      Engage.log('Video: Zoom for Flash is not supported');
-      return;
+        return newTracksArray;
+    }
+
+    function registerSynchronizeEvents() {
+        // throw some important synchronize.js-events for other plugins
+        $(document)
+            .on(event_sjs_allPlayersReady, function () {
+                videosReady = true;
+                Engage.trigger(plugin.events.ready.getName());
+            })
+            .on(event_sjs_playerLoaded, function () {
+                Engage.trigger(plugin.events.playerLoaded.getName());
+            })
+            .on(event_sjs_masterPlay, function () {
+                Engage.trigger(plugin.events.play.getName(), true);
+                pressedPlayOnce = true;
+            })
+            .on(event_sjs_masterPause, function () {
+                Engage.trigger(plugin.events.pause.getName(), true);
+            })
+            .on(event_sjs_masterEnded, function () {
+                Engage.trigger(plugin.events.ended.getName(), true);
+            })
+            .on(event_sjs_masterTimeupdate, function (event, time) {
+                Engage.trigger(plugin.events.timeupdate.getName(), time, true);
+            })
+            .on(event_sjs_synchronizing, function () {
+                Engage.trigger(plugin.events.synchronizing.getName());
+            })
+            .on(event_sjs_buffering, function () {
+                Engage.trigger(plugin.events.buffering.getName());
+            })
+            .on(event_sjs_bufferedAndAutoplaying, function () {
+                Engage.trigger(plugin.events.bufferedAndAutoplaying.getName());
+            })
+            .on(event_sjs_bufferedButNotAutoplaying, function () {
+                Engage.trigger(plugin.events.bufferedButNotAutoplaying.getName());
+            });
     }
 
-    var selector = 'video';
-    var lastEvent = null;
-    var wheelEvent = null;
-    var videoFocused = true;
-    var singleVideo = true;
-    var mapSelector = '#fullscreen_video_wrapper';
-    var minimapVisible = false;
-    var zoomLevels = [];
-    var ratio = aspectRatio[2] / aspectRatio[1];
-    var id = Engage.model.get('urlParameters').id;
-    var flag = 0;
-
-    /* Hides Minimap, e.g. when zoom < 1 */
-    function hideMinimap() {
-      $('#indicator').remove();
-      minimapVisible = false;
+    function initSynchronize() {
+        $(document)
+            .trigger(event_sjs_debug, Engage.model.get('isDebug'))
+            .trigger(event_sjs_stopBufferChecker);
     }
 
-    /* Shows Minimap when it's not already displayed */
-    function showMinimap() {
-      if ($(selector) === undefined || $(selector)[0] === undefined) {
-        return;
-      }
+    function initQualities(videoDataView) {
+        qualities = getQualities(videoDataView.model.get('videoSources'));
 
-      var zoom = $(selector)[0].style.transform.replace(/[a-z]*/, '');
-      zoom = zoom.replace('(', '');
-      zoom = zoom.replace(')', '');
+        if (qualities.length > 1) {
+            Engage.on(plugin.events.qualitySet.getName(), function (q) {
+                changeQuality(q);
+            });
+            Engage.trigger(plugin.events.videoFormatsFound.getName(), qualities);
+            if (isMobileMode) {
+                Engage.model.set('quality', 'low');
+            }
+            changeQuality(Engage.model.get('quality'));
+        }
+    }
+
+    function changeQuality(q) {
+        if (q) {
+            var isPaused = videodisplayMaster.paused();
+            Engage.trigger(plugin.events.pause.getName(), false);
+            var quality = q + '-quality';
+            Engage.model.set('quality', q);
+            Engage.log('Video: Setting quality to: ' + q);
+            var tuples = getSortedVideosourcesArray(globalVideoSource);
+            for (var i = 0; i < tuples.length; ++i) {
+                var value = tuples[i][1];
+                if (value[1][0]) {
+                    var track = filterTracksByTag(value[1], quality);
+                    if (track && track.length > 0) {
+                        videojs(value[0]).src(track[0].src);
+                    }
+                }
+            }
+            if (pressedPlayOnce && (currentTime > 0)) {
+                window.setTimeout(function () {
+                    initSynchronize(false);
+                    Engage.trigger(plugin.events.seek.getName(), currentTime);
+                    if (!isPaused) {
+                        Engage.trigger(plugin.events.play.getName());
+                    }
+                }, timer_qualitychange);
+            }
+        }
+    }
 
-      if (Number(zoom) <= 1) {
-        return;
-      }
+    function registerZoomLevelEvents() {
+        if (isUsingFlash) {
+            Engage.log('Video: Zoom for Flash is not supported');
+            return;
+        }
 
-      if ($(selector).length == 1) {
-        $(mapSelector).children().first().append('<canvas id="indicator"></canvas>');
-        var minimapWidth = $('#indicator').width();
+        var selector = 'video';
+        var lastEvent = null;
+        var wheelEvent = null;
+        var videoFocused = true;
+        var singleVideo = true;
+        var mapSelector = '#fullscreen_video_wrapper';
+        var minimapVisible = false;
+        var zoomLevels = [];
+        var ratio = aspectRatio[2] / aspectRatio[1];
+        var id = Engage.model.get('urlParameters').id;
+        var flag = 0;
 
-        var c = document.getElementById('indicator');
-        var ctx = c.getContext('2d');
+        /* Hides Minimap, e.g. when zoom < 1 */
+        function hideMinimap() {
+            $('#indicator').remove();
+            minimapVisible = false;
+        }
 
-        var mapWidth = minimapWidth / zoom;
-        var mapHeight = (minimapWidth * ratio) / zoom;
+        /* Shows Minimap when it's not already displayed */
+        function showMinimap() {
+            if ($(selector) === undefined || $(selector)[0] === undefined) {
+                return;
+            }
 
-        ctx.fillStyle = '#FFFFFF';
+            var zoom = $(selector)[0].style.transform.replace(/[a-z]*/, '');
+            zoom = zoom.replace('(', '');
+            zoom = zoom.replace(')', '');
 
-        ctx.fillRect(minimapWidth / 2 - mapWidth / 2, (minimapWidth * ratio) / 2 - mapHeight / 2, mapWidth, mapHeight);
+            if (Number(zoom) <= 1) {
+                return;
+            }
 
-        minimapVisible = true;
-        updateMinimap();
-      }
-    }
+            if ($(selector).length == 1) {
+                $(mapSelector).children().first().append('<canvas id="indicator"></canvas>');
+                var minimapWidth = $('#indicator').width();
 
-    /* Redraws Minimap, e.g. when other display is focused */
-    function redrawMinimap() {
-      hideMinimap();
-      showMinimap();
-    }
+                var c = document.getElementById('indicator');
+                var ctx = c.getContext('2d');
 
-    /* Updates Minimap, e.g. when moving video */
-    function updateMinimap() {
-      var zoom = $(selector)[0].style.transform.replace(/[a-z]*/, '');
-      zoom = zoom.replace('(', '');
-      zoom = zoom.replace(')', '');
-
-      if (Number(zoom) <= 1) {
-        return;
-      }
-      var h = $(mapSelector).height();
-      var w = $(mapSelector).width();
-      var minimapWidth = $('#indicator').width();
-
-      var left = $(selector).css('left').replace('px', '');
-      var top = $(selector).css('top').replace('px', '');
-
-      var hDiff = (h * zoom - h) / 2;
-      var wDiff = (w * zoom - w) / 2;
-
-      var relHDiff = top / hDiff;
-      var relWDiff = left / wDiff;
-
-      var mapWidth = minimapWidth / zoom;
-      var mapHeight = (minimapWidth * ratio) / zoom;
-
-      var c = document.getElementById('indicator');
-
-      if (c == undefined) {
-        return;
-      }
-      // reset drawings
-      c.width = $('#indicator').width();
-      c.height = $('#indicator').height();
-
-      var ctx = c.getContext('2d');
-      ctx.fillStyle = '#FFFFFF';
-      // calculate Position and draw it onto indicator
-      var x = (minimapWidth / 2 - mapWidth / 2) - ((minimapWidth / 2 - mapWidth / 2) * relWDiff);
-      var y = (minimapWidth * ratio) / 2 - mapHeight / 2 - (((minimapWidth * ratio) / 2 - mapHeight / 2) * relHDiff);
-      ctx.fillRect(x, y, mapWidth, mapHeight);
-    }
+                var mapWidth = minimapWidth / zoom;
+                var mapHeight = (minimapWidth * ratio) / zoom;
 
-    function isFocused() {
-      return Basil.get('focusvideo') != 'focus.none';
-    }
+                ctx.fillStyle = '#FFFFFF';
 
-    Engage.on(plugin.events.numberOfVideodisplaysSet.getName(), function (number) {
-      var videoDisplays = $('.' + videoDisplayClass);
-      if (Engage.model.get('meInfo').get('hide_video_context_menu')) {
-        videoDisplays.on('contextmenu', function (e) {
-          e.preventDefault();
-        });
-      }
-      if (number > 1) {
-        selector = '.videoFocused video';
-        videoFocused = false;
-        singleVideo = false;
-        videoDisplays.on('click', function () {
-          if (flag == 0) {
-            Engage.trigger(plugin.events.focusVideo.getName(), Utils.getFlavorForVideoDisplay(this));
-          }
-        });
-      }
-    });
+                ctx.fillRect(minimapWidth / 2 - mapWidth / 2, (minimapWidth * ratio) / 2 - mapHeight / 2, mapWidth, mapHeight);
 
-    Engage.on(plugin.events.togglePiP.getName(), function (pip) {
-      if (pip && videoFocused) {
-        selector = '.videoFocusedPiP video';
-        mapSelector = '.videoFocusedPiP';
-        setTimeout(redrawMinimap, zoomTimeout);
-      } else if (!pip && videoFocused) {
-        selector = '.videoFocused video';
-        mapSelector = '.videoFocused';
-        setTimeout(redrawMinimap, zoomTimeout);
-      } else {
-        selector = 'video';
-      }
-    });
+                minimapVisible = true;
+                updateMinimap();
+            }
+        }
 
-    Engage.on(plugin.events.resetLayout.getName(), function (v) {
-      videoFocused = false;
-      selector = 'video';
-      if (!singleVideo) {
-        hideMinimap();
-      }
-    });
+        /* Redraws Minimap, e.g. when other display is focused */
+        function redrawMinimap() {
+            hideMinimap();
+            showMinimap();
+        }
 
-    Engage.on(plugin.events.focusVideo.getName(), function (v) {
-      if (isPiP && !videoFocused) {
-        videoFocused = true;
-        selector = '.videoFocusedPiP video';
-        mapSelector = '.videoFocusedPiP';
-        if (isFocused()) {
-          setTimeout(showMinimap, zoomTimeout);
-        }
-      } else if (!isPiP && !videoFocused) {
-        selector = '.videoFocused video';
-        videoFocused = true;
-        mapSelector = '.videoFocused';
-        if (isFocused()) {
-          setTimeout(showMinimap, zoomTimeout);
-        }
-      } else if (!isPiP && videoFocused) {
-        // Toggle non-PiP displays or leave focused mode while nonPiP
-        if (singleVideo) {
-          // While video with one display loaded this could occur
-          videoFocused = false;
-          selector = 'video';
-          mapSelector = '.videoDisplay';
-          setTimeout(showMinimap, zoomTimeout);
-        } else {
-          Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
-          selector = '.videoFocused video';
-          setTimeout(redrawMinimap, zoomTimeout);
-        }
-      } else if (isPiP && videoFocused) {
-        // Toggle PiP displays or leave focused mode while PiP
-        if (singleVideo) {
-          // While video with one display loaded this could occur
-          videoFocused = false;
-          selector = 'video';
-          mapSelector = '.videoDisplay';
-          setTimeout(showMinimap, zoomTimeout);
-        } else {
-          // Reset before unfocus
-          Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
-          selector = '.videoFocusedPiP video';
-          setTimeout(redrawMinimap, zoomTimeout);
-        }
-      } else {
-        selector = 'video';
-        hideMinimap();
-      }
-      // move display
-      Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true, true]);
-    });
+        /* Updates Minimap, e.g. when moving video */
+        function updateMinimap() {
+            var zoom = $(selector)[0].style.transform.replace(/[a-z]*/, '');
+            zoom = zoom.replace('(', '');
+            zoom = zoom.replace(')', '');
 
-    $(selector).on('mousewheel', function (event) {
-      if (wheelEvent != null) {
-        if (event.timeStamp - wheelEvent.timeStamp < 30) {
-          event.preventDefault();
-          return;
-        }
-      }
-      // scrolling stays available
-      if (selector == 'video' && !singleVideo) {
-        return;
-      }
-      // calculate mouse position
-      var parentOffset = $(this).parent().offset();
-      var relX = event.pageX - parentOffset.left;
-      var relY = event.pageY - parentOffset.top;
-
-      var vX = ($(this).width() / 2);
-      var vY = ($(this).height() / 2);
-
-      var xdiff = relX - vX;
-      var ydiff = relY - vY;
-
-      event.preventDefault();
-      // zoom in
-      if (event.deltaY > 0) {
-        Engage.trigger(events.setZoomLevel.getName(), [zoom_step_size]);
-        // move towards mouse position
-        var z = zoomLevels[zoomLevels.indexOf($(selector)[0].id) + 1];
-
-        moveHorizontal(-((xdiff / 5) / z));
-        moveVertical(-((ydiff / 5) / z));
-      }
-
-      // zoom out
-      if (event.deltaY < 0) {
-        Engage.trigger(events.setZoomLevel.getName(), [-zoom_step_size]);
-      }
-
-      wheelEvent = event;
-    });
+            if (Number(zoom) <= 1) {
+                return;
+            }
+            var h = $(mapSelector).height();
+            var w = $(mapSelector).width();
+            var minimapWidth = $('#indicator').width();
 
-    $(selector).mousedown(function () {
-      flag = 0;
-      $(selector).mousemove(function (event) {
-        if (lastEvent != null) {
-          flag = 1;
-          var x_move = lastEvent.pageX - event.pageX;
-          var y_move = lastEvent.pageY - event.pageY;
-          Engage.trigger(plugin.events.moveHorizontal.getName(), -x_move);
-          Engage.trigger(plugin.events.moveVertical.getName(), -y_move);
-        }
-
-        lastEvent = event;
-      });
-      $('body').mouseup(function () {
-        $(selector).off('mousemove');
-        lastEvent = null;
-      });
-    });
+            var left = $(selector).css('left').replace('px', '');
+            var top = $(selector).css('top').replace('px', '');
 
-    Engage.on(plugin.events.moveHorizontal.getName(), function (step) {
-      moveHorizontal(step);
-    });
+            var hDiff = (h * zoom - h) / 2;
+            var wDiff = (w * zoom - w) / 2;
 
-    Engage.on(plugin.events.moveVertical.getName(), function (step) {
-      moveVertical(step);
-    });
+            var relHDiff = top / hDiff;
+            var relWDiff = left / wDiff;
 
-    function moveHorizontal(step) {
-      if (videoFocused || singleVideo) {
-        var offset = $(selector).css('left');
-        var left = $(selector).position().left / 2;
+            var mapWidth = minimapWidth / zoom;
+            var mapHeight = (minimapWidth * ratio) / zoom;
 
-        offset = offset.replace('px', '');
-        offset = Number(offset);
+            var c = document.getElementById('indicator');
 
-        if (step > 0 && Math.abs($(selector).position().left) < step) {
-          // Shift right, but too far
-          step = Math.abs($(selector).position().left);
-        }
+            if (c == undefined) {
+                return;
+            }
+            // reset drawings
+            c.width = $('#indicator').width();
+            c.height = $('#indicator').height();
 
-        if (step < 0 && (offset + step < left)) {
-          // Shift left but too far
-          step = (left - offset);
+            var ctx = c.getContext('2d');
+            ctx.fillStyle = '#FFFFFF';
+            // calculate Position and draw it onto indicator
+            var x = (minimapWidth / 2 - mapWidth / 2) - ((minimapWidth / 2 - mapWidth / 2) * relWDiff);
+            var y = (minimapWidth * ratio) / 2 - mapHeight / 2 - (((minimapWidth * ratio) / 2 - mapHeight / 2) * relHDiff);
+            ctx.fillRect(x, y, mapWidth, mapHeight);
         }
 
-        if (!(($(selector).position().left + step) > 0) && !((offset + step) < left)) {
-          $(selector).css('left', (offset + step) + 'px');
+        function isFocused() {
+            return Basil.get('focusvideo') != 'focus.none';
         }
 
-        updateMinimap();
-      }
-    }
+        Engage.on(plugin.events.numberOfVideodisplaysSet.getName(), function (number) {
+            var videoDisplays = $('.' + videoDisplayClass);
+            if (Engage.model.get('meInfo').get('hide_video_context_menu')) {
+                videoDisplays.on('contextmenu', function (e) {
+                    e.preventDefault();
+                });
+            }
+            if (number > 1) {
+                selector = '.videoFocused video';
+                videoFocused = false;
+                singleVideo = false;
+                videoDisplays.on('click', function () {
+                    if (flag == 0) {
+                        Engage.trigger(plugin.events.focusVideo.getName(), Utils.getFlavorForVideoDisplay(this));
+                    }
+                });
+            }
+        });
 
-    function moveVertical(step) {
-      if (videoFocused || singleVideo) {
-        var top = $(selector).position().top / 2;
-        var offset = $(selector).css('top');
+        Engage.on(plugin.events.togglePiP.getName(), function (pip) {
+            if (pip && videoFocused) {
+                selector = '.videoFocusedPiP video';
+                mapSelector = '.videoFocusedPiP';
+                setTimeout(redrawMinimap, zoomTimeout);
+            } else if (!pip && videoFocused) {
+                selector = '.videoFocused video';
+                mapSelector = '.videoFocused';
+                setTimeout(redrawMinimap, zoomTimeout);
+            } else {
+                selector = 'video';
+            }
+        });
 
-        offset = offset.replace('px', '');
-        offset = Number(offset);
+        Engage.on(plugin.events.resetLayout.getName(), function (v) {
+            videoFocused = false;
+            selector = 'video';
+            if (!singleVideo) {
+                hideMinimap();
+            }
+        });
 
-        if (step > 0 && (Math.abs($(selector).position().top) < step)) {
-          step = Math.abs($(selector).position().top);
-        }
+        Engage.on(plugin.events.focusVideo.getName(), function (v) {
+            if (isPiP && !videoFocused) {
+                videoFocused = true;
+                selector = '.videoFocusedPiP video';
+                mapSelector = '.videoFocusedPiP';
+                if (isFocused()) {
+                    setTimeout(showMinimap, zoomTimeout);
+                }
+            } else if (!isPiP && !videoFocused) {
+                selector = '.videoFocused video';
+                videoFocused = true;
+                mapSelector = '.videoFocused';
+                if (isFocused()) {
+                    setTimeout(showMinimap, zoomTimeout);
+                }
+            } else if (!isPiP && videoFocused) {
+                // Toggle non-PiP displays or leave focused mode while nonPiP
+                if (singleVideo) {
+                    // While video with one display loaded this could occur
+                    videoFocused = false;
+                    selector = 'video';
+                    mapSelector = '.videoDisplay';
+                    setTimeout(showMinimap, zoomTimeout);
+                } else {
+                    Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
+                    selector = '.videoFocused video';
+                    setTimeout(redrawMinimap, zoomTimeout);
+                }
+            } else if (isPiP && videoFocused) {
+                // Toggle PiP displays or leave focused mode while PiP
+                if (singleVideo) {
+                    // While video with one display loaded this could occur
+                    videoFocused = false;
+                    selector = 'video';
+                    mapSelector = '.videoDisplay';
+                    setTimeout(showMinimap, zoomTimeout);
+                } else {
+                    // Reset before unfocus
+                    Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
+                    selector = '.videoFocusedPiP video';
+                    setTimeout(redrawMinimap, zoomTimeout);
+                }
+            } else {
+                selector = 'video';
+                hideMinimap();
+            }
+            // move display
+            Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true, true]);
+        });
 
-        if (step < 0 && (offset + step < top)) {
-          step = (top - offset);
-        }
+        $(selector).on('mousewheel', function (event) {
+            if (wheelEvent != null) {
+                if (event.timeStamp - wheelEvent.timeStamp < 30) {
+                    event.preventDefault();
+                    return;
+                }
+            }
+            // scrolling stays available
+            if (selector == 'video' && !singleVideo) {
+                return;
+            }
+            // calculate mouse position
+            var parentOffset = $(this).parent().offset();
+            var relX = event.pageX - parentOffset.left;
+            var relY = event.pageY - parentOffset.top;
+
+            var vX = ($(this).width() / 2);
+            var vY = ($(this).height() / 2);
+
+            var xdiff = relX - vX;
+            var ydiff = relY - vY;
+
+            event.preventDefault();
+            // zoom in
+            if (event.deltaY > 0) {
+                Engage.trigger(events.setZoomLevel.getName(), [zoom_step_size]);
+                // move towards mouse position
+                var z = zoomLevels[zoomLevels.indexOf($(selector)[0].id) + 1];
+
+                moveHorizontal(-((xdiff / 5) / z));
+                moveVertical(-((ydiff / 5) / z));
+            }
 
-        if (!((offset + step) < top) && !(($(selector).position().top + step) > 0)) {
-          $(selector).css('top', (offset + step) + 'px');
-        }
+            // zoom out
+            if (event.deltaY < 0) {
+                Engage.trigger(events.setZoomLevel.getName(), [-zoom_step_size]);
+            }
 
-        updateMinimap();
-      }
-    }
+            wheelEvent = event;
+        });
 
-    Engage.on(plugin.events.setZoomLevel.getName(), function (data) {
-      var level = data[0];
-      var fixed = data[1];
-      var moveOnly = data[2];
-
-      fixed = typeof fixed !== 'undefined' ? fixed : false;
-      moveOnly = typeof moveOnly !== 'undefined' ? moveOnly : false;
-
-      if ($(selector)[0] === undefined || level === undefined) {
-        return;
-      }
-
-      if (zoomLevels.indexOf($(selector)[0].id) == -1) {
-        if (1.0 + level >= 1.0) {
-          if (!fixed) {
-            level = (1.0 + level);
-          }
-          zoomLevels.push($(selector)[0].id, Math.abs(level));
-        }
-      } else {
-        var before = parseFloat(zoomLevels[(zoomLevels.indexOf($(selector)[0].id) + 1)]);
-        if ((before + level) >= 1.0) {
-          if (!fixed) {
-            level = (before + level);
-          }
-        }
-      }
-
-      if (Number(level).toFixed(decimal_places) == Number(1).toFixed(decimal_places) && minimapVisible) {
-        hideMinimap();
-      }
-
-      if (Number(level).toFixed(decimal_places) >= Number(1).toFixed(decimal_places) && (videoFocused || singleVideo)) {
-        var topTrans = Number($(selector).css('top').replace('px', ''));
-        var leftTrans = Number($(selector).css('left').replace('px', ''));
-
-        var biggerThenOne = Number(level).toFixed(decimal_places) > Number(1).toFixed(decimal_places);
-
-        var leftOffset = ($(selector).width() * level - $(selector).width()) / 2;
-        leftOffset = leftOffset - Math.abs(leftTrans);
-        if (leftOffset < 0) {
-          if (leftTrans > 0) {
-            Engage.trigger(plugin.events.moveHorizontal.getName(), leftOffset);
-          }
-          if (leftTrans < 0) {
-            Engage.trigger(plugin.events.moveHorizontal.getName(), -leftOffset);
-          }
-        }
-
-        var topOffset = ($(selector).height() * level - $(selector).height()) / 2;
-        topOffset = topOffset - Math.abs(topTrans);
-        if (topOffset < 0) {
-          if (topTrans > 0) {
-            Engage.trigger(plugin.events.moveVertical.getName(), topOffset);
-          }
-          if (topTrans < 0) {
-            Engage.trigger(plugin.events.moveVertical.getName(), -topOffset);
-          }
-        }
-
-        var zoomLevel = Number(level).toFixed(decimal_places);
-
-        if (!moveOnly) {
-          $(selector)[0].style.transform = 'scale(' + zoomLevel + ')';
-          zoomLevels[(zoomLevels.indexOf($(selector)[0].id) + 1)] = parseFloat(Number(level).toFixed(decimal_places));
-          Engage.trigger(plugin.events.zoomChange.getName(), zoomLevel);
-
-          if (!minimapVisible && biggerThenOne) {
-            showMinimap();
-          } else if (minimapVisible && biggerThenOne) {
-            updateMinimap();
-          }
-        }
-      }
-    });
+        $(selector).mousedown(function () {
+            flag = 0;
+            $(selector).mousemove(function (event) {
+                if (lastEvent != null) {
+                    flag = 1;
+                    var x_move = lastEvent.pageX - event.pageX;
+                    var y_move = lastEvent.pageY - event.pageY;
+                    Engage.trigger(plugin.events.moveHorizontal.getName(), -x_move);
+                    Engage.trigger(plugin.events.moveVertical.getName(), -y_move);
+                }
 
-    Engage.on(plugin.events.zoomReset.getName(), function () {
-      var tmpSelector = selector;
-      for (var i = 0; i < zoomLevels.length; i++) {
-        selector = $('#' + zoomLevels[i])[0];
-        Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
-        i++;
-      }
-      selector = tmpSelector;
-    });
+                lastEvent = event;
+            });
+            $('body').mouseup(function () {
+                $(selector).off('mousemove');
+                lastEvent = null;
+            });
+        });
 
-    Engage.on(plugin.events.zoomIn.getName(), function () {
-      Engage.trigger(plugin.events.setZoomLevel.getName(), [zoom_step_size]);
-    });
+        Engage.on(plugin.events.moveHorizontal.getName(), function (step) {
+            moveHorizontal(step);
+        });
 
-    Engage.on(plugin.events.zoomOut.getName(), function () {
-      Engage.trigger(plugin.events.setZoomLevel.getName(), [-zoom_step_size]);
-    });
+        Engage.on(plugin.events.moveVertical.getName(), function (step) {
+            moveVertical(step);
+        });
 
-    $(window).resize(function () {
-      Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true, true]);
-      showMinimap();
-    });
-  }
+        function moveHorizontal(step) {
+            if (videoFocused || singleVideo) {
+                var offset = $(selector).css('left');
+                var left = $(selector).position().left / 2;
 
-  function initializeVideoJsGlobally(videoDataView, videoDisplays, tuples) {
-    Engage.log('Video: Preparing video.js video displays globally.');
-    for (var i = 0; i < tuples.length; ++i) {
-      var value = tuples[i][1];
+                offset = offset.replace('px', '');
+                offset = Number(offset);
 
-      globalVideoSource.push([videoDisplays[i], value]);
+                if (step > 0 && Math.abs($(selector).position().left) < step) {
+                    // Shift right, but too far
+                    step = Math.abs($(selector).position().left);
+                }
 
-      initVideojsVideo(videoDisplays[i], value, videoDataView.videojs_swf);
-    }
-  }
-
-  function calculateAspectRatioForVideos(videoDataView, videoDisplays, aspectRatio) {
-    Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[1] / aspectRatio[2]) * 100));
-    Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
-    $('.' + id_videoDisplayClass)
-      .css('width', (((1 / videoDisplays.length) * 100) - 0.5) + '%')
-      .each(function (index) {
-        if ((index % 2) === 1) {
-          $(videoDataView).css('float', 'right');
-        }
-      });
-    for (var j = 0; j < videoDisplays.length; ++j) {
-      $('#' + videoDisplays[j]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
-      singleVideoPaddingTop = (aspectRatio[2] / aspectRatio[1] * 100) + '%';
-    }
-  }
+                if (step < 0 && (offset + step < left)) {
+                    // Shift left but too far
+                    step = (left - offset);
+                }
 
-  Engage.on(plugin.events.aspectRatioSet.getName(), function (param) {
-    if (param === undefined) {
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
-    }
-  })
-
-  function synchronizeVideos(videoDisplays) {
-    registerSynchronizeEvents();
-
-    var cnt = 0;
-    for (var vd in videoDisplays) {
-      if (cnt > 0) {
-        // sync every other videodisplay with the master
-        $.synchronizeVideos(0, videoDisplays[0], videoDisplays[vd]);
-        Engage.log('Video: Videodisplay ' + vd + ' is now being synchronized with the master videodisplay');
-      }
-      ++cnt;
-    }
-    initSynchronize();
-  }
+                if (!(($(selector).position().left + step) > 0) && !((offset + step) < left)) {
+                    $(selector).css('left', (offset + step) + 'px');
+                }
 
-  function renderDesktop(videoDataView, videoSources, videoDisplays, aspectRatio) {
-    Engage.log('Video: Rendering for desktop view');
+                updateMinimap();
+            }
+        }
 
-    var tuples = getSortedVideosourcesArray(videoSources);
+        function moveVertical(step) {
+            if (videoFocused || singleVideo) {
+                var top = $(selector).position().top / 2;
+                var offset = $(selector).css('top');
 
-    initializeVideoJsGlobally(videoDataView, videoDisplays, tuples);
+                offset = offset.replace('px', '');
+                offset = Number(offset);
+
+                if (step > 0 && (Math.abs($(selector).position().top) < step)) {
+                    step = Math.abs($(selector).position().top);
+                }
 
-    /* set first videoDisplay as master */
-    var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
-    videodisplayMaster = videojs(videoDisplay);
+                if (step < 0 && (offset + step < top)) {
+                    step = (top - offset);
+                }
 
-    initQualities(videoDataView);
+                if (!((offset + step) < top) && !(($(selector).position().top + step) > 0)) {
+                    $(selector).css('top', (offset + step) + 'px');
+                }
 
-    if ((aspectRatio != null) && (videoDisplays.length > 0)) {
-      calculateAspectRatioForVideos(videoDataView, videoDisplays, aspectRatio);
-    } else {
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
-    }
+                updateMinimap();
+            }
+        }
+
+        Engage.on(plugin.events.setZoomLevel.getName(), function (data) {
+            var level = data[0];
+            var fixed = data[1];
+            var moveOnly = data[2];
+
+            fixed = typeof fixed !== 'undefined' ? fixed : false;
+            moveOnly = typeof moveOnly !== 'undefined' ? moveOnly : false;
+
+            if ($(selector)[0] === undefined || level === undefined) {
+                return;
+            }
+
+            if (zoomLevels.indexOf($(selector)[0].id) == -1) {
+                if (1.0 + level >= 1.0) {
+                    if (!fixed) {
+                        level = (1.0 + level);
+                    }
+                    zoomLevels.push($(selector)[0].id, Math.abs(level));
+                }
+            } else {
+                var before = parseFloat(zoomLevels[(zoomLevels.indexOf($(selector)[0].id) + 1)]);
+                if ((before + level) >= 1.0) {
+                    if (!fixed) {
+                        level = (before + level);
+                    }
+                }
+            }
 
-    // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
-    $('.' + class_vjsposter).show();
+            if (Number(level).toFixed(decimal_places) == Number(1).toFixed(decimal_places) && minimapVisible) {
+                hideMinimap();
+            }
 
-    registerZoomLevelEvents();
+            if (Number(level).toFixed(decimal_places) >= Number(1).toFixed(decimal_places) && (videoFocused || singleVideo)) {
+                var topTrans = Number($(selector).css('top').replace('px', ''));
+                var leftTrans = Number($(selector).css('left').replace('px', ''));
+
+                var biggerThenOne = Number(level).toFixed(decimal_places) > Number(1).toFixed(decimal_places);
+
+                var leftOffset = ($(selector).width() * level - $(selector).width()) / 2;
+                leftOffset = leftOffset - Math.abs(leftTrans);
+                if (leftOffset < 0) {
+                    if (leftTrans > 0) {
+                        Engage.trigger(plugin.events.moveHorizontal.getName(), leftOffset);
+                    }
+                    if (leftTrans < 0) {
+                        Engage.trigger(plugin.events.moveHorizontal.getName(), -leftOffset);
+                    }
+                }
 
-    Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
+                var topOffset = ($(selector).height() * level - $(selector).height()) / 2;
+                topOffset = topOffset - Math.abs(topTrans);
+                if (topOffset < 0) {
+                    if (topTrans > 0) {
+                        Engage.trigger(plugin.events.moveVertical.getName(), topOffset);
+                    }
+                    if (topTrans < 0) {
+                        Engage.trigger(plugin.events.moveVertical.getName(), -topOffset);
+                    }
+                }
 
-    if (videoDisplays.length > 0) {
-      var nr = tuples.length;
+                var zoomLevel = Number(level).toFixed(decimal_places);
 
-      registerEvents(videoDisplay, videoDisplays.length);
+                if (!moveOnly) {
+                    $(selector)[0].style.transform = 'scale(' + zoomLevel + ')';
+                    zoomLevels[(zoomLevels.indexOf($(selector)[0].id) + 1)] = parseFloat(Number(level).toFixed(decimal_places));
+                    Engage.trigger(plugin.events.zoomChange.getName(), zoomLevel);
 
-      if (nr >= 2) {
-        synchronizeVideos(videoDisplays);
-      } else {
-        videosReady = true;
-        if (!isAudioOnly) {
-          Engage.trigger(plugin.events.ready.getName());
-        }
-      }
+                    if (!minimapVisible && biggerThenOne) {
+                        showMinimap();
+                    } else if (minimapVisible && biggerThenOne) {
+                        updateMinimap();
+                    }
+                }
+            }
+        });
+
+        Engage.on(plugin.events.zoomReset.getName(), function () {
+            var tmpSelector = selector;
+            for (var i = 0; i < zoomLevels.length; i++) {
+                selector = $('#' + zoomLevels[i])[0];
+                Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true]);
+                i++;
+            }
+            selector = tmpSelector;
+        });
+
+        Engage.on(plugin.events.zoomIn.getName(), function () {
+            Engage.trigger(plugin.events.setZoomLevel.getName(), [zoom_step_size]);
+        });
+
+        Engage.on(plugin.events.zoomOut.getName(), function () {
+            Engage.trigger(plugin.events.setZoomLevel.getName(), [-zoom_step_size]);
+        });
 
-      if (videoDataView.model.get('type') !== 'audio') {
         $(window).resize(function () {
-          checkVideoDisplaySize();
+            Engage.trigger(plugin.events.setZoomLevel.getName(), [1.0, true, true]);
+            showMinimap();
         });
-      }
     }
-  }
 
-  function appendEmbedPlayer_switchPlayers(videoDisplays) {
-    $('.' + class_vjs_remaining_time).after("<div id=\"" + id_btn_switchPlayer + "\" class=\"" + class_vjs_switchPlayer + " vjs-menu-button vjs-menu-button-popup vjs-control vjs-button\" tabindex=\"0\" role=\"menuitem\" aria-live=\"polite\" aria-expanded=\"false\" aria-haspopup=\"true\">");
+    function initializeVideoJsGlobally(videoDataView, videoDisplays, tuples) {
+        Engage.log('Video: Preparing video.js video displays globally.');
+        for (var i = 0; i < tuples.length; ++i) {
+            var value = tuples[i][1];
 
-    var uls = '';
-    for (var i = 0; i < videoDisplays.length; ++i) {
-      uls += "<li id=\"btn-video" + (i + 1) + "\" class=\"vjs-menu-item " + class_vjs_menu_item + " " + class_btn_video + "\" tabindex=\"-1\" role=\"menuitem\" aria-live=\"polite\">" + translate("video", "Video") + " " + (i + 1) + "</li>";
-    }
+            globalVideoSource.push([videoDisplays[i], value]);
 
-    $('#' + id_btn_switchPlayer).append(
-      "<div class=\"vjs-menu\" role=\"presentation\">" +
-      "<ul class=\"" + class_vjs_menu_content + "\" role=\"menu\">" +
-      uls +
-      "</ul>" +
-      "</div>" +
-      "<span class=\"" + class_vjs_control_text + "\">" + translate("switchPlayer", "Switch player") + "</span>" +
-      "<div id=\"" + id_switchPlayer_value + "\" class=\"" + class_vjs_switchPlayer_value + "\">" + "Vid. 1" + "</div>"
-    );
-
-    for (var j = 0; j < videoDisplays.length; ++j) {
-      $('#btn-video' + (j + 1)).click(function (k) {
-        return function () {
-          $('#' + id_switchPlayer_value).html(translate('video_short', 'Vid.') + ' ' + (k + 1));
-          currentlySelectedVideodisplay = k;
-          videojs(globalVideoSource[0].id).src(globalVideoSource[k].src);
-        };
-      }(j));
+            initVideojsVideo(videoDisplays[i], value, videoDataView.videojs_swf);
+        }
     }
-  }
-
-  function appendEmbedPlayer_openInPlayer() {
-    $('.' + class_vjs_remaining_time).after('<button id="' + id_btn_openInPlayer + '" class="' + class_vjs_openInPlayer + ' vjs-control vjs-button" type="button" aria-live="polite"></button>');
-    $('.' + class_vjs_openInPlayer).append('<span class="' + class_vjs_control_text + ' vjs-control-text">' + translate('openInPlayer', 'Open in player') + '</span>');
-
-    $('#' + id_btn_openInPlayer).click(function (e) {
-      e.preventDefault();
-      var str = window.location.href;
-      if (str.indexOf('mode=embed') == -1) {
-        str += '&mode=embed';
-      } else {
-        str = Utils.replaceAll(str, 'mode=embed', 'mode=desktop');
-      }
-      Engage.trigger(plugin.events.pause.getName(), false);
-      window.open(str, '_blank');
-    });
-  }
-
-  function renderEmbed(videoDataView, videoSources, videoDisplays, aspectRatio) {
-    Engage.log('Video: Rendering for embeded view');
-    var init = false;
-
-    var tuples = getSortedVideosourcesArray(videoSources);
-    for (var i = 0; i < tuples.length; ++i) {
-      var value = tuples[i][1];
-
-      if (!init) { // just init the first video
-        init = true;
-        initVideojsVideo(videoDisplays[i], value, videoDataView.videojs_swf);
-      }
-      globalVideoSource.push({
-        id: videoDisplays[0],
-        src: value
-      });
+
+    function calculateAspectRatioForVideos(videoDataView, videoDisplays, aspectRatio) {
+        Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[1] / aspectRatio[2]) * 100));
+        Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
+        $('.' + id_videoDisplayClass)
+            .css('width', (((1 / videoDisplays.length) * 100) - 0.5) + '%')
+            .each(function (index) {
+                if ((index % 2) === 1) {
+                    $(videoDataView).css('float', 'right');
+                }
+            });
+        for (var j = 0; j < videoDisplays.length; ++j) {
+            $('#' + videoDisplays[j]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
+            singleVideoPaddingTop = (aspectRatio[2] / aspectRatio[1] * 100) + '%';
+        }
     }
 
-    /* set first videoDisplay as master */
-    var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
-    videodisplayMaster = videojs(videoDisplay);
+    Engage.on(plugin.events.aspectRatioSet.getName(), function (param) {
+        if (param === undefined) {
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
+        }
+    })
+
+    function synchronizeVideos(videoDisplays) {
+        registerSynchronizeEvents();
 
-    if ((videoDisplays.length > 1) && (globalVideoSource.length > 1)) {
-      appendEmbedPlayer_switchPlayers(videoDisplays);
-    }
-    appendEmbedPlayer_openInPlayer();
-
-    if ((aspectRatio != null) && (videoDisplays.length > 0)) {
-      aspectRatio[1] = parseInt(aspectRatio[1]);
-      aspectRatio[2] = parseInt(aspectRatio[2]);
-      Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[2] / aspectRatio[1]) * 100));
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
-      $('.' + id_videoDisplayClass).css('width', '100%');
-      for (var i = 0; i < videoDisplays.length; ++i) {
-        $('#' + videoDisplays[i]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
-        singleVideoPaddingTop = (aspectRatio[2] / aspectRatio[1] * 100) + '%';
-      }
-    } else {
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
+        var cnt = 0;
+        for (var vd in videoDisplays) {
+            if (cnt > 0) {
+                // sync every other videodisplay with the master
+                $.synchronizeVideos(0, videoDisplays[0], videoDisplays[vd]);
+                Engage.log('Video: Videodisplay ' + vd + ' is now being synchronized with the master videodisplay');
+            }
+            ++cnt;
+        }
+        initSynchronize();
     }
 
-    // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
-    $('.' + class_vjsposter).show();
-    Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
+    function renderDesktop(videoDataView, videoSources, videoDisplays, aspectRatio) {
+        Engage.log('Video: Rendering for desktop view');
 
-    if (videoDisplays.length > 0) {
-      registerEvents(videoDisplay, 1);
+        var tuples = getSortedVideosourcesArray(videoSources);
 
-      videosReady = true;
-      Engage.trigger(plugin.events.ready.getName());
+        initializeVideoJsGlobally(videoDataView, videoDisplays, tuples);
 
-      if (videoDataView.model.get('type') != 'audio') {
-        $(window).resize(function () {
-          checkVideoDisplaySize();
-        });
-      }
-    }
-  }
-
-  function renderMobile(videoDataView, videoSources, videoDisplays, aspectRatio) {
-    var tuples = getSortedVideosourcesArray(videoSources);
-    initializeVideoJsGlobally(videoDataView, videoDisplays, tuples);
-
-    /* set first videoDisplay as master */
-    var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
-    videodisplayMaster = videojs(videoDisplay);
-
-    initQualities(videoDataView);
-
-    if ((aspectRatio != null) && (videoDisplays.length > 0)) {
-      aspectRatio[1] = parseInt(aspectRatio[1]);
-      aspectRatio[2] = parseInt(aspectRatio[2]);
-      Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[2] / aspectRatio[1]) * 100));
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), aspectRatio[1], aspectRatio[2], (aspectRatio[2] / aspectRatio[1]) * 100);
-      $('.' + id_videoDisplayClass).css('width', '100%');
-      for (var j = 0; j < videoDisplays.length; ++j) {
-        $('#' + videoDisplays[j]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
-      }
-    } else {
-      Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
-    }
+        /* set first videoDisplay as master */
+        var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
+        videodisplayMaster = videojs(videoDisplay);
 
-    // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
-    $('.' + class_vjsposter).show();
-    Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
+        initQualities(videoDataView);
 
-    if (videoDisplays.length > 0) {
-      registerEvents(videoDisplay, videoDisplays.length);
+        if ((aspectRatio != null) && (videoDisplays.length > 0)) {
+            calculateAspectRatioForVideos(videoDataView, videoDisplays, aspectRatio);
+        } else {
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
+        }
 
-      videosReady = true;
-      Engage.trigger(plugin.events.ready.getName());
+        // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
+        $('.' + class_vjsposter).show();
 
-      if (videoDataView.model.get('type') != 'audio') {
-        $(window).resize(function () {
-          checkVideoDisplaySize();
-        });
-      }
-    }
-  }
-
-  function calculateAspectRatio(videoSources) {
-    Engage.log('Video: Calculating Aspect ratio');
-    var as1 = 0;
-    for (var flavor in videoResultions) {
-      if ((aspectRatio == null) || (as1 < videoResultions[flavor])) {
-        as1 = videoResultions[flavor][1];
-        aspectRatio = videoResultions[flavor];
-        id_generated_videojs_flash_component = 'videojs_videodisplay_' + flavor + '_flash_api';
-      }
+        registerZoomLevelEvents();
+
+        Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
+
+        if (videoDisplays.length > 0) {
+            var nr = tuples.length;
+
+            registerEvents(videoDisplay, videoDisplays.length);
+
+            if (nr >= 2) {
+                synchronizeVideos(videoDisplays);
+            } else {
+                videosReady = true;
+                if (!isAudioOnly) {
+                    Engage.trigger(plugin.events.ready.getName());
+                }
+            }
+
+            if (videoDataView.model.get('type') !== 'audio') {
+                $(window).resize(function () {
+                    checkVideoDisplaySize();
+                });
+            }
+        }
     }
-    for (var v in videoSources) {
-      for (var j = 0; j < videoSources[v].length; ++j) {
-        var aspectRatio_tmp = videoSources[v][j].resolution;
-        var t_tmp = $.type(aspectRatio_tmp);
-        if ((t_tmp === 'string') && (/\d+x\d+/.test(aspectRatio_tmp))) {
-          aspectRatio_tmp = aspectRatio_tmp.match(/(\d+)x(\d+)/);
-          if ((aspectRatio == null) || (as1 < parseInt(aspectRatio_tmp[1]))) {
-            as1 = parseInt(aspectRatio_tmp[1]);
-            aspectRatio = Utils.parseVideoResolution(videoSources[v][j].resolution);
-          }
-        }
-      }
+
+    function appendEmbedPlayer_switchPlayers(videoDisplays) {
+        $('.' + class_vjs_remaining_time).after("<div id=\"" + id_btn_switchPlayer + "\" class=\"" + class_vjs_switchPlayer + " vjs-menu-button vjs-menu-button-popup vjs-control vjs-button\" tabindex=\"0\" role=\"menuitem\" aria-live=\"polite\" aria-expanded=\"false\" aria-haspopup=\"true\">");
+
+        var uls = '';
+        for (var i = 0; i < videoDisplays.length; ++i) {
+            uls += "<li id=\"btn-video" + (i + 1) + "\" class=\"vjs-menu-item " + class_vjs_menu_item + " " + class_btn_video + "\" tabindex=\"-1\" role=\"menuitem\" aria-live=\"polite\">" + translate("video", "Video") + " " + (i + 1) + "</li>";
+        }
+
+        $('#' + id_btn_switchPlayer).append(
+            "<div class=\"vjs-menu\" role=\"presentation\">" +
+            "<ul class=\"" + class_vjs_menu_content + "\" role=\"menu\">" +
+            uls +
+            "</ul>" +
+            "</div>" +
+            "<span class=\"" + class_vjs_control_text + "\">" + translate("switchPlayer", "Switch player") + "</span>" +
+            "<div id=\"" + id_switchPlayer_value + "\" class=\"" + class_vjs_switchPlayer_value + "\">" + "Vid. 1" + "</div>"
+        );
+
+        for (var j = 0; j < videoDisplays.length; ++j) {
+            $('#btn-video' + (j + 1)).click(function (k) {
+                return function () {
+                    $('#' + id_switchPlayer_value).html(translate('video_short', 'Vid.') + ' ' + (k + 1));
+                    currentlySelectedVideodisplay = k;
+                    videojs(globalVideoSource[0].id).src(globalVideoSource[k].src);
+                };
+            }(j));
+        }
     }
-    Engage.log('Video: Calculated aspect ratio: ' + aspectRatio);
-  }
-
-  function renderVideoDisplay(videoDataView) {
-    Engage.log('Video: Rendering video displays');
-    var videoDisplays = videoDataView.model.get('ids');
-    var videoSources = videoDataView.model.get('videoSources');
-
-    var src = (videoSources && videoSources['audio']) ? videoSources['audio'] : [];
-    var tempVars = {
-      ids: videoDataView.model.get('ids'),
-      type: videoDataView.model.get('type'),
-      sources: src,
-      str_error_AudioCodecNotSupported: translate('error_AudioCodecNotSupported', 'Error: The audio codec is not supported by this browser.'),
-      str_error_AudioElementNotSupported: translate('error_AudioElementNotSupported', 'Error: Your browser does not support the audio element.')
-    };
-    if (isEmbedMode && !isAudioOnly) {
-      tempVars.id = videoDataView.model.get('ids')[0];
+
+    function appendEmbedPlayer_openInPlayer() {
+        $('.' + class_vjs_remaining_time).after('<button id="' + id_btn_openInPlayer + '" class="' + class_vjs_openInPlayer + ' vjs-control vjs-button" type="button" aria-live="polite"></button>');
+        $('.' + class_vjs_openInPlayer).append('<span class="' + class_vjs_control_text + ' vjs-control-text">' + translate('openInPlayer', 'Open in player') + '</span>');
+
+        $('#' + id_btn_openInPlayer).click(function (e) {
+            e.preventDefault();
+            var str = window.location.href;
+            if (str.indexOf('mode=embed') == -1) {
+                str += '&mode=embed';
+            } else {
+                str = Utils.replaceAll(str, 'mode=embed', 'mode=desktop');
+            }
+            Engage.trigger(plugin.events.pause.getName(), false);
+            window.open(str, '_blank');
+        });
     }
 
-    // compile template and load into the html
-    var template = _.template(videoDataView.template);
-    videoDataView.$el.html(template(tempVars));
+    function renderEmbed(videoDataView, videoSources, videoDisplays, aspectRatio) {
+        Engage.log('Video: Rendering for embeded view');
+        var init = false;
+
+        var tuples = getSortedVideosourcesArray(videoSources);
+        for (var i = 0; i < tuples.length; ++i) {
+            var value = tuples[i][1];
 
-    if (!mediapackageError) {
-      calculateAspectRatio(videoSources);
+            if (!init) { // just init the first video
+                init = true;
+                initVideojsVideo(videoDisplays[i], value, videoDataView.videojs_swf);
+            }
+            globalVideoSource.push({
+                id: videoDisplays[0],
+                src: value
+            });
+        }
 
-      isAudioOnly = videoDataView.model.get('type') == 'audio';
-      Engage.trigger(plugin.events.isAudioOnly.getName(), isAudioOnly);
+        /* set first videoDisplay as master */
+        var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
+        videodisplayMaster = videojs(videoDisplay);
 
-      if (videoSources && videoDisplays) {
-        if (isEmbedMode) {
-          renderEmbed(videoDataView, videoSources, videoDisplays, aspectRatio);
-        } else if (isMobileMode) {
-          renderMobile(videoDataView, videoSources, videoDisplays, aspectRatio);
-        } else { // isDesktopMode
-          renderDesktop(videoDataView, videoSources, videoDisplays, aspectRatio);
+        if ((videoDisplays.length > 1) && (globalVideoSource.length > 1)) {
+            appendEmbedPlayer_switchPlayers(videoDisplays);
         }
-        if (videoDataView.model.get('type') != 'audio') {
-          delayedCalculateVideoAreaAspectRatio();
+        appendEmbedPlayer_openInPlayer();
+
+        if ((aspectRatio != null) && (videoDisplays.length > 0)) {
+            aspectRatio[1] = parseInt(aspectRatio[1]);
+            aspectRatio[2] = parseInt(aspectRatio[2]);
+            Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[2] / aspectRatio[1]) * 100));
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), [aspectRatio[1], aspectRatio[2], (aspectRatio[1] / aspectRatio[2]) * 100]);
+            $('.' + id_videoDisplayClass).css('width', '100%');
+            for (var i = 0; i < videoDisplays.length; ++i) {
+                $('#' + videoDisplays[i]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
+                singleVideoPaddingTop = (aspectRatio[2] / aspectRatio[1] * 100) + '%';
+            }
+        } else {
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
         }
-      }
-    }
-    console.log(videodisplayMaster);
-
-    loadAndAppendCaptions(videoDataView);
-  }
-
-  function prepareRenderingVideoDisplay(videoDataView) {
-    if (loadHls) {
-      require([relative_plugin_path + mediaSourcesPath], function () {
-        Engage.log('Video: Lib videojs media sources loaded');
-        require([relative_plugin_path + hlsPath], function () {
-          Engage.log('Video: Lib videojs HLS playback loaded');
-          renderVideoDisplay(videoDataView);
-        });
-      });
-    } else {
-      renderVideoDisplay(videoDataView);
-    }
-  }
-
-  var VideoDataView = Backbone.View.extend({
-    el: $('#' + id_engage_video),
-    initialize: function (videoDataModel, template, videojs_swf) {
-      this.setElement($(plugin.container));
-      this.model = videoDataModel;
-      this.template = template;
-      this.videojs_swf = videojs_swf;
-      _.bindAll(this, 'render');
-      this.model.bind('change', this.render);
-      this.render();
-    },
-    render: function () {
-      prepareRenderingVideoDisplay(this);
-    }
-  });
-
-  function initVideojsVideo(id, videoSource, videojs_swf) {
-    Engage.log('Video: Initializing video.js-display ' + id);
-
-    if (id) {
-      if (videoSource) {
-        if (!isAudioOnly) {
-          var videoOptions = {
-            controls: false,
-            autoplay: false,
-            preload: 'auto',
-            poster: videoSource.poster ? videoSource.poster : '',
-            loop: false,
-            width: '100%',
-            height: '100%'
-          };
-          if (isEmbedMode) {
-            videoOptions.controls = true;
-          }
-
-          // init video.js
-          videojs(id, videoOptions, function () {
-            var videodisplay = this;
-            // set sources
-            videodisplay.src(videoSource);
-          });
-          // URL to the flash swf
-          if (videojs_swf) {
-            Engage.log('Video: Loaded flash component');
-            videojs.options.flash.swf = videojs_swf;
-          } else {
-            Engage.log('Video: No flash component loaded');
-          }
-          isUsingFlash = $('#' + id_generated_videojs_flash_component).length > 0;
-          Engage.trigger(plugin.events.usingFlash.getName(), isUsingFlash);
-        }
-      } else {
-        Engage.log('Video: Error: No video source available');
-        $('#' + id_videojs_wrapper).html('No video sources available.');
-      }
-    } else {
-      Engage.log('Video: Error: No ID available');
-      $('#' + id_videojs_wrapper).html('No video available.');
-    }
-  }
-
-  function delayedCalculateVideoAreaAspectRatio() {
-    calculateVideoAreaAspectRatio();
-    window.setTimeout(calculateVideoAreaAspectRatio, checkVideoDisplaySizeTimeout);
-  }
-
-  function calculateVideoAreaAspectRatio() {
-    var $engageVideoId = $('#' + id_engage_video);
-    var oldAspectRatio = videoAreaAspectRatio;
-
-    var videoHeight = $engageVideoId.height();
-    var videoWidth = $engageVideoId.width();
-    if (videoWidth !== undefined && videoHeight !== undefined &&
-        videoWidth === 0 && videoHeight === 0) {
-        return;
-    }
-    if (isEmbedMode) {
-      if (videoWidth !== undefined && videoHeight !== undefined &&
-          videoWidth > 0 && videoHeight > 0) {
-        videoAreaAspectRatio = videoWidth / videoHeight;
-      }
-    } else if (!isDefaultLayout()) {
-      videoHeight = $('.' + videoFocusedClass).height();
-      if (isPiP) {
-        videoWidth = $('.' + videoFocusedClass).width();
-      }
-    }
-    if (videoWidth !== undefined && videoHeight !== undefined &&
-        videoWidth > 0 && videoHeight > 0) {
-      videoAreaAspectRatio = videoWidth / videoHeight;
-    }
 
-    if (videoAreaAspectRatio !== oldAspectRatio) {
-      checkVideoDisplaySize();
-    }
-  }
-
-  function checkVideoDisplaySize() {
-    var $engageVideoId = $('#' + id_engage_video);
-    var $videoUnfocused = $('.' + videoUnfocusedClass);
-
-    var videoHeight = $engageVideoId.height();
-
-    if (!isMobileMode) {
-      var controlsHeight = ($('#' + id_resize_container).height() - videoHeight) + 5;
-      if (controlsHeight <= 0) {
-        controlsHeight = $('#' + id_engageControls).height() + 30;
-      }
-      var maxVideoAreaHeight = $(window).height() - controlsHeight;
-    } else {
-      var maxVideoAreaHeight = $(window).height();
-    }
+        // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
+        $('.' + class_vjsposter).show();
+        Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
 
-    if (isEmbedMode) {
-      maxVideoAreaHeight = $(window).height();
-    }
+        if (videoDisplays.length > 0) {
+            registerEvents(videoDisplay, 1);
 
-    if (videoAreaAspectRatio === undefined && !isMobileMode) {
-      calculateVideoAreaAspectRatio();
-    }
+            videosReady = true;
+            Engage.trigger(plugin.events.ready.getName());
 
-    if (!isMobileMode) {
-      var maxVideoAreaWidth = parseInt(maxVideoAreaHeight * videoAreaAspectRatio);
-      var minVideoAreaHeight = parseInt(parseInt($engageVideoId.css('min-width')) / videoAreaAspectRatio);
-    } else {
-      var maxVideoAreaWidth = parseInt(maxVideoAreaHeight * (aspectRatio[1] / aspectRatio[2]));
-      var minVideoAreaHeight = parseInt(parseInt($engageVideoId.css('min-width')) / (aspectRatio[1] / aspectRatio[2]));
+            if (videoDataView.model.get('type') != 'audio') {
+                $(window).resize(function () {
+                    checkVideoDisplaySize();
+                });
+            }
+        }
     }
 
-    var minWidth = parseInt($engageVideoId.css('min-width'));
-    if (maxVideoAreaWidth > minWidth) {
-      if (maxVideoAreaWidth > $(window).width()) {
-        $engageVideoId.css('max-width', $(window).width() + 'px');
-      } else {
-        $engageVideoId.css('max-width', maxVideoAreaWidth + 'px');
-      }
-    } else {
-      $engageVideoId.css('max-width', minWidth + 'px');
-    }
-    $engageVideoId.css('min-height', minVideoAreaHeight + 'px');
-    if (maxVideoAreaHeight > minVideoAreaHeight) {
-      $engageVideoId.css('max-height', maxVideoAreaHeight + 'px');
-    } else {
-      $engageVideoId.css('max-height', minVideoAreaHeight + 'px');
-    }
+    function renderMobile(videoDataView, videoSources, videoDisplays, aspectRatio) {
+        var tuples = getSortedVideosourcesArray(videoSources);
+        initializeVideoJsGlobally(videoDataView, videoDisplays, tuples);
+
+        /* set first videoDisplay as master */
+        var videoDisplay = isAudioOnly ? id_audioDisplay : videoDisplays[0];
+        videodisplayMaster = videojs(videoDisplay);
+
+        initQualities(videoDataView);
 
-    if (!isDefaultLayout()) {
-      if (isPiP) {
-        var distance = 0;
-        $videoUnfocused.each(function () {
-          var width = $(this).width();
-          var height = $(this).height();
-          $(this).css('left', 0 - (width / 2) + 'px');
-          $(this).css('top', distance - (height / 2) + 'px');
-          distance = distance + height + 10;
-        });
-        var marginLeft;
-        if (pipPos === 'left') {
-          marginLeft = 12;
+        if ((aspectRatio != null) && (videoDisplays.length > 0)) {
+            aspectRatio[1] = parseInt(aspectRatio[1]);
+            aspectRatio[2] = parseInt(aspectRatio[2]);
+            Engage.log('Video: Aspect ratio: ' + aspectRatio[1] + 'x' + aspectRatio[2] + ' == ' + ((aspectRatio[2] / aspectRatio[1]) * 100));
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), aspectRatio[1], aspectRatio[2], (aspectRatio[2] / aspectRatio[1]) * 100);
+            $('.' + id_videoDisplayClass).css('width', '100%');
+            for (var j = 0; j < videoDisplays.length; ++j) {
+                $('#' + videoDisplays[j]).css('padding-top', (aspectRatio[2] / aspectRatio[1] * 100) + '%').addClass('auto-height');
+            }
         } else {
-          marginLeft = 88;
+            Engage.trigger(plugin.events.aspectRatioSet.getName(), -1, -1, -1);
         }
-        $videoUnfocused.css('margin-left', marginLeft + '%');
-      } else {
-        $engageVideoId.height($('.' + videoFocusedClass).height());
-      }
-    }
-  }
 
-  function clearAutoplay() {
-    window.clearInterval(interval_autoplay);
-  }
+        // small hack for the posters: A poster is only being displayed when controls=true, so do it manually
+        $('.' + class_vjsposter).show();
+        Engage.trigger(plugin.events.numberOfVideodisplaysSet.getName(), videoDisplays.length);
 
-  function clearInitialSeek() {
-    window.clearInterval(interval_initialSeek);
-  }
+        if (videoDisplays.length > 0) {
+            registerEvents(videoDisplay, videoDisplays.length);
 
-  function changePlaybackRate(value, videodisplayMaster) {
-    if (pressedPlayOnce) {
-      var rate = videodisplayMaster.playbackRate();
-      Engage.trigger(plugin.events.playbackRateChanged.getName(), (rate + value));
+            videosReady = true;
+            Engage.trigger(plugin.events.ready.getName());
+
+            if (videoDataView.model.get('type') != 'audio') {
+                $(window).resize(function () {
+                    checkVideoDisplaySize();
+                });
+            }
+        }
     }
-  }
-
-  function startAudioPlayer(audio) {
-    clearAutoplay();
-    audio.play();
-    pressedPlayOnce = true;
-  }
-
-  function registerEventsAudioOnly(videoDisplay) {
-    var audioPlayer_id = $('#' + videoDisplay);
-    var audioPlayer = audioPlayer_id[0];
-    var audioLoadTimeout = window.setTimeout(function () {
-      Engage.trigger(plugin.events.audioCodecNotSupported.getName());
-      $('.' + class_audioDisplay).hide();
-      $('.' + class_audioDisplayError).show();
-    }, audioLoadTimeoutCheckDelay);
-    audioPlayer_id.on('canplay', function () {
-      videosReady = true;
-      Engage.trigger(plugin.events.ready.getName());
-      window.clearTimeout(audioLoadTimeout);
-    });
-    audioPlayer_id.on('play', function () {
-      Engage.trigger(plugin.events.play.getName(), true);
-      pressedPlayOnce = true;
-    });
-    audioPlayer_id.on('pause', function () {
-      Engage.trigger(plugin.events.pause.getName(), true);
-    });
-    audioPlayer_id.on('ended', function () {
-      Engage.trigger(plugin.events.ended.getName(), true);
-    });
-    audioPlayer_id.on('timeupdate', function () {
-      Engage.trigger(plugin.events.timeupdate.getName(), audioPlayer.currentTime, true);
-    });
-    audioPlayer_id.on(event_html5player_volumechange, function () {
-      Engage.trigger(plugin.events.volumechange.getName(), audioPlayer.volume * 100);
-    });
-    Engage.on(plugin.events.play.getName(), function (triggeredByMaster) {
-      if (!triggeredByMaster && videosReady) {
-        startAudioPlayer(audioPlayer);
-      }
-    });
-    Engage.on(plugin.events.autoplay.getName(), function () {
-      interval_autoplay = window.setInterval(function () {
-        if (pressedPlayOnce) {
-          clearAutoplay();
-        } else if (videosReady) {
-          audioPlayer.play();
-          clearAutoplay();
+
+    function calculateAspectRatio(videoSources) {
+        Engage.log('Video: Calculating Aspect ratio');
+        var as1 = 0;
+        for (var flavor in videoResultions) {
+            if ((aspectRatio == null) || (as1 < videoResultions[flavor])) {
+                as1 = videoResultions[flavor][1];
+                aspectRatio = videoResultions[flavor];
+                id_generated_videojs_flash_component = 'videojs_videodisplay_' + flavor + '_flash_api';
+            }
         }
-      }, interval_autoplay_ms);
-    });
-    Engage.on(plugin.events.initialSeek.getName(), function (e) {
-      parsedSeconds = Utils.parseSeconds(e);
-      interval_initialSeek = window.setInterval(function () {
-        if (pressedPlayOnce) {
-          clearInitialSeek();
-        } else if (videosReady) {
-          audioPlayer.play();
-          window.setTimeout(function () {
-            Engage.trigger(plugin.events.seek.getName(), parsedSeconds);
-          }, timeout_initialSeek_ms);
-          clearInitialSeek();
-        }
-      }, interval_initialSeek_ms);
-    });
-    Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
-      if (!triggeredByMaster && pressedPlayOnce) {
-        clearAutoplay();
-        audioPlayer.pause();
-      }
-    });
-    Engage.on(plugin.events.playPause.getName(), function () {
-      if (audioPlayer.paused()) {
-        Engage.trigger(plugin.events.play.getName());
-      } else {
-        Engage.trigger(plugin.events.pause.getName());
-      }
-    });
-    Engage.on(plugin.events.seekLeft.getName(), function () {
-      if (pressedPlayOnce) {
-        var currTime = audioPlayer.currentTime();
-        if ((currTime - seekSeconds) >= 0) {
-          Engage.trigger(plugin.events.seek.getName(), currTime - seekSeconds);
-        } else {
-          Engage.trigger(plugin.events.seek.getName(), 0);
+        for (var v in videoSources) {
+            for (var j = 0; j < videoSources[v].length; ++j) {
+                var aspectRatio_tmp = videoSources[v][j].resolution;
+                var t_tmp = $.type(aspectRatio_tmp);
+                if ((t_tmp === 'string') && (/\d+x\d+/.test(aspectRatio_tmp))) {
+                    aspectRatio_tmp = aspectRatio_tmp.match(/(\d+)x(\d+)/);
+                    if ((aspectRatio == null) || (as1 < parseInt(aspectRatio_tmp[1]))) {
+                        as1 = parseInt(aspectRatio_tmp[1]);
+                        aspectRatio = Utils.parseVideoResolution(videoSources[v][j].resolution);
+                    }
+                }
+            }
         }
-      }
-    });
-    Engage.on(plugin.events.seekRight.getName(), function () {
-      if (pressedPlayOnce) {
-        var currTime = audioPlayer.currentTime();
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
-        if (duration && ((currTime + seekSeconds) < duration)) {
-          Engage.trigger(plugin.events.seek.getName(), currTime + seekSeconds);
-        } else {
-          Engage.trigger(plugin.events.seek.getName(), duration);
+        Engage.log('Video: Calculated aspect ratio: ' + aspectRatio);
+    }
+
+    function renderVideoDisplay(videoDataView) {
+        Engage.log('Video: Rendering video displays');
+        var videoDisplays = videoDataView.model.get('ids');
+        var videoSources = videoDataView.model.get('videoSources');
+
+        var src = (videoSources && videoSources['audio']) ? videoSources['audio'] : [];
+        var tempVars = {
+            ids: videoDataView.model.get('ids'),
+            type: videoDataView.model.get('type'),
+            sources: src,
+            str_error_AudioCodecNotSupported: translate('error_AudioCodecNotSupported', 'Error: The audio codec is not supported by this browser.'),
+            str_error_AudioElementNotSupported: translate('error_AudioElementNotSupported', 'Error: Your browser does not support the audio element.')
+        };
+        if (isEmbedMode && !isAudioOnly) {
+            tempVars.id = videoDataView.model.get('ids')[0];
         }
-      }
-    });
-    Engage.on(plugin.events.playbackRateIncrease.getName(), function () {
-      changePlaybackRate(0.125, videodisplayMaster);
-    });
-    Engage.on(plugin.events.playbackRateDecrease.getName(), function () {
-      changePlaybackRate(-0.125, videodisplayMaster);
-    });
-    Engage.on(plugin.events.volumeSet.getName(), function (volume) {
-      if ((volume >= 0) && (volume <= 1)) {
-        Engage.log('Video: Volume changed to ' + volume);
-        audioPlayer.volume = volume;
-      }
-    });
-    Engage.on(plugin.events.volumeGet.getName(), function (callback) {
-      callback(audioPlayer.volume);
-    });
-    Engage.on(plugin.events.timeupdate.getName(), function (time) {
-      currentTime = time;
-    });
-    Engage.on(plugin.events.seek.getName(), function (time) {
-      Engage.log('Video: Seek to ' + time);
-      if (videosReady) {
-        if (! pressedPlayOnce) {
-            startAudioPlayer(audioPlayer);
-        }
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
-        if (duration && (time < duration)) {
-          audioPlayer.currentTime = time;
+
+        // compile template and load into the html
+        var template = _.template(videoDataView.template);
+        videoDataView.$el.html(template(tempVars));
+
+        if (!mediapackageError) {
+            calculateAspectRatio(videoSources);
+
+            isAudioOnly = videoDataView.model.get('type') == 'audio';
+            Engage.trigger(plugin.events.isAudioOnly.getName(), isAudioOnly);
+
+            if (videoSources && videoDisplays) {
+                if (isEmbedMode) {
+                    renderEmbed(videoDataView, videoSources, videoDisplays, aspectRatio);
+                } else if (isMobileMode) {
+                    renderMobile(videoDataView, videoSources, videoDisplays, aspectRatio);
+                } else { // isDesktopMode
+                    renderDesktop(videoDataView, videoSources, videoDisplays, aspectRatio);
+                }
+                if (videoDataView.model.get('type') != 'audio') {
+                    delayedCalculateVideoAreaAspectRatio();
+                }
+            }
+        }
+        console.log(videodisplayMaster);
+
+        loadAndAppendCaptions(videoDataView);
+    }
+
+    function prepareRenderingVideoDisplay(videoDataView) {
+        if (loadHls) {
+            require([relative_plugin_path + mediaSourcesPath], function () {
+                Engage.log('Video: Lib videojs media sources loaded');
+                require([relative_plugin_path + hlsPath], function () {
+                    Engage.log('Video: Lib videojs HLS playback loaded');
+                    renderVideoDisplay(videoDataView);
+                });
+            });
         } else {
-          Engage.trigger(plugin.events.customError.getName(), translate('givenTime', 'The given time') + ' (' + Utils.formatSeconds(time) + ') ' + translate('hasToBeSmallerThanDuration', 'has to be smaller than the duration') + ' (' + Utils.formatSeconds(duration) + ').');
-          Engage.trigger(plugin.events.timeupdate.getName(), audioPlayer.currentTime);
+            renderVideoDisplay(videoDataView);
+        }
+    }
+
+    var VideoDataView = Backbone.View.extend({
+        el: $('#' + id_engage_video),
+        initialize: function (videoDataModel, template, videojs_swf) {
+            this.setElement($(plugin.container));
+            this.model = videoDataModel;
+            this.template = template;
+            this.videojs_swf = videojs_swf;
+            _.bindAll(this, 'render');
+            this.model.bind('change', this.render);
+            this.render();
+        },
+        render: function () {
+            prepareRenderingVideoDisplay(this);
+        }
+    });
+
+    function initVideojsVideo(id, videoSource, videojs_swf) {
+        Engage.log('Video: Initializing video.js-display ' + id);
+
+        if (id) {
+            if (videoSource) {
+                if (!isAudioOnly) {
+                    var videoOptions = {
+                        controls: false,
+                        autoplay: false,
+                        preload: 'auto',
+                        poster: videoSource.poster ? videoSource.poster : '',
+                        loop: false,
+                        width: '100%',
+                        height: '100%'
+                    };
+                    if (isEmbedMode) {
+                        videoOptions.controls = true;
+                    }
+
+                    // init video.js
+                    videojs(id, videoOptions, function () {
+                        var videodisplay = this;
+                        // set sources
+                        videodisplay.src(videoSource);
+                    });
+                    // URL to the flash swf
+                    if (videojs_swf) {
+                        Engage.log('Video: Loaded flash component');
+                        videojs.options.flash.swf = videojs_swf;
+                    } else {
+                        Engage.log('Video: No flash component loaded');
+                    }
+                    isUsingFlash = $('#' + id_generated_videojs_flash_component).length > 0;
+                    Engage.trigger(plugin.events.usingFlash.getName(), isUsingFlash);
+                }
+            } else {
+                Engage.log('Video: Error: No video source available');
+                $('#' + id_videojs_wrapper).html('No video sources available.');
+            }
+        } else {
+            Engage.log('Video: Error: No ID available');
+            $('#' + id_videojs_wrapper).html('No video available.');
         }
-      } else {
-        Engage.trigger(plugin.events.customNotification.getName(), translate('msg_waitToSetTime', 'Please wait until the video has been loaded to set a time.'));
-        Engage.trigger(plugin.events.timeupdate.getName(), 0);
-      }
-    });
-    Engage.on(plugin.events.sliderStop.getName(), function (time) {
-      Engage.log('Video: Slider stopped at ' + time);
-      if (videosReady) {
-        if (! pressedPlayOnce) {
-            startAudioPlayer(audioPlayer);
-        }
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
-        audioPlayer.currentTime = (time / 1000) * (duration / 1000);
-      } else {
-        Engage.trigger(plugin.events.customNotification.getName(), translate('msg_startPlayingToSeek', 'Please start playing the video once to seek.'));
-        Engage.trigger(plugin.events.timeupdate.getName(), 0);
-      }
-    });
-    Engage.on(plugin.events.ended.getName(), function (time) {
-      if (videosReady) {
-        Engage.log('Video: Ended at ' + time);
-        audioPlayer.pause();
-        Engage.trigger(plugin.events.pause.getName());
-        audioPlayer.currentTime = audioPlayer.duration;
-      }
-    });
-  }
-
-  function startVideoPlayer(video) {
-    $('.' + class_vjsposter).detach();
-    clearAutoplay();
-    video.play();
-    pressedPlayOnce = true;
-  }
-
-  function registerEventsVideo(videoDisplay, numberOfVideodisplays) {
-    $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', function () {
-      fullscreen = !fullscreen;
-      if (fullscreen) {
-        Engage.trigger(plugin.events.fullscreenEnable.getName());
-      } else {
-        Engage.trigger(plugin.events.fullscreenCancel.getName());
-      }
-    });
+    }
 
-    var $videoDisplay = $('#' + videoDisplay);
+    function delayedCalculateVideoAreaAspectRatio() {
+        calculateVideoAreaAspectRatio();
+        window.setTimeout(calculateVideoAreaAspectRatio, checkVideoDisplaySizeTimeout);
+    }
 
-    if (!isMobileMode) {
-      videodisplayMaster
-        .on('play', function () {
-          startVideoPlayer(videodisplayMaster);
-        })
-        .on('pause', function () {
-          Engage.trigger(plugin.events.pause.getName(), true);
-        })
-        .on('ended', function () {
-          Engage.trigger(plugin.events.ended.getName(), true);
-        })
-        .on('timeupdate', function () {
-          Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime(), true);
-        });
-    } else {
-      // To get rid of the undesired "click on poster to play" functionality,
-      // we remove all event listeners attached to the vjs posters by cloning the dom element.
-      $('.' + class_vjsposter).replaceWith(function () {
-        return $(this).clone();
-      });
+    function calculateVideoAreaAspectRatio() {
+        var $engageVideoId = $('#' + id_engage_video);
+        var oldAspectRatio = videoAreaAspectRatio;
 
-      // register events on every video display in mobile mode
-      // because only one display is playing at the same time
-      Engage.model.get('videoDataModel').get('ids').forEach(function (id) {
-        videojs(id).on('play', function () {
-          Engage.trigger(plugin.events.play.getName(), true);
-        });
-        videojs(id).on('ended', function () {
-          Engage.trigger(plugin.events.ended.getName(), true);
-        });
-        videojs(id).on('timeupdate', function () {
-          Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime(), true);
-        });
-      });
+        var videoHeight = $engageVideoId.height();
+        var videoWidth = $engageVideoId.width();
+        if (videoWidth !== undefined && videoHeight !== undefined &&
+            videoWidth === 0 && videoHeight === 0) {
+            return;
+        }
+        if (isEmbedMode) {
+            if (videoWidth !== undefined && videoHeight !== undefined &&
+                videoWidth > 0 && videoHeight > 0) {
+                videoAreaAspectRatio = videoWidth / videoHeight;
+            }
+        } else if (!isDefaultLayout()) {
+            videoHeight = $('.' + videoFocusedClass).height();
+            if (isPiP) {
+                videoWidth = $('.' + videoFocusedClass).width();
+            }
+        }
+        if (videoWidth !== undefined && videoHeight !== undefined &&
+            videoWidth > 0 && videoHeight > 0) {
+            videoAreaAspectRatio = videoWidth / videoHeight;
+        }
+
+        if (videoAreaAspectRatio !== oldAspectRatio) {
+            checkVideoDisplaySize();
+        }
     }
 
-    $('#' + id_btn_fullscreenCancel).click(function (e) {
-      e.preventDefault();
-      Engage.trigger(plugin.events.fullscreenCancel.getName());
-    });
+    function checkVideoDisplaySize() {
+        var $engageVideoId = $('#' + id_engage_video);
+        var $videoUnfocused = $('.' + videoUnfocusedClass);
+
+        var videoHeight = $engageVideoId.height();
+
+        if (!isMobileMode) {
+            var controlsHeight = ($('#' + id_resize_container).height() - videoHeight) + 5;
+            if (controlsHeight <= 0) {
+                controlsHeight = $('#' + id_engageControls).height() + 30;
+            }
+            var maxVideoAreaHeight = $(window).height() - controlsHeight;
+        } else {
+            var maxVideoAreaHeight = $(window).height();
+        }
+
+        if (isEmbedMode) {
+            maxVideoAreaHeight = $(window).height();
+        }
+
+        if (videoAreaAspectRatio === undefined && !isMobileMode) {
+            calculateVideoAreaAspectRatio();
+        }
 
-    Engage.on(plugin.events.fullscreenEnable.getName(), function () {
-      if (numberOfVideodisplays === 1) {
-        videodisplayMaster.requestFullscreen();
-        $('#' + videoDisplay).css('padding-top', '0px');
-      } else if (!fullscreen) {
         if (!isMobileMode) {
-          var viewer = document.getElementById(id_engage_video_fullsceen_wrapper);
+            var maxVideoAreaWidth = parseInt(maxVideoAreaHeight * videoAreaAspectRatio);
+            var minVideoAreaHeight = parseInt(parseInt($engageVideoId.css('min-width')) / videoAreaAspectRatio);
         } else {
-          var viewer = document.getElementById(id_video_wrapper);
-        }
-        if (viewer.mozRequestFullScreen) {
-          viewer.mozRequestFullScreen();
-        } else if (viewer.webkitRequestFullscreen) {
-          viewer.webkitRequestFullscreen();
-        } else if (viewer.requestFullscreen) {
-          viewer.requestFullscreen();
-        } else if (viewer.msRequestFullscreen) {
-          viewer.msRequestFullscreen();
+            var maxVideoAreaWidth = parseInt(maxVideoAreaHeight * (aspectRatio[1] / aspectRatio[2]));
+            var minVideoAreaHeight = parseInt(parseInt($engageVideoId.css('min-width')) / (aspectRatio[1] / aspectRatio[2]));
+        }
+
+        var minWidth = parseInt($engageVideoId.css('min-width'));
+        if (maxVideoAreaWidth > minWidth) {
+            if (maxVideoAreaWidth > $(window).width()) {
+                $engageVideoId.css('max-width', $(window).width() + 'px');
+            } else {
+                $engageVideoId.css('max-width', maxVideoAreaWidth + 'px');
+            }
         } else {
-          $(window).scrollTop(0);
-          $('body').css('overflow', 'hidden');
-          $(window).scroll(function () {
-            $(this).scrollTop(0);
-          });
-          $('#' + id_engage_video).css('z-index', 995).css('position', 'relative');
-          $('#' + id_page_cover).css('opacity', 0.9).fadeIn(300);
-          fullscreen = true;
-        }
-      }
-      if (!isMobileMode) {
-        $('#' + videoDisplay).removeClass('vjs-controls-disabled').addClass('vjs-controls-enabled');
-        $('.' + id_videoDisplayClass).css('max-width', $(window).height() * videoAreaAspectRatio);
-      }
-    });
-    Engage.on(plugin.events.fullscreenCancel.getName(), function () {
-      if (numberOfVideodisplays === 1) {
-        $('#' + videoDisplay).css('padding-top', singleVideoPaddingTop);
-      }
-      if (fullscreen && (numberOfVideodisplays > 1)) {
-        if (document.mozCancelFullScreen) {
-          document.mozCancelFullScreen();
-        } else if (document.webkitExitFullscreen) {
-          document.webkitExitFullscreen();
-        } else if (document.exitFullscreen) {
-          document.exitFullscreen();
-        } else if (document.msExitFullscreen) {
-          document.msExitFullscreen();
+            $engageVideoId.css('max-width', minWidth + 'px');
+        }
+        $engageVideoId.css('min-height', minVideoAreaHeight + 'px');
+        if (maxVideoAreaHeight > minVideoAreaHeight) {
+            $engageVideoId.css('max-height', maxVideoAreaHeight + 'px');
         } else {
-          $('body').css('overflow', 'auto');
-          $(window).unbind('scroll');
-          $('#' + id_page_cover).css('opacity', 0.9).fadeOut(300, function () {
-            $('#' + id_engage_video).css('z-index', 0).css('position', '');
-          });
-          fullscreen = false;
-        }
-      }
-      if(!isMobileMode) {
-        $('#' + videoDisplay).removeClass('vjs-controls-enabled').addClass('vjs-controls-disabled');
-      }
-      $('.' + id_videoDisplayClass).css('max-width', '');
-      checkVideoDisplaySize();
-    });
+            $engageVideoId.css('max-height', minVideoAreaHeight + 'px');
+        }
+
+        if (!isDefaultLayout()) {
+            if (isPiP) {
+                var distance = 0;
+                $videoUnfocused.each(function () {
+                    var width = $(this).width();
+                    var height = $(this).height();
+                    $(this).css('left', 0 - (width / 2) + 'px');
+                    $(this).css('top', distance - (height / 2) + 'px');
+                    distance = distance + height + 10;
+                });
+                var marginLeft;
+                if (pipPos === 'left') {
+                    marginLeft = 12;
+                } else {
+                    marginLeft = 88;
+                }
+                $videoUnfocused.css('margin-left', marginLeft + '%');
+            } else {
+                $engageVideoId.height($('.' + videoFocusedClass).height());
+            }
+        }
+    }
 
-    Engage.on(plugin.events.playbackRateChanged.getName(), function (rate) {
-      if (pressedPlayOnce) {
-        Engage.log('Video: Playback rate changed to rate ' + rate);
-        videodisplayMaster.playbackRate(rate);
-      }
-    });
+    function clearAutoplay() {
+        window.clearInterval(interval_autoplay);
+    }
 
-    Engage.on(plugin.events.play.getName(), function (triggeredByMaster) {
-      if (!triggeredByMaster && videosReady) {
-          startVideoPlayer(videodisplayMaster);
-      }
-    });
+    function clearInitialSeek() {
+        window.clearInterval(interval_initialSeek);
+    }
 
-    Engage.on(plugin.events.autoplay.getName(), function () {
-      interval_autoplay = window.setInterval(function () {
+    function changePlaybackRate(value, videodisplayMaster) {
         if (pressedPlayOnce) {
-          clearAutoplay();
-        } else if (videosReady) {
-          videodisplayMaster.play();
-          clearAutoplay();
+            var rate = videodisplayMaster.playbackRate();
+            Engage.trigger(plugin.events.playbackRateChanged.getName(), (rate + value));
         }
-      }, interval_autoplay_ms);
-    });
+    }
 
-    Engage.on(plugin.events.initialSeek.getName(), function (e) {
-      parsedSeconds = Utils.parseSeconds(e);
-      interval_initialSeek = window.setInterval(function () {
-        if (pressedPlayOnce) {
-          clearInitialSeek();
-        } else if (videosReady) {
-          videodisplayMaster.play();
-          window.setTimeout(function () {
-            Engage.trigger(plugin.events.seek.getName(), parsedSeconds);
-          }, timeout_initialSeek_ms);
-          clearInitialSeek();
-        }
-      }, interval_initialSeek_ms);
-    });
+    function startAudioPlayer(audio) {
+        clearAutoplay();
+        audio.play();
+        pressedPlayOnce = true;
+    }
 
-    Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
-      if (!triggeredByMaster && pressedPlayOnce) {
+    function registerEventsAudioOnly(videoDisplay) {
+        var audioPlayer_id = $('#' + videoDisplay);
+        var audioPlayer = audioPlayer_id[0];
+        var audioLoadTimeout = window.setTimeout(function () {
+            Engage.trigger(plugin.events.audioCodecNotSupported.getName());
+            $('.' + class_audioDisplay).hide();
+            $('.' + class_audioDisplayError).show();
+        }, audioLoadTimeoutCheckDelay);
+        audioPlayer_id.on('canplay', function () {
+            videosReady = true;
+            Engage.trigger(plugin.events.ready.getName());
+            window.clearTimeout(audioLoadTimeout);
+        });
+        audioPlayer_id.on('play', function () {
+            Engage.trigger(plugin.events.play.getName(), true);
+            pressedPlayOnce = true;
+        });
+        audioPlayer_id.on('pause', function () {
+            Engage.trigger(plugin.events.pause.getName(), true);
+        });
+        audioPlayer_id.on('ended', function () {
+            Engage.trigger(plugin.events.ended.getName(), true);
+        });
+        audioPlayer_id.on('timeupdate', function () {
+            Engage.trigger(plugin.events.timeupdate.getName(), audioPlayer.currentTime, true);
+        });
+        audioPlayer_id.on(event_html5player_volumechange, function () {
+            Engage.trigger(plugin.events.volumechange.getName(), audioPlayer.volume * 100);
+        });
+        Engage.on(plugin.events.play.getName(), function (triggeredByMaster) {
+            if (!triggeredByMaster && videosReady) {
+                startAudioPlayer(audioPlayer);
+            }
+        });
+        Engage.on(plugin.events.autoplay.getName(), function () {
+            interval_autoplay = window.setInterval(function () {
+                if (pressedPlayOnce) {
+                    clearAutoplay();
+                } else if (videosReady) {
+                    audioPlayer.play();
+                    clearAutoplay();
+                }
+            }, interval_autoplay_ms);
+        });
+        Engage.on(plugin.events.initialSeek.getName(), function (e) {
+            parsedSeconds = Utils.parseSeconds(e);
+            interval_initialSeek = window.setInterval(function () {
+                if (pressedPlayOnce) {
+                    clearInitialSeek();
+                } else if (videosReady) {
+                    audioPlayer.play();
+                    window.setTimeout(function () {
+                        Engage.trigger(plugin.events.seek.getName(), parsedSeconds);
+                    }, timeout_initialSeek_ms);
+                    clearInitialSeek();
+                }
+            }, interval_initialSeek_ms);
+        });
+        Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
+            if (!triggeredByMaster && pressedPlayOnce) {
+                clearAutoplay();
+                audioPlayer.pause();
+            }
+        });
+        Engage.on(plugin.events.playPause.getName(), function () {
+            if (audioPlayer.paused()) {
+                Engage.trigger(plugin.events.play.getName());
+            } else {
+                Engage.trigger(plugin.events.pause.getName());
+            }
+        });
+        Engage.on(plugin.events.seekLeft.getName(), function () {
+            if (pressedPlayOnce) {
+                var currTime = audioPlayer.currentTime();
+                if ((currTime - seekSeconds) >= 0) {
+                    Engage.trigger(plugin.events.seek.getName(), currTime - seekSeconds);
+                } else {
+                    Engage.trigger(plugin.events.seek.getName(), 0);
+                }
+            }
+        });
+        Engage.on(plugin.events.seekRight.getName(), function () {
+            if (pressedPlayOnce) {
+                var currTime = audioPlayer.currentTime();
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
+                if (duration && ((currTime + seekSeconds) < duration)) {
+                    Engage.trigger(plugin.events.seek.getName(), currTime + seekSeconds);
+                } else {
+                    Engage.trigger(plugin.events.seek.getName(), duration);
+                }
+            }
+        });
+        Engage.on(plugin.events.playbackRateIncrease.getName(), function () {
+            changePlaybackRate(0.125, videodisplayMaster);
+        });
+        Engage.on(plugin.events.playbackRateDecrease.getName(), function () {
+            changePlaybackRate(-0.125, videodisplayMaster);
+        });
+        Engage.on(plugin.events.volumeSet.getName(), function (volume) {
+            if ((volume >= 0) && (volume <= 1)) {
+                Engage.log('Video: Volume changed to ' + volume);
+                audioPlayer.volume = volume;
+            }
+        });
+        Engage.on(plugin.events.volumeGet.getName(), function (callback) {
+            callback(audioPlayer.volume);
+        });
+        Engage.on(plugin.events.timeupdate.getName(), function (time) {
+            currentTime = time;
+        });
+        Engage.on(plugin.events.seek.getName(), function (time) {
+            Engage.log('Video: Seek to ' + time);
+            if (videosReady) {
+                if (!pressedPlayOnce) {
+                    startAudioPlayer(audioPlayer);
+                }
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
+                if (duration && (time < duration)) {
+                    audioPlayer.currentTime = time;
+                } else {
+                    Engage.trigger(plugin.events.customError.getName(), translate('givenTime', 'The given time') + ' (' + Utils.formatSeconds(time) + ') ' + translate('hasToBeSmallerThanDuration', 'has to be smaller than the duration') + ' (' + Utils.formatSeconds(duration) + ').');
+                    Engage.trigger(plugin.events.timeupdate.getName(), audioPlayer.currentTime);
+                }
+            } else {
+                Engage.trigger(plugin.events.customNotification.getName(), translate('msg_waitToSetTime', 'Please wait until the video has been loaded to set a time.'));
+                Engage.trigger(plugin.events.timeupdate.getName(), 0);
+            }
+        });
+        Engage.on(plugin.events.sliderStop.getName(), function (time) {
+            Engage.log('Video: Slider stopped at ' + time);
+            if (videosReady) {
+                if (!pressedPlayOnce) {
+                    startAudioPlayer(audioPlayer);
+                }
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
+                audioPlayer.currentTime = (time / 1000) * (duration / 1000);
+            } else {
+                Engage.trigger(plugin.events.customNotification.getName(), translate('msg_startPlayingToSeek', 'Please start playing the video once to seek.'));
+                Engage.trigger(plugin.events.timeupdate.getName(), 0);
+            }
+        });
+        Engage.on(plugin.events.ended.getName(), function (time) {
+            if (videosReady) {
+                Engage.log('Video: Ended at ' + time);
+                audioPlayer.pause();
+                Engage.trigger(plugin.events.pause.getName());
+                audioPlayer.currentTime = audioPlayer.duration;
+            }
+        });
+    }
+
+    function startVideoPlayer(video) {
+        $('.' + class_vjsposter).detach();
         clearAutoplay();
-        videodisplayMaster.pause();
-      }
-    });
+        video.play();
+        pressedPlayOnce = true;
+    }
 
-    Engage.on(plugin.events.playPause.getName(), function () {
-      if (videodisplayMaster.paused()) {
-        Engage.trigger(plugin.events.play.getName());
-      } else {
-        Engage.trigger(plugin.events.pause.getName());
-        if (isMobileMode && fullscreen) {
-          Engage.trigger(plugin.events.fullscreenCancel.getName());
-        }
-      }
-    });
-    Engage.on(plugin.events.seekLeft.getName(), function () {
-      if (pressedPlayOnce) {
-        var currTime = videodisplayMaster.currentTime();
-        if ((currTime - seekSeconds) >= 0) {
-          Engage.trigger(plugin.events.seek.getName(), currTime - seekSeconds);
-        } else {
-          Engage.trigger(plugin.events.seek.getName(), 0);
-        }
-      }
-    });
+    function registerEventsVideo(videoDisplay, numberOfVideodisplays) {
+        $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', function () {
+            fullscreen = !fullscreen;
+            if (fullscreen) {
+                Engage.trigger(plugin.events.fullscreenEnable.getName());
+            } else {
+                Engage.trigger(plugin.events.fullscreenCancel.getName());
+            }
+        });
 
-    Engage.on(plugin.events.seekRight.getName(), function () {
-      if (pressedPlayOnce) {
-        var currTime = videodisplayMaster.currentTime();
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
-        if (duration && ((currTime + seekSeconds) < duration)) {
-          Engage.trigger(plugin.events.seek.getName(), currTime + seekSeconds);
+        var $videoDisplay = $('#' + videoDisplay);
+
+        if (!isMobileMode) {
+            videodisplayMaster
+                .on('play', function () {
+                    startVideoPlayer(videodisplayMaster);
+                })
+                .on('pause', function () {
+                    Engage.trigger(plugin.events.pause.getName(), true);
+                })
+                .on('ended', function () {
+                    Engage.trigger(plugin.events.ended.getName(), true);
+                })
+                .on('timeupdate', function () {
+                    Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime(), true);
+                });
         } else {
-          Engage.trigger(plugin.events.seek.getName(), duration);
+            // To get rid of the undesired "click on poster to play" functionality,
+            // we remove all event listeners attached to the vjs posters by cloning the dom element.
+            $('.' + class_vjsposter).replaceWith(function () {
+                return $(this).clone();
+            });
+
+            // register events on every video display in mobile mode
+            // because only one display is playing at the same time
+            Engage.model.get('videoDataModel').get('ids').forEach(function (id) {
+                videojs(id).on('play', function () {
+                    Engage.trigger(plugin.events.play.getName(), true);
+                });
+                videojs(id).on('ended', function () {
+                    Engage.trigger(plugin.events.ended.getName(), true);
+                });
+                videojs(id).on('timeupdate', function () {
+                    Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime(), true);
+                });
+            });
         }
-      }
-    });
 
-    Engage.on(plugin.events.playbackRateIncrease.getName(), function () {
-      changePlaybackRate(0.125, videodisplayMaster);
-    });
+        $('#' + id_btn_fullscreenCancel).click(function (e) {
+            e.preventDefault();
+            Engage.trigger(plugin.events.fullscreenCancel.getName());
+        });
 
-    Engage.on(plugin.events.playbackRateDecrease.getName(), function () {
-      changePlaybackRate(-0.125, videodisplayMaster);
-    });
+        Engage.on(plugin.events.fullscreenEnable.getName(), function () {
+            if (numberOfVideodisplays === 1) {
+                videodisplayMaster.requestFullscreen();
+                $('#' + videoDisplay).css('padding-top', '0px');
+            } else if (!fullscreen) {
+                if (!isMobileMode) {
+                    var viewer = document.getElementById(id_engage_video_fullsceen_wrapper);
+                } else {
+                    var viewer = document.getElementById(id_video_wrapper);
+                }
+                if (viewer.mozRequestFullScreen) {
+                    viewer.mozRequestFullScreen();
+                } else if (viewer.webkitRequestFullscreen) {
+                    viewer.webkitRequestFullscreen();
+                } else if (viewer.requestFullscreen) {
+                    viewer.requestFullscreen();
+                } else if (viewer.msRequestFullscreen) {
+                    viewer.msRequestFullscreen();
+                } else {
+                    $(window).scrollTop(0);
+                    $('body').css('overflow', 'hidden');
+                    $(window).scroll(function () {
+                        $(this).scrollTop(0);
+                    });
+                    $('#' + id_engage_video).css('z-index', 995).css('position', 'relative');
+                    $('#' + id_page_cover).css('opacity', 0.9).fadeIn(300);
+                    fullscreen = true;
+                }
+            }
+            if (!isMobileMode) {
+                $('#' + videoDisplay).removeClass('vjs-controls-disabled').addClass('vjs-controls-enabled');
+                $('.' + id_videoDisplayClass).css('max-width', $(window).height() * videoAreaAspectRatio);
+            }
+        });
+        Engage.on(plugin.events.fullscreenCancel.getName(), function () {
+            if (numberOfVideodisplays === 1) {
+                $('#' + videoDisplay).css('padding-top', singleVideoPaddingTop);
+            }
+            if (fullscreen && (numberOfVideodisplays > 1)) {
+                if (document.mozCancelFullScreen) {
+                    document.mozCancelFullScreen();
+                } else if (document.webkitExitFullscreen) {
+                    document.webkitExitFullscreen();
+                } else if (document.exitFullscreen) {
+                    document.exitFullscreen();
+                } else if (document.msExitFullscreen) {
+                    document.msExitFullscreen();
+                } else {
+                    $('body').css('overflow', 'auto');
+                    $(window).unbind('scroll');
+                    $('#' + id_page_cover).css('opacity', 0.9).fadeOut(300, function () {
+                        $('#' + id_engage_video).css('z-index', 0).css('position', '');
+                    });
+                    fullscreen = false;
+                }
+            }
+            if (!isMobileMode) {
+                $('#' + videoDisplay).removeClass('vjs-controls-enabled').addClass('vjs-controls-disabled');
+            }
+            $('.' + id_videoDisplayClass).css('max-width', '');
+            checkVideoDisplaySize();
+        });
 
-    Engage.on(plugin.events.volumeSet.getName(), function (volume) {
-      if ((volume >= 0) && (volume <= 1)) {
-        Engage.log('Video: Volume changed to ' + volume);
-        videodisplayMaster.volume(volume);
-      }
-    });
+        Engage.on(plugin.events.playbackRateChanged.getName(), function (rate) {
+            if (pressedPlayOnce) {
+                Engage.log('Video: Playback rate changed to rate ' + rate);
+                videodisplayMaster.playbackRate(rate);
+            }
+        });
 
-    Engage.on(plugin.events.volumeGet.getName(), function (callback) {
-      if (callback) {
-        callback(videodisplayMaster.volume());
-      }
-    });
+        Engage.on(plugin.events.play.getName(), function (triggeredByMaster) {
+            if (!triggeredByMaster && videosReady) {
+                startVideoPlayer(videodisplayMaster);
+            }
+        });
 
-    Engage.on(plugin.events.timeupdate.getName(), function (time) {
-      currentTime = time;
-    });
+        Engage.on(plugin.events.autoplay.getName(), function () {
+            interval_autoplay = window.setInterval(function () {
+                if (pressedPlayOnce) {
+                    clearAutoplay();
+                } else if (videosReady) {
+                    videodisplayMaster.play();
+                    clearAutoplay();
+                }
+            }, interval_autoplay_ms);
+        });
 
-    Engage.on(plugin.events.seek.getName(), function (time) {
-      Engage.log('Video: Seek to ' + time);
-      if (videosReady) {
-        if (!pressedPlayOnce) {
-          startVideoPlayer(videodisplayMaster);
-        }
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
-        if (duration && (time < duration)) {
-          videodisplayMaster.currentTime(time);
-        } else {
-          Engage.trigger(plugin.events.customError.getName(), translate('givenTime', 'The given time') + ' (' + Utils.formatSeconds(time) + ') ' + translate('hasToBeSmallerThanDuration', 'has to be smaller than the duration') + ' (' + Utils.formatSeconds(duration) + ').');
-          Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime());
-        }
-      } else {
-        Engage.trigger(plugin.events.customNotification.getName(), translate('msg_waitToSetTime', 'Please wait until the video has been loaded to set a time.'));
-        Engage.trigger(plugin.events.timeupdate.getName(), 0);
-      }
-    });
+        Engage.on(plugin.events.initialSeek.getName(), function (e) {
+            parsedSeconds = Utils.parseSeconds(e);
+            interval_initialSeek = window.setInterval(function () {
+                if (pressedPlayOnce) {
+                    clearInitialSeek();
+                } else if (videosReady) {
+                    videodisplayMaster.play();
+                    window.setTimeout(function () {
+                        Engage.trigger(plugin.events.seek.getName(), parsedSeconds);
+                    }, timeout_initialSeek_ms);
+                    clearInitialSeek();
+                }
+            }, interval_initialSeek_ms);
+        });
 
-    Engage.on(plugin.events.sliderStop.getName(), function (time) {
-      if (videosReady) {
-        if (!pressedPlayOnce) {
-          Engage.trigger(plugin.events.play.getName(), false);
-        }
-        var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
-        var normTime = (time / 1000) * (duration / 1000);
-        videodisplayMaster.currentTime(normTime);
-      } else {
-        Engage.trigger(plugin.events.customNotification.getName(), translate('msg_startPlayingToSeek', 'Please start playing the video once to seek.'));
-        Engage.trigger(plugin.events.timeupdate.getName(), 0);
-      }
-    });
+        Engage.on(plugin.events.pause.getName(), function (triggeredByMaster) {
+            if (!triggeredByMaster && pressedPlayOnce) {
+                clearAutoplay();
+                videodisplayMaster.pause();
+            }
+        });
 
-    Engage.on(plugin.events.ended.getName(), function () {
-      if (videosReady) {
-        Engage.log('Video: Video ended and ready');
-        videodisplayMaster.pause();
-        Engage.trigger(plugin.events.pause.getName());
-        videodisplayMaster.currentTime(0);
-        if (isMobileMode) {
-          Engage.trigger(plugin.events.fullscreenCancel.getName());
-        }
-      }
-    });
+        Engage.on(plugin.events.playPause.getName(), function () {
+            if (videodisplayMaster.paused()) {
+                Engage.trigger(plugin.events.play.getName());
+            } else {
+                Engage.trigger(plugin.events.pause.getName());
+                if (isMobileMode && fullscreen) {
+                    Engage.trigger(plugin.events.fullscreenCancel.getName());
+                }
+            }
+        });
+        Engage.on(plugin.events.seekLeft.getName(), function () {
+            if (pressedPlayOnce) {
+                var currTime = videodisplayMaster.currentTime();
+                if ((currTime - seekSeconds) >= 0) {
+                    Engage.trigger(plugin.events.seek.getName(), currTime - seekSeconds);
+                } else {
+                    Engage.trigger(plugin.events.seek.getName(), 0);
+                }
+            }
+        });
+
+        Engage.on(plugin.events.seekRight.getName(), function () {
+            if (pressedPlayOnce) {
+                var currTime = videodisplayMaster.currentTime();
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
+                if (duration && ((currTime + seekSeconds) < duration)) {
+                    Engage.trigger(plugin.events.seek.getName(), currTime + seekSeconds);
+                } else {
+                    Engage.trigger(plugin.events.seek.getName(), duration);
+                }
+            }
+        });
+
+        Engage.on(plugin.events.playbackRateIncrease.getName(), function () {
+            changePlaybackRate(0.125, videodisplayMaster);
+        });
 
-    videodisplayMaster
-      .on(event_html5player_volumechange, function () {
-        Engage.trigger(plugin.events.volumechange.getName(), videodisplayMaster.volume());
-      })
-      .on(event_html5player_fullscreenchange, function () {
-        Engage.trigger(plugin.events.fullscreenChange.getName());
-      });
+        Engage.on(plugin.events.playbackRateDecrease.getName(), function () {
+            changePlaybackRate(-0.125, videodisplayMaster);
+        });
 
-    var $videoDisplayClass = $('.' + id_videoDisplayClass);
+        Engage.on(plugin.events.volumeSet.getName(), function (volume) {
+            if ((volume >= 0) && (volume <= 1)) {
+                Engage.log('Video: Volume changed to ' + volume);
+                videodisplayMaster.volume(volume);
+            }
+        });
 
-    if (!isMobileMode) {
-      Engage.on(plugin.events.focusVideo.getName(), function (display) {
-        Engage.log('Video: received focusing video ' + display);
-        var videoDiv;
+        Engage.on(plugin.events.volumeGet.getName(), function (callback) {
+            if (callback) {
+                callback(videodisplayMaster.volume());
+            }
+        });
 
-        if (display === undefined || display === 'focus.none') {
-          Engage.trigger(plugin.events.resetLayout.getName());
-          return;
-        }
+        Engage.on(plugin.events.timeupdate.getName(), function (time) {
+            currentTime = time;
+        });
 
-        if (display === 'focus.next' || display === 'focus.prev') {
-          if (isDefaultLayout()) {
-            if (display === 'focus.next') {
-              Engage.trigger(plugin.events.focusVideo.getName(),
-                Utils.getFlavorForVideoDisplay($('.' + videoDisplayClass).first()));
-              return;
-            } else {
-              Engage.trigger(plugin.events.focusVideo.getName(),
-                Utils.getFlavorForVideoDisplay($('.' + videoDisplayClass).last()));
-              return;
-            }
-          } else {
-            var vidDisp = $videoDisplayClass;
-            var selectNext = false;
-            var last;
-            var i = 0;
-            for (var elem in vidDisp) {
-              if (selectNext) {
-                Engage.trigger(plugin.events.focusVideo.getName(),
-                  Utils.getFlavorForVideoDisplay($(vidDisp[elem])));
-                return;
-              } else if ($(vidDisp[elem]).hasClass(videoFocusedClass)) {
-                if ((display === 'focus.prev' && last === undefined) ||
-                  (display === 'focus.next' && i === vidDisp.length - 1)) {
-                  Engage.log('Video: Resetting videodisplay layout');
-                  Engage.trigger(plugin.events.resetLayout.getName());
-                  return;
-                } else if (display === 'focus.next') {
-                  selectNext = true;
+        Engage.on(plugin.events.seek.getName(), function (time) {
+            Engage.log('Video: Seek to ' + time);
+            if (videosReady) {
+                if (!pressedPlayOnce) {
+                    startVideoPlayer(videodisplayMaster);
+                }
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration')) / 1000;
+                if (duration && (time < duration)) {
+                    videodisplayMaster.currentTime(time);
                 } else {
-                  Engage.trigger(plugin.events.focusVideo.getName(),
-                    Utils.getFlavorForVideoDisplay(last));
-                  return;
+                    Engage.trigger(plugin.events.customError.getName(), translate('givenTime', 'The given time') + ' (' + Utils.formatSeconds(time) + ') ' + translate('hasToBeSmallerThanDuration', 'has to be smaller than the duration') + ' (' + Utils.formatSeconds(duration) + ').');
+                    Engage.trigger(plugin.events.timeupdate.getName(), videodisplayMaster.currentTime());
                 }
-              }
-              last = $(vidDisp[elem]);
-              i++;
+            } else {
+                Engage.trigger(plugin.events.customNotification.getName(), translate('msg_waitToSetTime', 'Please wait until the video has been loaded to set a time.'));
+                Engage.trigger(plugin.events.timeupdate.getName(), 0);
             }
-          }
-        } else {
-          videoDiv = getDivForFlavor(display);
-          if (videoDiv === undefined) {
-            Engage.trigger(plugin.events.resetLayout.getName());
-            return;
-          }
-          if ($(videoDiv).hasClass(videoFocusedClass)) {
-            Engage.log('Video: Resetting videodisplay layout');
-            Engage.trigger(plugin.events.resetLayout.getName());
-            return;
-          }
-        }
-        $videoDisplayClass.css({
-          'width': '',
-          'left': '',
-          'top': '',
-          'margin-left': ''
-        });
-        $('#engage_video').css('height', '');
-        $videoDisplayClass.removeClass(videoDefaultLayoutClass).addClass(videoUnfocusedClass);
-        $('.' + videoUnfocusedClass).removeClass(videoFocusedClass);
-        $(videoDiv).addClass(videoFocusedClass).removeClass(videoUnfocusedClass);
-
-
-        if (isPiP) {
-          var distance = 0;
-          $('.' + videoUnfocusedClass).each(function () {
-            var width = $(this).width();
-            var height = $(this).height();
-            $(this).css({
-              'left': 0 - (width / 2) + 'px',
-              'top': distance - (height / 2) + 'px'
-            });
-            distance = distance + height + 10;
-          });
-          var marginLeft;
-          if (pipPos === 'left') {
-            marginLeft = 12;
-          } else {
-            marginLeft = 88;
-          }
-          $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
-        } else {
-          var height = $('.' + videoFocusedClass).height();
-          $('#engage_video').height(height + 10);
-        }
-
-        delayedCalculateVideoAreaAspectRatio();
-      });
-
-      Engage.on(plugin.events.resetLayout.getName(), function () {
-        Engage.log('Video: received resetting layout');
-        $('#engage_video').css('height', '');
-        $videoDisplayClass.css({
-          'width': '',
-          'left': '',
-          'top': '',
-          'margin-left': ''
-        });
-        $videoDisplayClass.removeClass(videoFocusedClass).removeClass(videoUnfocusedClass).addClass(videoDefaultLayoutClass);
-        var numberDisplays = $videoDisplayClass.length;
-        $videoDisplayClass.css('width', (((1 / numberDisplays) * 100) - 0.5) + '%');
-        delayedCalculateVideoAreaAspectRatio();
-      });
-
-      Engage.on(plugin.events.movePiP.getName(), function (pos) {
-        var numberDisplays = $('.' + videoDisplayClass).length;
-        if (numberDisplays <= 1) return;
-        if (pos !== undefined) {
-          pipPos = pos;
-        }
-        if (!isPiP) {
-          return;
-        }
-        Engage.log('Video: moving PiP');
-        var marginLeft;
-        if (pipPos === 'right') {
-          marginLeft = 88;
-          pipPos = 'right';
-        } else {
-          marginLeft = 12;
-          pipPos = 'left';
-        }
-        $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
-
-        delayedCalculateVideoAreaAspectRatio();
-      });
-
-      Engage.on(plugin.events.togglePiP.getName(), function (pip) {
-        var numberDisplays = $videoDisplayClass.length;
-        if (numberDisplays <= 1) return;
-
-        Engage.log('Video: setting PiP to ' + pip);
-        if ((pip && isPiP) || (!pip && !isPiP)) {
-          return;
-        }
-        if (!pip) {
-          videoUnfocusedClass = unfocusedClass;
-          videoFocusedClass = focusedClass;
-          isPiP = false;
-          if (!isDefaultLayout()) {
-            $videoDisplayClass.css({
-              'width': '',
-              'left': '',
-              'top': '',
-              'margin-left': ''
-            });
-            $('.' + unfocusedPiPClass).addClass(videoUnfocusedClass).removeClass(unfocusedPiPClass);
-            $('.' + focusedPiPClass).addClass(videoFocusedClass).removeClass(focusedPiPClass);
-            var height = $('.' + videoFocusedClass).height();
-            $('#engage_video').height(height + 10);
-          }
-        } else {
-          videoUnfocusedClass = unfocusedPiPClass;
-          videoFocusedClass = focusedPiPClass;
-          isPiP = true;
-          if (!isDefaultLayout()) {
-            $('.' + unfocusedClass).addClass(videoUnfocusedClass).removeClass(unfocusedClass);
-            $('.' + focusedClass).addClass(videoFocusedClass).removeClass(focusedClass);
-            $('#engage_video').css('height', '');
-            var distance = 0;
-            $('.' + videoUnfocusedClass).each(function () {
-              var width = $(this).width();
-              var height = $(this).height();
-              $(this).css({
-                'left': 0 - (width / 2) + 'px',
-                'top': distance - (height / 2) + 'px'
-              });
-              distance = distance + height + 10;
-            });
-            var marginLeft;
-            if (pipPos === 'left') {
-              marginLeft = 12;
+        });
+
+        Engage.on(plugin.events.sliderStop.getName(), function (time) {
+            if (videosReady) {
+                if (!pressedPlayOnce) {
+                    Engage.trigger(plugin.events.play.getName(), false);
+                }
+                var duration = parseInt(Engage.model.get('videoDataModel').get('duration'));
+                var normTime = (time / 1000) * (duration / 1000);
+                videodisplayMaster.currentTime(normTime);
             } else {
-              marginLeft = 88;
+                Engage.trigger(plugin.events.customNotification.getName(), translate('msg_startPlayingToSeek', 'Please start playing the video once to seek.'));
+                Engage.trigger(plugin.events.timeupdate.getName(), 0);
             }
-            $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
-          }
-        }
-        delayedCalculateVideoAreaAspectRatio();
+        });
 
-      });
-    }
+        Engage.on(plugin.events.ended.getName(), function () {
+            if (videosReady) {
+                Engage.log('Video: Video ended and ready');
+                videodisplayMaster.pause();
+                Engage.trigger(plugin.events.pause.getName());
+                videodisplayMaster.currentTime(0);
+                if (isMobileMode) {
+                    Engage.trigger(plugin.events.fullscreenCancel.getName());
+                }
+            }
+        });
 
-    /* event used to switch between videos in single video display (e.g. mobile) mode */
-    Engage.on(plugin.events.switchVideo.getName(), function (id) {
-      /* check if current video is paused */
-      var isPaused = videodisplayMaster.paused();
+        videodisplayMaster
+            .on(event_html5player_volumechange, function () {
+                Engage.trigger(plugin.events.volumechange.getName(), videodisplayMaster.volume());
+            })
+            .on(event_html5player_fullscreenchange, function () {
+                Engage.trigger(plugin.events.fullscreenChange.getName());
+            });
 
-      $('#' + id_videoDisplayClass + (currentlySelectedVideodisplay+1)).removeClass('active');
+        var $videoDisplayClass = $('.' + id_videoDisplayClass);
 
-      /* assign currentlySelectedVideodisplay in the available bounds */
-      var n = globalVideoSource.length;
-      currentlySelectedVideodisplay = Math.max(0, Math.min(id, n-1));
+        if (!isMobileMode) {
+            Engage.on(plugin.events.focusVideo.getName(), function (display) {
+                Engage.log('Video: received focusing video ' + display);
+                var videoDiv;
 
-      var oldVideodisplayMaster = videodisplayMaster;
-      videodisplayMaster = videojs(Engage.model.get('videoDataModel').get('ids')[currentlySelectedVideodisplay]);
+                if (display === undefined || display === 'focus.none') {
+                    Engage.trigger(plugin.events.resetLayout.getName());
+                    return;
+                }
 
-      /* synchronize videos */
-      if (pressedPlayOnce) {
-        Engage.trigger(plugin.events.seek.getName(), currentTime);
-        if (!isPaused) {
-          oldVideodisplayMaster.pause();
-          videodisplayMaster.play();
-        }
-      }
+                if (display === 'focus.next' || display === 'focus.prev') {
+                    if (isDefaultLayout()) {
+                        if (display === 'focus.next') {
+                            Engage.trigger(plugin.events.focusVideo.getName(),
+                                Utils.getFlavorForVideoDisplay($('.' + videoDisplayClass).first()));
+                            return;
+                        } else {
+                            Engage.trigger(plugin.events.focusVideo.getName(),
+                                Utils.getFlavorForVideoDisplay($('.' + videoDisplayClass).last()));
+                            return;
+                        }
+                    } else {
+                        var vidDisp = $videoDisplayClass;
+                        var selectNext = false;
+                        var last;
+                        var i = 0;
+                        for (var elem in vidDisp) {
+                            if (selectNext) {
+                                Engage.trigger(plugin.events.focusVideo.getName(),
+                                    Utils.getFlavorForVideoDisplay($(vidDisp[elem])));
+                                return;
+                            } else if ($(vidDisp[elem]).hasClass(videoFocusedClass)) {
+                                if ((display === 'focus.prev' && last === undefined) ||
+                                    (display === 'focus.next' && i === vidDisp.length - 1)) {
+                                    Engage.log('Video: Resetting videodisplay layout');
+                                    Engage.trigger(plugin.events.resetLayout.getName());
+                                    return;
+                                } else if (display === 'focus.next') {
+                                    selectNext = true;
+                                } else {
+                                    Engage.trigger(plugin.events.focusVideo.getName(),
+                                        Utils.getFlavorForVideoDisplay(last));
+                                    return;
+                                }
+                            }
+                            last = $(vidDisp[elem]);
+                            i++;
+                        }
+                    }
+                } else {
+                    videoDiv = getDivForFlavor(display);
+                    if (videoDiv === undefined) {
+                        Engage.trigger(plugin.events.resetLayout.getName());
+                        return;
+                    }
+                    if ($(videoDiv).hasClass(videoFocusedClass)) {
+                        Engage.log('Video: Resetting videodisplay layout');
+                        Engage.trigger(plugin.events.resetLayout.getName());
+                        return;
+                    }
+                }
+                $videoDisplayClass.css({
+                    'width': '',
+                    'left': '',
+                    'top': '',
+                    'margin-left': ''
+                });
+                $('#engage_video').css('height', '');
+                $videoDisplayClass.removeClass(videoDefaultLayoutClass).addClass(videoUnfocusedClass);
+                $('.' + videoUnfocusedClass).removeClass(videoFocusedClass);
+                $(videoDiv).addClass(videoFocusedClass).removeClass(videoUnfocusedClass);
+
+
+                if (isPiP) {
+                    var distance = 0;
+                    $('.' + videoUnfocusedClass).each(function () {
+                        var width = $(this).width();
+                        var height = $(this).height();
+                        $(this).css({
+                            'left': 0 - (width / 2) + 'px',
+                            'top': distance - (height / 2) + 'px'
+                        });
+                        distance = distance + height + 10;
+                    });
+                    var marginLeft;
+                    if (pipPos === 'left') {
+                        marginLeft = 12;
+                    } else {
+                        marginLeft = 88;
+                    }
+                    $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
+                } else {
+                    var height = $('.' + videoFocusedClass).height();
+                    $('#engage_video').height(height + 10);
+                }
 
-      $('#' + id_videoDisplayClass + (currentlySelectedVideodisplay+1)).addClass('active');
+                delayedCalculateVideoAreaAspectRatio();
+            });
 
-      Engage.log('Switched to video ' + currentlySelectedVideodisplay);
-    });
+            Engage.on(plugin.events.resetLayout.getName(), function () {
+                Engage.log('Video: received resetting layout');
+                $('#engage_video').css('height', '');
+                $videoDisplayClass.css({
+                    'width': '',
+                    'left': '',
+                    'top': '',
+                    'margin-left': ''
+                });
+                $videoDisplayClass.removeClass(videoFocusedClass).removeClass(videoUnfocusedClass).addClass(videoDefaultLayoutClass);
+                var numberDisplays = $videoDisplayClass.length;
+                $videoDisplayClass.css('width', (((1 / numberDisplays) * 100) - 0.5) + '%');
+                delayedCalculateVideoAreaAspectRatio();
+            });
 
-    /* listen on ready event with query argument */
-    Engage.on(plugin.events.ready.getName(), function (query) {
-      if (query === true) {
-        Engage.trigger(plugin.events.ready.getName());
-      }
-    });
-    /* listen on videoFormatsFound event with query argument */
-    Engage.on(plugin.events.videoFormatsFound.getName(), function (query) {
-      if (query === true) {
-        Engage.trigger(plugin.events.videoFormatsFound.getName(), qualities);
-      }
-    });
-  }
+            Engage.on(plugin.events.movePiP.getName(), function (pos) {
+                var numberDisplays = $('.' + videoDisplayClass).length;
+                if (numberDisplays <= 1) return;
+                if (pos !== undefined) {
+                    pipPos = pos;
+                }
+                if (!isPiP) {
+                    return;
+                }
+                Engage.log('Video: moving PiP');
+                var marginLeft;
+                if (pipPos === 'right') {
+                    marginLeft = 88;
+                    pipPos = 'right';
+                } else {
+                    marginLeft = 12;
+                    pipPos = 'left';
+                }
+                $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
 
-  function registerEvents(videoDisplay, numberOfVideodisplays) {
-    if (isAudioOnly) {
-      registerEventsAudioOnly(videoDisplay, numberOfVideodisplays);
-    } else {
-      registerEventsVideo(videoDisplay, numberOfVideodisplays);
-    }
-  }
-
-  function isDefaultLayout() {
-    return $('.' + videoDefaultLayoutClass).length > 0;
-  }
-
-  function getDivForFlavor(flavor) {
-    var found;
-    $('.' + videoDisplayClass).each(function () {
-      if (Utils.getFlavorForVideoDisplay(this) === flavor) {
-        found = this;
-        return;
-      }
-    });
-    return found;
-  }
+                delayedCalculateVideoAreaAspectRatio();
+            });
 
-  function extractFlavorsAndMimetypes(mediaInfo) {
-    var flavors = '';
-    var mimetypes = '';
+            Engage.on(plugin.events.togglePiP.getName(), function (pip) {
+                var numberDisplays = $videoDisplayClass.length;
+                if (numberDisplays <= 1) return;
 
-    var allowedTags = Engage.model.get('meInfo').get('allowedtags');
-    var allowedFormats = Engage.model.get('meInfo').get('allowedformats');
-    mediaInfo.tracks = filterTracksByFormat(filterTracksByTag(mediaInfo.tracks, allowedTags), allowedFormats);
+                Engage.log('Video: setting PiP to ' + pip);
+                if ((pip && isPiP) || (!pip && !isPiP)) {
+                    return;
+                }
+                if (!pip) {
+                    videoUnfocusedClass = unfocusedClass;
+                    videoFocusedClass = focusedClass;
+                    isPiP = false;
+                    if (!isDefaultLayout()) {
+                        $videoDisplayClass.css({
+                            'width': '',
+                            'left': '',
+                            'top': '',
+                            'margin-left': ''
+                        });
+                        $('.' + unfocusedPiPClass).addClass(videoUnfocusedClass).removeClass(unfocusedPiPClass);
+                        $('.' + focusedPiPClass).addClass(videoFocusedClass).removeClass(focusedPiPClass);
+                        var height = $('.' + videoFocusedClass).height();
+                        $('#engage_video').height(height + 10);
+                    }
+                } else {
+                    videoUnfocusedClass = unfocusedPiPClass;
+                    videoFocusedClass = focusedPiPClass;
+                    isPiP = true;
+                    if (!isDefaultLayout()) {
+                        $('.' + unfocusedClass).addClass(videoUnfocusedClass).removeClass(unfocusedClass);
+                        $('.' + focusedClass).addClass(videoFocusedClass).removeClass(focusedClass);
+                        $('#engage_video').css('height', '');
+                        var distance = 0;
+                        $('.' + videoUnfocusedClass).each(function () {
+                            var width = $(this).width();
+                            var height = $(this).height();
+                            $(this).css({
+                                'left': 0 - (width / 2) + 'px',
+                                'top': distance - (height / 2) + 'px'
+                            });
+                            distance = distance + height + 10;
+                        });
+                        var marginLeft;
+                        if (pipPos === 'left') {
+                            marginLeft = 12;
+                        } else {
+                            marginLeft = 88;
+                        }
+                        $('.' + videoUnfocusedClass).css('margin-left', marginLeft + '%');
+                    }
+                }
+                delayedCalculateVideoAreaAspectRatio();
 
-    if (mediaInfo.tracks && (mediaInfo.tracks.length > 0)) {
-      for (var k = 0; k < mediaInfo.tracks.length; ++k) {
-        if (flavors.indexOf(mediaInfo.tracks[k].type) < 0) {
-          flavors += mediaInfo.tracks[k].type + ',';
+            });
         }
 
-        // rtmp is treated differently for video.js. Mimetype and URL have to be changed
-        if ((mediaInfo.tracks[k].mimetype == 'video/mp4') &&
-            (mediaInfo.tracks[k].url.toLowerCase().indexOf('rtmp://') > -1)) {
-          mediaInfo.tracks[k].mimetype = 'rtmp/mp4';
-          mediaInfo.tracks[k].url = Utils.replaceAll(mediaInfo.tracks[k].url, 'mp4:', '&mp4:');
-        }
+        /* event used to switch between videos in single video display (e.g. mobile) mode */
+        Engage.on(plugin.events.switchVideo.getName(), function (id) {
+            /* check if current video is paused */
+            var isPaused = videodisplayMaster.paused();
 
-        // adaptive streaming manifests don't have a resolution. Extract these from regular videos
-        if (mediaInfo.tracks[k].mimetype.match(/video/g) && mediaInfo.tracks[k] &&
-            mediaInfo.tracks[k].video && mediaInfo.tracks[k].video.resolution &&
-            videoResultions[Utils.extractFlavorMainType(mediaInfo.tracks[k].type)] == null) {
-          videoResultions[Utils.extractFlavorMainType(mediaInfo.tracks[k].type)] = Utils.parseVideoResolution(mediaInfo.tracks[k].video.resolution);
-        }
+            $('#' + id_videoDisplayClass + (currentlySelectedVideodisplay + 1)).removeClass('active');
 
-        if (mimetypes.indexOf(mediaInfo.tracks[k].mimetype) < 0) {
-          mimetypes += mediaInfo.tracks[k].mimetype + ',';
-        }
-      }
+            /* assign currentlySelectedVideodisplay in the available bounds */
+            var n = globalVideoSource.length;
+            currentlySelectedVideodisplay = Math.max(0, Math.min(id, n - 1));
+
+            var oldVideodisplayMaster = videodisplayMaster;
+            videodisplayMaster = videojs(Engage.model.get('videoDataModel').get('ids')[currentlySelectedVideodisplay]);
+
+            /* synchronize videos */
+            if (pressedPlayOnce) {
+                Engage.trigger(plugin.events.seek.getName(), currentTime);
+                if (!isPaused) {
+                    oldVideodisplayMaster.pause();
+                    videodisplayMaster.play();
+                }
+            }
+
+            $('#' + id_videoDisplayClass + (currentlySelectedVideodisplay + 1)).addClass('active');
+
+            Engage.log('Switched to video ' + currentlySelectedVideodisplay);
+        });
+
+        /* listen on ready event with query argument */
+        Engage.on(plugin.events.ready.getName(), function (query) {
+            if (query === true) {
+                Engage.trigger(plugin.events.ready.getName());
+            }
+        });
+        /* listen on videoFormatsFound event with query argument */
+        Engage.on(plugin.events.videoFormatsFound.getName(), function (query) {
+            if (query === true) {
+                Engage.trigger(plugin.events.videoFormatsFound.getName(), qualities);
+            }
+        });
     }
 
-    return {
-      flavors: flavors.substring(0, flavors.length - 1),
-      mimetypes: mimetypes.substring(0, mimetypes.length - 1)
+    function registerEvents(videoDisplay, numberOfVideodisplays) {
+        if (isAudioOnly) {
+            registerEventsAudioOnly(videoDisplay, numberOfVideodisplays);
+        } else {
+            registerEventsVideo(videoDisplay, numberOfVideodisplays);
+        }
     }
-  }
 
-  function extractVideoSourcesAndDuration(mediaInfo, flavorsArray) {
-    var videoSources = [];
-    var duration = 0;
-    var hasAudio = false;
-    var hasVideo = false;
-    videoSources.audio = [];
+    function isDefaultLayout() {
+        return $('.' + videoDefaultLayoutClass).length > 0;
+    }
 
-    for (var j = 0; j < flavorsArray.length; ++j) {
-      videoSources[Utils.extractFlavorMainType(flavorsArray[j])] = [];
+    function getDivForFlavor(flavor) {
+        var found;
+        $('.' + videoDisplayClass).each(function () {
+            if (Utils.getFlavorForVideoDisplay(this) === flavor) {
+                found = this;
+                return;
+            }
+        });
+        return found;
     }
 
-    if (mediaInfo.tracks) {
-      $(mediaInfo.tracks).each(function (i, track) {
-        if (track.mimetype && track.type && acceptFormat(track)) {
-          if (track.mimetype.match(/video/g) || track.mimetype.match(/application/g) || track.mimetype.match(/rtmp/g)) {
-            hasVideo = true;
-            if (track.duration > duration) {
-              duration = track.duration;
-            }
-            var resolution = (track.video && track.video.resolution) ? track.video.resolution : '';
-            // filter for different video sources
-            Engage.log('Video: Adding video source: ' + track.url + ' (' + track.mimetype + ')');
-            if (track.mimetype == 'application/dash+xml') {
-              loadDash = true;
-            } else if (track.mimetype == 'application/x-mpegURL') {
-              loadHls = true;
-            }
-            videoSources[Utils.extractFlavorMainType(track.type)].push({
-              src: track.url,
-              type: track.mimetype,
-              typemh: track.type,
-              resolution: resolution,
-              tags: track.tags
-            });
-          } else if (track.mimetype.match(/audio/g)) {
-            hasAudio = true;
-            if (track.duration > duration) {
-              duration = track.duration;
-            }
-            videoSources.audio.push({
-              src: track.url,
-              type: track.mimetype,
-              typemh: track.type,
-              tags: track.tags
-            });
-          }
+    function extractFlavorsAndMimetypes(mediaInfo) {
+        var flavors = '';
+        var mimetypes = '';
+
+        var allowedTags = Engage.model.get('meInfo').get('allowedtags');
+        var allowedFormats = Engage.model.get('meInfo').get('allowedformats');
+        mediaInfo.tracks = filterTracksByFormat(filterTracksByTag(mediaInfo.tracks, allowedTags), allowedFormats);
+
+        if (mediaInfo.tracks && (mediaInfo.tracks.length > 0)) {
+            for (var k = 0; k < mediaInfo.tracks.length; ++k) {
+                if (flavors.indexOf(mediaInfo.tracks[k].type) < 0) {
+                    flavors += mediaInfo.tracks[k].type + ',';
+                }
+
+                // rtmp is treated differently for video.js. Mimetype and URL have to be changed
+                if ((mediaInfo.tracks[k].mimetype == 'video/mp4') &&
+                    (mediaInfo.tracks[k].url.toLowerCase().indexOf('rtmp://') > -1)) {
+                    mediaInfo.tracks[k].mimetype = 'rtmp/mp4';
+                    mediaInfo.tracks[k].url = Utils.replaceAll(mediaInfo.tracks[k].url, 'mp4:', '&mp4:');
+                }
+
+                // adaptive streaming manifests don't have a resolution. Extract these from regular videos
+                if (mediaInfo.tracks[k].mimetype.match(/video/g) && mediaInfo.tracks[k] &&
+                    mediaInfo.tracks[k].video && mediaInfo.tracks[k].video.resolution &&
+                    videoResultions[Utils.extractFlavorMainType(mediaInfo.tracks[k].type)] == null) {
+                    videoResultions[Utils.extractFlavorMainType(mediaInfo.tracks[k].type)] = Utils.parseVideoResolution(mediaInfo.tracks[k].video.resolution);
+                }
+
+                if (mimetypes.indexOf(mediaInfo.tracks[k].mimetype) < 0) {
+                    mimetypes += mediaInfo.tracks[k].mimetype + ',';
+                }
+            }
         }
-      });
 
-      if (!hasVideo) {
-        for (var i = 0; i < videoSources.length; ++i) {
-          if (videoSources[i] !== videoSources.audio) {
-            delete videoSources.flavor;
-          }
+        return {
+            flavors: flavors.substring(0, flavors.length - 1),
+            mimetypes: mimetypes.substring(0, mimetypes.length - 1)
+        }
+    }
+
+    function extractVideoSourcesAndDuration(mediaInfo, flavorsArray) {
+        var videoSources = [];
+        var duration = 0;
+        var hasAudio = false;
+        var hasVideo = false;
+        videoSources.audio = [];
+
+        for (var j = 0; j < flavorsArray.length; ++j) {
+            videoSources[Utils.extractFlavorMainType(flavorsArray[j])] = [];
+        }
+
+        if (mediaInfo.tracks) {
+            $(mediaInfo.tracks).each(function (i, track) {
+                if (track.mimetype && track.type && acceptFormat(track)) {
+                    if (track.mimetype.match(/video/g) || track.mimetype.match(/application/g) || track.mimetype.match(/rtmp/g)) {
+                        hasVideo = true;
+                        if (track.duration > duration) {
+                            duration = track.duration;
+                        }
+                        var resolution = (track.video && track.video.resolution) ? track.video.resolution : '';
+                        // filter for different video sources
+                        Engage.log('Video: Adding video source: ' + track.url + ' (' + track.mimetype + ')');
+                        if (track.mimetype == 'application/dash+xml') {
+                            loadDash = true;
+                        } else if (track.mimetype == 'application/x-mpegURL') {
+                            loadHls = true;
+                        }
+                        videoSources[Utils.extractFlavorMainType(track.type)].push({
+                            src: track.url,
+                            type: track.mimetype,
+                            typemh: track.type,
+                            resolution: resolution,
+                            tags: track.tags
+                        });
+                    } else if (track.mimetype.match(/audio/g)) {
+                        hasAudio = true;
+                        if (track.duration > duration) {
+                            duration = track.duration;
+                        }
+                        videoSources.audio.push({
+                            src: track.url,
+                            type: track.mimetype,
+                            typemh: track.type,
+                            tags: track.tags
+                        });
+                    }
+                }
+            });
+
+            if (!hasVideo) {
+                for (var i = 0; i < videoSources.length; ++i) {
+                    if (videoSources[i] !== videoSources.audio) {
+                        delete videoSources.flavor;
+                    }
+                }
+            }
+
+            if (hasVideo || !hasAudio) {
+                delete videoSources.audio;
+            }
         }
-      }
 
-      if (hasVideo || !hasAudio) {
-        delete videoSources.audio;
-      }
+        return {
+            videoSources: videoSources,
+            duration: duration
+        };
     }
 
-    return {
-      videoSources: videoSources,
-      duration: duration
-    };
-  }
+    function extractVideoDisplays(videoSources) {
+        var videoDisplays = [];
 
-  function extractVideoDisplays(videoSources) {
-    var videoDisplays = [];
+        for (var v in videoSources) {
+            if (videoSources[v].length > 0) {
+                var name = videoDisplayNamePrefix.concat(v);
+                videoDisplays.push(name);
+            }
+        }
 
-    for (var v in videoSources) {
-      if (videoSources[v].length > 0) {
-        var name = videoDisplayNamePrefix.concat(v);
-        videoDisplays.push(name);
-      }
+        return videoDisplays;
     }
 
-    return videoDisplays;
-  }
-
-  function setVideoSourcePosters(mediaInfo, videoSources) {
-    if (mediaInfo.attachments && (mediaInfo.attachments.length > 0)) {
-      $(mediaInfo.attachments).each(function (i, attachment) {
-        if (attachment.mimetype &&
-            attachment.type &&
-            attachment.url &&
-            attachment.mimetype.match(/image/g) &&
-            attachment.type.match(/player/g) &&
-            videoSources[Utils.extractFlavorMainType(attachment.type)]) {
-          // filter for different video sources
-          videoSources[Utils.extractFlavorMainType(attachment.type)]['poster'] = attachment.url;
-        }
-      });
+    function setVideoSourcePosters(mediaInfo, videoSources) {
+        if (mediaInfo.attachments && (mediaInfo.attachments.length > 0)) {
+            $(mediaInfo.attachments).each(function (i, attachment) {
+                if (attachment.mimetype &&
+                    attachment.type &&
+                    attachment.url &&
+                    attachment.mimetype.match(/image/g) &&
+                    attachment.type.match(/player/g) &&
+                    videoSources[Utils.extractFlavorMainType(attachment.type)]) {
+                    // filter for different video sources
+                    videoSources[Utils.extractFlavorMainType(attachment.type)]['poster'] = attachment.url;
+                }
+            });
+        }
     }
-  }
 
-  function setupStreams(tracks, attachments) {
-    Engage.log('Video: Setting up streams');
+    function setupStreams(tracks, attachments) {
+        Engage.log('Video: Setting up streams');
 
-    var mediaInfo = {};
-    var videoSources;
-    var videoDisplays;
-    var duration = 0;
+        var mediaInfo = {};
+        var videoSources;
+        var videoDisplays;
+        var duration = 0;
 
-    mastervideotype = Engage.model.get('meInfo').get('mastervideotype').toLowerCase();
-    Engage.log('Video: Master video type is \'' + mastervideotype + '\'');
+        mastervideotype = Engage.model.get('meInfo').get('mastervideotype').toLowerCase();
+        Engage.log('Video: Master video type is \'' + mastervideotype + '\'');
 
-    mediaInfo.tracks = tracks;
-    mediaInfo.attachments = attachments;
+        mediaInfo.tracks = tracks;
+        mediaInfo.attachments = attachments;
 
-    if (mediaInfo.tracks && (mediaInfo.tracks.length > 0)) {
-      var flavorsAndMimetypes = extractFlavorsAndMimetypes(mediaInfo);
-      flavors = flavorsAndMimetypes.flavors;
-      mimetypes = flavorsAndMimetypes.mimetypes;
-      Engage.log('Video: Extracted flavors: ' + flavors, mimetypes);
-      Engage.log('Video: Extracted mimetypes: ' + mimetypes);
+        if (mediaInfo.tracks && (mediaInfo.tracks.length > 0)) {
+            var flavorsAndMimetypes = extractFlavorsAndMimetypes(mediaInfo);
+            flavors = flavorsAndMimetypes.flavors;
+            mimetypes = flavorsAndMimetypes.mimetypes;
+            Engage.log('Video: Extracted flavors: ' + flavors, mimetypes);
+            Engage.log('Video: Extracted mimetypes: ' + mimetypes);
 
-      var flavorsArray = flavors.split(',');
+            var flavorsArray = flavors.split(',');
 
-      // look for video sources
-      var videoSourcesAndDuration = extractVideoSourcesAndDuration(mediaInfo, flavorsArray);
-      videoSources = videoSourcesAndDuration.videoSources;
-      duration = videoSourcesAndDuration.duration;
+            // look for video sources
+            var videoSourcesAndDuration = extractVideoSourcesAndDuration(mediaInfo, flavorsArray);
+            videoSources = videoSourcesAndDuration.videoSources;
+            duration = videoSourcesAndDuration.duration;
 
-      setVideoSourcePosters(mediaInfo, videoSources);
+            setVideoSourcePosters(mediaInfo, videoSources);
 
-      videoDisplays = extractVideoDisplays(videoSources);
-      Engage.log('Video: Extracted video displays: ' + videoDisplays.join(', '));
+            videoDisplays = extractVideoDisplays(videoSources);
+            Engage.log('Video: Extracted video displays: ' + videoDisplays.join(', '));
 
-      Engage.model.set('videoDataModel', new VideoDataModel(videoDisplays, videoSources, duration));
+            Engage.model.set('videoDataModel', new VideoDataModel(videoDisplays, videoSources, duration));
+        }
     }
-  }
-
-  function getSortedVideosourcesArray(videoSources) {
-    var tuples = [];
 
-    for (var key in videoSources) {
-      tuples.push([key, videoSources[key]]);
-    }
+    function getSortedVideosourcesArray(videoSources) {
+        var tuples = [];
 
-    tuples.sort(compareVideoSources);
+        for (var key in videoSources) {
+            tuples.push([key, videoSources[key]]);
+        }
 
-    return tuples;
-  }
+        tuples.sort(compareVideoSources);
 
-  function compareVideoSources(a, b) {
-    if (a === undefined || b === undefined || a[1][0] === undefined ||
-      b[1][0] === undefined) {
-      return 0;
-    }
-    var s1 = a[1][0].typemh;
-    var s2 = b[1][0].typemh;
-    if (s1 == mastervideotype) {
-      return -1;
-    } else if (s2 == mastervideotype) {
-      return 1;
+        return tuples;
     }
 
-    return 0;
-  }
-
-  /**
-   * Try to load captions for video
-   * @returns {undefined}
-   */
-  function loadAndAppendCaptions(videoDataView) {
-    Engage.log("Video: Loading Captions.");
-    var tracks        = Engage.model.get('mediaPackage').get('tracks');
-    var attachments   = Engage.model.get('mediaPackage').get('attachments')
-    var videoDisplays = videoDataView.model.get('ids');
-    var captionsURL   = null;
-
-    // Load from attachment
-    for(var a in attachments) {
-      if(attachments[a].mimetype == "text/vtt") {
-        Engage.log("Found caption in attachments.");
-        captionsURL = attachments[a].url;
-        Engage.model.set("captions", true);
-        Engage.trigger(plugin.events.captionsFound.getName());
-      }
+    function compareVideoSources(a, b) {
+        if (a === undefined || b === undefined || a[1][0] === undefined ||
+            b[1][0] === undefined) {
+            return 0;
+        }
+        var s1 = a[1][0].typemh;
+        var s2 = b[1][0].typemh;
+        if (s1 == mastervideotype) {
+            return -1;
+        } else if (s2 == mastervideotype) {
+            return 1;
+        }
+
+        return 0;
     }
 
-    // Load from track
-    for(var a in tracks) {
-      if(tracks[a].mimetype == "text/vtt") {
-        Engage.log("Found caption in tracks");
-        captionsURL = tracks[a].url;
-        Engage.model.set("captions", true);
-        Engage.trigger(plugin.events.captionsFound.getName());
-      }
+    /**
+     * Try to load captions for video
+     * @returns {undefined}
+     */
+    function loadAndAppendCaptions(videoDataView) {
+        Engage.log("Video: Loading Captions.");
+        var tracks = Engage.model.get('mediaPackage').get('tracks');
+        var attachments = Engage.model.get('mediaPackage').get('attachments')
+        var videoDisplays = videoDataView.model.get('ids');
+        var captionsURL = null;
+
+        // Load from attachment
+        for (var a in attachments) {
+            if (attachments[a].mimetype == "text/vtt") {
+                Engage.log("Found caption in attachments.");
+                captionsURL = attachments[a].url;
+                Engage.model.set("captions", true);
+                Engage.trigger(plugin.events.captionsFound.getName());
+            }
+        }
+
+        // Load from track
+        for (var a in tracks) {
+            if (tracks[a].mimetype == "text/vtt") {
+                Engage.log("Found caption in tracks");
+                captionsURL = tracks[a].url;
+                Engage.model.set("captions", true);
+                Engage.trigger(plugin.events.captionsFound.getName());
+            }
+        }
+
+        if (captionsURL == null) {
+            return;
+        }
+
+        $.each(videoDisplays, function (i, j) {
+            var caption = videojs(j).addRemoteTextTrack({
+                kind: 'caption',
+                language: 'en',
+                label: 'Caption',
+                src: captionsURL,
+                mode: "hidden"
+            }, true);
+        });
+
+        activeCaption = videojs(videoDisplays[0]).remoteTextTracks()[0];
+
+        Engage.on(plugin.events.toggleCaptions.getName(), function (data) {
+            if (data) {
+                activeCaption.mode = "showing";
+            } else {
+                activeCaption.mode = "hidden";
+            }
+        });
+
+        Engage.on(plugin.events.focusVideo.getName(), function (data) {
+            var captionMode = activeCaption.mode;
+            activeCaption.mode = "hidden";
+            activeCaption = videojs("videojs_videodisplay_" + data).textTracks()[0];
+            activeCaption.mode = captionMode;
+            if (data == "none") {
+                console.warn("none " + data);
+            } else {
+                console.warn("else " + data);
+            }
+        });
     }
 
-    if(captionsURL == null) {
-      return;
+    function initPlugin() {
+        Engage.log('Video: Init Plugin');
+
+        // only init if plugin template was inserted into the DOM
+        if (plugin.inserted) {
+            Engage.log('Video: Video Plugin inserted');
+            // set path to swf player
+            var videojs_swf = plugin.pluginPath + videojs_swf_path;
+            Engage.log('Video: SWF path: ' + videojs_swf_path);
+            Engage.model.on(videoDataModelChange, function () {
+                Engage.log('Video: The video data model changed, refreshing the view.');
+                videoDataView = new VideoDataView(this.get('videoDataModel'), plugin.template, videojs_swf);
+            });
+            Engage.on(plugin.events.mediaPackageModelError.getName(), function () {
+                mediapackageError = true;
+            });
+            Engage.model.get('mediaPackage').on('change', function () {
+                setupStreams(this.get('tracks'), this.get('attachments'));
+            });
+            if (Engage.model.get('mediaPackage').get('tracks')) {
+                Engage.log('Video: Mediapackage already available.');
+                setupStreams(Engage.model.get('mediaPackage').get('tracks'), Engage.model.get('mediaPackage').get('attachments'));
+            }
+        }
     }
 
-    $.each(videoDisplays, function(i, j){
-      var caption = videojs(j).addRemoteTextTrack({
-        kind: 'caption',
-        language: 'en',
-        label: 'Caption',
-        src: captionsURL,
-        mode: "hidden"
-      }, true);
-    });
+    // init Event
+    Engage.log('Video: Init');
+    var relative_plugin_path = Engage.getPluginPath('EngagePluginVideoVideoJS');
 
-    activeCaption = videojs(videoDisplays[0]).remoteTextTracks()[0];
+    // listen on a change/set of the mediaPackage model
+    Engage.model
+        .on(mediapackageChange, function () {
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        })
+        .on(infoMeChange, function () {
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        });
 
-    Engage.on(plugin.events.toggleCaptions.getName(), function(data) {
-      if(data) {
-        activeCaption.mode = "showing";
-      } else {
-        activeCaption.mode = "hidden";
-      }
+    // all plugins loaded
+    Engage.on(plugin.events.plugin_load_done.getName(), function () {
+        Engage.log('Video: Plugin load done');
+        initCount -= 1;
+        if (initCount <= 0) {
+            initPlugin();
+        }
+    });
+    requirejs.config({
+        waitSeconds: 60
     });
 
-    Engage.on(plugin.events.focusVideo.getName(), function (data) {
-      var captionMode = activeCaption.mode;
-      activeCaption.mode = "hidden";
-      activeCaption = videojs("videojs_videodisplay_" + data).textTracks()[0];
-      activeCaption.mode = captionMode;
-      if(data == "none") {
-        console.warn("none " + data);
-      } else {
-        console.warn("else " + data);
-      }
+    // load utils class
+    require([relative_plugin_path + 'utils'], function (utils) {
+        Engage.log('Video: Utils class loaded');
+        Utils = new utils();
+        initTranslate(Engage.model.get("language"), function () {
+            Engage.log('Video: Successfully translated.');
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        }, function () {
+            Engage.log('Video: Error translating...');
+            initCount -= 1;
+            if (initCount <= 0) {
+                initPlugin();
+            }
+        });
     });
-  }
-
-  function initPlugin() {
-    Engage.log('Video: Init Plugin');
-
-    // only init if plugin template was inserted into the DOM
-    if (plugin.inserted) {
-      Engage.log('Video: Video Plugin inserted');
-      // set path to swf player
-      var videojs_swf = plugin.pluginPath + videojs_swf_path;
-      Engage.log('Video: SWF path: ' + videojs_swf_path);
-      Engage.model.on(videoDataModelChange, function () {
-        Engage.log('Video: The video data model changed, refreshing the view.');
-        videoDataView = new VideoDataView(this.get('videoDataModel'), plugin.template, videojs_swf);
-      });
-      Engage.on(plugin.events.mediaPackageModelError.getName(), function () {
-        mediapackageError = true;
-      });
-      Engage.model.get('mediaPackage').on('change', function () {
-        setupStreams(this.get('tracks'), this.get('attachments'));
-      });
-      if (Engage.model.get('mediaPackage').get('tracks')) {
-        Engage.log('Video: Mediapackage already available.');
-        setupStreams(Engage.model.get('mediaPackage').get('tracks'), Engage.model.get('mediaPackage').get('attachments'));
-      }
-    }
-  }
-
-  // init Event
-  Engage.log('Video: Init');
-  var relative_plugin_path = Engage.getPluginPath('EngagePluginVideoVideoJS');
-
-  // listen on a change/set of the mediaPackage model
-  Engage.model
-    .on(mediapackageChange, function () {
-      initCount -= 1;
-      if (initCount <= 0) {
-        initPlugin();
-      }
-    })
-    .on(infoMeChange, function () {
-      initCount -= 1;
-      if (initCount <= 0) {
-        initPlugin();
-      }
+
+    // load videoData model
+    require([relative_plugin_path + 'models/videoData'], function (model) {
+        Engage.log('Video: VideoData model loaded');
+        VideoDataModel = model;
+        initCount -= 1;
+        if (initCount <= 0) {
+            initPlugin();
+        }
     });
 
-  // all plugins loaded
-  Engage.on(plugin.events.plugin_load_done.getName(), function () {
-    Engage.log('Video: Plugin load done');
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
-    }
-  });
-  requirejs.config({
-    waitSeconds: 60
-  });
-
-  // load utils class
-  require([relative_plugin_path + 'utils'], function (utils) {
-    Engage.log('Video: Utils class loaded');
-    Utils = new utils();
-    initTranslate(Engage.model.get("language"), function () {
-      Engage.log('Video: Successfully translated.');
-      initCount -= 1;
-      if (initCount <= 0) {
-        initPlugin();
-      }
-    }, function () {
-      Engage.log('Video: Error translating...');
-      initCount -= 1;
-      if (initCount <= 0) {
-        initPlugin();
-      }
+    // load video.js lib
+    require([relative_plugin_path + videoPath], function (videojs) {
+        Engage.log('Video: Lib video loaded');
+        window.videojs = videojs;
+        initCount -= 1;
+        if (initCount <= 0) {
+            initPlugin();
+        }
+    });
+
+    // load synchronize.js lib
+    require([relative_plugin_path + synchronizePath], function (synchronizejs) {
+        Engage.log('Video: Lib synchronize loaded');
+        initCount -= 1;
+        if (initCount <= 0) {
+            initPlugin();
+        }
     });
-  });
-
-  // load videoData model
-  require([relative_plugin_path + 'models/videoData'], function (model) {
-    Engage.log('Video: VideoData model loaded');
-    VideoDataModel = model;
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
-    }
-  });
-
-  // load video.js lib
-  require([relative_plugin_path + videoPath], function (videojs) {
-    Engage.log('Video: Lib video loaded');
-    window.videojs = videojs;
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
-    }
-  });
-
-  // load synchronize.js lib
-  require([relative_plugin_path + synchronizePath], function (synchronizejs) {
-    Engage.log('Video: Lib synchronize loaded');
-    initCount -= 1;
-    if (initCount <= 0) {
-      initPlugin();
-    }
-  });
 
-  return plugin;
+    return plugin;
 })
diff --git a/player/plugin/video-videojs/styles/desktop.css b/player/plugin/video-videojs/styles/desktop.css
index f6c5de9..3d38615 100644
--- a/player/plugin/video-videojs/styles/desktop.css
+++ b/player/plugin/video-videojs/styles/desktop.css
@@ -4,7 +4,7 @@
 
 .videojs_wrapper {
     width: 100%;
-    height: 100%;
+    /*height: 100%;*/
     position: relative;
     margin: 0 auto;
     cursor: pointer;
@@ -30,7 +30,7 @@
 
 .videoFrame {
     width: 100%;
-    height: 100%;
+    /*height: 100%;*/
 }
 
 .videoFocusedPiP {
diff --git a/player/templates/core_desktop_bottom.html b/player/templates/core_desktop_bottom.html
index 3480753..da39db8 100644
--- a/player/templates/core_desktop_bottom.html
+++ b/player/templates/core_desktop_bottom.html
@@ -2,7 +2,7 @@
 <div id="engage_content">
     <!-- videodisplay plugin container -->
     <div id="engage_resize_container">
-        <div id="engage_controls_second"></div>
+<!--        <div id="engage_controls_second"></div> -->
         <div id="engage_video"></div>
         <div id="engage_top_bar">
     </div>
diff --git a/settings.php b/settings.php
index 46cbba9..3ad01b5 100644
--- a/settings.php
+++ b/settings.php
@@ -33,4 +33,6 @@ if ($ADMIN->fulltree) {
 
     $settings->add(new admin_setting_configselect('filter_opencast/issuerid', get_string('setting_issuer', 'filter_opencast'),
         get_string('setting_issuer_desc', 'filter_opencast'), 0, $choices));
+    $settings->add(new admin_setting_configtext('filter_opencast/baseurlapi', get_string('setting_baseurlapi', 'filter_opencast'),
+        get_string('setting_baseurlapi_desc', 'filter_opencast'), ''));
 }
diff --git a/version.php b/version.php
index 4f500e6..c5bd2c7 100644
--- a/version.php
+++ b/version.php
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2018010903;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2018010906;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'filter_opencast'; // Full name of the plugin (used for diagnostics)
-- 
GitLab