diff --git a/src/main/resources/kinosearch/webapp/player.ftl b/src/main/resources/kinosearch/webapp/player.ftl
index 59d015d..71e86bf 100644
--- a/src/main/resources/kinosearch/webapp/player.ftl
+++ b/src/main/resources/kinosearch/webapp/player.ftl
@@ -1,60 +1,13 @@
[#ftl]
[#include "/header.inc.ftl"]
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
[#include "/fother.inc.ftl"]
\ No newline at end of file
diff --git a/src/main/resources/kinosearch/webapp/static/js/ksplayer.js b/src/main/resources/kinosearch/webapp/static/js/ksplayer.js
new file mode 100644
index 0000000..3596747
--- /dev/null
+++ b/src/main/resources/kinosearch/webapp/static/js/ksplayer.js
@@ -0,0 +1,257 @@
+const KSPlayer = function(containerId, data) {
+ /* --- FIELDS -------------- */
+
+ let isShowTitle = false;
+
+ /* --- PRIVATE FIELDS ------ */
+
+ let titleElement;
+ let seasonSerials = [];
+ const _self = this;
+ let lastActiveSerialItem;
+ let lastActiveSeasonItem;
+
+ /* --- PRIVATE FUNCTIONS --- */
+
+ function createSerialMenuElement(serials) {
+ let div = document.createElement('div');
+ div.id = 'pl-serial';
+ div.className = 'dropdown';
+ div.style = 'display: inline-block';
+
+ let button = document.createElement('button');
+ button.className = 'btn btn-default dropdown-toggle';
+ button.type = 'button';
+ button.id = 'dropdownSerial';
+ button.setAttribute('data-toggle', 'dropdown');
+ button.setAttribute('aria-haspopup', 'true');
+ button.setAttribute('aria-expanded', 'true');
+
+ let text = document.createTextNode('Serials');
+
+ let span = document.createElement('span');
+ span.className = 'caret';
+ span.style = 'margin-left: .5em';
+
+ let ul = document.createElement('ul');
+ ul.id = 'pl-serial-menu';
+ ul.className = 'dropdown-menu';
+ ul.setAttribute('aria-labelledby', 'dropdownSerial');
+
+ serials.forEach(item => {
+ let li = document.createElement('li');
+ let a = document.createElement('a');
+ a.href = '#';
+ a.innerText = item.title;
+ a.onclick = function() {
+ text.nodeValue = item.title;
+ setTitle(item.title);
+
+ if (lastActiveSerialItem) {
+ lastActiveSerialItem.classList.remove('active');
+ }
+ li.classList.add('active');
+ lastActiveSerialItem = li;
+
+ setSource(item.file);
+
+ return false;
+ }
+
+ li.appendChild(a);
+ ul.appendChild(li);
+ });
+
+ button.appendChild(text);
+ button.appendChild(span);
+ div.appendChild(button);
+ div.appendChild(ul);
+
+ return div;
+ }
+
+ function createSeasonMenuElement(seasons) {
+ let div = document.createElement('div');
+ div.id = 'pl-season';
+ div.className = 'dropdown';
+ div.style = 'display: inline-block';
+ div.kspSerialMenuElement = undefined;
+
+ let button = document.createElement('button');
+ button.className = 'btn btn-default dropdown-toggle';
+ button.type = 'button';
+ button.id = 'dropdownSeason';
+ button.setAttribute('data-toggle', 'dropdown');
+ button.setAttribute('aria-haspopup', 'true');
+ button.setAttribute('aria-expanded', 'true');
+
+ let text = document.createTextNode('Seasons');
+
+ let span = document.createElement('span');
+ span.className = 'caret';
+ span.style = 'margin-left: .5em';
+
+ let ul = document.createElement('ul');
+ ul.id = 'pl-season-menu';
+ ul.className = 'dropdown-menu';
+ ul.setAttribute('aria-labelledby', 'dropdownSeason');
+
+ seasons.forEach((item, idx) => {
+ let li = document.createElement('li');
+ let a = document.createElement('a');
+ a.href = '#';
+ a.innerText = item.title;
+ a.setAttribute('data-number', idx);
+ a.onclick = function() {
+ text.nodeValue = item.title;
+
+ if (lastActiveSeasonItem) {
+ lastActiveSeasonItem.classList.remove('active');
+ }
+ li.classList.add('active');
+ lastActiveSeasonItem = li;
+
+ if (div.kspSerialMenuElement) {
+ containerElement.removeChild(div.kspSerialMenuElement);
+ }
+ containerElement.insertAfter(seasonSerials[idx], div);
+ div.kspSerialMenuElement = seasonSerials[idx];
+
+ return false;
+ }
+
+ seasonSerials.push(createSerialMenuElement(item.serials));
+ li.appendChild(a);
+ ul.appendChild(li);
+ });
+
+ button.appendChild(text);
+ button.appendChild(span);
+ div.appendChild(button);
+ div.appendChild(ul);
+
+ return div;
+ }
+
+ function initTitleElement() {
+ titleElement = document.createElement('h2');
+ titleElement.id = 'title';
+ }
+
+ function createVideoElement() {
+ let videoElement = document.createElement('video');
+ videoElement.id = 'player';
+ videoElement.className = 'center-block';
+ videoElement.setAttribute('controls', 'controls');
+ videoElement.setAttribute('preload', 'none');
+
+ if (videoElement.requestFullscreen) {
+ videoElement.kspFullScreen = videoElement.requestFullscreen;
+ } else if (videoElement.mozRequestFullScreen) {
+ videoElement.kspFullScreen = videoElement.mozRequestFullScreen; // Firefox
+ } else if (videoElement.webkitRequestFullscreen) {
+ videoElement.kspFullScreen = videoElement.webkitRequestFullscreen; // Chrome and Safari
+ } else {
+ console.warn('KSPlayer: can\'t use fullscreen mode =(');
+ videoElement.kspFullScreen = function() { return false; };
+ }
+
+ videoElement.onkeydown = function(e) {
+ // 32 - Space
+ if (e.keyCode === 32) {
+ if (videoElement.paused) {
+ videoElement.play();
+ } else {
+ videoElement.pause();
+ }
+ }
+
+ // 37 - Left arrow
+ if (e.keyCode === 37) {
+ videoElement.currentTime -= 5;
+ }
+ // 39 - Right arrow
+ else if (e.keyCode === 39) {
+ videoElement.currentTime += 5;
+ }
+
+ // 38 - Up arrow
+ if (e.keyCode === 38 && videoElement.volume < 1) {
+ if ((videoElement.volume + 0.1) < 1) {
+ videoElement.volume += 0.1;
+ } else {
+ videoElement.volume = 1;
+ }
+ }
+ // 40 - Down arrow
+ else if (e.keyCode === 40 && videoElement.volume > 0) {
+ if ((videoElement.volume - 0.1) >= 0) {
+ videoElement.volume -= 0.1;
+ } else {
+ videoElement.volume = 0;
+ }
+ }
+
+ // 70 - F
+ if (e.keyCode === 70) {
+ videoElement.kspFullScreen();
+ }
+
+ return false;
+ }
+
+ return videoElement;
+ }
+
+ function setSource(source) {
+ videoElement.src = source;
+ }
+
+ function setTitle(text) {
+ if (text) {
+ if (!titleElement) initTitleElement();
+ titleElement.innerText = text;
+
+ if (!isShowTitle) {
+ containerElement.insertBefore(titleElement, videoElement);
+ isShowTitle = true;
+ }
+ } else {
+ if (isShowTitle && titleElement) {
+ containerElement.removeChild(titleElement);
+ isShowTitle = false;
+ }
+ }
+ }
+
+ /* --- CONSTRUCTOR --------- */
+
+ const containerElement = document.getElementById(containerId);
+ if (containerElement === null) {
+ throw `Container "${containerId}" not found!`;
+ }
+
+ containerElement.insertAfter = function(newChild, refChild) {
+ this.insertBefore(newChild, refChild.nextSibling);
+ }
+
+ let videoElement = createVideoElement();
+
+ if (data.hasOwnProperty('title')) {
+ this.setTitle(data.title);
+ }
+
+ if (data.type === 'simple_serial') {
+ let serialMenu = createSerialMenuElement(data.serials);
+ containerElement.appendChild(serialMenu);
+ containerElement.appendChild(document.createElement('br'));
+ containerElement.appendChild(document.createElement('br'));
+ } else if (data.type === 'seasons_serial') {
+ let seasonMenu = createSeasonMenuElement(data.seasons);
+ containerElement.appendChild(seasonMenu);
+ containerElement.appendChild(document.createElement('br'));
+ containerElement.appendChild(document.createElement('br'));
+ }
+
+ containerElement.appendChild(videoElement);
+}
diff --git a/src/main/resources/kinosearch/webapp/static/js/player.js b/src/main/resources/kinosearch/webapp/static/js/player.js
deleted file mode 100644
index 06065ee..0000000
--- a/src/main/resources/kinosearch/webapp/static/js/player.js
+++ /dev/null
@@ -1,199 +0,0 @@
-const PlayerCore = function(playerObj, titleObj, videoData) {
- this.path = window.location.pathname;
- this.origDocTitle = document.title;
- this.timeLast = 0;
-
- const _this = this;
-
-/* временно отключаю возможность авто-сохранения времени просмотра
- // сохранение времени просмотра
- playerObj.bind('play', function() {
- _this.timeLast = $.now();
- });
-
- playerObj.bind('timeupdate', function() {
- let timeCurrent = $.now();
- let sec = Math.floor((timeCurrent - _this.timeLast)/1000);
- if (sec >= 5) {
- let playerCurrentTime = playerObj[0].currentTime;
- if (Math.floor(playerCurrentTime) <= 10)
- return;
- let save_data = { 'time': playerCurrentTime };
- Cookies.set(_this.path, save_data, { 'expires': 30 });
- _this.timeLast = timeCurrent;
- console.debug({
- 'path': _this.path,
- 'saveTime': save_data
- }); //TODO убрать на продакшене
- }
- });
-*/
- this.getType = function() {
- return videoData.type;
- };
-
- this.setTitle = function(title) {
- if (!title) {
- title = videoData.title;
- }
- document.title = title + " :: " + _this.origDocTitle;
- titleObj.text(title);
- titleObj.show();
- };
-
- this.setupForOneFilm = function() {
- playerObj.attr('src', videoData.file);
- playerObj.load();
- };
-
- this.setupForSimpleSerial = function(serialBlock) {
- let menu = serialBlock.find('.dropdown-menu');
- menu.html('');
- let _self = this;
- videoData.serials.forEach(function(item, i) {
- let aTag = $('', { 'href': '#', 'text': item.title });
- aTag.click(function() {
- _self.setSerial(i, serialBlock);
- });
- let liTag = $('');
- liTag.append(aTag);
- menu.append(liTag);
- });
-
- serialBlock.removeClass('hide');
- };
-
- this.setupForSeasonSerial = function(seasonBlock, serialBlock) {
- let menu = seasonBlock.find('.dropdown-menu');
- menu.html('');
- let _self = this;
- videoData.seasons.forEach(function(item, i) {
- let aTag = $('', { 'href': '#', 'text': item.title });
- aTag.click(function() {
- _self.setSeason(i, seasonBlock, serialBlock);
- });
- let liTag = $('');
- liTag.append(aTag);
- menu.append(liTag);
- });
-
- seasonBlock.removeClass('hide');
- };
-
- this.setSerial = function(idx, serialBlock, sidx) {
- if (!sidx) {
- sidx = 0;
- }
-
- let title;
- let playerSrc;
- if (_this.getType() == 'seasons_serial') {
- title = videoData.seasons[sidx].serials[idx].title;
- playerSrc = videoData.seasons[sidx].serials[idx].file;
- } else {
- title = videoData.serials[idx].title;
- playerSrc = videoData.serials[idx].file;
- }
- _this.setTitle(title);
-
- let menuBtn = serialBlock.find('#dropdownSerial');
- menuBtn.html(title + ' ');
-
- playerObj.attr('src', playerSrc);
- playerObj.attr('data-serial', idx);
- };
-
- this.setTime = function(time) {
- playerObj[0].currentTime = time;
- };
-
- this.load = function() {
- playerObj.load();
- };
-};
-
-function msToTime(ms) {
- function addZ(n) {
- return (n < 10 ? '0' : '') + n;
- }
-
- const _ms = ms % 1000;
- ms = (ms - _ms) / 1000;
- const _sec = ms % 60;
- ms = (ms - _sec) / 60;
- const _min = ms % 60;
- const _hr = (ms - _min) / 60;
-
- return {
- 'sec': addZ(_sec),
- 'min': addZ(_min),
- 'hour': addZ(_hr)
- };
-}
-
-/*
-function loadPlayerCookieData(playerCore) {
- let data = Cookies.getJSON(playerCore.path);
-
- if (data != null) {
- let fulltime = msToTime(data.time * 1000);
- $('#mdl-vtime').text(fulltime.hour + ':' + fulltime.min + ':' + fulltime.sec);
-
- if (playerCore.getType() == 'simple_serial') {
- $('#mdl-serial').find('span').text(data.serial + 1);
- $('#mdl-serial').removeClass('hide');
-
- $('#mdl-btn-yes').click(function() {
- playerCore.setSerial(data.serial, $('#pl-serial'));
-
- playerCore.setTime(data.time);
- playerCore.load();
- });
-
- $('#mdl-btn-no').click(function() {
- playerCore.load();
- });
- } else if (playerCore.getType() == 'seasons_serial') {
- $('#mdl-season').find('span').text(data.season + 1);
- $('#mdl-season').removeClass('hide');
- $('#mdl-serial').find('span').text(data.serial + 1);
- $('#mdl-serial').removeClass('hide');
-
- $('#mdl-btn-yes').click(function() {
- playerCore.setSeason(data.season, $('#pl-season'));
- playerCore.setSerial(data.serial, $('#pl-serial'), data.season);
-
- playerCore.setTime(data.time);
- playerCore.load();
- });
-
- $('#mdl-btn-no').click(function() {
- playerCore.load();
- });
- }
- $('#modal').modal('show');
- }
-}
-*/
-
-function initPlayer(video_data) {
- const playerCore = new PlayerCore($('#player'), $('#title'), video_data);
-
- // загрузка ранее сохранённых данных
- //loadPlayerCookieData(playerCore);
-
- if (playerCore.getType() == 'one_film') {
- playerCore.setTitle();
- playerCore.setupForOneFilm();
- } else if (playerCore.getType() == 'simple_serial') {
- playerCore.setupForSimpleSerial($('#pl-serial'));
- $('#title').hide();
- } else if (playerCore.getType() == 'seasons_serial') {
- playerCore.setupForSeasonSerial($('#pl-season'), $('#pl-serial'));
- $('#title').hide();
- } else {
- console.debug(video_data); //TODO убрать из продакшена
- }
-
- return playerCore;
-}