(function($, window){
'use strict';
window.NggTikTokVideo=window.NggTikTokVideo||{};
let linkHandlersInitialized=false;
const galleryIdCache=new Map();
const DEFAULT_DIMENSIONS={ width: 480, height: 854 };
const ASPECT_RATIO=9 / 16;
const MAX_DEPTH=15;
const INIT_DELAY=100;
NggTikTokVideo.getTikTokSettings=(galleryId)=> {
if(!window.ngg_tiktok_gallery_settings){
window.ngg_tiktok_gallery_settings={
global: {
link: '0',
link_target: '0'
}};}
const settings=window.ngg_tiktok_gallery_settings;
const galleryIdStr=galleryId ? String(galleryId):null;
if(galleryIdStr&&settings[`gallery_${galleryIdStr}`]){
const gallerySettings=settings[`gallery_${galleryIdStr}`];
if(gallerySettings&&(gallerySettings.link!==undefined||gallerySettings.link_target!==undefined)){
return {
link: String(gallerySettings.link ?? '0'),
link_target: String(gallerySettings.link_target ?? '0')
};}}
const globalSettings=settings.global||{};
return {
link: String(globalSettings.link||'0'),
link_target: String(globalSettings.link_target||'0')
};};
const findGalleryId=($anchor, imageId)=> {
const cacheKey=imageId||$anchor[0];
const cachedResult=galleryIdCache.get(cacheKey);
if(cachedResult){
return cachedResult;
}
let $galleryContainer=null;
let galleryId=null;
$galleryContainer=$anchor.closest('[data-gallery-id]');
if($galleryContainer.length){
galleryId=$galleryContainer.attr('data-gallery-id')||$galleryContainer.data('gallery-id');
}
if(!galleryId){
$galleryContainer=$anchor.closest('.ngg-galleryoverview, .ngg-imagebrowser, .ngg-slideshow');
if($galleryContainer.length){
galleryId=$galleryContainer.attr('data-gallery-id') ||
$galleryContainer.data('gallery-id') ||
$galleryContainer.attr('data-nextgen-gallery-id') ||
$galleryContainer.data('nextgen-gallery-id');
}}
if(!galleryId){
let $current=$anchor;
let depth=0;
while (depth < MAX_DEPTH&&$current.length){
if($current.is('[data-gallery-id]')){
galleryId=$current.attr('data-gallery-id')||$current.data('gallery-id');
$galleryContainer=$current;
break;
}
const $sibling=$current.siblings('[data-gallery-id]').first();
if($sibling.length){
galleryId=$sibling.attr('data-gallery-id')||$sibling.data('gallery-id');
$galleryContainer=$sibling;
break;
}
$current=$current.parent();
depth++;
}}
if(!galleryId&&imageId){
const $allContainers=$('[data-gallery-id]');
$allContainers.each(function(){
const $container=$(this);
if($container.find($anchor).length > 0){
galleryId=$container.attr('data-gallery-id')||$container.data('gallery-id');
$galleryContainer=$container;
return false;
}});
}
const result={
galleryId: galleryId ? String(galleryId):null,
$galleryContainer
};
galleryIdCache.set(cacheKey, result);
return result;
};
const getTikTokDataFromAnchor=($anchor, imageId)=> {
if(imageId&&window.ngg_tiktok_images?.[imageId]){
return window.ngg_tiktok_images[imageId];
}
const playUrl=$anchor.attr('data-tiktok-play-url');
const shareUrl=$anchor.attr('data-tiktok-share-url');
const embedUrl=$anchor.attr('data-tiktok-embed-url');
if(playUrl||shareUrl||embedUrl){
return {
playUrl: playUrl||'',
shareUrl: shareUrl||'',
embedUrl: embedUrl||''
};}
return null;
};
const handleTikTokLinkClick=(e)=> {
const anchor=e.target.closest('a[data-image-id]');
if(!anchor){
return;
}
const $anchor=$(anchor);
const imageId=$anchor.attr('data-image-id');
const tiktokData=getTikTokDataFromAnchor($anchor, imageId);
if(!tiktokData){
return;
}
const { galleryId }=findGalleryId($anchor, imageId);
const tiktokSettings=NggTikTokVideo.getTikTokSettings(galleryId);
const linkSetting=String(tiktokSettings.link||'0');
const linkTarget=String(tiktokSettings.link_target||'0');
if(linkSetting!=='1'&&linkSetting!=='2'){
return;
}
if(linkSetting==='1'&&!tiktokData.shareUrl){
return;
}
if(linkSetting==='2'&&!tiktokData.embedUrl&&!tiktokData.shareUrl){
return;
}
e.preventDefault();
e.stopPropagation();
const openNewTab=linkTarget==='1'||linkTarget==='_blank';
let targetUrl='';
if(linkSetting==='1'){
targetUrl=tiktokData.shareUrl||'';
}else if(linkSetting==='2'){
targetUrl=tiktokData.embedUrl||tiktokData.shareUrl||'';
}
if(targetUrl){
if(openNewTab){
window.open(targetUrl, '_blank', 'noopener,noreferrer');
}else{
window.location.href=targetUrl;
}}
};
NggTikTokVideo.initLinkHandlers=()=> {
if(linkHandlersInitialized){
return;
}
linkHandlersInitialized=true;
document.addEventListener('click', handleTikTokLinkClick, true);
};
NggTikTokVideo.isTikTokImage=(element)=> {
const $el=$(element);
const $anchor=$el.is('a') ? $el:$el.closest('a');
if($anchor.attr('data-ngg-tiktok-source')==='true'){
return true;
}
const imageId=$anchor.attr('data-image-id');
if(imageId&&window.ngg_tiktok_images?.[imageId]){
const $galleryContainer=$anchor.closest('[data-gallery-id]');
const galleryId=$galleryContainer.length ? $galleryContainer.attr('data-gallery-id'):null;
const settings=NggTikTokVideo.getTikTokSettings(galleryId);
return String(settings.link||'0')==='0';
}
return false;
};
NggTikTokVideo.getTikTokData=(element)=> {
const $el=$(element);
const $anchor=$el.is('a') ? $el:$el.closest('a');
const playUrl=$anchor.attr('data-ngg-tiktok-play-url');
const shareUrl=$anchor.attr('data-ngg-tiktok-share-url');
const embedUrl=$anchor.attr('data-ngg-tiktok-embed-url');
const tiktokId=$anchor.attr('data-ngg-tiktok-id');
if(playUrl||shareUrl||embedUrl){
return {
tiktokId: tiktokId||'',
playUrl: playUrl||'',
shareUrl: shareUrl||'',
embedUrl: embedUrl||'',
linkSetting: '0'
};}
const imageId=$anchor.attr('data-image-id');
if(imageId&&window.ngg_tiktok_images?.[imageId]){
return window.ngg_tiktok_images[imageId];
}
return null;
};
NggTikTokVideo.getVideoUrl=(tiktokData)=> {
if(!tiktokData){
return '';
}
if(tiktokData.playUrl?.length > 0){
return tiktokData.playUrl;
}
if(tiktokData.shareUrl?.length > 0){
return tiktokData.shareUrl;
}
return '';
};
NggTikTokVideo.getEmbedUrl=(tiktokData)=> {
if(!tiktokData){
return '';
}
if(tiktokData.embedUrl){
return tiktokData.embedUrl;
}
if(tiktokData.shareUrl){
const match=tiktokData.shareUrl.match(/video\/(\d+)/);
if(match?.[1]){
return `https://www.tiktok.com/embed/v2/${match[1]}`;
}}
return '';
};
const createErrorMessage=(message)=> {
return $('<div class="ngg-tiktok-error"></div>')
.text(message)
.css({
color: '#fff',
textAlign: 'center',
padding: '20px'
});
};
const createVideoElement=(videoUrl, autoplay, onReady, onError)=> {
const $video=$('<video></video>').attr({
src: videoUrl,
controls: true,
autoplay: autoplay,
playsinline: true,
preload: 'auto'
}).css({
width: '100%',
height: '100%',
objectFit: 'contain'
});
$video.on('loadeddata', ()=> {
onReady($video[0]);
});
$video.on('error', ()=> {
$video.remove();
onError(new Error('Video failed to load'));
});
return $video;
};
NggTikTokVideo.createPlayer=(options={})=> {
const {
tiktokData,
width=DEFAULT_DIMENSIONS.width,
height=DEFAULT_DIMENSIONS.height,
autoplay=true,
onReady=()=> {},
onError=()=> {}}=options;
const $container=$('<div class="ngg-tiktok-video-container"></div>').css({
position: 'relative',
width,
height,
maxWidth: '100%',
maxHeight: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
});
const videoUrl=NggTikTokVideo.getVideoUrl(tiktokData);
if(videoUrl&&videoUrl.includes('tiktokcdn.com')){
const $video=createVideoElement(videoUrl, autoplay, onReady, (error)=> {
$container.append(createErrorMessage('Video failed to load'));
onError(error);
});
$container.append($video);
}else{
$container.append(createErrorMessage('Video not available'));
onError(new Error('No video URL available'));
}
return $container;
};
NggTikTokVideo._createEmbedPlayer=($container, embedUrl, width, height, autoplay, onReady, onError)=> {
$container.empty();
if(!embedUrl){
$container.append(createErrorMessage('Video not available'));
onError(new Error('No embed URL available'));
return;
}
const url=autoplay
? `${embedUrl}${embedUrl.includes('?') ? '&':'?'}autoplay=1`
: embedUrl;
const $iframe=$('<iframe></iframe>').attr({
src: url,
frameborder: '0',
allowfullscreen: true,
allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'
}).css({
width: '100%',
height: '100%',
border: 'none'
});
$iframe.on('load', ()=> {
onReady($iframe[0]);
});
$iframe.on('error', ()=> {
onError(new Error('Failed to load TikTok embed'));
});
$container.append($iframe);
};
NggTikTokVideo.replaceImageWithVideo=(imageElement, options={})=> {
const $image=$(imageElement);
const $anchor=$image.closest('a');
const tiktokData=options.tiktokData||NggTikTokVideo.getTikTokData($anchor);
if(!tiktokData){
return null;
}
const width=options.width||$image.width()||DEFAULT_DIMENSIONS.width;
const height=options.height||$image.height()||DEFAULT_DIMENSIONS.height;
const playerOptions={
...options,
tiktokData,
width,
height
};
const $player=NggTikTokVideo.createPlayer(playerOptions);
$image.replaceWith($player);
return $player;
};
NggTikTokVideo.createLightboxPlayer=(tiktokData, lightboxOptions={})=> {
const {
maxWidth=window.innerWidth * 0.8,
maxHeight=window.innerHeight * 0.9,
onReady,
onError
}=lightboxOptions;
let width, height;
if(maxHeight * ASPECT_RATIO <=maxWidth){
height=maxHeight;
width=height * ASPECT_RATIO;
}else{
width=maxWidth;
height=width / ASPECT_RATIO;
}
return NggTikTokVideo.createPlayer({
tiktokData,
width: Math.round(width),
height: Math.round(height),
autoplay: true,
onReady,
onError
});
};
NggTikTokVideo.destroyPlayer=($container)=> {
if(!$container?.length){
return;
}
const $video=$container.find('video');
if($video.length){
$video[0].pause();
$video.attr('src', '');
}
const $iframe=$container.find('iframe');
if($iframe.length){
$iframe.attr('src', '');
}
$container.remove();
};
$(()=> {
setTimeout(()=> {
NggTikTokVideo.initLinkHandlers();
}, INIT_DELAY);
});
})(jQuery, window);