2021-10-26 17:58:07 +02:00
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
( function ( ) {
var lastTime = 0 ;
var vendors = [ 'ms' , 'moz' , 'webkit' , 'o' ] ;
for ( var x = 0 ; x < vendors . length && ! window . requestAnimationFrame ; ++ x ) {
window . requestAnimationFrame = window [ vendors [ x ] + 'RequestAnimationFrame' ] ;
window . cancelAnimationFrame = window [ vendors [ x ] + 'CancelAnimationFrame' ]
|| window [ vendors [ x ] + 'CancelRequestAnimationFrame' ] ;
}
if ( ! window . requestAnimationFrame )
window . requestAnimationFrame = function ( callback , element ) {
var currTime = new Date ( ) . getTime ( ) ;
var timeToCall = Math . max ( 0 , 16 - ( currTime - lastTime ) ) ;
var id = window . setTimeout ( function ( ) { callback ( currTime + timeToCall ) ; } ,
timeToCall ) ;
lastTime = currTime + timeToCall ;
return id ;
} ;
if ( ! window . cancelAnimationFrame )
window . cancelAnimationFrame = function ( id ) {
clearTimeout ( id ) ;
} ;
} ( ) ) ;
/*! npm.im/iphone-inline-video 2.0.2 */
var enableInlineVideo = function ( ) { "use strict" ; /*! npm.im/intervalometer */
2021-10-26 19:55:57 +02:00
function e ( e , i , n , r ) { function t ( n ) { d = i ( t , r ) , e ( n - ( a || n ) ) , a = n } var d , a ; return { start : function ( ) { d || t ( 0 ) } , stop : function ( ) { n ( d ) , d = null , a = 0 } } } function i ( i ) { return e ( i , requestAnimationFrame , cancelAnimationFrame ) } function n ( e , i , n , r ) { function t ( i ) { Boolean ( e [ n ] ) === Boolean ( r ) && i . stopImmediatePropagation ( ) , delete e [ n ] } return e . addEventListener ( i , t , ! 1 ) , t } function r ( e , i , n , r ) { function t ( ) { return n [ i ] } function d ( e ) { n [ i ] = e } r && d ( e [ i ] ) , Object . defineProperty ( e , i , { get : t , set : d } ) } function t ( e , i , n ) { n . addEventListener ( i , function ( ) { return e . dispatchEvent ( new Event ( i ) ) } ) } function d ( e , i ) { Promise . resolve ( ) . then ( function ( ) { e . dispatchEvent ( new Event ( i ) ) } ) } function a ( e ) { var i = new Audio ; return t ( e , "play" , i ) , t ( e , "playing" , i ) , t ( e , "pause" , i ) , i . crossOrigin = e . crossOrigin , i . src = e . src || e . currentSrc || "data:" , i } function o ( e , i , n ) { ( m || 0 ) + 200 < Date . now ( ) && ( e [ b ] = ! 0 , m = Date . now ( ) ) , n || ( e . currentTime = i ) , w [ ++ T % 3 ] = 100 * i | 0 } function u ( e ) { return e . driver . currentTime >= e . video . duration } function s ( e ) { var i = this ; i . video . readyState >= i . video . HAVE _FUTURE _DATA ? ( i . hasAudio || ( i . driver . currentTime = i . video . currentTime + e * i . video . playbackRate / 1e3 , i . video . loop && u ( i ) && ( i . driver . currentTime = 0 ) ) , o ( i . video , i . driver . currentTime ) ) : i . video . networkState === i . video . NETWORK _IDLE && 0 === i . video . buffered . length && i . video . load ( ) , i . video . ended && ( delete i . video [ b ] , i . video . pause ( ! 0 ) ) } function c ( ) { var e = this , i = e [ h ] ; return e . webkitDisplayingFullscreen ? void e [ g ] ( ) : ( "data:" !== i . driver . src && i . driver . src !== e . src && ( o ( e , 0 , ! 0 ) , i . driver . src = e . src ) , void ( e . paused && ( i . paused = ! 1 , 0 === e . buffered . length && e . load ( ) , i . driver . play ( ) , i . updater . start ( ) , i . hasAudio || ( d ( e , "play" ) , i . video . readyState >= i . video . HAVE _ENOUGH _DATA && d ( e , "playing" ) ) ) ) ) } function v ( e ) { var i = this , n = i [ h ] ; n . driver . pause ( ) , n . updater . stop ( ) , i . webkitDisplayingFullscreen && i [ E ] ( ) , n . paused && ! e || ( n . paused = ! 0 , n . hasAudio || d ( i , "pause" ) , i . ended && ( i [ b ] = ! 0 , d ( i , "ended" ) ) ) } function p ( e , n ) { var r = e [ h ] = { } ; r . paused = ! 0 , r . hasAudio = n , r . video = e , r . updater = i ( s . bind ( r ) ) , n ? r . driver = a ( e ) : ( e . addEventListener ( "canplay" , function ( ) { e . paused || d ( e , "playing" ) } ) , r . driver = { src : e . src || e . currentSrc || "data:" , muted : ! 0 , paused : ! 0 , pause : function ( ) { r . driver . paused = ! 0 } , play : function ( ) { r . driver . paused = ! 1 , u ( r ) && o ( e , 0 ) } , get ended ( ) { return u ( r ) } } ) , e . addEventListener ( "emptied" , function ( ) { var i = ! r . driver . src || "data:" === r . driver . src ; r . driver . src && r . driver . src !== e . src && ( o ( e , 0 , ! 0 ) , r . driver . src = e . src , i ? r . driver . play ( ) : r . updater . stop ( ) ) } , ! 1 ) , e . addEventListener ( "webkitbeginfullscreen" , function ( ) { e . paused ? n && 0 === r . driver . buffered . length && r . driver . load ( ) : ( e . pause ( ) , e [ g ] ( ) ) } ) , n && ( e . addEventListener ( "webkitendfullscreen" , function ( ) { r . driver . currentTime = e . currentTime } ) , e . addEventListener ( "seeking" , function ( ) { w . indexOf ( 100 * e . currentTime | 0 ) < 0 && ( r . driver . currentTime = e . currentTime ) } ) ) } function l ( e ) { var i = e [ h ] ; e [ g ] = e . play , e [ E ] = e . pause , e . play = c , e . pause = v , r ( e , "paused" , i . driver ) , r ( e , "muted" , i . driver , ! 0 ) , r ( e , "playbackRate" , i . driver , ! 0 ) , r ( e , "ended" , i . driver ) , r ( e , "loop" , i . driver , ! 0 ) , n ( e , "seeking" ) , n ( e , "seeked" ) , n ( e , "timeupdate" , b , ! 1 ) , n ( e , "ended" , b , ! 1 ) } function f ( e , i ) { if ( void 0 === i && ( i = { } ) , ! e [ h ] ) { if ( ! i . everywhere ) { if ( ! y ) return ; if ( ! ( i . iPad || i . ipad ? /iPhone|iPod|iPad/ : /iPhone|iPod/ ) . test ( navigator . userAgent ) ) return } ! e . paused && e . webkitDisplayingFullscreen && e . pause ( ) , p ( e , ! e . muted ) , l ( e ) , e . classList . add ( "IIV" ) , e . muted && e . autoplay && e . play ( ) , /iPhone|iPod|iPad/ . test ( navigator . platform ) || console . warn ( "iphone-inline-video is not guaranteed to work in emulated environments" ) } } var m , y = "object" == typeof document && "object-fit" in document . head . style && ! matchMedia ( "(-webkit-video-playable-inline)" ) . matches , h = "bfred-it:iphone-inline-video" , b = "bfred-it:iphone-inline-video:event" , g = "bfred-it:iphone-inline-video:nativeplay" , E = "bfred-it:iphone-inline-video:nativepause" , w = [ ] , T = 0 ; return f } ;
2021-10-26 17:58:07 +02:00
if ( ! Array . isArray ) {
Array . isArray = function ( arg ) {
return Object . prototype . toString . call ( arg ) === '[object Array]' ;
} ;
}
( ! this . CustomEvent || typeof this . CustomEvent === "object" ) && ( function ( ) {
this . CustomEvent = function CustomEvent ( type , eventInitDict ) {
var event ;
eventInitDict = eventInitDict || { bubbles : false , cancelable : false , detail : undefined } ;
try {
event = document . createEvent ( 'CustomEvent' ) ;
event . initCustomEvent ( type , eventInitDict . bubbles , eventInitDict . cancelable , eventInitDict . detail ) ;
} catch ( error ) {
event = document . createEvent ( 'Event' ) ;
event . initEvent ( type , eventInitDict . bubbles , eventInitDict . cancelable ) ;
event . detail = eventInitDict . detail ;
}
return event ;
} ;
} ) ( ) ;
var Keys = {
BACKSPACE : 8 ,
ESC : 27 ,
TAB : 9 ,
RETURN : 13 ,
LEFT : 37 ,
UP : 38 ,
RIGHT : 39 ,
DOWN : 40
} ;
var TWidget = {
options : { } ,
isFocused : false
} ;
function inFrame ( ) {
return ( window . parent != null && window != window . parent ) ;
}
function inFullFrame ( ) {
return inFrame ( ) && TWidget . options . auto _height ;
}
function isFocused ( ) {
return inFrame ( ) ? TWidget . isFocused : document . hasFocus ( ) ;
}
function l ( lang _key , params , def _value ) {
if ( typeof params === 'string' ) {
def _value = params ;
params = { } ;
}
params = params || { } ;
var value = l . _keys [ lang _key ] || def _value || lang _key ;
value = value . replace ( /\{\{([A-Za-z_\-\d]{1,32}):(.+?)\}\}/g , function ( lang _value , token , options ) {
var number = + params [ token ] || 0 ;
var numeric _options = options . split ( '|' ) ;
var i ;
if ( number == 1 ) i = 0 ;
else i = 1 ;
if ( typeof numeric _options [ i ] === 'undefined' ) {
i = 1 ;
}
var numeric _option = numeric _options [ i ] || '#' ;
return numeric _option . replace ( /#/g , number ) ;
} ) ;
value = value . replace ( /\{([A-Za-z_\-\d]{1,32}):(.{1,256}?)\}/g , function ( lang _value , token , options ) {
var number = + params [ token ] || 0 ;
var numeric _options = options . split ( '|' ) ;
var i ;
if ( ! number ) i = 0 ;
else if ( number == 1 ) i = 1 ;
else i = 2 ;
if ( typeof numeric _options [ i ] === 'undefined' ) {
i = 0 ;
}
var numeric _option = numeric _options [ i ] || '#' ;
return numeric _option . replace ( /#/g , number ) ;
} ) ;
for ( var param in params ) {
value = value . split ( '{' + param + '}' ) . join ( params [ param ] ) ;
}
return value ;
}
l . _keys = { } ;
l . add = function ( lang _values ) {
for ( var lang _key in lang _values ) {
l . _keys [ lang _key ] = lang _values [ lang _key ] ;
}
}
var PostMessage = {
_callbacks : { } ,
_lastId : 0 ,
send : function ( data , origin , callback ) {
if ( typeof origin === 'function' ) {
callback = origin ; origin = null ;
}
try {
if ( callback ) {
data . _cb = ++ PostMessage . _lastId ;
PostMessage . _callbacks [ data . _cb ] = callback ;
}
window . parent . postMessage ( JSON . stringify ( data ) , origin || '*' ) ;
} catch ( e ) {
if ( origin ) alert ( 'Bot domain invalid' ) ;
}
} ,
onMessage : function ( event ) {
if ( event . source !== window . parent ) return ;
try {
var data = JSON . parse ( event . data ) ;
} catch ( e ) {
var data = { } ;
}
if ( data . event == 'visible' ) {
if ( ! frameWasVisible ) {
frameWasVisible = true ;
TWidget . options . onVisible && TWidget . options . onVisible ( ) ;
}
PostMessage . send ( { event : 'visible_off' } ) ;
}
else if ( data . event == 'focus' ) {
TWidget . isFocused = data . has _focus ;
triggerEvent ( window , 'tg:focuschange' ) ;
}
else if ( data . event == 'set_options' ) {
triggerEvent ( window , 'tg:optionschange' , { detail : data . options } ) ;
}
else if ( data . event == 'get_info' ) {
triggerEvent ( window , 'tg:inforequest' , { detail : {
callback : function ( value ) {
PostMessage . send ( { event : 'callback' , _cb : data . _cb , value : value } ) ;
}
} } ) ;
}
else if ( data . event == 'visible' ) {
if ( ! frameWasVisible ) {
frameWasVisible = true ;
TWidget . options . onVisible && TWidget . options . onVisible ( ) ;
}
PostMessage . send ( { event : 'visible_off' } ) ;
}
else if ( data . event == 'callback' ) {
if ( PostMessage . _callbacks [ data . _cb ] ) {
PostMessage . _callbacks [ data . _cb ] ( data . value ) ;
delete PostMessage . _callbacks [ data . _cb ] ;
} else {
console . warn ( 'Callback #' + data . _cb + ' not found' ) ;
}
}
}
} ;
var TPopups = {
_list : [ ] ,
_lastId : 1000000 ,
_inited : false ,
init : function ( ) {
if ( ! TPopups . _inited ) {
TPopups . _inited = true ;
if ( window . Popups ) {
TPopups . _list = window . Popups ; // legacy
}
addEvent ( document , 'keydown' , function ( e ) {
if ( e . keyCode == Keys . ESC && TPopups . _list . length > 0 ) {
e . stopImmediatePropagation ( ) ;
e . preventDefault ( ) ;
TPopups . close ( ) ;
}
} ) ;
}
} ,
open : function ( popup _el , options ) {
TPopups . init ( ) ;
popup _el = ge1 ( popup _el ) ;
if ( ! popup _el ) {
return popup _el ;
}
options = options || { } ;
var popup _id = popup _el . _ _puid ;
if ( ! popup _id ) {
popup _id = ++ TPopups . _lastId ;
popup _el . _ _puid = popup _id ;
}
popup _el . _ _options = options ;
var index = TPopups . _list . indexOf ( popup _id ) ;
if ( index >= 0 ) {
TPopups . _list . splice ( index , 1 ) ;
}
TPopups . _list . push ( popup _id ) ;
document . body . style . overflow = 'hidden' ;
document . body . appendChild ( popup _el ) ;
removeClass ( popup _el , 'hide' ) ;
TPopups . setPosition ( popup _el ) ;
if ( document . activeElement ) {
document . activeElement . blur ( ) ;
}
if ( ge1 ( '.js-popup_box' , popup _el ) ) {
addEvent ( popup _el , 'click' , function ( e ) {
if ( elInBody ( e . target ) &&
! hasClass ( e . target , 'js-popup_box' ) &&
! gpeByClass ( e . target , 'js-popup_box' ) ) {
TPopups . close ( popup _el ) ;
}
} ) ;
}
gec ( '.js-popup_close' , function ( ) {
addEvent ( this , 'click' , function ( ) {
TPopups . close ( popup _el ) ;
} ) ;
} , popup _el ) ;
triggerEvent ( popup _el , 'tg:popupopen' ) ;
return popup _el ;
} ,
close : function ( popup _el ) {
if ( ! TPopups . _list . length ) return false ;
var popup _id ;
if ( popup _el ) {
popup _id = popup _el . _ _puid ;
} else {
popup _id = TPopups . _list . pop ( ) ;
gec ( '.js-popup_container' , function ( ) {
if ( popup _id == this . _ _puid ) {
popup _el = this ;
return false ;
}
} ) ;
}
if ( ! popup _el ) {
return false ;
}
var options = popup _el . _ _options ;
var index = TPopups . _list . indexOf ( popup _id ) ;
if ( index >= 0 ) {
TPopups . _list . splice ( index , 1 ) ;
}
if ( ! TPopups . _list . length ) {
document . body . style . overflow = '' ;
}
removeEvent ( popup _el , 'click' ) ;
gec ( '.js-popup_close' , function ( ) {
removeEvent ( this , 'click' ) ;
} , popup _el ) ;
addClass ( popup _el , 'hide' ) ;
triggerEvent ( popup _el , 'tg:popupclose' ) ;
} ,
closeAll : function ( ) {
while ( TPopups . _list . length ) {
TPopups . close ( ) ;
}
} ,
setPosition : function ( popul _el ) {
var popup _box = ge1 ( '.js-popup_box' , popul _el ) ;
if ( ! popup _box ) return ;
getCoords ( function ( coords ) {
var style = window . getComputedStyle ( popul _el ) ;
var contTop = parseInt ( style . paddingTop ) ;
var contBottom = parseInt ( style . paddingBottom ) ;
var marginMax = popul _el . offsetHeight - contTop - contBottom - coords . elHeight ;
var frameTop = coords . frameTop || 0 ;
var deltaY = ( coords . clientHeight - coords . elHeight ) / 2 ;
var marginTop = deltaY - contTop - frameTop ;
marginTop = Math . max ( 0 , Math . min ( marginMax , marginTop ) ) ;
popup _box . style . marginTop = marginTop + 'px' ;
} , popup _box ) ;
} ,
show : function ( html , buttons , options ) {
options = options || { } ;
var popup _el = newEl ( 'div' , 'tgme_popup_container js-popup_container tgme_popup_alert hide' , '<div class="tgme_popup js-popup_box"><div class="tgme_popup_body"><div class="tgme_popup_text js-popup_text"></div><div class="tgme_popup_buttons js-popup_buttons"></div></div></div></div>' ) ;
var text _el = ge1 ( '.js-popup_text' , popup _el ) ;
var buttons _el = ge1 ( '.js-popup_buttons' , popup _el ) ;
setHtml ( text _el , html ) ;
var enterBtn = null , onEnterPress = null ;
for ( var i = 0 ; i < buttons . length ; i ++ ) {
var btn = buttons [ i ] ;
var button _el = newEl ( 'div' , 'tgme_popup_button' + ( btn . close ? ' js-popup_close' : '' ) , btn . label ) ;
btn . el = button _el ;
buttons _el . appendChild ( button _el ) ;
if ( btn . enter ) {
enterBtn = button _el ;
}
if ( btn . onPress ) {
addEvent ( button _el , 'click' , btn . onPress ) ;
}
}
if ( enterBtn ) {
onEnterPress = function ( e ) {
if ( e . keyCode == Keys . RETURN ) {
e . stopImmediatePropagation ( ) ;
e . preventDefault ( ) ;
triggerEvent ( enterBtn , 'click' ) ;
}
} ;
addEvent ( document , 'keydown' , onEnterPress ) ;
}
var onPopupClose = function ( e ) {
if ( enterBtn && onEnterPress ) {
removeEvent ( document , 'keydown' , onEnterPress ) ;
}
for ( var i = 0 ; i < buttons . length ; i ++ ) {
var btn = buttons [ i ] ;
if ( btn . onPress ) {
removeEvent ( btn . el , 'click' , btn . onPress ) ;
}
}
removeEvent ( popup _el , 'tg:popupclose' , onPopupClose ) ;
removeEl ( popup _el ) ;
} ;
addEvent ( popup _el , 'tg:popupclose' , onPopupClose ) ;
return TPopups . open ( popup _el ) ;
}
} ;
function showAlert ( html , onClose ) {
return TPopups . show ( html , [ {
label : l ( 'WEB_CLOSE' , 'Close' ) ,
enter : true ,
close : true
} ] ) ;
}
function showConfirm ( html , onConfirm , confirm _btn , onCancel , cancel _btn ) {
var popup _el = TPopups . show ( html , [ {
label : cancel _btn || l ( 'WEB_CANCEL' , 'Cancel' ) ,
onPress : function ( ) {
onCancel && onCancel ( popup _el ) ;
} ,
close : true
} , {
label : confirm _btn || l ( 'WEB_OK' , 'OK' ) ,
onPress : function ( ) {
onConfirm && onConfirm ( popup _el ) ;
TPopups . close ( popup _el ) ;
} ,
enter : true
} ] ) ;
return popup _el ;
}
function addEvent ( el , event , handler ) {
gec ( el , function ( ) {
var events = event . split ( /\s+/ ) ;
for ( var i = 0 ; i < events . length ; i ++ ) {
if ( this . addEventListener ) {
this . addEventListener ( events [ i ] , handler , false ) ;
} else {
this . attachEvent ( 'on' + events [ i ] , handler ) ;
}
}
} ) ;
}
function removeEvent ( el , event , handler ) {
gec ( el , function ( ) {
var events = event . split ( /\s+/ ) ;
for ( var i = 0 ; i < events . length ; i ++ ) {
if ( this . removeEventListener ) {
this . removeEventListener ( events [ i ] , handler ) ;
} else {
this . detachEvent ( 'on' + events [ i ] , handler ) ;
}
}
} ) ;
}
function triggerEvent ( el , event _type , init _dict ) {
gec ( el , function ( ) {
var event = new CustomEvent ( event _type , init _dict ) ;
this . dispatchEvent ( event ) ;
} ) ;
}
function geById ( el _or _id ) {
if ( typeof el _or _id == 'string' || el _or _id instanceof String ) {
return document . getElementById ( el _or _id ) ;
} else if ( el _or _id instanceof HTMLElement ) {
return el _or _id ;
}
return null ;
}
function gec ( el , callback , context ) {
var list = ge ( el , context ) ;
for ( var i = 0 , l = list . length ; i < l ; i ++ ) {
var result = callback . call ( list [ i ] , list [ i ] , i , list ) ;
if ( result === false ) {
break ;
}
}
}
function ge ( el , context ) {
var list = [ ] ;
if ( typeof el === 'string' ) {
list = ( ge1 ( context ) || document ) . querySelectorAll ( el ) ;
} else if ( el instanceof Node || el instanceof Window ) {
list = [ el ] ;
} else if ( Array . isArray ( el ) ) {
list = el ;
} else if ( el ) {
console . warn ( 'unknown type of el' , el ) ;
return [ el ] ;
}
if ( list instanceof NodeList ) {
list = Array . prototype . slice . call ( list ) ;
}
return list ;
}
function ge1 ( el , context ) {
if ( typeof el === 'string' ) {
return ( ge1 ( context ) || document ) . querySelector ( el ) ;
} else if ( el instanceof Node || el instanceof Window ) {
return el ;
} else if ( el instanceof NodeList ) {
return el . item ( 0 ) ;
} else if ( el instanceof Array ) {
return el [ 0 ] ;
} else if ( el ) {
console . warn ( 'unknown type of el' , el ) ;
return el ;
}
return null ;
}
function newEl ( tag , cl , html , styles ) {
var el = document . createElement ( ( tag || 'DIV' ) . toUpperCase ( ) ) ;
if ( cl ) el . className = cl ;
if ( styles ) {
for ( var k in styles ) {
el . style [ k ] = styles [ k ] ;
}
}
if ( html ) {
el . innerHTML = html ;
}
return el ;
}
function gpeByClass ( el , cl ) {
if ( ! el ) return null ;
while ( el = el . parentNode ) {
if ( hasClass ( el , cl ) ) break ;
}
return el || null ;
}
function elInBody ( el ) {
if ( ! el ) return false ;
while ( el = el . parentNode ) {
if ( el === document . body ) return true ;
}
return false ;
}
function getCoords ( callback , el ) {
var rect = { } ;
if ( el = ge1 ( el ) ) {
rect = el . getBoundingClientRect ( ) ;
}
var docEl = document . documentElement ;
var coords = { } ;
if ( inFullFrame ( ) ) {
PostMessage . send ( { event : 'get_coords' } , function ( coords ) {
coords . inFrame = true ;
if ( el ) {
coords . elTop = rect . top + coords . frameTop ;
coords . elBottom = rect . bottom + coords . frameTop ;
coords . elLeft = rect . left + coords . frameLeft ;
coords . elRight = rect . right + coords . frameLeft ;
coords . elWidth = rect . width ;
coords . elHeight = rect . height ;
}
callback && callback ( coords ) ;
} ) ;
return ;
} else {
if ( el ) {
coords . elTop = rect . top ;
coords . elBottom = rect . bottom ;
coords . elLeft = rect . left ;
coords . elRight = rect . right ;
coords . elWidth = rect . width ;
coords . elHeight = rect . height ;
}
coords . scrollTop = window . pageYOffset ;
coords . scrollLeft = window . pageXOffset ;
coords . clientWidth = docEl . clientWidth ;
coords . clientHeight = docEl . clientHeight ;
callback && callback ( coords ) ;
}
}
function scrollToY ( y ) {
if ( inFullFrame ( ) ) {
PostMessage . send ( { event : 'scroll_to' , y : y } ) ;
} else {
window . scrollTo ( 0 , y ) ;
}
}
function addClass ( el , cl ) {
gec ( el , function ( ) {
var cls = cl . split ( /\s+/ ) ;
for ( var i = 0 ; i < cls . length ; i ++ ) {
this . classList . add ( cls [ i ] ) ;
}
} ) ;
}
function removeClass ( el , cl ) {
gec ( el , function ( ) {
var cls = cl . split ( /\s+/ ) ;
for ( var i = 0 ; i < cls . length ; i ++ ) {
this . classList . remove ( cls [ i ] ) ;
}
} ) ;
}
function toggleClass ( el , cl , add ) {
gec ( el , function ( ) {
var cls = cl . split ( /\s+/ ) ;
for ( var i = 0 ; i < cls . length ; i ++ ) {
cl = cls [ i ] ;
var add _cl = ( typeof add !== 'undefined' ) ? add : ! hasClass ( this , cl ) ;
add _cl ? this . classList . add ( cl ) : this . classList . remove ( cl ) ;
}
} ) ;
}
function hasClass ( el , cl ) {
var item = ge1 ( el ) ;
return ( item && item . classList && item . classList . contains ( cl ) ) ;
}
function removeEl ( el ) {
gec ( el , function ( ) {
if ( this && this . parentNode ) {
this . parentNode . removeChild ( this ) ;
}
} ) ;
}
function getHtml ( el , context ) {
var item = ge1 ( el , context ) ;
return item ? item . innerHTML : null ;
}
function setHtml ( el , html ) {
gec ( el , function ( ) {
if ( this ) {
this . innerHTML = html ;
}
} ) ;
}
function getAttr ( el , attr ) {
var item = ge1 ( el ) ;
return item ? item . getAttribute ( attr ) : null ;
}
function setAttr ( el , attr , value ) {
gec ( el , function ( ) {
if ( this ) {
this . setAttribute ( attr , value ) ;
}
} ) ;
}
function isLSEnabled ( ) {
try {
return window . localStorage ? true : false ;
} catch ( e ) {
return false ;
}
}
function parseHeaders ( headers ) {
var headers _strs = headers . replace ( /^\s+|\s+$/g , '' ) . split ( /[\r\n]+/ ) ;
var headers _arr = [ ] ;
for ( var i = 0 ; i < headers _strs . length ; i ++ ) {
var header _str = headers _strs [ i ] ;
var parts = header _str . split ( ': ' ) ;
var name = parts . shift ( ) . toLowerCase ( ) ;
var value = parts . join ( ': ' ) ;
headers _arr . push ( { name : name , value : value } ) ;
}
return headers _arr ;
}
function setLS ( xhr ) {
if ( ! isLSEnabled ( ) ) return ;
try {
var headers = parseHeaders ( xhr . getAllResponseHeaders ( ) ) ;
for ( var i = 0 ; i < headers . length ; i ++ ) {
var header = headers [ i ] ;
if ( header . name == 'x-set-local-storage' ) {
var arr = header . value . split ( '=' ) ;
var key = decodeURIComponent ( arr [ 0 ] ) ;
var val = decodeURIComponent ( arr [ 1 ] ) ;
if ( val . length ) {
localStorage . setItem ( key , val ) ;
} else {
localStorage . removeItem ( key ) ;
}
}
}
} catch ( e ) { }
}
function getLSString ( ) {
if ( ! isLSEnabled ( ) ) return false ;
var arr = [ ] ;
for ( var i = 0 ; i < localStorage . length ; i ++ ) {
var key = localStorage . key ( i ) ;
arr . push ( encodeURIComponent ( key ) + '=' + encodeURIComponent ( localStorage [ key ] ) ) ;
}
return arr . join ( '; ' ) ;
}
function getXHR ( ) {
if ( navigator . appName == "Microsoft Internet Explorer" ) {
return new ActiveXObject ( "Microsoft.XMLHTTP" ) ;
} else {
return new XMLHttpRequest ( ) ;
}
}
function xhrRequest ( href , postdata , onCallback , retry _delay ) {
var xhr = getXHR ( ) , type = 'GET' , data = null , ls _header ;
if ( postdata !== false ) {
type = 'POST' ;
var data _arr = [ ] ;
for ( var field in postdata ) {
data _arr . push ( encodeURIComponent ( field ) + '=' + encodeURIComponent ( postdata [ field ] ) ) ;
}
data = data _arr . join ( '&' ) ;
}
xhr . open ( type , href ) ;
if ( postdata !== false ) {
xhr . setRequestHeader ( 'Content-Type' , 'application/x-www-form-urlencoded; charset=UTF-8' ) ;
}
xhr . setRequestHeader ( 'X-Requested-With' , 'XMLHttpRequest' ) ;
if ( ls _header = getLSString ( ) ) {
xhr . setRequestHeader ( 'X-Local-Storage' , ls _header ) ;
}
xhr . onerror = function ( ) {
if ( xhr . _retried ) return ;
xhr . _retried = true ;
retry _delay = retry _delay || 1000 ;
if ( retry _delay > 60000 ) {
onCallback && onCallback ( 'Server unavailable' ) ;
return ;
}
setTimeout ( function ( ) {
xhrRequest ( href , postdata , onCallback , retry _delay * 2 ) ;
} , retry _delay ) ;
} ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState == 4 ) {
setLS ( xhr ) ;
if ( typeof xhr . responseBody == 'undefined' && xhr . responseText ) {
try {
var result = JSON . parse ( xhr . responseText ) ;
} catch ( e ) {
var result = { } ;
}
if ( xhr . status == 401 ) { // Unauthorized
TWidgetAuth . reload ( ) ;
return ;
}
if ( result . error && result . flood _wait ) {
console . log ( 'flood_wait' , result . flood _wait ) ;
setTimeout ( function ( ) {
xhrRequest ( href , postdata , onCallback ) ;
} , result . flood _wait * 1000 ) ;
return ;
}
onCallback && onCallback ( null , result ) ;
} else {
xhr . onerror ( ) ;
}
}
} ;
xhr . withCredentials = true ;
xhr . send ( data ) ;
return xhr ;
}
function xhrUploadRequest ( href , params , onCallback , onProgress ) {
var xhr = getXHR ( ) , data = new FormData ( ) , ls _header ;
xhr . open ( 'POST' , href , true ) ;
xhr . setRequestHeader ( 'X-Requested-With' , 'XMLHttpRequest' ) ;
if ( ls _header = getLSString ( ) ) {
xhr . setRequestHeader ( 'X-Local-Storage' , ls _header ) ;
}
xhr . upload . addEventListener ( 'progress' , function ( event ) {
if ( event . lengthComputable ) {
onProgress && onProgress ( event . loaded , event . total ) ;
}
} ) ;
xhr . onerror = function ( ) {
onCallback && onCallback ( 'Server unavailable' ) ;
} ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState == 4 ) {
setLS ( xhr ) ;
if ( typeof xhr . responseBody == 'undefined' && xhr . responseText ) {
try {
var result = JSON . parse ( xhr . responseText ) ;
} catch ( e ) {
var result = { } ;
}
if ( result . error && result . flood _wait ) {
console . log ( 'flood_wait' , result . flood _wait ) ;
setTimeout ( function ( ) {
xhrUploadRequest ( href , params , onCallback , onProgress ) ;
} , result . flood _wait * 1000 ) ;
return ;
}
onCallback && onCallback ( null , result ) ;
} else {
xhr . onerror ( ) ;
}
}
} ;
for ( var k in params ) {
var value = params [ k ] ;
if ( value instanceof File ) {
data . append ( k , value , value . name ) ;
} else {
data . append ( k , value ) ;
}
}
xhr . withCredentials = true ;
xhr . send ( data ) ;
return xhr ;
}
window . TWidgetAuth = {
init : function ( options ) {
options = options || { } ;
TWidgetAuth . options = options ;
} ,
apiRequest : function ( method , params , callback ) {
var options = TWidgetAuth . options || { } ;
if ( ! options . api _url ) {
console . warn ( 'API url not found' ) ;
return null ;
}
params . method = method ;
return xhrRequest ( options . api _url , params , callback ) ;
} ,
uploadRequest : function ( params , onCallback , onProgress ) {
var options = TWidgetAuth . options || { } ;
if ( ! options . upload _url ) {
console . warn ( 'Upload url not found' ) ;
return null ;
}
return xhrUploadRequest ( options . upload _url , params , onCallback , onProgress ) ;
} ,
logIn : function ( ) {
var options = TWidgetAuth . options || { } ;
if ( ! options . bot _id ) {
console . warn ( 'Bot id not found' ) ;
return ;
}
if ( TWidgetAuth . isLoggedIn ( ) ) {
return ;
}
Telegram . Login . auth ( { bot _id : options . bot _id , lang : 'en' } , function ( user ) {
if ( user ) {
xhrRequest ( '/auth' , user , function ( err , result ) {
if ( result . ok ) {
TWidgetAuth . reload ( result . host ) ;
} else {
location . reload ( ) ;
}
} ) ;
}
} ) ;
} ,
reload : function ( host , callback ) {
var xhr = getXHR ( ) , data = null , ls _header ;
var url = location . href ;
if ( host ) {
var a = newEl ( 'a' ) ;
a . href = url ; a . hostname = host ; url = a . href ;
}
xhr . open ( 'GET' , url ) ;
xhr . setRequestHeader ( 'X-Requested-With' , 'relogin' ) ;
if ( ls _header = getLSString ( ) ) {
xhr . setRequestHeader ( 'X-Local-Storage' , ls _header ) ;
}
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState == 4 ) {
setLS ( xhr ) ;
if ( typeof xhr . responseBody == 'undefined' && xhr . responseText ) {
document . open ( ) ;
document . write ( xhr . responseText ) ;
document . close ( ) ;
callback && callback ( ) ;
} else {
location . reload ( ) ;
}
}
} ;
xhr . onerror = function ( ) {
location . reload ( ) ;
} ;
xhr . withCredentials = true ;
xhr . send ( ) ;
} ,
isLoggedIn : function ( ) {
var options = TWidgetAuth . options || { } ;
return options && ! options . unauth ;
}
} ;
window . apiRequest = TWidgetAuth . apiRequest ;
window . uploadRequest = TWidgetAuth . uploadRequest ;
function loadImage ( file , callback ) {
var image = new Image ( ) ;
image . onload = function ( ) {
var w = image . naturalWidth ;
var h = image . naturalHeight ;
callback && callback ( null , {
url : image . src ,
width : w ,
height : h ,
image : image
} ) ;
} ;
image . onerror = function ( ) {
callback && callback ( 'LOAD_FAILED' ) ;
} ;
image . src = URL . createObjectURL ( file ) ;
}
function initWidgetFrame ( options ) {
TWidget . options = options || { } ;
if ( window . devicePixelRatio >= 2 ) {
addClass ( document . body , 'r2x' ) ;
}
if ( TWidget . options . auto _height ||
TWidget . options . auto _width ) {
addEvent ( window , 'resize' , checkFrameSize ) ;
checkFrameSize ( ) ;
}
addEvent ( window , 'message' , PostMessage . onMessage ) ;
addEvent ( window , 'focus blur' , function ( ) {
triggerEvent ( window , 'tg:focuschange' ) ;
} ) ;
PostMessage . send ( { event : 'ready' } ) ;
}
var frameLastHeight = null ,
frameLastWidth = null ,
frameWasVisible = false ;
function checkFrameSize ( ) {
var height , width , style ;
if ( document . body ) {
if ( window . getComputedStyle ) {
style = window . getComputedStyle ( document . body ) ;
height = style . height ;
if ( height . substr ( - 2 ) == 'px' ) {
height = height . slice ( 0 , - 2 ) ;
}
width = style . width ;
if ( width . substr ( - 2 ) == 'px' ) {
width = width . slice ( 0 , - 2 ) ;
}
} else {
height = document . body . offsetHeight ;
width = document . body . offsetWidth ;
}
var data = { event : 'resize' } , resized = false ;
if ( TWidget . options . auto _height ) {
height = Math . ceil ( height ) ;
if ( height != frameLastHeight ) {
frameLastHeight = height ;
data . height = height ;
resized = true ;
}
}
if ( TWidget . options . auto _width ) {
width = Math . ceil ( width ) ;
if ( width != frameLastWidth ) {
frameLastWidth = width ;
data . width = width ;
resized = true ;
}
}
if ( resized ) {
PostMessage . send ( data ) ;
}
}
requestAnimationFrame ( checkFrameSize ) ;
}
( function ( ) {
var ua = navigator . userAgent . toLowerCase ( ) ;
var browser = {
opera : ( /opera/i . test ( ua ) || /opr/i . test ( ua ) ) ,
msie : ( /msie/i . test ( ua ) && ! /opera/i . test ( ua ) || /trident\//i . test ( ua ) ) || /edge/i . test ( ua ) ,
msie _edge : ( /edge/i . test ( ua ) && ! /opera/i . test ( ua ) ) ,
mozilla : /firefox/i . test ( ua ) ,
chrome : /chrome/i . test ( ua ) && ! /edge/i . test ( ua ) ,
safari : ( ! ( /chrome/i . test ( ua ) ) && /webkit|safari|khtml/i . test ( ua ) ) ,
iphone : /iphone/i . test ( ua ) ,
ipod : /ipod/i . test ( ua ) ,
ipad : /ipad/i . test ( ua ) ,
android : /android/i . test ( ua ) ,
mobile : /iphone|ipod|ipad|opera mini|opera mobi|iemobile|android/i . test ( ua ) ,
safari _mobile : /iphone|ipod|ipad/i . test ( ua ) ,
opera _mobile : /opera mini|opera mobi/i . test ( ua ) ,
opera _mini : /opera mini/i . test ( ua ) ,
mac : /mac/i . test ( ua ) ,
} ;
var TBaseUrl = window . TBaseUrl || '//telegram.org/' ;
function formatDateTime ( datetime ) {
var date = new Date ( datetime ) ;
var cur _date = new Date ( ) ;
if ( cur _date . getFullYear ( ) == date . getFullYear ( ) &&
cur _date . getMonth ( ) == date . getMonth ( ) &&
cur _date . getDate ( ) == date . getDate ( ) ) {
return formatTime ( datetime ) ;
}
return formatDate ( datetime ) ;
}
function formatDate ( datetime ) {
var date = new Date ( datetime ) ;
var cur _date = new Date ( ) ;
var j = date . getDate ( ) ;
var M = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ] [ date . getMonth ( ) ] ;
var Y = date . getFullYear ( ) ;
if ( cur _date . getFullYear ( ) == date . getFullYear ( ) ) {
return M + ' ' + j ;
}
return M + ' ' + j + ', ' + Y ;
}
function formatTime ( datetime ) {
var date = new Date ( datetime ) ;
var H = date . getHours ( ) ;
if ( H < 10 ) H = '0' + H ;
var i = date . getMinutes ( ) ;
if ( i < 10 ) i = '0' + i ;
return H + ':' + i ;
}
function formatDuration ( duration ) {
duration = Math . floor ( duration ) ;
duration = Math . max ( 0 , duration ) ;
var duration _str = '' ;
if ( duration >= 3600 ) {
var hours = Math . floor ( duration / 3600 ) ;
duration _str += hours + ':' ;
var minutes = Math . floor ( ( duration % 3600 ) / 60 ) ;
if ( minutes < 10 ) minutes = '0' + minutes ;
} else {
var minutes = Math . floor ( duration / 60 ) ;
}
duration _str += minutes + ':' ;
var seconds = duration % 60 ;
if ( seconds < 10 ) seconds = '0' + seconds ;
duration _str += seconds ;
return duration _str ;
}
function doesSupportEmoji ( ) {
var context , smile , canvas = document . createElement ( 'canvas' ) ;
if ( ! canvas . getContext ) return false ;
context = canvas . getContext ( '2d' ) ;
if ( typeof context . fillText != 'function' ) return false ;
smile = '#' + String . fromCharCode ( 65039 ) + String . fromCharCode ( 8419 ) ;
context . textBaseline = 'top' ;
context . font = '32px Arial' ;
context . fillText ( smile , 0 , 0 ) ;
if ( context . getImageData ( 16 , 16 , 1 , 1 ) . data [ 0 ] === 0 ) return false ;
var div = document . createElement ( 'div' ) ;
div . style . position = 'absolute' ;
div . style . overflow = 'hidden' ;
div . style . top = '-1000px' ;
var span = document . createElement ( 'span' ) ;
div . style . fontSize = '16px' ;
span . innerHTML = smile ;
div . appendChild ( span ) ;
document . body . insertBefore ( div , document . body . firstChild ) ;
var width = span . offsetWidth ;
document . body . removeChild ( div ) ;
if ( width < 18 ) return false ;
return true ;
}
function cloneArr ( arrLike ) {
return Array . prototype . slice . apply ( arrLike ) ;
}
var loadedLibs = { } ;
function loadLib ( file , callback ) {
if ( ! loadedLibs [ file ] ) {
loadedLibs [ file ] = {
loaded : null ,
callbacks : [ callback ]
} ;
var script = document . createElement ( 'script' ) ;
script . type = 'text/javascript' ;
script . async = true ;
script . src = file ;
script . onerror = function ( ) {
loadedLibs [ file ] . loaded = false ;
applyCallbacks ( loadedLibs [ file ] . callbacks , loadedLibs [ file ] . loaded ) ;
}
script . onload = function ( ) {
loadedLibs [ file ] . loaded = true ;
applyCallbacks ( loadedLibs [ file ] . callbacks , loadedLibs [ file ] . loaded ) ;
}
var head = document . getElementsByTagName ( 'head' ) [ 0 ] ;
head . appendChild ( script ) ;
return script ;
} else if ( loadedLibs [ file ] . loaded === null ) {
loadedLibs [ file ] . callbacks . push ( callback ) ;
} else {
callback ( loadedLibs [ file ] . loaded ) ;
}
} ;
var webpNativeSupport = null , webpFallbackSupport = null , webpImage = null , webpCallbacks = [ ] ;
function applyCallbacks ( callbacks ) {
var args = cloneArr ( arguments ) ; args . shift ( ) ;
for ( var i = 0 ; i < callbacks . length ; i ++ ) {
callbacks [ i ] . apply ( null , args ) ;
}
}
function doesSupportWebp ( callback ) {
if ( webpFallbackSupport !== null ) {
callback ( webpNativeSupport , webpFallbackSupport ) ;
} else {
webpCallbacks . push ( callback ) ;
if ( ! webpImage ) {
webpImage = new Image ( ) ;
webpImage . onerror = webpImage . onload = function ( ) {
if ( this . width === 2 && this . height === 1 ) {
webpNativeSupport = true ;
webpFallbackSupport = false ;
applyCallbacks ( webpCallbacks , webpNativeSupport , webpFallbackSupport ) ;
} else {
webpNativeSupport = false ;
var script = document . createElement ( 'script' ) ;
script . type = 'text/javascript' ;
script . async = true ;
script . src = TBaseUrl + 'js/libwebp-0.2.0.js' ;
script . onerror = function ( ) {
webpFallbackSupport = false ;
applyCallbacks ( webpCallbacks , webpNativeSupport , webpFallbackSupport ) ;
}
script . onload = function ( ) {
webpFallbackSupport = true ;
applyCallbacks ( webpCallbacks , webpNativeSupport , webpFallbackSupport ) ;
}
var head = document . getElementsByTagName ( 'head' ) [ 0 ] ;
head . appendChild ( script ) ;
}
}
webpImage . src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==' ;
}
}
}
function getPngDataUrlFromWebp ( data ) {
var decoder = new WebPDecoder ( ) ;
var config = decoder . WebPDecoderConfig ;
var buffer = config . j || config . output ;
var bitstream = config . input ;
if ( ! decoder . WebPInitDecoderConfig ( config ) ) {
throw new Error ( '[webpjs] Library version mismatch!' ) ;
}
var StatusCode = decoder . VP8StatusCode ;
status = decoder . WebPGetFeatures ( data , data . length , bitstream ) ;
if ( status != ( StatusCode . VP8 _STATUS _OK || 0 ) ) {
throw new Error ( '[webpjs] status error' ) ;
}
var mode = decoder . WEBP _CSP _MODE ;
buffer . colorspace = mode . MODE _RGBA ;
buffer . J = 4 ;
try {
status = decoder . WebPDecode ( data , data . length , config ) ;
} catch ( e ) {
status = e
}
var ok = ( status == 0 ) ;
if ( ! ok ) {
throw new Error ( '[webpjs] decoding failed' ) ;
}
var bitmap = buffer . c . RGBA . ma ;
if ( ! bitmap ) {
throw new Error ( '[webpjs] bitmap error' ) ;
}
var biHeight = buffer . height ;
var biWidth = buffer . width ;
var canvas = document . createElement ( 'canvas' ) ;
var context = canvas . getContext ( '2d' ) ;
canvas . height = biHeight ;
canvas . width = biWidth ;
var output = context . createImageData ( canvas . width , canvas . height ) ;
var outputData = output . data ;
for ( var h = 0 ; h < biHeight ; h ++ ) {
for ( var w = 0 ; w < biWidth ; w ++ ) {
outputData [ 0 + w * 4 + ( biWidth * 4 ) * h ] = bitmap [ 1 + w * 4 + ( biWidth * 4 ) * h ] ;
outputData [ 1 + w * 4 + ( biWidth * 4 ) * h ] = bitmap [ 2 + w * 4 + ( biWidth * 4 ) * h ] ;
outputData [ 2 + w * 4 + ( biWidth * 4 ) * h ] = bitmap [ 3 + w * 4 + ( biWidth * 4 ) * h ] ;
outputData [ 3 + w * 4 + ( biWidth * 4 ) * h ] = bitmap [ 0 + w * 4 + ( biWidth * 4 ) * h ] ;
}
}
context . putImageData ( output , 0 , 0 ) ;
return canvas . toDataURL ( 'image/png' ) ;
}
function proccessWebpImage ( imgEl , failed _callback , success _callback ) {
var imgEl = geById ( imgEl ) ;
if ( ! imgEl || imgEl . _ _inited ) return ;
imgEl . _ _inited = true ;
failed _callback = failed _callback || function ( ) { } ;
success _callback = success _callback || function ( ) { } ;
doesSupportWebp ( function ( nativeSupport , fallbackSupport ) {
var isImage , src ;
var webpSrc = imgEl . getAttribute ( 'data-webp' ) ;
if ( imgEl . tagName && imgEl . tagName . toUpperCase ( ) == 'IMG' && imgEl . src ) {
isImage = true ;
src = imgEl . src ;
} else {
isImage = false ;
var bgImage ;
if ( window . getComputedStyle ) {
bgImage = window . getComputedStyle ( imgEl ) . backgroundImage ;
} else {
bgImage = imgEl . style && imgEl . style . backgroundImage ;
}
src = bgImage . slice ( 4 , - 1 ) . replace ( /["|']/g , '' ) ;
}
var setImgSrc = function ( src ) {
if ( isImage ) {
imgEl . src = src ;
} else {
imgEl . style . backgroundImage = "url('" + src + "')" ;
}
addClass ( imgEl , 'webp_sticker_done' ) ;
} ;
if ( nativeSupport ) {
if ( webpSrc ) {
var img = new Image ( ) ;
img . onload = function ( ) {
setImgSrc ( webpSrc ) ;
success _callback ( ) ;
}
img . onerror = function ( ) {
failed _callback ( ) ;
}
img . src = webpSrc ;
} else {
success _callback ( ) ;
}
return ;
} else if ( ! fallbackSupport ) {
failed _callback ( ) ;
return ;
}
if ( hasClass ( imgEl , 'webp_sticker_done' ) ) {
success _callback ( ) ;
return ;
}
if ( ! src ) {
failed _callback ( ) ;
return ;
}
if ( webpSrc ) {
src = webpSrc ;
}
var xhr = getXHR ( ) ;
xhr . open ( 'get' , src ) ;
if ( xhr . overrideMimeType ) {
xhr . overrideMimeType ( 'text/plain; charset=x-user-defined' ) ;
} else {
xhr . setRequestHeader ( 'Accept-Charset' , 'x-user-defined' ) ;
}
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState == 4 ) {
if ( typeof xhr . responseBody == 'undefined' && xhr . responseText ) {
var rlen = xhr . responseText . length , uarr = new Uint8Array ( rlen ) ;
for ( var i = 0 ; i < rlen ; i ++ ) {
uarr [ i ] = xhr . responseText . charCodeAt ( i ) ;
}
try {
var src = getPngDataUrlFromWebp ( uarr ) ;
if ( isImage ) {
imgEl . src = src ;
} else {
imgEl . style . backgroundImage = "url('" + src + "')" ;
}
addClass ( imgEl , 'webp_sticker_done' ) ;
success _callback ( ) ;
} catch ( e ) {
failed _callback ( ) ;
}
} else {
failed _callback ( ) ;
}
}
} ;
xhr . send ( null ) ;
} ) ;
}
function checkVideo ( el , error _callback ) {
var timeout , eventAdded ;
if ( ! eventAdded ) {
function destroyCheck ( ) {
clearTimeout ( timeout ) ;
removeEvent ( el , 'canplay' , onCanPlay ) ;
removeEvent ( el , 'error' , onError ) ;
}
function onCanPlay ( ) {
destroyCheck ( ) ;
}
function onError ( ) {
destroyCheck ( ) ;
error _callback ( ) ;
}
eventAdded = true ;
addEvent ( el , 'canplay' , onCanPlay ) ;
addEvent ( el , 'error' , onError ) ;
}
if ( el . readyState >= 2 ) {
destroyCheck ( ) ;
} else {
timeout = setTimeout ( function ( ) {
checkVideo ( el , error _callback ) ;
} , 50 ) ;
}
}
window . TPost = {
init : function ( postEl , options ) {
postEl = geById ( postEl ) ;
options = options || { } ;
if ( ! postEl || postEl . _ _inited ) return ;
postEl . _ _inited = true ;
gec ( 'time[datetime]' , function ( ) {
var datetime = this . getAttribute ( 'datetime' ) ;
if ( datetime ) {
if ( hasClass ( this , 'datetime' ) ) {
this . innerHTML = formatDate ( datetime ) + ' at ' + formatTime ( datetime ) ;
} else if ( hasClass ( this , 'time' ) ) {
this . innerHTML = formatTime ( datetime ) ;
} else {
this . innerHTML = formatDateTime ( datetime ) ;
}
}
} , postEl ) ;
gec ( '.js-message_footer.compact' , function ( ) {
var timeEl = ge1 ( 'time[datetime]' , this )
, textEl = this . previousElementSibling ;
if ( textEl && ! textEl . _ _inited && hasClass ( textEl , 'js-message_text' ) ) {
var text _rect = textEl . getBoundingClientRect ( ) ;
var tnode = textEl . firstChild ;
while ( tnode && tnode . nodeType == tnode . ELEMENT _NODE ) {
tnode = tnode . firstChild ;
}
if ( tnode ) {
var r = document . createRange ( ) ;
r . setStart ( tnode , 0 ) ;
r . setEnd ( tnode , 1 ) ;
var char _rect = r . getBoundingClientRect ( ) ;
textEl . _ _inited = true ;
if ( Math . abs ( char _rect . right - text _rect . right ) > 3 ) {
var infoEl = ge1 ( '.js-message_info' , this ) ;
if ( infoEl ) {
var shadowEl = document . createElement ( 'span' ) ;
shadowEl . style . display = 'inline-block' ;
shadowEl . style . width = infoEl . offsetWidth + 'px' ;
textEl . appendChild ( shadowEl ) ;
addClass ( textEl , 'before_footer' ) ;
}
}
}
}
} , postEl ) ;
gec ( '.js-message_video_player' , function ( ) {
TVideo . init ( this ) ;
} , postEl ) ;
gec ( '.js-message_photo' , function ( ) {
TPhoto . init ( this ) ;
} , postEl ) ;
gec ( '.js-message_grouped_wrap' , function ( ) {
TGrouped . init ( this ) ;
} , postEl ) ;
gec ( '.js-message_roundvideo_player' , function ( ) {
TRoundVideo . init ( this ) ;
} , postEl ) ;
gec ( '.js-message_voice_player' , function ( ) {
TVoice . init ( this ) ;
} , postEl ) ;
gec ( '.js-sticker_image' , function ( ) {
TSticker . init ( this , function ( ) {
addClass ( postEl , 'media_not_supported' ) ;
removeClass ( postEl , 'no_bubble' ) ;
} ) ;
} , postEl ) ;
gec ( '.js-sticker_thumb' , function ( ) {
TSticker . init ( this ) ;
} , postEl ) ;
gec ( '.js-tgsticker_image' , function ( ) {
if ( options . tgs _workers _limit ) {
RLottie . WORKERS _LIMIT = options . tgs _workers _limit ;
} else if ( options . frame ) {
RLottie . WORKERS _LIMIT = 1 ;
}
RLottie . init ( this , {
playOnce : this . hasAttribute ( 'data-play-once' )
} ) ;
} , postEl ) ;
} ,
view : function ( postEl ) {
postEl = geById ( postEl ) ;
if ( ! postEl ) return ;
var view = postEl . getAttribute ( 'data-view' ) ;
if ( view ) {
var xhr = getXHR ( ) ;
xhr . open ( 'get' , '/v/?views=' + encodeURIComponent ( view ) ) ;
xhr . setRequestHeader ( 'X-Requested-With' , 'XMLHttpRequest' ) ;
xhr . send ( null ) ;
}
}
} ;
var TPhoto = window . TPhoto = {
init : function ( photoEl ) {
photoEl = geById ( photoEl ) ;
if ( ! photoEl || photoEl . _ _inited ) return ;
photoEl . _ _inited = true ;
var inGroup = hasClass ( photoEl , 'grouped_media_wrap' )
, opened
, overTo ;
if ( inGroup ) {
addEvent ( photoEl , 'click' , function togglePhoto ( e ) {
if ( e . metaKey || e . ctrlKey ) return true ;
e . stopPropagation ( ) ;
if ( ! photoEl ) return true ;
if ( opened ) {
opened = false ;
removeClass ( photoEl , 'active' ) ;
overTo = setTimeout ( function ( ) {
removeClass ( photoEl , 'over' ) ;
} , 200 ) ;
} else {
opened = true ;
clearTimeout ( overTo ) ;
addClass ( photoEl , 'over active' ) ;
}
e . preventDefault ( ) ;
return false ;
} ) ;
}
}
} ;
var TVideo = window . TVideo = {
init : function ( playerEl ) {
playerEl = geById ( playerEl ) ;
if ( ! playerEl || playerEl . _ _inited ) return ;
playerEl . _ _inited = true ;
var videoEl = ge1 ( '.js-message_video' , playerEl )
, videoBluredEl = ge1 ( '.js-message_video_blured' , playerEl )
, playEl = ge1 ( '.js-message_video_play' , playerEl )
, durationEl = ge1 ( '.js-message_video_duration' , playerEl )
, inGroup = hasClass ( playerEl , 'grouped_media_wrap' )
, looped
, overTo ;
if ( ! videoEl ) return ;
looped = videoEl . hasAttribute ( 'loop' ) ;
if ( inGroup ) {
addEvent ( playerEl , 'click' , function videoToggleInGroup ( e ) {
if ( e . metaKey || e . ctrlKey ) return true ;
if ( hasClass ( e . target , 'message_media_view_in_telegram' ) ) return true ;
e . stopPropagation ( ) ;
if ( ! playerEl ) return true ;
if ( hasClass ( playerEl , 'active' ) ) {
removeClass ( playerEl , 'active' ) ;
overTo = setTimeout ( function ( ) {
removeClass ( playerEl , 'over' ) ;
} , 200 ) ;
} else {
clearTimeout ( overTo ) ;
addClass ( playerEl , 'over active' ) ;
}
e . preventDefault ( ) ;
return false ;
} ) ;
}
if ( videoEl . hasAttribute ( 'playsinline' ) ) {
enableInlineVideo ( videoEl ) ;
if ( videoBluredEl ) {
enableInlineVideo ( videoBluredEl ) ;
}
}
function fixControls ( ) {
if ( videoEl . controls ) videoEl . controls = false ;
}
var MutationObserver = window . MutationObserver || window . WebKitMutationObserver ;
if ( MutationObserver ) {
( new MutationObserver ( fixControls ) ) . observe ( videoEl , { attributes : true } ) ;
}
checkVideo ( videoEl , function ( ) {
addClass ( playerEl , 'not_supported' ) ;
} ) ;
addEvent ( videoEl , 'play' , function ( ) {
fixControls ( ) ;
addClass ( playerEl , 'playing' ) ;
if ( inGroup ) {
clearTimeout ( overTo ) ;
addClass ( playerEl , 'over active' ) ;
}
if ( videoBluredEl ) {
videoBluredEl . currentTime = videoEl . currentTime ;
if ( ! browser . mobile ) {
videoBluredEl . play ( ) ;
}
}
if ( ! looped ) {
triggerEvent ( videoEl , 'tg:play' , { bubbles : true } ) ;
}
} ) ;
addEvent ( document , 'tg:play' , function ( e ) {
if ( e . target === videoEl || looped ) return true ;
if ( ! videoEl . paused ) {
videoEl . pause ( ) ;
if ( videoBluredEl ) {
videoBluredEl . pause ( ) ;
}
}
} ) ;
addEvent ( videoEl , 'pause' , function ( ) {
fixControls ( ) ;
removeClass ( playerEl , 'playing' ) ;
if ( inGroup ) {
removeClass ( playerEl , 'active' ) ;
overTo = setTimeout ( function ( ) {
removeClass ( playerEl , 'over' ) ;
} , 200 ) ;
}
if ( videoBluredEl ) {
videoBluredEl . currentTime = videoEl . currentTime ;
videoBluredEl . pause ( ) ;
}
if ( looped ) {
videoEl . play ( ) ;
}
} ) ;
addEvent ( videoEl , 'timeupdate' , function ( e ) {
fixControls ( ) ;
if ( videoBluredEl && videoBluredEl . currentTime != videoEl . currentTime ) {
videoBluredEl . currentTime = videoEl . currentTime ;
}
if ( durationEl && videoEl . duration ) {
var duration = Math . floor ( videoEl . duration ) ;
durationEl . innerHTML = formatDuration ( duration - videoEl . currentTime ) ;
}
} ) ;
addEvent ( videoEl , 'ended load' , function ( e ) {
fixControls ( ) ;
if ( durationEl && videoEl . duration ) {
var duration = Math . floor ( videoEl . duration ) ;
durationEl . innerHTML = formatDuration ( duration ) ;
}
} ) ;
if ( looped ) {
addEvent ( document , 'touchstart' , function ( ) { videoEl . play ( ) ; } ) ;
} else {
addClass ( playerEl , 'ready' ) ;
}
if ( playEl ) {
addEvent ( playEl , 'click' , function toggleVideo ( e ) {
if ( e . metaKey || e . ctrlKey ) return true ;
e . stopPropagation ( ) ;
if ( ! videoEl ) return true ;
if ( videoEl . paused ) {
videoEl . play ( ) ;
if ( videoBluredEl ) {
videoBluredEl . play ( ) ;
}
} else {
videoEl . pause ( ) ;
if ( videoBluredEl ) {
videoBluredEl . pause ( ) ;
}
}
e . preventDefault ( ) ;
return false ;
} ) ;
}
}
} ;
var TGrouped = window . TGrouped = {
init : function ( groupedWrapEl ) {
groupedWrapEl = geById ( groupedWrapEl ) ;
if ( ! groupedWrapEl || groupedWrapEl . _ _inited ) return ;
groupedWrapEl . _ _inited = true ;
var groupedEl = ge1 ( '.js-message_grouped' , groupedWrapEl )
, groupedLayerEl = ge1 ( '.js-message_grouped_layer' , groupedEl )
, thumbsEl = groupedLayerEl . children
, margin _w = + groupedWrapEl . getAttribute ( 'data-margin-w' ) || 2
, margin _h = + groupedWrapEl . getAttribute ( 'data-margin-h' ) || 2 ;
if ( ! thumbsEl . length ) {
return false ;
}
addEvent ( window , 'resize' , function ( ) {
if ( groupedLayerEl . offsetWidth != groupedEl . offsetWidth ) {
recalcGrouped ( groupedWrapEl . offsetWidth ) ;
}
} ) ;
recalcGrouped ( groupedWrapEl . offsetWidth ) ;
function updateThumb ( thumbEl , x , y , width , height , th _width , th _height , position ) {
if ( ! thumbEl ) return ;
var t = false , r = false , b = false , l = false ;
for ( var i = 0 ; i < position . length ; i ++ ) {
if ( position [ i ] == 't' ) t = true ;
else if ( position [ i ] == 'r' ) r = true ;
else if ( position [ i ] == 'b' ) b = true ;
else if ( position [ i ] == 'l' ) l = true ;
}
thumbEl . style . left = x + 'px' ;
thumbEl . style . top = y + 'px' ;
thumbEl . style . width = width + 'px' ;
thumbEl . style . height = height + 'px' ;
thumbEl . style . marginRight = ( ! r ? margin _w : 0 ) + 'px' ;
thumbEl . style . marginBottom = ( ! b ? margin _h : 0 ) + 'px' ;
var th _ratio = th _width / th _height ;
var ratio = + thumbEl . getAttribute ( 'data-ratio' ) || 1.0 ;
var mediaEl = ge1 ( '.grouped_media' , thumbEl ) ;
var helperEl = ge1 ( '.grouped_media_helper' , thumbEl ) ;
if ( mediaEl ) {
var media _height = Math . ceil ( width / ratio ) ;
var media _tb = height - media _height ;
if ( media _tb < 0 ) {
var media _t = Math . floor ( media _tb / 2 ) ;
var media _b = media _tb - media _t ;
mediaEl . style . left = 0 ;
mediaEl . style . right = 0 ;
mediaEl . style . top = media _t + 'px' ;
mediaEl . style . bottom = media _b + 'px' ;
} else {
var media _width = Math . ceil ( height * ratio ) ;
var media _lr = width - media _width ;
var media _l = Math . floor ( media _lr / 2 ) ;
var media _r = media _lr - media _l ;
mediaEl . style . top = 0 ;
mediaEl . style . bottom = 0 ;
mediaEl . style . left = media _l + 'px' ;
mediaEl . style . right = media _r + 'px' ;
}
}
if ( helperEl ) {
var helper _height = Math . floor ( th _width / ratio ) ;
var helper _tb = th _height - helper _height ;
if ( helper _tb > 0 ) {
var helper _t = Math . floor ( helper _tb / 2 ) ;
var helper _b = helper _tb - helper _t ;
helperEl . style . left = 0 ;
helperEl . style . right = 0 ;
helperEl . style . top = helper _t + 'px' ;
helperEl . style . bottom = helper _b + 'px' ;
} else {
var helper _width = Math . ceil ( th _height * ratio ) ;
var helper _lr = th _width - helper _width ;
var helper _l = Math . floor ( helper _lr / 2 ) ;
var helper _r = helper _lr - helper _l ;
helperEl . style . top = 0 ;
helperEl . style . bottom = 0 ;
helperEl . style . left = helper _l + 'px' ;
helperEl . style . right = helper _r + 'px' ;
}
}
}
function recalcGrouped ( max _w ) {
var orients = '' ;
var ratios = [ ] ;
var cnt = thumbsEl . length ;
var ratios _sum = 0 ;
for ( var i = 0 ; i < thumbsEl . length ; i ++ ) {
var thumbEl = thumbsEl [ i ] ;
var ratio = + thumbEl . getAttribute ( 'data-ratio' ) || 1.0 ;
orients += ratio > 1.2 ? 'w' : ( ratio < 0.8 ? 'n' : 'q' ) ;
ratios _sum += ratio ;
ratios . push ( ratio ) ;
}
var avg _ratio = ratios . length ? ratios _sum / ratios . length : 1.0 ;
var max _ratio = 0.75 ;
var min _w = 75 ;
var max _h = max _w / max _ratio ;
var w , h , w0 , w1 , w2 , h0 , h1 , h2 , x , y , x1 , x2 , y1 , y2 ,
th _width , th _height ;
if ( cnt == 2 ) {
if ( orients == 'ww' &&
avg _ratio > 1.4 * max _ratio &&
( ratios [ 1 ] - ratios [ 0 ] ) < 0.2 ) {
// 2 wide pics are one below the other
w = max _w ;
h = Math . min ( w / ratios [ 0 ] , Math . min ( w / ratios [ 1 ] , ( max _h - margin _h ) / 2.0 ) ) ;
th _width = max _w ;
th _height = 2 * h + margin _h ;
h0 = Math . floor ( h ) ;
h1 = th _height - h0 - margin _h ;
y = h0 + margin _h ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w , h0 , th _width , th _height , 'trl' ) ;
updateThumb ( thumbsEl [ 1 ] , 0 , y , w , h1 , th _width , th _height , 'rbl' ) ;
}
else if ( orients == 'ww' || orients == 'qq' ) {
// 2 equal width pics
w = ( max _w - margin _w ) / 2 ;
h = Math . floor ( Math . min ( max _h , Math . min ( w / ratios [ 0 ] , w / ratios [ 1 ] ) ) ) ;
th _width = max _w ;
th _height = h ;
w0 = Math . floor ( w ) ;
w1 = max _w - w0 - margin _w ;
x = w0 + margin _w ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w0 , h , th _width , th _height , 'tbl' ) ;
updateThumb ( thumbsEl [ 1 ] , x , 0 , w1 , h , th _width , th _height , 'trb' ) ;
}
else {
// so, we have one wide and one not wide (square or narrow)
w0 = Math . floor ( ( max _w - margin _w ) / ratios [ 1 ] / ( 1 / ratios [ 0 ] + 1 / ratios [ 1 ] ) ) ;
w1 = max _w - w0 - margin _w ;
h = Math . floor ( Math . min ( max _h , Math . min ( w0 / ratios [ 0 ] , w1 / ratios [ 1 ] ) ) ) ;
th _width = max _w ;
th _height = h ;
x = w0 + margin _w ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w0 , h , th _width , th _height , 'tbl' ) ;
updateThumb ( thumbsEl [ 1 ] , x , 0 , w1 , h , th _width , th _height , 'trb' ) ;
}
}
else if ( cnt == 3 ) {
if ( orients [ 0 ] == 'n' ) {
// 2nd and 3rd photos are on the right part
h0 = max _h ;
h2 = Math . floor ( Math . min ( ( max _h - margin _h ) * 0.5 , ratios [ 1 ] * ( max _h - margin _h ) / ( ratios [ 2 ] + ratios [ 1 ] ) ) ) ;
h1 = max _h - h2 - margin _h ;
w1 = Math . floor ( Math . max ( min _w , Math . min ( ( max _w - margin _w ) * 0.5 , Math . min ( h2 * ratios [ 2 ] , h1 * ratios [ 1 ] ) ) ) ) ;
w0 = Math . min ( Math . floor ( h0 * ratios [ 0 ] ) , ( max _w - w1 - margin _w ) ) ;
th _width = w0 + w1 + margin _w ;
th _height = max _h ;
x = w0 + margin _w ;
y = h1 + margin _h ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w0 , h0 , th _width , th _height , 'tbl' ) ;
updateThumb ( thumbsEl [ 1 ] , x , 0 , w1 , h1 , th _width , th _height , 'tr' ) ;
updateThumb ( thumbsEl [ 2 ] , x , y , w1 , h2 , th _width , th _height , 'rb' ) ;
}
else {
// 2nd and 3rd photos are on the next line
w0 = max _w ;
h0 = Math . floor ( Math . min ( w0 / ratios [ 0 ] , ( max _h - margin _h ) * 0.66 ) ) ;
w = ( max _w - margin _w ) / 2 ;
h = Math . floor ( Math . min ( max _h - h0 - margin _h , Math . min ( w / ratios [ 1 ] , w / ratios [ 2 ] ) ) ) ;
th _width = max _w ;
th _height = h0 + h + margin _h ;
w1 = Math . floor ( w ) ;
w2 = max _w - w1 - margin _w ;
x = w1 + margin _w ;
y = h0 + margin _h ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w0 , h0 , th _width , th _height , 'tlr' ) ;
updateThumb ( thumbsEl [ 1 ] , 0 , y , w1 , h , th _width , th _height , 'bl' ) ;
updateThumb ( thumbsEl [ 2 ] , x , y , w2 , h , th _width , th _height , 'rb' ) ;
}
}
else if ( cnt == 4 ) {
if ( orients == 'wwww' || orients [ 0 ] == 'w' ) {
// 2nd, 3rd and 4th photos are on the next line
w = max _w ;
h0 = Math . floor ( Math . min ( w / ratios [ 0 ] , ( max _h - margin _h ) * 0.66 ) ) ;
h = ( max _w - 2 * margin _w ) / ( ratios [ 1 ] + ratios [ 2 ] + ratios [ 3 ] ) ;
w0 = Math . floor ( Math . max ( min _w , Math . min ( ( max _w - 2 * margin _w ) * 0.4 , h * ratios [ 1 ] ) ) ) ;
w2 = Math . floor ( Math . max ( min _w , Math . min ( ( max _w - 2 * margin _w ) * 0.33 , h * ratios [ 3 ] ) ) ) ;
w1 = w - w0 - w2 - 2 * margin _w ;
h = Math . floor ( Math . min ( max _h - h0 - margin _h , h ) ) ;
th _width = max _w ;
th _height = h0 + h + margin _h ;
y = h0 + margin _h ;
x1 = w0 + margin _w ;
x2 = x1 + w1 + margin _w ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w , h0 , th _width , th _height , 'tlr' ) ;
updateThumb ( thumbsEl [ 1 ] , 0 , y , w0 , h , th _width , th _height , 'bl' ) ;
updateThumb ( thumbsEl [ 2 ] , x1 , y , w1 , h , th _width , th _height , 'b' ) ;
updateThumb ( thumbsEl [ 3 ] , x2 , y , w2 , h , th _width , th _height , 'rb' ) ;
}
else {
// 2nd, 3rd and 4th photos are on the right part
h = max _h ;
w0 = Math . floor ( Math . min ( h * ratios [ 0 ] , ( max _w - margin _w ) * 0.66 ) ) ;
w = Math . floor ( ( max _h - 2 * margin _h ) / ( 1 / ratios [ 1 ] + 1 / ratios [ 2 ] + 1 / ratios [ 3 ] ) ) ;
h0 = Math . floor ( w / ratios [ 1 ] ) ;
h2 = Math . floor ( w / ratios [ 3 ] ) ;
h1 = h - h0 - h2 - 2 * margin _h ;
w = Math . max ( min _w , Math . min ( max _w - w0 - margin _w , w ) ) ;
th _width = w0 + w + margin _w ;
th _height = max _h ;
x = w0 + margin _w ;
y1 = h0 + margin _h ;
y2 = y1 + h1 + margin _h ;
updateThumb ( thumbsEl [ 0 ] , 0 , 0 , w0 , h , th _width , th _height , 'tbl' ) ;
updateThumb ( thumbsEl [ 1 ] , x , 0 , w , h0 , th _width , th _height , 'tr' ) ;
updateThumb ( thumbsEl [ 2 ] , x , y1 , w , h1 , th _width , th _height , 'r' ) ;
updateThumb ( thumbsEl [ 3 ] , x , y2 , w , h2 , th _width , th _height , 'rb' ) ;
}
}
else {
var ratios _cropped = [ ] ;
for ( var i = 0 ; i < ratios . length ; i ++ ) {
var ratio = ratios [ i ] ;
if ( avg _ratio > 1.1 ) {
ratio _cropped = Math . max ( 1.0 , ratio ) ;
} else {
ratio _cropped = Math . min ( 1.0 , ratio ) ;
}
ratio _cropped = Math . max ( 0.66667 , Math . min ( 1.7 , ratio _cropped ) ) ;
ratios _cropped . push ( ratio _cropped ) ;
}
var multiHeight = function ( ratios ) {
var ratios _sum = 0 ;
for ( var i = 0 ; i < ratios . length ; i ++ ) {
var ratio = ratios [ i ] ;
ratios _sum += ratio ;
}
return ( max _w - ( ratios . length - 1 ) * margin _w ) / ratios _sum ;
} ;
var tries = [ ] ;
var first _line , second _line , third _line , fourth _line ;
// Two lines
for ( first _line = 1 ; first _line <= cnt - 1 ; first _line ++ ) {
second _line = cnt - first _line ;
if ( first _line > 3 ||
second _line > 3 ) {
continue ;
}
tries . push ( [ [ first _line , second _line ] , [
multiHeight ( ratios _cropped . slice ( 0 , first _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line ) ) ,
] ] ) ;
}
// Three lines
for ( first _line = 1 ; first _line <= cnt - 2 ; first _line ++ ) {
for ( second _line = 1 ; second _line <= cnt - first _line - 1 ; second _line ++ ) {
third _line = cnt - first _line - second _line ;
if ( first _line > 3 ||
second _line > ( avg _ratio < 0.85 ? 4 : 3 ) ||
third _line > 3 ) {
continue ;
}
tries . push ( [ [ first _line , second _line , third _line ] , [
multiHeight ( ratios _cropped . slice ( 0 , first _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line , first _line + second _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line + second _line ) ) ,
] ] ) ;
}
}
// Four lines
for ( first _line = 1 ; first _line <= cnt - 3 ; first _line ++ ) {
for ( second _line = 1 ; second _line <= cnt - first _line - 2 ; second _line ++ ) {
for ( third _line = 1 ; third _line <= cnt - first _line - second _line - 1 ; third _line ++ ) {
fourth _line = cnt - first _line - second _line - third _line ;
if ( first _line > 3 ||
second _line > 3 ||
third _line > 3 ||
fourth _line > 3 ) {
continue ;
}
tries . push ( [ [ first _line , second _line , third _line , fourth _line ] , [
multiHeight ( ratios _cropped . slice ( 0 , first _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line , first _line + second _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line + second _line , first _line + second _line + third _line ) ) ,
multiHeight ( ratios _cropped . slice ( first _line + second _line + third _line ) ) ,
] ] ) ;
}
}
}
// Looking for minimum difference between thumbs block height and max_h (may probably be little over)
var opt _i = false ;
var opt _conf = false ;
var opt _diff = false ;
var opt _h = false ;
for ( var i = 0 ; i < tries . length ; i ++ ) {
var conf _nums = tries [ i ] [ 0 ] ;
var heights = tries [ i ] [ 1 ] ;
var heights _sum = 0 ;
var heights _min = Infinity ;
for ( var j = 0 ; j < heights . length ; j ++ ) {
heights _sum += heights [ j ] ;
if ( heights _min > heights [ j ] ) {
heights _min = heights [ j ] ;
}
}
var conf _h = Math . floor ( heights _sum + margin _h * ( heights . length - 1 ) ) ;
var conf _diff = Math . abs ( conf _h - max _h ) ;
if ( conf _nums . length > 1 ) {
if ( conf _nums [ 0 ] > conf _nums [ 1 ] ||
conf _nums [ 2 ] && conf _nums [ 1 ] > conf _nums [ 2 ] ||
conf _nums [ 3 ] && conf _nums [ 2 ] > conf _nums [ 3 ] ) {
conf _diff *= 1.5 ;
}
}
if ( heights _min < min _w ) {
conf _diff *= 1.5 ;
}
if ( opt _conf === false || conf _diff < opt _diff ) {
opt _i = i ;
opt _conf = cloneArr ( conf _nums ) ;
opt _diff = conf _diff ;
opt _h = conf _h ;
}
}
// Generating optimal thumbs
th _width = max _w ;
th _height = opt _h ;
var thumbs _remain = cloneArr ( thumbsEl ) ;
var ratios _remain = cloneArr ( ratios _cropped ) ;
var chunks = cloneArr ( opt _conf ) ;
var opt _heights = cloneArr ( tries [ opt _i ] [ 1 ] ) ;
var chunks _num = chunks . length ;
var last _row = chunks _num - 1 ;
var sy = 0 ;
for ( var i = 0 ; i < chunks . length ; i ++ ) {
var line _chunks _num = chunks [ i ] ;
var line _thumbs = thumbs _remain . splice ( 0 , line _chunks _num ) ;
var line _height = opt _heights . shift ( ) ;
var last _column = line _thumbs . length - 1 ;
var h = Math . floor ( line _height ) ;
var sx = 0 ;
var t = '' , r = '' , b = '' , l = '' ;
if ( i == 0 ) {
t = 't' ;
}
if ( i == last _row ) {
b = 'b' ;
h = th _height - sy ;
}
for ( var j = 0 ; j < line _thumbs . length ; j ++ ) {
var thumbEl = line _thumbs [ j ] ;
var thumb _ratio = ratios _remain . shift ( ) ;
var w = Math . floor ( thumb _ratio * h ) ;
if ( j == 0 ) {
l = 'l' ;
}
if ( j == last _column ) {
r = 'r' ;
w = th _width - sx ;
}
updateThumb ( thumbEl , sx , sy , w , h , th _width , th _height , t + r + b + l ) ;
sx += w + margin _w ;
}
sy += h + margin _h ;
}
}
groupedEl . style . paddingTop = ( th _height / th _width * 100 ) + '%' ;
groupedLayerEl . style . width = th _width + 'px' ;
groupedLayerEl . style . height = th _height + 'px' ;
}
}
} ;
var TRoundVideo = window . TRoundVideo = {
init : function ( playerEl ) {
playerEl = geById ( playerEl ) ;
if ( ! playerEl || playerEl . _ _inited ) return ;
playerEl . _ _inited = true ;
var videoEl = ge1 ( '.js-message_roundvideo' , playerEl )
, playEl = ge1 ( '.js-message_roundvideo_play' , playerEl )
, progressEl = ge1 ( '.js-message_roundvideo_progress' , playerEl )
, durationEl = ge1 ( '.js-message_roundvideo_duration' , playerEl )
, playing = false ;
if ( ! videoEl ) return ;
function autoplay ( ) {
if ( ! videoEl ) return ;
removeEvent ( document , 'touchstart' , autoplay ) ;
removeClass ( playerEl , 'playing' ) ;
playing = false ;
videoEl . muted = true ;
videoEl . loop = true ;
videoEl . currentTime = 0 ;
play ( ) ;
showProgress ( ) ;
}
function showProgress ( ) {
if ( ! videoEl ) return ;
if ( playing && ! videoEl . paused ) {
requestAnimationFrame ( function ( ) { showProgress ( ) ; } ) ;
}
redrawProgress ( ) ;
if ( videoEl . duration ) {
var duration = Math . floor ( videoEl . duration ) ;
durationEl . innerHTML = formatDuration ( duration - videoEl . currentTime ) ;
}
}
function redrawProgress ( updateSVG ) {
if ( ! videoEl ) return ;
var progress ;
if ( playing ) {
progress = videoEl . currentTime / videoEl . duration ;
} else {
progress = 0 ;
}
progress = Math . max ( 0 , Math . min ( progress , 1 ) ) ;
var wrapWidth = playerEl . offsetWidth ;
if ( wrapWidth ) {
var rd = progressEl . getAttribute ( 'data-rd' ) || 3 ;
var d = ( wrapWidth - rd ) ;
var l = ( d * Math . PI ) ;
progressEl . setAttribute ( 'r' , ( d / 2 ) ) ;
progressEl . setAttribute ( 'stroke-dasharray' , l ) ;
progressEl . setAttribute ( 'stroke-dashoffset' , l * ( 1 - progress ) ) ;
if ( updateSVG ) {
progressEl . style . transform = ! progressEl . style . transform ? 'rotateZ(270deg)' : '' ;
}
}
}
function play ( ) {
if ( ! videoEl ) return ;
var video = videoEl ;
var isPlaying = ( video . currentTime > 0 ) &&
! video . paused &&
! video . ended &&
( video . readyState > 2 ) ;
if ( ! isPlaying ) {
video . play ( ) ;
if ( playing ) {
triggerEvent ( videoEl , 'tg:play' , { bubbles : true } ) ;
}
}
}
addEvent ( document , 'tg:play' , function ( e ) {
if ( e . target === videoEl || ! playing ) return true ;
if ( videoEl . paused ) {
play ( ) ;
showProgress ( ) ;
} else {
autoplay ( ) ;
}
} ) ;
function pause ( ) {
if ( ! videoEl ) return ;
videoEl . pause ( ) ;
}
function toggle ( e ) {
e . stopPropagation ( ) ;
if ( ! playing ) {
redrawProgress ( ) ;
addClass ( playerEl , 'playing' ) ;
playing = true ;
videoEl . muted = false ;
videoEl . loop = false ;
videoEl . currentTime = 0 ;
play ( ) ;
showProgress ( ) ;
} else {
if ( videoEl . paused ) {
play ( ) ;
showProgress ( ) ;
} else {
pause ( ) ;
}
}
}
enableInlineVideo ( videoEl ) ;
checkVideo ( videoEl , function ( ) {
addClass ( playerEl , 'not_supported' ) ;
} ) ;
autoplay ( ) ;
addEvent ( document , 'touchstart' , autoplay ) ;
addEvent ( videoEl , 'ended' , function ( ) {
autoplay ( ) ;
} ) ;
addEvent ( window , 'resize' , function ( ) {
redrawProgress ( true )
} ) ;
if ( playEl ) {
addEvent ( playEl , 'click' , toggle ) ;
}
}
} ;
var TVoice = window . TVoice = {
init : function ( playerEl ) {
playerEl = geById ( playerEl ) ;
if ( ! playerEl || playerEl . _ _inited ) return ;
playerEl . _ _inited = true ;
var audioEl = ge1 ( '.js-message_voice' , playerEl )
, durationEl = ge1 ( '.js-message_voice_duration' , playerEl )
, progressEl = ge1 ( '.js-message_voice_progress' , playerEl )
, progressWrapEl = ge1 ( '.js-message_voice_progress_wrap' , playerEl )
, player = null
, isOGG = audioEl . hasAttribute ( 'data-ogg' )
, seekTo = null
, seeking = false
, disableClick = false ;
if ( ! audioEl ) return ;
function initPlayer ( ) {
addClass ( playerEl , 'ready' ) ;
addEvent ( player , 'play' , function ( ) {
addClass ( playerEl , 'playing' ) ;
triggerEvent ( playerEl , 'tg:play' , { bubbles : true } ) ;
} ) ;
addEvent ( player , 'pause' , function ( ) {
removeClass ( playerEl , 'playing' ) ;
} ) ;
addEvent ( player , 'ended' , function ( ) {
player . currentTime = 0 ;
showProgress ( ) ;
} ) ;
addEvent ( player , 'loadedmetadata' , function ( ) {
showProgress ( ) ;
} ) ;
addEvent ( playerEl , 'click' , toggle ) ;
addEvent ( progressWrapEl , 'mousedown touchstart' , seekStart ) ;
addEvent ( document , 'tg:play' , stop ) ;
}
function toggle ( e ) {
e . stopPropagation ( ) ;
if ( ! disableClick ) {
if ( ! player ) return true ;
if ( player . paused ) {
player . play ( ) ;
showProgress ( ) ;
} else {
player . pause ( ) ;
showProgress ( ) ;
}
} else {
disableClick = false ;
}
e . preventDefault ( ) ;
return false ;
}
function stop ( e ) {
if ( e . target === playerEl || ! player ) return true ;
if ( ! player . paused ) {
player . pause ( ) ;
showProgress ( ) ;
}
return false ;
}
function seekStart ( e ) {
if ( player &&
player . duration !== Infinity &&
( ! player . paused ||
player . currentTime > 0 && player . currentTime < player . duration ) ) {
e . preventDefault ( ) ;
seeking = true ;
disableClick = false ;
player . pause ( ) ;
addEvent ( document , 'mousemove touchmove' , seek ) ;
addEvent ( document , 'mouseup mouseleave touchend touchcancel' , seekEnd ) ;
seek ( e ) ;
}
}
function seek ( e ) {
if ( ! seeking ) return ;
var px = e . pageX ;
var op = progressWrapEl ;
var x = op . offsetLeft ;
var w = op . offsetWidth ;
while ( op = op . offsetParent ) {
x += op . offsetLeft ;
}
var ct = Math . max ( 0 , Math . min ( px - x , w ) ) / w ;
seekTo = ct ;
showProgress ( ) ;
}
function seekEnd ( e ) {
if ( ! seeking ) return ;
seek ( e ) ;
var duration = Math . floor ( player . duration ) ;
player . currentTime = seekTo * duration ;
seekTo = null ;
seeking = false ;
if ( e . type . substr ( 0 , 5 ) == 'mouse' ) {
disableClick = true ;
}
player . play ( ) ;
showProgress ( ) ;
removeEvent ( document , 'mousemove touchmove' , seek ) ;
removeEvent ( document , 'mouseup touchend' , seekEnd ) ;
}
function showProgress ( ) {
if ( ! player ) return ;
if ( ! player . paused ) {
requestAnimationFrame ( function ( ) { showProgress ( ) ; } ) ;
}
if ( player . duration && player . duration !== Infinity ) {
var duration = Math . floor ( player . duration ) ;
if ( seeking ) {
var currentTime = seekTo * duration ;
} else {
var currentTime = Math . max ( 0 , player . currentTime ) ;
}
if ( progressEl ) {
progressEl . style . width = Math . min ( 100 , currentTime / duration * 100 ) + '%' ;
}
if ( durationEl ) {
durationEl . innerHTML = formatDuration ( duration - currentTime ) ;
}
}
}
function redrawProgress ( ) {
if ( ! audioEl ) return ;
var ss = progressWrapEl . getElementsByTagName ( 'S' ) ;
var ss _count = ss . length / 2 ;
var waveform _str = audioEl . getAttribute ( 'data-waveform' ) || '' ;
var waveform = waveform _str . split ( ',' ) ;
var lines _cnt = Math . floor ( ( progressWrapEl . offsetWidth + 2 ) / 6 ) ;
var p = waveform . length / lines _cnt ;
var values = [ ] ;
var max _value = 0 ;
for ( var i = 0 ; i < lines _cnt ; i ++ ) {
var ws = i * p ;
var we = ws + p ;
var wsi = Math . floor ( ws ) ;
var wei = Math . floor ( we ) ;
if ( wsi == wei ) {
var value = waveform [ wsi ] * ( we - ws ) ;
} else {
var value = 0 ;
for ( var j = wsi ; j <= wei ; j ++ ) {
var wv = + waveform [ j ] || 0 ;
if ( j == wsi ) {
value += wv * ( j + 1 - ws ) ;
} else if ( j == wei ) {
value += wv * ( we - j ) ;
} else {
value += wv ;
}
}
}
value = value / p ;
max _value = Math . max ( value , max _value ) ;
values . push ( value ) ;
}
for ( var i = 0 ; i < ss . length ; i ++ ) {
var li = i % ss _count ;
if ( li < lines _cnt ) {
var height = ( values [ li ] / max _value ) * 100 ;
ss [ i ] . style . height = height + '%' ;
ss [ i ] . style . display = '' ;
} else {
ss [ i ] . style . display = 'none' ;
}
}
}
loadLib ( TBaseUrl + 'js/ogvjs/ogv-support.js' , function ( success ) {
if ( ! success ) return ;
if ( isOGG &&
OGVCompat . hasWebAudio ( ) &&
OGVCompat . supported ( 'OGVPlayer' ) ) {
loadLib ( TBaseUrl + 'js/ogvjs/ogv.js' , function ( success ) {
if ( ! success ) return ;
player = new OGVPlayer ( ) ;
player . src = audioEl . src ;
initPlayer ( ) ;
} ) ;
} else {
player = audioEl ;
initPlayer ( ) ;
}
} ) ;
addEvent ( window , 'resize' , function ( ) { redrawProgress ( ) } ) ;
redrawProgress ( ) ;
}
} ;
var TSticker = window . TSticker = {
init : proccessWebpImage
} ;
window . TWidgetPost = {
init : function ( options ) {
if ( ! doesSupportEmoji ( ) ) {
removeClass ( document . body , 'emoji_default' ) ;
addClass ( document . body , 'emoji_image' ) ;
}
options = options || { } ;
TWidgetPost . options = options ;
gec ( '.js-widget_message' , function ( ) {
TPost . init ( this , { tgs _workers _limit : 1 } ) ;
addEvent ( ge ( '.js-poll_option' , this ) , 'click' , TWidgetPost . eSelectPollOption ) ;
addEvent ( ge ( '.js-poll_vote_btn' , this ) , 'click' , TWidgetPost . eSendVotes ) ;
} ) ;
initWidgetFrame ( {
auto _height : true ,
onVisible : function ( ) {
gec ( '.js-widget_message' , function ( ) {
TPost . view ( this ) ;
} ) ;
}
} ) ;
addEvent ( window , 'tg:optionschange' , TWidgetPost . onOptionsChange ) ;
} ,
onOptionsChange : function ( e ) {
var new _options = e . detail , transition _off = false ;
if ( typeof new _options . dark !== undefined ) {
transition _off = true ;
addClass ( document . body , 'no_transitions' ) ;
toggleClass ( document . body , 'dark' , ! ! new _options . dark ) ;
toggleClass ( document . body , 'nodark' , ! new _options . dark ) ;
}
if ( transition _off ) {
setTimeout ( function ( ) {
removeClass ( document . body , 'no_transitions' ) ;
} , 100 ) ;
}
} ,
eSelectPollOption : function ( e ) {
e . preventDefault ( ) ;
if ( ! TWidgetAuth . isLoggedIn ( ) ) {
return TWidgetAuth . logIn ( ) ;
}
var poll _el = gpeByClass ( this , 'js-poll' ) ;
if ( ! poll _el ) {
return false ;
}
toggleClass ( this , 'selected' ) ;
toggleClass ( poll _el , 'selected' , ge ( '.js-poll_option.selected' , poll _el ) . length > 0 ) ;
if ( ! hasClass ( poll _el , 'multiple' ) ) {
TWidgetPost . sendPollVote ( poll _el , this ) ;
}
} ,
eSendVotes : function ( e ) {
e . preventDefault ( ) ;
if ( ! TWidgetAuth . isLoggedIn ( ) ) {
return TWidgetAuth . logIn ( ) ;
}
var poll _el = gpeByClass ( this , 'js-poll' ) ;
if ( ! poll _el ) {
return false ;
}
TWidgetPost . sendPollVote ( poll _el , this ) ;
} ,
sendPollVote : function ( poll _el , option _el ) {
if ( ! poll _el || hasClass ( poll _el , 'sending' ) ) {
return false ;
}
var option _els = ge ( '.js-poll_option.selected' , poll _el ) ;
var options = TWidgetPost . options || { } ;
var post _el = gpeByClass ( option _el , 'js-widget_message' ) ;
if ( ! post _el ) {
return false ;
}
var peer = getAttr ( post _el , 'data-peer' ) ;
var peer _hash = getAttr ( post _el , 'data-peer-hash' ) ;
var post _id = getAttr ( post _el , 'data-post-id' ) ;
if ( ! peer || ! peer _hash || ! post _id ) {
return false ;
}
var poll _options = [ ] ;
gec ( option _els , function ( ) {
poll _options . push ( getAttr ( this , 'data-value' ) ) ;
} ) ;
removeClass ( poll _el , 'selected' ) ;
addClass ( poll _el , 'sending' ) ;
apiRequest ( 'sendVote' , {
peer : peer ,
peer _hash : peer _hash ,
post _id : post _id ,
options : poll _options . join ( ';' )
} , function ( err , result ) {
removeClass ( poll _el , 'sending' ) ;
if ( result . media _html ) {
var media _wrap = newEl ( 'div' , '' , result . media _html ) ;
var media _html = getHtml ( '.js-poll' , media _wrap ) ;
setHtml ( poll _el , media _html ) ;
addEvent ( ge ( '.js-poll_option' , poll _el ) , 'click' , TWidgetPost . eSelectPollOption ) ;
addEvent ( ge ( '.js-poll_vote_btn' , poll _el ) , 'click' , TWidgetPost . eSendVotes ) ;
}
toggleClass ( poll _el , 'selected' , ge ( '.js-poll_option.selected' , poll _el ) . length > 0 ) ;
} ) ;
}
} ;
var TWidgetLogin = {
init : function ( id , bot _id , params , init _auth , lang ) {
initWidgetFrame ( {
auto _height : true ,
auto _width : true
} ) ;
TWidgetLogin . widgetEl = document . getElementById ( id ) ;
TWidgetLogin . botId = bot _id ;
TWidgetLogin . params = params ;
TWidgetLogin . lang = lang ;
var params _encoded = '' , params _arr = [ ] ;
for ( var k in params ) {
params _arr . push ( encodeURIComponent ( k ) + '=' + encodeURIComponent ( params [ k ] ) ) ;
}
TWidgetLogin . paramsEncoded = params _arr . join ( '&' ) ;
if ( init _auth ) {
TWidgetLogin . getAuth ( true ) ;
}
addEvent ( window , 'message' , function ( event ) {
try {
var data = JSON . parse ( event . data ) ;
} catch ( e ) {
var data = { } ;
}
if ( event . source !== TWidgetLogin . activePopup ) return ;
if ( data . event == 'auth_result' ) {
TWidgetLogin . onAuth ( data . origin , data . result ) ;
}
} ) ;
} ,
auth : function ( ) {
var width = 550 ;
var height = 470 ;
var left = Math . max ( 0 , ( screen . width - width ) / 2 ) + ( screen . availLeft | 0 ) ,
top = Math . max ( 0 , ( screen . height - height ) / 2 ) + ( screen . availTop | 0 ) ;
function checkClose ( ) {
if ( ! TWidgetLogin . activePopup || TWidgetLogin . activePopup . closed ) {
return TWidgetLogin . onClose ( ) ;
}
setTimeout ( checkClose , 100 ) ;
}
TWidgetLogin . activePopup = window . open ( '/auth?bot_id=' + TWidgetLogin . botId + ( TWidgetLogin . paramsEncoded ? '&' + TWidgetLogin . paramsEncoded : '' ) , 'telegram_oauth' , 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',status=0,location=0,menubar=0,toolbar=0' ) ;
TWidgetLogin . authFinished = false ;
if ( TWidgetLogin . activePopup ) {
TWidgetLogin . activePopup . focus ( ) ;
checkClose ( ) ;
}
} ,
getAuth : function ( init ) {
var xhr = getXHR ( ) ;
xhr . open ( 'POST' , '/auth/get?bot_id=' + TWidgetLogin . botId + ( TWidgetLogin . lang ? '&lang=' + encodeURIComponent ( TWidgetLogin . lang ) : '' ) ) ;
xhr . setRequestHeader ( 'Content-Type' , 'application/x-www-form-urlencoded; charset=UTF-8' ) ;
xhr . setRequestHeader ( 'X-Requested-With' , 'XMLHttpRequest' ) ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState == 4 ) {
if ( typeof xhr . responseBody == 'undefined' && xhr . responseText ) {
try {
var result = JSON . parse ( xhr . responseText ) ;
} catch ( e ) {
var result = { } ;
}
if ( result . html && TWidgetLogin . widgetEl . innerHTML != result . html ) {
TWidgetLogin . widgetEl . innerHTML = result . html ;
}
if ( result . user ) {
TWidgetLogin . onAuth ( result . origin , result . user , init ) ;
} else {
TWidgetLogin . onAuth ( result . origin , false , init ) ;
}
} else {
TWidgetLogin . onAuth ( '*' , false , init ) ;
}
}
} ;
xhr . onerror = function ( ) {
TWidgetLogin . onAuth ( '*' , false , init ) ;
} ;
xhr . withCredentials = true ;
xhr . send ( TWidgetLogin . paramsEncoded ) ;
} ,
onAuth : function ( origin , authData , init ) {
if ( TWidgetLogin . authFinished ) return ;
if ( authData ) {
var data = { event : 'auth_user' , auth _data : authData } ;
} else {
var data = { event : 'unauthorized' } ;
}
if ( init ) {
data . init = true ;
}
PostMessage . send ( data , origin ) ;
TWidgetLogin . authFinished = true ;
} ,
onClose : function ( ) {
TWidgetLogin . getAuth ( ) ;
}
} ;
window . TWidgetLogin = TWidgetLogin ;
var TStats = {
init : function ( ) {
if ( ! doesSupportEmoji ( ) ) {
removeClass ( document . body , 'emoji_default' ) ;
addClass ( document . body , 'emoji_image' ) ;
}
gec ( '.js-sticker_thumb' , function ( ) {
TSticker . init ( this ) ;
} ) ;
}
}
window . TStats = TStats ;
window . TWidget = {
initFrame : initWidgetFrame
} ;
} ) ( ) ;