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; -}