AutoPlayable = true;
function checkEditorStateVideo($that) {
if (jQuery($that).parents('div[contenteditable]').attr('contenteditable') == 'false') {
let hasBeenAnimated = false;
jQuery(window).scroll(function() {
if (jQuery($that).isInViewportVideo($that) && !hasBeenAnimated) {
hasBeenAnimated = true;
$that.dispatchEvent(new CustomEvent('click'));
}
});
window.dispatchEvent(new CustomEvent('scroll'));
}
}
jQuery.fn.isInViewportVideo = function ($that) {
if (typeof jQuery($that)[0] != 'undefined' && jQuery($that)[0].length != 0) {
let elementTop = jQuery($that).offset().top;
let elementBottom = elementTop + jQuery($that).outerHeight();
let viewportTop = jQuery(window).scrollTop();
let viewportBottom = viewportTop + window.innerHeight;
return elementBottom > viewportTop && elementTop < viewportBottom;
}
else return true;
};
class LiteYTEmbed extends HTMLElement {
connectedCallback() {
window.videoApiLoaded = [];
window.videoApiLoaded.youtube = false;
this.videoId = this.getAttribute('videoid');
this.height = jQuery(this).css('height');
this.autoPlay = this.getAttribute('autoplaycheck');
var imageSrc = '';
var $that = this;
if (typeof jQuery(this).attr('data-thumbnail-link') != 'undefined' && jQuery(this).attr('data-thumbnail-link') != 'undefined') {
imageSrc = jQuery(this).attr('data-thumbnail-link');
}
//jQuery(this).empty();
let playBtnEl = this.querySelector('.lty-playbtn');
// A label for the button takes priority over a [playlabel] attribute on the custom-element
this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute('playlabel') || 'Play';
var widget = jQuery('.widget');
widget.each(function () {
var _this = this;
jQuery(_this).children().children().first().find('.insertedImageContainer').each(function() {
if (jQuery(this).parent().prop("tagName") != 'LITE-YOUTUBE' && jQuery(this).parent().prop("tagName") != 'LITE-VIMEO')
jQuery(this).remove();
});
});
if (jQuery(this).find('img').length == 0) {
if (imageSrc == '')
this.innerHTML = `

`;
else this.innerHTML = `
`;
}
// Set up play button, and its visually hidden label
if (!playBtnEl) {
playBtnEl = document.createElement('button');
playBtnEl.type = 'button';
playBtnEl.classList.add('lty-playbtn');
jQuery(this).find('.insertedImageContainer')[0].append(playBtnEl);
}
if (!playBtnEl.textContent) {
const playBtnLabelEl = document.createElement('span');
playBtnLabelEl.className = 'lyt-visually-hidden';
playBtnLabelEl.textContent = this.playLabel;
if (jQuery(this).find('button').length == 0) {
jQuery(this).find('.insertedImageContainer')[0].append(playBtnEl);
playBtnEl.append(playBtnLabelEl);
}
}
if (jQuery(this).find('button').length == 0) {
jQuery(this).find('.insertedImageContainer')[0].append(playBtnEl);
playBtnEl.append(playBtnLabelEl);
}
// On hover (or tap), warm up the TCP connections we're (likely) about to use.
this.addEventListener('pointerover', LiteYTEmbed.warmConnections, {once: true});
this.addEventListener('click', this.addIframe);
if (this.autoPlay == 'true' && jQuery(this).attr('playvideolocation') != 'videoModal'){
setTimeout(function () {
if (jQuery(window).width() >= 782) {
checkEditorStateVideo($that);
}
}, 500);
}
}
static addPrefetch(kind, url, as) {
const linkEl = document.createElement('link');
linkEl.rel = kind;
linkEl.href = url;
if (as) {
linkEl.as = as;
}
document.head.append(linkEl);
}
static warmConnections() {
if (LiteYTEmbed.preconnected) return;
// The iframe document and most of its subresources come right off youtube.com
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube-nocookie.com');
// The botguard script is fetched off from google.com
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com');
// Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling.
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net');
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net');
LiteYTEmbed.preconnected = true;
}
addIframe(e) {
if (this.classList.contains('lyt-activated')) return;
this.style.backgroundImage = '';
e.preventDefault();
this.classList.add('lyt-activated');
const params = new URLSearchParams(this.getAttribute('params') || []);
params.append('autoplay', '1');
//params.append('allow', 'autoplay');
const iframeEl = document.createElement('div');
//iframeEl.width = 560;
//iframeEl.height = 315;
iframeEl.id = 'player'+this.videoId;
//iframeEl.style.padding = jQuery(this).css('padding');
// No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include
//iframeEl.title = this.playLabel;
//iframeEl.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture';
// iframeEl.allowFullscreen = true;
// AFAIK, the encoding here isn't necessary for XSS, but we'll do it only because this is a URL
// https://stackoverflow.com/q/64959723/89484
// iframeEl.src = `https://www.youtube.com/embed/${encodeURIComponent(this.videoId)}?${params.toString()}`;
if (jQuery(this).attr('playvideolocation') == 'videoModal') {
this.classList.remove('lyt-activated');
//iframeEl.style = "aspect-ratio: 16/9;width: 100%;height:auto;border:none;background:black;";
//loadYoutubeVideo(this.videoId);
var YTPlayer = jQuery("lite-youtube[videoid='"+this.videoId+"']").YTPlayer({
videoURL: 'http://youtu.be/'+this.videoId,
containment:jQuery('#siteVideosModal').find('.siteVideosBody'),
mute:true,
autoPlay:true,
loop:false,
ratio:'16/9',
stopMovieOnBlur: false,
});
jQuery('#player'+this.videoId).attr('style', 'width:100%;aspect-ratio:16/9;height:auto;');
jQuery("lite-youtube[videoid='"+this.videoId+"']").show();
jQuery('#siteVideosModal').modal('show');
jQuery('#closeSiteVideosModal').click(function(e) {
YTPlayer.YTPPlayerDestroy();
})
jQuery('#siteVideosModal').on('hidden.bs.modal', function (e) {
YTPlayer.YTPPlayerDestroy();
});
}
else {
jQuery(this).attr('style', jQuery(this).attr('style') + ';height:'+this.height+'!important;');
this.append(iframeEl);
let myPlayer = jQuery("lite-youtube[videoid='"+this.videoId+"']").YTPlayer({
videoURL: 'http://youtu.be/'+this.videoId,
containment:'self',
mute:true,
autoPlay:true,
loop:false,
ratio:'16/9',
stopMovieOnBlur: false,
});
//loadYoutubeVideo(this.videoId);
jQuery('#player'+this.videoId).attr('style', 'padding:'+jQuery(this).css('padding')+';width:100%;height:'+this.height+';aspect-ratio:16/9;');
var _that = this;
setTimeout(function() {
//jQuery(_that).find('img').attr('style', 'display:none;');
}, 1500);
setTimeout(function() {
jQuery(_that).find('button').fadeOut();
jQuery(_that).find('.insertedImageContainer').append('
')
}, 300);
myPlayer.on("YTPReady",function(e){
jQuery(_that).find('img').fadeOut();
});
}
// Set focus for a11y
iframeEl.focus();
}
}
var ytLoaded = false;
function loadYoutubeVideo(videoId) {
window.onYouTubeIframeAPIReady = function() { document.dispatchEvent(new CustomEvent('onYouTubeIframeAPIReady', {})) };
var player;
if(ytLoaded === false) {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
ytLoaded = true;
} else {
player = new YT.Player('player'+videoId, {
height: '400',
width: '600',
videoId: videoId,
playerVars: {
'playsinline': 1,
'autoplay': 1
},
events: {
'onReady': onPlayerReady,
}
});
}
document.addEventListener('onYouTubeIframeAPIReady', function (e) {
player = new YT.Player('player'+videoId, {
height: '400',
width: '600',
videoId: videoId,
playerVars: {
'playsinline': 1,
'autoplay': 1,
'allow': 'autoplay'
},
events: {
'onReady': onPlayerReady,
}
});
}, false);
jQuery('#player'+videoId).attr('style', 'width:100%;');
function onPlayerReady(event) {
player.playVideo();
}
}
// Register custom element
customElements.define('lite-youtube', LiteYTEmbed);
class LiteVimeo extends HTMLElement {
constructor() {
super();
// TODO: support dynamically setting the attribute via attributeChangedCallback
}
connectedCallback() {
// Gotta encode the untrusted value
// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-2---attribute-escape-before-inserting-untrusted-data-into-html-common-attributes
this.videoId = encodeURIComponent(this.getAttribute('videoid'));
this.height = jQuery(this).css('height');
var imageSrc = '';
var $that = this;
this.autoPlay = this.getAttribute('autoplaycheck');
if (typeof jQuery(this).attr('data-thumbnail-link') != 'undefined' && jQuery(this).attr('data-thumbnail-link') != 'undefined') {
imageSrc = jQuery(this).attr('data-thumbnail-link');
}
jQuery(this).empty();
/**
* Lo, the vimeo placeholder image! (aka the thumbnail, poster image, etc)
* We have to use the Vimeo API.
*/
let { width, height } = getThumbnailDimensions(this.getBoundingClientRect());
const devicePixelRatio = window.devicePixelRatio || 1;
width *= devicePixelRatio;
height *= devicePixelRatio;
var widget = jQuery('.widget');
widget.each(function () {
var _this = this;
jQuery(_this).children().children().first().find('.insertedImageContainer').each(function() {
if (jQuery(this).parent().prop("tagName") != 'LITE-YOUTUBE' && jQuery(this).parent().prop("tagName") != 'LITE-VIMEO')
jQuery(this).remove();
});
});
//this.style.backgroundImage = `url("${thumbnailUrl}")`;
if (jQuery(this).find('img').length == 0) {
if (imageSrc == '')
this.innerHTML = `
`;
else this.innerHTML = `
`;
}
const playBtn = document.createElement('button');
playBtn.type = 'button';
playBtn.classList.add('ltv-playbtn');
if (jQuery(this).find('button').length == 0) {
jQuery(this).find('.insertedImageContainer')[0].append(playBtn);
}
jQuery(this).css('background', 'transparent');
// On hover (or tap), warm up the TCP connections we're (likely) about to use.
this.addEventListener('pointerover', LiteVimeo._warmConnections, {
once: true
});
this.addEventListener('click', () => this._addIframe());
if (this.autoPlay == 'true' && jQuery(this).attr('playvideolocation') != 'videoModal'){
setTimeout(function () {
if (jQuery(window).width() >= 782) {
checkEditorStateVideo($that);
}
}, 500);
}
}
static _warmConnections() {
if (LiteVimeo.preconnected) return;
// The iframe document and most of its subresources come right off player.vimeo.com
addPrefetch('preconnect', 'https://player.vimeo.com');
// Images
addPrefetch('preconnect', 'https://i.vimeocdn.com');
// Files .js, .css
addPrefetch('preconnect', 'https://f.vimeocdn.com');
// Metrics
addPrefetch('preconnect', 'https://fresnel.vimeocdn.com');
LiteVimeo.preconnected = true;
}
_addIframe() {
this.classList.add('ltv-activated');
jQuery(this).find('img').css('object-fit','contain')
const iframeHTML = `
`;
if (jQuery(this).attr('playvideolocation') == 'videoModal') {
this.classList.remove('ltv-activated');
const iframeHTML = `
`;
jQuery('#siteVideosModal').find('.siteVideosBody').html(iframeHTML);
jQuery('#siteVideosModal').modal('show');
}
else {
jQuery(this).attr('style', jQuery(this).attr('style') + ';height:'+this.height+'!important;');
this.insertAdjacentHTML('beforeend', iframeHTML);
}
}
}
// Register custome element
customElements.define('lite-vimeo', LiteVimeo);
/**
* Add a to the head
*/
function addPrefetch(kind, url, as) {
const linkElem = document.createElement('link');
linkElem.rel = kind;
linkElem.href = url;
if (as) {
linkElem.as = as;
}
linkElem.crossorigin = true;
document.head.appendChild(linkElem);
}
function canUseWebP() {
var elem = document.createElement('canvas');
if (elem.getContext && elem.getContext('2d')) {
// was able or not to get WebP representation
return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;
}
// very old browser like IE 8, canvas not supported
return false;
}
/**
* Get the thumbnail dimensions to use for a given player size.
*
* @param {Object} options
* @param {number} options.width The width of the player
* @param {number} options.height The height of the player
* @return {Object} The width and height
*/
function getThumbnailDimensions({ width, height }) {
let roundedWidth = width;
let roundedHeight = height;
if (roundedWidth % 320 !== 0) {
roundedWidth = Math.ceil(width / 100) * 100;
roundedHeight = Math.round((roundedWidth / width) * height);
}
return {
width: roundedWidth,
height: roundedHeight
};
}