2017-09-24 01:54:46 +02:00
if ( Debug . debug )
console . log ( "Loading: Resizer.js" ) ;
2018-05-12 02:51:58 +02:00
var StretchMode = {
2018-05-13 21:05:11 +02:00
NO _STRETCH : 0 ,
2018-05-24 23:29:30 +02:00
BASIC : 1 ,
HYBRID : 2 ,
CONDITIONAL : 3
2018-05-12 02:51:58 +02:00
}
2018-05-08 23:35:16 +02:00
class Resizer {
2017-09-24 01:54:46 +02:00
2018-05-12 02:51:58 +02:00
constructor ( videoData ) {
this . conf = videoData ;
2018-05-08 23:35:16 +02:00
this . video = videoData . video ;
2018-08-05 23:48:56 +02:00
this . settings = videoData . settings ;
2018-05-12 02:51:58 +02:00
2018-05-18 23:26:20 +02:00
this . scaler = new Scaler ( this . conf ) ;
this . stretcher = new Stretcher ( this . conf ) ;
this . zoom = new Zoom ( this . conf ) ;
2018-05-12 02:51:58 +02:00
// load up default values
2018-05-13 15:22:28 +02:00
this . correctedVideoDimensions = { } ;
this . currentCss = { } ;
2018-08-21 00:48:15 +02:00
this . currentStyleString = "" ;
this . currentCssValidFor = { } ;
2018-05-12 02:51:58 +02:00
// restore watchdog. While true, applyCss() tries to re-apply new css until this value becomes false again
// value becomes false when width and height of <video> tag match with what we want to set. Only necessary when
// calling _res_restore() for some weird reason.
this . restore _wd = false ;
2018-05-13 15:22:28 +02:00
2018-08-21 00:48:15 +02:00
// CSS watcher will trigger _very_ often for this many iterations
this . cssWatcherIncreasedFrequencyCounter = 0 ;
2018-09-17 00:39:32 +02:00
this . lastAr = this . settings . getDefaultAr ( ) ; // this is the aspect ratio we start with
this . videoFloat = this . settings . getDefaultVideoAlignment ( ) ; // this is initial video alignment
2018-05-16 23:26:47 +02:00
this . destroyed = false ;
2018-08-30 00:56:15 +02:00
this . resizerId = ( Math . random ( 99 ) * 100 ) . toFixed ( 0 ) ;
2018-09-13 23:47:20 +02:00
if ( this . settings . active . pan ) {
2018-09-17 00:39:32 +02:00
console . log ( "can pan:" , this . settings . active . miscFullscreenSettings . mousePan . enabled , "(default:" , this . settings . active . miscFullscreenSettings . mousePan . enabled , ")" )
this . canPan = this . settings . active . miscFullscreenSettings . mousePan . enabled ;
2018-09-13 23:47:20 +02:00
} else {
this . canPan = false ;
}
2017-09-24 01:54:46 +02:00
}
2018-05-23 23:57:51 +02:00
start ( ) {
this . startCssWatcher ( ) ;
}
stop ( ) {
this . stopCssWatcher ( ) ;
}
2018-05-16 23:26:47 +02:00
destroy ( ) {
2018-08-30 00:56:15 +02:00
if ( Debug . debug ) {
console . log ( ` [Resizer::destroy] <rid: ${ this . resizerId } > received destroy command. ` ) ;
}
2018-05-16 23:26:47 +02:00
this . destroyed = true ;
this . stopCssWatcher ( ) ;
}
2018-05-13 15:22:28 +02:00
2018-05-24 23:29:30 +02:00
2018-05-12 02:51:58 +02:00
setAr ( ar , lastAr ) {
2018-08-30 00:56:15 +02:00
if ( this . destroyed ) {
return ;
}
2018-08-21 00:48:15 +02:00
this . startCssWatcher ( ) ;
this . cssWatcherIncreasedFrequencyCounter = 20 ;
2018-05-08 23:35:16 +02:00
if ( Debug . debug ) {
2018-08-30 00:56:15 +02:00
console . log ( '[Resizer::setAr] <rid:' + this . resizerId + '> trying to set ar. New ar:' , ar )
2018-05-08 23:35:16 +02:00
}
2017-09-24 01:54:46 +02:00
2018-05-12 02:51:58 +02:00
if ( lastAr ) {
this . lastAr = lastAr ;
} else {
2018-05-13 15:22:28 +02:00
if ( isNaN ( ar ) ) {
this . lastAr = { type : 'legacy' , ar : ar }
} else {
this . lastAr = { type : 'static' , ar : ar } ;
}
2018-05-12 02:51:58 +02:00
}
2018-05-01 23:09:58 +02:00
2018-05-08 23:35:16 +02:00
if ( ! this . video ) {
2018-05-16 20:26:55 +02:00
// console.log("No video detected.")
2018-05-16 23:26:47 +02:00
this . videoData . destroy ( ) ;
2018-05-08 23:35:16 +02:00
}
2018-05-01 23:09:58 +02:00
2018-07-11 23:13:40 +02:00
// pause AR on basic stretch, unpause when using other mdoes
2018-07-15 16:22:32 +02:00
// fir sine reason unpause doesn't unpause. investigate that later
// if (this.stretcher.mode === StretchMode.BASIC) {
// this.conf.arDetector.pause();
// } else {
// this.conf.arDetector.unpause();
// }
2018-05-16 20:26:55 +02:00
2018-07-11 23:13:40 +02:00
// do stretch thingy
2018-05-30 23:20:23 +02:00
if ( this . stretcher . mode === StretchMode . NO _STRETCH || this . stretcher . mode === StretchMode . CONDITIONAL ) {
2018-05-24 23:29:30 +02:00
var stretchFactors = this . scaler . calculateCrop ( ar ) ;
if ( ! stretchFactors || stretchFactors . error ) {
if ( Debug . debug ) {
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::setAr] <rid:" + this . resizerId + "> failed to set AR due to problem with calculating crop. Error:" , ( stretchFactors ? stretchFactors . error : stretchFactors ) ) ;
2018-05-24 23:29:30 +02:00
}
2018-07-11 00:01:44 +02:00
if ( stretchFactors . error === 'no_video' ) {
2018-05-24 23:29:30 +02:00
this . conf . destroy ( ) ;
}
return ;
2018-05-16 23:26:47 +02:00
}
2018-05-30 23:20:23 +02:00
if ( this . stretcher . mode === StretchMode . CONDITIONAL ) {
2018-05-25 21:37:09 +02:00
this . stretcher . applyConditionalStretch ( stretchFactors , ar ) ;
2018-05-16 20:26:55 +02:00
}
2018-05-30 23:20:23 +02:00
} else if ( this . stretcher . mode === StretchMode . HYBRID ) {
2018-05-24 23:29:30 +02:00
var stretchFactors = this . stretcher . calculateStretch ( ar ) ;
2018-06-15 00:33:10 +02:00
} else if ( this . stretcher . mode === StretchMode . BASIC ) {
var stretchFactors = this . stretcher . calculateBasicStretch ( ) ;
2018-05-16 20:26:55 +02:00
}
2018-05-24 23:29:30 +02:00
this . zoom . applyZoom ( stretchFactors ) ;
2018-05-02 17:52:25 +02:00
2018-05-24 23:29:30 +02:00
//TODO: correct these two
2018-05-25 21:37:09 +02:00
var translate = this . computeOffsets ( stretchFactors ) ;
this . applyCss ( stretchFactors , translate ) ;
2018-05-16 23:26:47 +02:00
2018-07-10 20:36:12 +02:00
}
2018-06-15 00:33:10 +02:00
2018-07-10 20:36:12 +02:00
resetLastAr ( ) {
this . lastAr = { type : 'original' } ;
2018-05-12 02:51:58 +02:00
}
2018-05-02 17:52:25 +02:00
2018-05-14 20:39:15 +02:00
setLastAr ( override ) {
this . lastAr = override ;
}
2018-05-15 21:40:53 +02:00
getLastAr ( ) {
return this . lastAr ;
}
2018-05-13 15:22:28 +02:00
setStretchMode ( stretchMode ) {
2018-05-30 23:20:23 +02:00
this . stretcher . mode = stretchMode ;
2018-05-27 21:41:08 +02:00
this . restore ( ) ;
2018-05-13 15:22:28 +02:00
}
2018-05-02 17:52:25 +02:00
2018-09-13 23:47:20 +02:00
panHandler ( event ) {
// console.log("this.conf.canPan:", this.conf.canPan)
if ( this . canPan ) {
// console.log("event?", event)
// console.log("this?", this)
if ( ! this . conf . player || ! this . conf . player . element ) {
return ;
}
const player = this . conf . player . element ;
const relativeX = ( event . pageX - player . offsetLeft ) / player . offsetWidth ;
const relativeY = ( event . pageY - player . offsetTop ) / player . offsetHeight ;
this . setPan ( relativeX , relativeY ) ;
}
}
2018-05-13 15:22:28 +02:00
setPan ( relativeMousePosX , relativeMousePosY ) {
// relativeMousePos[X|Y] - on scale from 0 to 1, how close is the mouse to player edges.
// use these values: top, left: 0, bottom, right: 1
if ( ! this . pan ) {
this . pan = { } ;
}
2018-02-04 17:39:26 +01:00
2018-09-13 23:47:20 +02:00
this . pan . relativeOffsetX = - ( relativeMousePosX * 1.1 ) + 0.55 ;
this . pan . relativeOffsetY = - ( relativeMousePosY * 1.1 ) + 0.55 ;
// if(Debug.debug){
// console.log("[Resizer::setPan] relative cursor pos:", relativeMousePosX, ",",relativeMousePosY, " | new pan obj:", this.pan)
// }
this . restore ( ) ;
2018-05-13 15:22:28 +02:00
}
2018-05-02 17:52:25 +02:00
2018-05-13 15:22:28 +02:00
startCssWatcher ( ) {
2018-08-30 00:56:15 +02:00
if ( this . destroyed ) {
return ;
}
2018-05-16 23:26:47 +02:00
// this.haltCssWatcher = false;
2018-08-21 00:48:15 +02:00
if ( ! this . cssWatcherTimer ) {
this . scheduleCssWatcher ( 1 ) ;
} else {
clearTimeout ( this . cssWatcherTimer ) ;
this . scheduleCssWatcher ( 1 ) ;
}
}
2018-05-16 23:26:47 +02:00
2018-08-21 00:48:15 +02:00
scheduleCssWatcher ( timeout , force _reset ) {
2018-08-30 00:56:15 +02:00
if ( this . destroyed ) {
return ;
}
2018-08-21 00:48:15 +02:00
if ( timeout === undefined ) {
console . log ( "?" )
this . cssCheck ( ) ; // no timeout = one-off
return ;
}
if ( this . cssWatcherTimeout ) {
clearTimeout ( this . cssWatcherTimer ) ;
2018-05-16 23:26:47 +02:00
}
2018-08-21 00:48:15 +02:00
var ths = this ;
this . cssWatcherTimer = setTimeout ( function ( ) {
ths . cssWatcherTimer = null ;
try {
ths . cssCheck ( ) ;
} catch ( e ) {
if ( Debug . debug ) {
console . log ( "[Resizer.js::scheduleCssWatcher] Css check failed. Error:" , e ) ;
}
}
} , timeout ) ;
2018-05-13 15:22:28 +02:00
}
2017-09-24 01:54:46 +02:00
2018-06-15 00:33:10 +02:00
stopCssWatcher ( ) {
2018-05-16 23:26:47 +02:00
if ( Debug . debug ) console . log ( "[Resizer.js] STOPPING CSS WATCHER!" )
2018-05-13 15:22:28 +02:00
clearInterval ( this . cssWatcherTimeout ) ;
}
2018-05-02 17:52:25 +02:00
2018-06-15 00:33:10 +02:00
restore ( ) {
2018-05-13 15:22:28 +02:00
if ( Debug . debug ) {
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::restore] <rid:" + this . resizerId + "> attempting to restore aspect ratio. this & settings:" , { 'this' : this , "settings" : this . settings } ) ;
2018-05-13 15:22:28 +02:00
}
// this is true until we verify that css has actually been applied
this . restore _wd = true ;
if ( this . lastAr . type === 'original' ) {
this . setAr ( 'reset' ) ;
}
else {
this . setAr ( this . lastAr . ar , this . lastAr )
}
}
2018-05-02 17:52:25 +02:00
2018-05-13 15:22:28 +02:00
reset ( ) {
this . setStretchMode ( StretchMode . NO _STRETCH ) ;
this . zoom . setZoom ( 1 ) ;
this . resetPan ( ) ;
this . setAr ( 'reset' ) ;
2017-09-24 01:54:46 +02:00
}
2018-05-13 15:22:28 +02:00
2018-09-13 23:47:20 +02:00
setPanMode ( mode ) {
if ( mode === 'enable' ) {
this . canPan = true ;
} else if ( mode === 'disable' ) {
this . canPan = false ;
} else if ( mode === 'toggle' ) {
this . canPan = ! this . canPan ;
}
}
2018-05-13 15:22:28 +02:00
resetPan ( ) {
this . pan = undefined ;
2017-09-24 01:54:46 +02:00
}
2018-05-13 15:22:28 +02:00
2018-09-18 23:37:33 +02:00
setZoom ( zoomLevel ) {
this . zoom . setZoom ( zoomLevel ) ;
}
2018-05-24 20:50:37 +02:00
zoomStep ( step ) {
this . zoom . zoomStep ( step ) ;
}
2018-05-13 15:22:28 +02:00
resetZoom ( ) {
this . zoom . setZoom ( 1 ) ;
this . restore ( ) ;
2017-09-24 01:54:46 +02:00
}
2018-05-13 15:22:28 +02:00
resetCrop ( ) {
this . setAr ( 'reset' ) ;
2017-09-24 01:54:46 +02:00
}
2018-05-13 15:22:28 +02:00
resetStretch ( ) {
2018-05-30 23:20:23 +02:00
this . stretcher . mode = StretchMode . NO _STRETCH ;
2018-05-13 15:22:28 +02:00
this . restore ( ) ;
2017-09-24 01:54:46 +02:00
}
2018-01-02 03:36:29 +01:00
2018-05-13 15:22:28 +02:00
// mostly internal stuff
2018-05-25 21:37:09 +02:00
computeOffsets ( stretchFactors ) {
2018-05-13 15:22:28 +02:00
2018-09-13 23:47:20 +02:00
if ( Debug . debug ) {
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::_res_computeOffsets] <rid:" + this . resizerId + "> video will be aligned to " , this . settings . active . miscFullscreenSettings . videoFloat ) ;
2018-09-13 23:47:20 +02:00
}
2018-05-25 21:37:09 +02:00
var actualWidth = this . conf . video . offsetWidth * stretchFactors . xFactor ;
var actualHeight = this . conf . video . offsetHeight * stretchFactors . yFactor ;
2018-09-13 23:47:20 +02:00
var wdiff = actualWidth - this . conf . player . dimensions . width ;
var hdiff = actualHeight - this . conf . player . dimensions . height ;
2018-05-25 21:37:09 +02:00
var translate = { x : 0 , y : 0 } ;
2018-04-22 14:35:40 +02:00
2018-07-15 16:22:32 +02:00
if ( this . pan ) {
2018-09-13 23:47:20 +02:00
// don't offset when video is smaller than player
if ( wdiff < 0 && hdiff < 0 ) {
return translate ;
}
translate . x = wdiff * this . pan . relativeOffsetX / this . zoom . scale ;
translate . y = hdiff * this . pan . relativeOffsetY / this . zoom . scale ;
2018-05-13 15:22:28 +02:00
} else {
2018-09-17 00:39:32 +02:00
if ( this . videoFloat == "left" ) {
2018-09-13 23:47:20 +02:00
translate . x = wdiff * 0.5 ;
2018-05-13 15:22:28 +02:00
}
2018-09-17 00:39:32 +02:00
else if ( this . videoFloat == "right" ) {
2018-09-13 23:47:20 +02:00
translate . x = wdiff * - 0.5 ;
2018-05-13 15:22:28 +02:00
}
}
2018-09-13 23:47:20 +02:00
if ( Debug . debug ) {
console . log ( "[Resizer::_res_computeOffsets] <rid:" + this . resizerId + "> calculated offsets:" , translate ) ;
}
2018-05-25 21:37:09 +02:00
return translate ;
2018-05-13 15:22:28 +02:00
}
2018-05-25 21:37:09 +02:00
applyCss ( stretchFactors , translate ) {
2018-05-13 15:22:28 +02:00
2018-07-15 16:22:32 +02:00
if ( ! this . video ) {
2018-09-13 23:47:20 +02:00
if ( Debug . debug ) {
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::_res_applyCss] <rid:" + this . resizerId + "> Video went missing, doing nothing." ) ;
2018-09-13 23:47:20 +02:00
}
2018-05-16 23:26:47 +02:00
this . conf . destroy ( ) ;
2018-04-22 14:35:40 +02:00
return ;
}
2018-01-02 03:36:29 +01:00
2018-05-16 23:26:47 +02:00
// save stuff for quick tests (before we turn numbers into css values):
this . currentVideoSettings = {
validFor : this . conf . player . dimensions ,
2018-05-25 21:37:09 +02:00
// videoWidth: dimensions.width,
// videoHeight: dimensions.height
2018-05-16 23:26:47 +02:00
}
2018-05-13 15:22:28 +02:00
var styleArrayStr = this . video . getAttribute ( 'style' ) ;
2018-05-25 21:37:09 +02:00
if ( styleArrayStr ) {
2018-01-02 03:36:29 +01:00
2018-05-13 15:22:28 +02:00
var styleArray = styleArrayStr . split ( ";" ) ;
for ( var i in styleArray ) {
styleArray [ i ] = styleArray [ i ] . trim ( ) ;
2018-05-25 21:37:09 +02:00
if ( styleArray [ i ] . startsWith ( "transform:" ) ) {
delete styleArray [ i ] ;
2018-05-13 15:22:28 +02:00
}
2018-01-02 03:36:29 +01:00
}
}
else {
2018-05-13 15:22:28 +02:00
var styleArray = [ ] ;
}
// add remaining elements
if ( stretchFactors ) {
2018-05-25 21:37:09 +02:00
styleArray . push ( ` transform: scale( ${ stretchFactors . xFactor } , ${ stretchFactors . yFactor } ) translate( ${ translate . x } px, ${ translate . y } px) ` ) ;
2018-01-02 03:36:29 +01:00
}
2018-04-22 14:35:40 +02:00
2018-05-13 15:22:28 +02:00
// build style string back
var styleString = "" ;
for ( var i in styleArray )
2018-05-25 21:37:09 +02:00
if ( styleArray [ i ] )
2018-05-13 15:22:28 +02:00
styleString += styleArray [ i ] + "; " ;
this . setStyleString ( styleString ) ;
2018-04-22 14:35:40 +02:00
}
2018-05-13 15:22:28 +02:00
setStyleString ( styleString , count = 0 ) {
2018-05-15 21:40:53 +02:00
this . video . setAttribute ( "style" , styleString ) ;
2018-08-21 00:48:15 +02:00
this . currentStyleString = this . video . getAttribute ( 'style' ) ;
this . currentCssValidFor = this . conf . player . dimensions ;
2017-11-13 22:35:04 +01:00
2018-05-13 15:22:28 +02:00
if ( this . restore _wd ) {
2018-05-25 21:37:09 +02:00
if ( ! this . video ) {
2018-05-13 15:22:28 +02:00
if ( Debug . debug )
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::_res_setStyleString] <rid:" + this . resizerId + "> Video element went missing, nothing to do here." )
2018-05-13 15:22:28 +02:00
return ;
2017-12-02 21:09:08 +01:00
}
2018-05-13 15:22:28 +02:00
2018-05-25 21:37:09 +02:00
// if(
// styleString.indexOf("width: " + this.video.style.width) == -1 ||
// styleString.indexOf("height: " + this.video.style.height) == -1) {
// // css ni nastavljen?
// // css not set?
// if(Debug.debug)
// console.log("[Resizer::_res_setStyleString] Style string not set ???");
2018-05-13 15:22:28 +02:00
2018-08-05 23:48:56 +02:00
// if(count < settings.active.resizer.setStyleString.maxRetries){
// setTimeout( this.setStyleString, settings.active.resizer.setStyleString.retryTimeout, count + 1);
2018-05-25 21:37:09 +02:00
// }
// else if(Debug.debug){
// console.log("[Resizer::_res_setStyleString] we give up. css string won't be set");
// }
// }
// else{
2018-05-13 15:22:28 +02:00
this . restore _wd = false ;
2018-05-25 21:37:09 +02:00
// }
2017-11-13 22:35:04 +01:00
}
2018-05-13 15:22:28 +02:00
else {
if ( Debug . debug )
2018-08-30 00:56:15 +02:00
console . log ( "[Resizer::_res_setStyleString] <rid:" + this . resizerId + "> css applied. Style string:" , styleString ) ;
2018-05-13 15:22:28 +02:00
}
2017-11-13 22:35:04 +01:00
}
2018-04-25 20:39:52 +02:00
2018-08-21 00:48:15 +02:00
cssCheck ( ) {
2018-05-13 15:22:28 +02:00
// this means we haven't set our CSS yet, or that we changed video.
2018-08-21 00:48:15 +02:00
// if(! this.currentCss.tranform) {
// this.scheduleCssWatcher(200);
// return;
// }
2018-05-13 15:22:28 +02:00
2018-05-16 23:26:47 +02:00
// this means video went missing. videoData will be re-initialized when the next video is found
2018-08-21 00:48:15 +02:00
if ( ! this . video ) {
2018-08-30 00:56:15 +02:00
if ( Debug . debug ) {
console . log ( "[Resizer::cssCheck] <rid:" + this . resizerId + "> no video detecting, issuing destroy command" ) ;
}
2018-08-21 00:48:15 +02:00
this . conf . destroy ( ) ;
2018-05-13 15:22:28 +02:00
return ;
2018-05-16 23:26:47 +02:00
}
2018-05-13 15:22:28 +02:00
2018-08-30 00:56:15 +02:00
if ( this . destroyed ) {
if ( Debug . debug ) {
console . log ( "[Resizer::cssCheck] <rid:" + this . resizerId + "> destroyed flag is set, we shouldnt be running" ) ;
}
return ;
}
2018-05-16 23:26:47 +02:00
2018-08-21 00:48:15 +02:00
var styleString = this . video . getAttribute ( 'style' ) ;
2018-05-16 23:26:47 +02:00
// first, a quick test:
2018-08-21 00:48:15 +02:00
// if (this.currentVideoSettings.validFor == this.conf.player.dimensions ){
2018-08-30 00:56:15 +02:00
if ( this . currentStyleString !== styleString ) {
this . restore ( ) ;
this . scheduleCssWatcher ( 10 ) ;
return ;
}
2018-08-21 00:48:15 +02:00
if ( this . cssWatcherIncreasedFrequencyCounter > 0 ) {
-- this . cssWatcherIncreasedFrequencyCounter ;
this . scheduleCssWatcher ( 20 ) ;
} else {
this . scheduleCssWatcher ( 1000 ) ;
2018-02-05 22:46:38 +01:00
}
}
}