/*jshint esversion: 6 */ /*jshint sub:true*/ /*globals jQuery, videojs, Mustache, Element*/ /** * esversion:6 * @param {jQuery} $ * @returns {void} */ ; (function ($, window, document, undefined) { if (jQuery) (function ($) { $.fn.extend({ /** * The following optoins can be passed to the videoJS videowall plugin * @param {wallOptions}, default: 'carousel', //carousel,thumb,playlist * @param {slideshow}, default: false, // true,false depending on the video wall mode you selected to load * @param {slideshowDelay},default: 2000, // slideshow delay * @param {videoWallId}, default: "video-wall", //id of the video-wall container * @param {videoWallContainer}: default :'video-wall-container', // class for the video wall container * @param {containerId}, default: 'video-wall-slides', //slides container id * @param {containerClass}, default : "slides-container", // slides container class * @param {helpImproveVideoJS}, default : false, * @param {thumbPageSize}, default : 12, default pagesize for thumbnail view * @param {playlistPageSize}, default : 8, total playlist on a single page for playlist mode * @param {videos}, default : [], videos list in the playlist to be loaded in the playlist mode * @param {playlist}, default : [], playlists for loading in the playlist mode * @param {loadSelectAssets}, default: true, to load the select2 assets internally by plugin or manual use false to load your own version * @param {loadBootstrapAssets}, default : true, to load bootstrap assets internally by plugin itself, use false to provide your own files * @param {bootstrapCssSource}, default : '//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', source to be loaded * by the plugin internally for the bootstrap css, you can provide you own custom version. * @param {bootstrapJsSource}, default : '//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', source to be loaded * by the plugin internally for the bootstrap js, you can provide you own custom version. * @param {select2CssSource}, default : '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css', source to be loaded * by the plugin internally for the select2 plugin css, you can provide you own custom version. * @param {select2JsSource}, default : '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css',source to be loaded * by the plugin internally for the select2 plugin javascript, you can provide you own custom version. * @param {openOnStart}, default : true, if the plugin should start with the wall opened * @param {callback}, default : () => {}, the callback function to be called after the plugin has loaded completely * @returns {void} */ idowsVideowall: function (params) { "use strict"; let elemId, $this, playAll; let loopList = {}; //merge defaults let options = $.extend({}, $.fn.idowsVideowall.defaults, params); /** * @description DOM Element prototype for the library * @param {attributes} , HTMLElement attributes to be set */ Element.prototype.setAttributes = function (attributes) { for (var attributeName in attributes) { let isHTML = attributeName === 'html'; if (isHTML) { this.innerHTML = attributes[attributeName]; } else { this.setAttribute(attributeName, attributes[attributeName]); } } }; this.triggerEvent = (event, params) => { $this.trigger(event, params); }; /** * @description ,main function that initializes the plugin depending on the selected options * and loads the necessary css and js files if selected to be * loaded internally by plugin configurations/options. */ this.init = () => { //optimize video js if (!options.helpImproveVideoJS) window.HELP_IMPROVE_VIDEOJS = false; let player = $this.dependencyCheck(); let walltypes = { 'carousel': () => { //add carousel to videojs player $this.addCarousel({ player: player, videos: options.videos, elem: elemId, }); }, 'thumb': () => { $this.addThumbWall({ player: player, videos: options.videos, elem: elemId, }); }, 'playlist': () => { $this.addPlaylist({ player: player, playlists: options.playlists, elem: elemId, }); } }; if (walltypes.hasOwnProperty(options.wallType)) walltypes[options.wallType].call(this); //add video wall bar $this.bindWallbarController({ player: player, }); if (options.openOnStart) $this.toggleWall({ player: player }); //handle playback end event and play-all event for the playlist mode player.on('ended', function (e) { let isMorePlaylistItems = playAll && !$.isEmptyObject(loopList); if (isMorePlaylistItems) { let nextVideo = $.fn.findNextVideo(loopList); if (nextVideo) { loopList[nextVideo].isActive = true; loopList[parseInt(nextVideo - 1)].isActive = false; return $this.playVideo({ title: loopList[nextVideo].title, player: player, mime: loopList[nextVideo].mime, src: loopList[nextVideo].src }); } else { $this.triggerEvent('onPlaylistEnd', { playlist: loopList }); } } player.exitFullscreen(); player.hasStarted(false); $('#' + elemId + '-' + options.videoWallId).stop(true, true).slideToggle(); }); }; /** * @description checks for pre-reqs and options required to run the plugin correctly * @returns {VideoJs Element} player */ this.dependencyCheck = () => { //check if pre-reqs are available let player = videojs(elemId); let isNotVideoJs = typeof player === 'undefined'; let isNotPlaylist = typeof options.playlists !== 'object'; if (isNotVideoJs) { console.log('videojs object not initialized, you must include the script after the video js script and make sure the video js plugin is initialized'); return false; } if (options.wallType === 'playlist' && isNotPlaylist) { throw new Error('You need to provide the playlist object to initialize the paylist.'); } if (options.loadBootstrapAssets) { let loadBootstrapCss = options.bootstrapCssSource !== false && !$.fn.AssetLoaded({ file: options.bootstrapCssSource, type: 'link' }); //load css file for bootstrap if (loadBootstrapCss) { //load css style sheet let stylesheet = document.createElement('link'); $(stylesheet).attr({ rel: "stylesheet", type: "text/css", href: options.bootstrapCssSource, integrity: "sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u", crossorigin: "anonymous" }).prependTo("head"); } let loadBootstrapJs = options.bootstrapJsSource !== false && !$.fn.AssetLoaded({ file: options.bootstrapJsSource, type: 'script' }); //load js file for bootstrap if (loadBootstrapJs) { $.getScript(options.bootstrapJsSource, function (data, textStatus, jqxhr) { let statusOk = jqxhr.status === 200; //videojs.options.flash.swf = 'http://tinyii.my/js/tinymce/plugins/idowsfilemanager/js/video-js.swf'; if (!statusOk) { throw new Error('Could not load bootstrap js source specified make sure the internet is connected if you are using default options for loading the sources or provide local source otherwise.'); } }); } } let isThumbView = options.wallType === 'thumb' && options.loadSelectAssets; //check if thuimbview called if (isThumbView) { let loadSelect2Css = options.select2CssSource !== false && !$.fn.AssetLoaded({ file: options.select2CssSource, type: 'link' }); //check if select2 css loaded if (loadSelect2Css) { let selectTheme = document.createElement('link'); $(selectTheme).attr({ rel: "stylesheet", type: "text/css", href: options.select2CssSource, }).appendTo("head"); } } return player; }; /** * @description Create A New HTMLElement * @param {elementType} params.elementType, the type of element to be created * @param {attributes} params.attributes, the attributes for the HTMLElement to be created * @returns {element}, HTMLElementObject */ this.createHtmlElement = (params) => { let $d = document; let element = $d.createElement(params.elementType); element.setAttributes(params.attributes); return element; }; /** * @description, Adds containers for the video wall * @param {elem}, parent HTMLElement wrapper for the containers */ this.addContainers = (elem) => { //video wall main container $this.addMainContainer(elem); //thumbs container let videothumbContainer = $this.createHtmlElement({ elementType: 'div', attributes: { id: elemId + '-' + options.containerId, class: options.containerClass } }); $('#' + elemId + '-' + options.videoWallId).append(videothumbContainer); }; /** * @description ,Adds main video wall container div element * @param {elem} , Wrapper HTMLElement for the main container */ this.addMainContainer = (elem) => { //video wall container let wallContainer = $this.createHtmlElement({ elementType: 'div', attributes: { id: elemId + '-' + options.videoWallId, class: options.videoWallContainer, style: 'display:none;width:' + $($this).width() + 'px;height:' + $($this).height() + 'px' } }); $("#" + elem).append(wallContainer); }; /** * @description ,Add Slide Thumbs for the slider * @param {counter} params.counter, the counter for the curernt page * @param {poster} params.poster, the poster of the video for the wall (Carousel Mode) * @returns {HTMLElementObject} */ this.addWallSlideThumb = (params) => { return $this.createHtmlElement({ elementType: 'div', attributes: { id: elemId + '-slide-' + params.counter, class: 'wall-slide mode-' + options.wallType + ' ' + ((params.counter === 0) ? 'active' : ''), style: 'background:url(' + params.poster + '); background-size:cover; background-repeat:no-repeat;top:0' }, }); }; /** * @description , binds the play button functionality * @param {wrapper} params.wrapper, the wrapper HTMLElement to bind the click function * @param {videoParams} params.videoParams, the video params to be loaded into the videoJS tag */ this.bindPlayVideo = (params) => { //load video on play $(params.wrapper).on('click', function (e) { loopList = {}; playAll = 0; $this.playVideo(params.videoParams); }); }; /** * @description , Plays the video passed to the function * @param {player} params.player , player object videoJS * @param {mime} params.mime, mime type for the video * @param {poster} params.poster, the poster image to be loaded in the videoJS player */ this.playVideo = (params) => { let player = params.player; //trigger before playback event $this.triggerEvent('onBeforePlayback', { title: params.title, mime: params.mime, player: params.player, src: params.src }); $('#' + elemId + '-' + options.videoWallId).stop(true, true).slideUp('slow', function () { $('#' + elemId).hide(); player.pause(); player.src({ type: params.mime, src: params.src }); // load the new sources player.load(); $('#' + elemId).show(); player.play(); }); //trigger before playback event $this.triggerEvent('onAfterPlayback', { title: params.title, mime: params.mime, player: params.player, src: params.src }); }; /** * @description ,Slides a slide to right * @returns {void} */ this.slideRight = () => { $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active').removeClass('active').next().addClass('active'); $("#" + elemId + '-' + options.containerId + " > .wall-slide").stop(true, true, true).animate({ right: '+=' + $('#' + elemId).width() }, 500, 'linear'); }; /** * @description ,Slides a slide to left * @returns {void} */ this.slideLeft = () => { $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active').removeClass('active').prev().addClass('active'); $("#" + elemId + "-" + options.containerId + ">.wall-slide").stop(true, true, true).animate({ right: '-=' + $('#' + elemId).width() }, 500, 'linear'); }; /** * @description , Create Navigation for the video wall * to navigate between the pages left and right * @returns {void} */ this.addNavigation = () => { let arrowRight = $this.createHtmlElement({ elementType: "a", attributes: { id: elemId + '-arrow-right', class: 'fa fa-chevron-circle-right' } }); //bind slide right on click arrow right $(arrowRight).on('click', function (e) { e.preventDefault(); let curSlide = $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active'); let nextSlide = curSlide.next(); let hasNextSlide = nextSlide.length; if (hasNextSlide) { $this.triggerEvent('onBeforeNext', { nextSlide: nextSlide, currentSlide: curSlide }); $this.slideRight(); $this.triggerEvent('onAfterNext', { previousSlide: curSlide, currentSlide: nextSlide }); } }).appendTo('#' + elemId + '-' + options.videoWallId); //add navigation arrow left let arrowLeft = $this.createHtmlElement({ elementType: "a", attributes: { id: elemId + '-arrow-left', class: 'fa fa-chevron-circle-left' } }); //bind slide right on click arrow left $(arrowLeft).on('click', function (e) { e.preventDefault(); let curSlide = $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active'); let prevSlide = curSlide.prev(); let hasPrevSlide = prevSlide.length; if (hasPrevSlide) { $this.triggerEvent('onBeforePrev', { nextSlide: prevSlide, currentSlide: curSlide }); $this.slideLeft(); $this.triggerEvent('onAfterPrev', { currentSlide: prevSlide, previousSlide: curSlide }); } }).appendTo('#' + elemId + '-' + options.videoWallId); }; /** * @description , Adds Keyboard bindings for the left right keys * @returns {void} */ this.addKeyboardNavigation = () => { let keyboardBindings = { ArrowLeft: (e) => { let curSlide = $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active'); let prevSlide = curSlide.prev(); let hasPrevSlide = prevSlide.length; if (hasPrevSlide) { $this.triggerEvent('onBeforePrev', { nextSlide: prevSlide, currentSlide: curSlide }); $this.slideLeft(); $this.triggerEvent('onAfterPrev', { currentSlide: prevSlide, previousSlide: curSlide }); } }, ArrowRight: (e) => { let curSlide = $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active'); let nextSlide = curSlide.next(); let hasNextSlide = $('#' + elemId + '-' + options.containerId + '.' + options.containerClass).find('div.active').next().length; if (hasNextSlide) { $this.triggerEvent('onBeforeNext', { nextSlide: nextSlide, currentSlide: curSlide }); $this.slideRight(); $this.triggerEvent('onAfterNext', { previousSlide: curSlide, currentSlide: nextSlide }); } }, Enter: (e) => { $('#' + elemId + '-' + options.containerId + ' > .wall-slide.active>.play-wrapper>i').trigger('click'); } }; //bind mouseover element for binding keyboard navigation to active wall only $('#' + elemId + '-' + options.videoWallId).on('mouseover', function (e) { document.onkeydown = function (e) { let wallVisible = $('#' + elemId + '-' + options.videoWallId + ":visible").length; if (wallVisible) { if (keyboardBindings.hasOwnProperty(e.key)) keyboardBindings[e.key].call(this, e); } }; }); //Firefox $('#' + elemId + '-' + options.videoWallId).bind('DOMMouseScroll', function (e) { let wallVisible = $('#' + elemId + '-' + options.videoWallId + ":visible").length; let scrollEnabled = !!$(this).find('.card').filter(function () { return $(this).is(":hover"); }).length; if (wallVisible && !scrollEnabled) { e.preventDefault(); if (e.detail > 0) { //scroll down if (keyboardBindings.hasOwnProperty('ArrowRight')) keyboardBindings.ArrowRight.call(this, e); } else { //scroll up if (keyboardBindings.hasOwnProperty('ArrowLeft')) keyboardBindings.ArrowLeft.call(this, e); } } }); // Detect IE version var iev = 0; var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent)); var trident = !!navigator.userAgent.match(/Trident\/7.0/); var rv = navigator.userAgent.indexOf("rv:11.0"); if (ieold) iev = new Number(RegExp.$1); if (navigator.appVersion.indexOf("MSIE 10") != -1) iev = 10; if (trident && rv != -1) iev = 11; // IE 11 let isIE11 = typeof InstallTrigger !== 'undefined' || iev == 11; if (isIE11) { var lastScrollTop = 0; $('#' + elemId + '-' + options.videoWallId).on('scroll', function (e) { let scrollEnabled = !!$(this).find('.card').filter(function () { return $(this).is(":hover"); }).length; let wallVisible = $('#' + elemId + '-' + options.videoWallId + ":visible").length; let st = $(this).scrollTop(); if (wallVisible && !scrollEnabled) { e.preventDefault(); if (st < lastScrollTop) { if (keyboardBindings.hasOwnProperty('ArrowLeft')) keyboardBindings['ArrowLeft'].call(this, e); } else if (st > lastScrollTop) { if (keyboardBindings.hasOwnProperty('ArrowRight')) keyboardBindings['ArrowRight'].call(this, e); } } lastScrollTop = st; }); } // Chrome else { $('#' + elemId + '-' + options.videoWallId).on('mousewheel', function (e) { let wallVisible = $('#' + elemId + '-' + options.videoWallId + ":visible").length; let scrollEnabled = !!$(this).find('.card').filter(function () { return $(this).is(":hover"); }).length; if (wallVisible && !scrollEnabled) { e.preventDefault(); if (e.originalEvent.wheelDelta > 0) { if (keyboardBindings.hasOwnProperty('ArrowLeft')) keyboardBindings['ArrowLeft'].call(this, e); } else if (e.originalEvent.wheelDelta < 0) { if (keyboardBindings.hasOwnProperty('ArrowRight')) keyboardBindings['ArrowRight'].call(this, e); } } }); } }; /** * @description ,Creates the playlist view for the player * @param {elem} params.elem, HTMLElement wrapper element to inject the containers * @param {playlists} params.playlists, the playlists to be loaded inside the videowall * @param {player} params.player, VideoJS player object */ this.addPlaylist = (params) => { //add containers $this.addContainers(params.elem); //create document fragment let fragment = document.createDocumentFragment(); let playlists = params.playlists; //calculate total slides let totalSlides = Math.ceil(playlists.length / options.playlistPageSize); //scope the local functions for use inside the loop let addThumbFunc = $this.addWallSlideThumb; let addElementFunc = $this.createHtmlElement; let bindPlayAllFunc = $this.bindPlayAll; let bindPlayFunc = $this.bindPlayVideo; //end scope the local functions for use inside the loop for (var i = 0; i < totalSlides; i++) { //create wall thumb slide let wallThumbSlide = addThumbFunc({ poster: '', counter: i }); //iterate the playlists and create pages depending on the pagesize for the playlist mode for (var key = options.playlistPageSize * i; (key < options.playlistPageSize * (i + 1) && key < playlists.length); key++) { let playlistCardId = elemId + '-playlist-card-' + key; let playlistHeaderId = elemId + '-playlist-header-' + key; let playlistTemplate = $.fn.getTemplate('playlist'); //playlist params let playlistName = playlists[key].name; let totalVideos = playlists[key].videos.length; let cover = playlists[key].cover; let videos = playlists[key].videos; //atributes for the card HTMLElement let attributes = { playlistHeaderId: playlistHeaderId, playlistName: playlistName, videoCount: totalVideos, cover: cover }; //creates a playlistcard element let playlistCard = addElementFunc({ elementType: 'div', attributes: { class: 'card playlist-card', id: playlistCardId, } }); //add playlist template playlistCard.innerHTML = Mustache.render(playlistTemplate, attributes); //append the playlist card to the current selected slide / page wallThumbSlide.appendChild(playlistCard); //append to the document fragment fragment.appendChild(wallThumbSlide); //get the playlist body and header objects from document fragment let playlistBody = fragment.querySelector('#' + playlistCardId + ' .playlist-body'); let playlistHeader = fragment.querySelector('#' + playlistCardId + ' .playlist-header'); //bind the playall function for the playlist bindPlayAllFunc({ button: playlistHeader.querySelector('button'), playlist: playlists[key].videos, playlistId: key, player: params.player }); //loop through the videos and add them to the current playlist card for (var video in videos) { if (videos.hasOwnProperty(video)) { //get the video params let src = videos[video].src; let poster = videos[video].poster; let mime = videos[video].mime; let title = videos[video].title; //get the template for the songlist let songlist = $.fn.getTemplate('songlist'); //prepare song list data to be parsed let songData = { playlistSongId: playlistCardId + '-song-list-' + video, poster: poster, songTitle: title }; //get the rendered html from the template for the songlist let songlistHtml = Mustache.render(songlist, songData); //the songlist wrapper element let songWrapper = addElementFunc({ elementType: 'div' }); //insert the songlist to the wrapper songWrapper.innerHTML = songlistHtml; //append as child to the playlistBody playlistBody.appendChild(songWrapper.firstChild); //get the play button object let playButton = playlistBody.querySelector('#' + playlistCardId + '-song-list-' + video + '>.control>.play-wrapper-playlist'); //bind the play button with the play functionality bindPlayFunc({ wrapper: playButton, videoParams: { player: params.player, mime: mime, src: src } }); } } } } if (totalSlides > 1) { //add navigation arrow right $this.addNavigation(); //bind arrow key left and right to the slide show $this.addKeyboardNavigation(); } //append the thumbnails to the wall container document.querySelector('#' + elemId + '-' + options.containerId).appendChild(fragment); }; /** * @description , the playAll functionality for the "playlist" mode * @param {button} params.button, the button object to bind the playall functionality * @param {playlist} params.playlist , the videos list in the playlist to be played * @param {player} params.player, the VideoJS player object */ this.bindPlayAll = (params) => { $(params.button).on('click', function (e) { playAll = 1; loopList = params.playlist.map(function (video, index) { var videos = Object.assign({}, video); videos.isActive = !index ? true : false; return videos; }); $this.triggerEvent('onPlaylistStart', { playlist: loopList }); $this.playVideo({ title: params.playlist[0].title, player: params.player, mime: params.playlist[0].mime, src: params.playlist[0].src }); }); }; /** * @description Adds the carousel for the video wall * @param {elem} params.elem , HTMLElement wrapper element to inject the containers * @param {videos} params.videos, the playlists to be loaded inside the videowall * @param {player} params.player, VideoJS player object */ this.addCarousel = (params) => { //add containers $this.addContainers(params.elem); //create document fragment let fragment = document.createDocumentFragment(); //local scope functions let addElementFunc = $this.createHtmlElement; let MustacheRenderFunc = Mustache.render; //create wall thumbs slider for (var key in params.videos) { if (params.videos.hasOwnProperty(key)) { let src = params.videos[key].src; let poster = params.videos[key].poster; let mime = params.videos[key].mime; let title = params.videos[key].title; let carouselTemplate = $.fn.getTemplate('carousel'); let attributes = { slide_id: elemId + '-slide-' + parseInt(key), mode: options.wallType, status: ((parseInt(key) === 0) ? 'active' : ''), poster: poster, title: title }; let temp = addElementFunc({ elementType: 'div', attributes: { html: MustacheRenderFunc(carouselTemplate, attributes) } }); fragment.appendChild(temp.firstChild); } } //appends the document fragment as a child to the document container document.querySelector('#' + elemId + '-' + options.containerId).appendChild(fragment); //add navigation arrow right $this.addNavigation(); //bind arrow key left and right to the slide show $this.addKeyboardNavigation(); }; /** * @description creates a thumbnail wall for the videos * @param {elem} params.elem, HTMLElement wrapper element to inject the containers * @param {videos} params.videos, the videos to be loaded inside the video wall * @param {player} params.player, VideoJS player object * */ this.addThumbWall = (params) => { //add contianer divs $this.addContainers(params.elem); //create document fragment to create and attach elements on runtime let fragment = document.createDocumentFragment(); //add filter input to search available videos $this.createFilterInput(); //calculate total slides let totalSlides = Math.ceil(params.videos.length / options.thumbPageSize); //local scope functions for sue in loop let addSlideFunc = $this.addWallSlideThumb; let getTemplateFunc = $.fn.getTemplate; let addElementFunc = $this.createHtmlElement; let bindPlayVideo = $this.bindPlayVideo; let MustacheRenderFunc = Mustache.render; for (var i = 0; i < totalSlides; i++) { //create wall thumb slide let wallThumbSlide = addSlideFunc({ poster: '', counter: parseInt(i) }); //append slide to fragment fragment.appendChild(wallThumbSlide); //iterate videos list and create thumbnails for (var key = options.thumbPageSize * i; (key < options.thumbPageSize * (i + 1) && key < params.videos.length); key++) { let src = params.videos[key].src; let poster = params.videos[key].poster; let mime = params.videos[key].mime; let title = params.videos[key].title; let thumbnailTemplate = getTemplateFunc('thumbnail'); let attributes = { thumb_id: elemId + '-video-thumb-' + key, poster: poster, video_title: title, data_title: title, }; //add playlist template let temp = $this.createHtmlElement({ elementType: 'div', attributes: { html: MustacheRenderFunc(thumbnailTemplate, attributes) } }); fragment.querySelector('#' + elemId + '-slide-' + i).appendChild(temp.firstChild); bindPlayVideo({ wrapper: fragment.querySelector('#' + attributes.thumb_id + '> .play-wrapper-thumbnail'), videoParams: { title: title, player: params.player, src: src, mime: mime } }); } } if (totalSlides > 1) { //add navigation arrow right $this.addNavigation(); //bind arrow key left and right to the slide show $this.addKeyboardNavigation(); } //append the thumbnails to the wall container document.querySelector('#' + elemId + '-' + options.containerId).appendChild(fragment); }; /** * @description ,Adds Wall controller bar * @param {player} params.player , the VideoJS player Object * @returns {void} */ this.bindWallbarController = (params) => { let wallbar = $this.createWallBar(); wallbar.on('click', function () { $this.toggleWall(params); }); }; /** * @description ,slideToggle the video wall * @param {player} params.player , the VideoJS player Object */ this.toggleWall = (params) => { $('#' + elemId + '-' + options.videoWallId).stop(true, true).slideToggle('slow'); params.player.pause(); }; /** * @description ,Creates a Wall Bar controller element * @returns {HTMLElementObject} wallbar */ this.createWallBar = () => { let wallbar = $this.createHtmlElement({ elementType: 'div', attributes: { id: elemId + '-wall-control', class: 'wall-bar', html: '', style: 'width:' + $($this).width() + 'px;' } }); return $(wallbar).insertAfter("#" + elemId); }; /** * @description creates a filter input for the video search */ this.createFilterInput = () => { (options.select2JsSource !== false && options.loadSelectAssets) ? //load script file $.getScript(options.select2JsSource, function (data, textStatus, jqxhr) { let statusOk = jqxhr.status === 200; (statusOk) && $this.bindSelect2Sources(); }): $this.bindSelect2Sources(); }; /** * @description creates the select2 input for the search filter video. * @returns {undefined} */ this.bindSelect2Sources = () => { let html = '
' + '' + '
'; let range = document.createElement('div'); range.innerHTML = html; document.querySelector('#' + elemId + '-' + options.videoWallId).insertBefore(range.firstChild, document.querySelector('#' + elemId + '-' + options.containerId)); $("#" + elemId + "-filter").select2({ "allowClear": true, // "closeOnSelect": false, "theme": "default", "width": "100%", "placeholder": "Search Videos", 'minimumInputLength': 2, "dropdownCssClass": 'bigdrop', "templateResult": function (video) { if (!video.id) { return video.text; } var $video = $( '

' + video.text + 'Select to play the file

' ); return $video; }, "templateSelection": function (video) { if (!video.id) { return video.text; } var $video = $( '

  Playing Now ' + video.text + '

' ); return $video; } }).on('select2:select', function (e) { e.preventDefault(); var data = e.params.data; $('#' + data.id + ' >.play-wrapper-thumbnail').trigger('click'); }); //populate select2 data $("#" + elemId + "-filter").refreshFilterResults($this.filteredData()); }; /** * @description Formats files list as Select2 Data * @returns {data} JSON */ this.filteredData = () => { let filterableFiles = $('#' + elemId + '-' + options.videoWallId + ' div.thumb-title'); let data = [{ "id": '', "text": 'Search Files', "href": '', "cover": '' }]; for (var i = 0; i < filterableFiles.length; i++) { let elementRef = $(filterableFiles[i]); let filename = elementRef.data('title'); let cover = elementRef.parent().css('background-image'); let bi = cover.slice(4, -1); let elementId = elementRef.parent().prop('id'); // For IE we need to remove quotes to the proper url bi = cover.slice(4, -1).replace(/"/g, ""); data.push({ "id": elementId, "text": filename, "cover": bi, "href": elementId }); } return data; }; elemId = $(this).prop('id'); $this = this; $this.init(); options.callback.call(this); return $this; } }); //set default options $.fn.idowsVideowall.defaults = { wallOptions: 'carousel', //slide,thumb,playlist slideshowDelay: 2000, // slideshow delay videoWallId: "video-wall", //id of the video-wall container videoWallContainer: 'video-wall-container', // class for the video wall container containerId: 'video-wall-slides', //slides container id containerClass: "slides-container", // slides container class helpImproveVideoJS: false, thumbPageSize: 15, playlistPageSize: 8, videos: [], playlists: [], loadSelectAssets: true, loadBootstrapAssets: true, bootstrapCssSource: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', bootstrapJsSource: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', select2CssSource: '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css', select2JsSource: '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.full.min.js', openOnStart: true, callback: () => {}, }; /** * @description ,Returns template for the selected templateSelection * @param {template} , the name of the template to be retrieved */ $.fn.getTemplate = (template) => { let templateSelection = { playlist: () => { return [ '', '
', '', '{{playlistName}}', '
', '', '
', '{{videoCount}} ', '
', '', '
', '
', '', '
', '
', '
', '
', ].join("\n"); }, songlist: () => { return [ '
', '', '', '', '', '', '{{songTitle}}', '
', ].join("\n"); }, thumbnail: () => { return [ '
', '
{{video_title}}
', '
', '', '
', '
', ].join("\n"); }, carousel: () => { return [ '
', '
{{title}}
', '
', '', '
', '
' ].join("\n"); } }; if (templateSelection.hasOwnProperty(template)) { return templateSelection[template].call(this); } }; /** *@description determines if the script or css files were actually loaded *@param {file},the file path to be loaded could be loacal or live cdn *@param {type}, the type of file script or css *@returns {true|false}, returns true or false if loaded or loaded */ $.fn.AssetLoaded = (params) => { if (params.type === 'script') { var scripts = document.getElementsByTagName("script"); for (let i = 0; i < scripts.length; i++) { if (scripts[i].src.substr(-params.file.length) == params.file) return true; } } else { var links = document.getElementsByTagName("link"); for (let i = 0; i < links.length; i++) { if (links[i].href.substr(-params.file.length) == params.file) return true; } } return false; }; /** * @description finds the next video to be played in the playlist * @param loopList an object for the select playlist with the list of videos * @returns {object|false} returns next video object or false depending on if there is a next video to be played */ $.fn.findNextVideo = (loopList) => { for (let video in loopList) { if (loopList[video].isActive && parseInt(video) < parseInt(Object.keys(loopList).length - 1)) { return parseInt(video) + 1; } } return false; }; /** * @description refreshes the select2 with new data to be replaced with current * @param {data} JSON , the json data to be mapped to the selecte2 */ $.fn.refreshFilterResults = function (data) { this.select2('data', data); // Update options var $select = $(this[0]); var options = data.map(function (item) { return ''; }); $select.html(options.join('')).change(); }; })(jQuery); })(jQuery, window, document);