1// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 2// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 3 4// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel 5 6// MIT license 7 8(function() { 9 var lastTime = 0; 10 var vendors = ['ms', 'moz', 'webkit', 'o']; 11 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 12 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 13 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 14 || window[vendors[x]+'CancelRequestAnimationFrame']; 15 } 16 17 if (!window.requestAnimationFrame) 18 window.requestAnimationFrame = function(callback, element) { 19 var currTime = new Date().getTime(); 20 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 21 var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 22 timeToCall); 23 lastTime = currTime + timeToCall; 24 return id; 25 }; 26 27 if (!window.cancelAnimationFrame) 28 window.cancelAnimationFrame = function(id) { 29 clearTimeout(id); 30 }; 31}()); 32 33 34 35/*! npm.im/iphone-inline-video 2.0.2 */ 36 37var enableInlineVideo=function(){"use strict";/*! npm.im/intervalometer */ 38function 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}(); 39 40if (!Array.isArray) { 41 Array.isArray = function(arg) { 42 return Object.prototype.toString.call(arg) === '[object Array]'; 43 }; 44} 45 46(!this.CustomEvent || typeof this.CustomEvent === "object") && (function() { 47 this.CustomEvent = function CustomEvent(type, eventInitDict) { 48 var event; 49 eventInitDict = eventInitDict || {bubbles: false, cancelable: false, detail: undefined}; 50 51 try { 52 event = document.createEvent('CustomEvent'); 53 event.initCustomEvent(type, eventInitDict.bubbles, eventInitDict.cancelable, eventInitDict.detail); 54 } catch (error) { 55 event = document.createEvent('Event'); 56 event.initEvent(type, eventInitDict.bubbles, eventInitDict.cancelable); 57 event.detail = eventInitDict.detail; 58 } 59 60 return event; 61 }; 62})(); 63 64var Keys = { 65 BACKSPACE: 8, 66 ESC: 27, 67 TAB: 9, 68 RETURN: 13, 69 LEFT: 37, 70 UP: 38, 71 RIGHT: 39, 72 DOWN: 40 73}; 74 75var TWidget = { 76 options: {}, 77 isFocused: false 78}; 79function inFrame() { 80 return (window.parent != null && window != window.parent); 81} 82function inFullFrame() { 83 return inFrame() && TWidget.options.auto_height; 84} 85function isFocused() { 86 return inFrame() ? TWidget.isFocused : document.hasFocus(); 87} 88 89function l(lang_key, params, def_value) { 90 if (typeof params === 'string') { 91 def_value = params; 92 params = {}; 93 } 94 params = params || {}; 95 var value = l._keys[lang_key] || def_value || lang_key; 96 value = value.replace(/\{([A-Za-z_\-\d]{1,32}):(.{1,256}?)\}/, function(lang_value, token, options) { 97 var number = +params[token] || 0; 98 var numeric_options = options.split('|'); 99 var i; 100 if (!number) i = 0; 101 else if (number == 1) i = 1; 102 else i = 2; 103 if (typeof numeric_options[i] === 'undefined') { 104 i = 0; 105 } 106 var numeric_option = numeric_options[i] || '#'; 107 return numeric_option.replace('#', number); 108 }); 109 for (var param in params) { 110 value = value.replace('{' + param + '}', params[param]); 111 } 112 return value; 113} 114l._keys = {}; 115l.add = function(lang_values) { 116 for (var lang_key in lang_values) { 117 l._keys[lang_key] = lang_values[lang_key]; 118 } 119} 120 121var PostMessage = { 122 _callbacks: {}, 123 _lastId: 0, 124 send: function(data, origin, callback) { 125 if (typeof origin === 'function') { 126 callback = origin; origin = null; 127 } 128 try { 129 if (callback) { 130 data._cb = ++PostMessage._lastId; 131 PostMessage._callbacks[data._cb] = callback; 132 } 133 134 window.parent.postMessage(JSON.stringify(data), origin || '*'); 135 } catch(e) {
136 if (origin) alert('Bot domain invalid'); 137 } 138 }, 139 onMessage: function(event) { 140 if (event.source !== window.parent) return; 141 try { 142 var data = JSON.parse(event.data); 143 } catch(e) { 144 var data = {}; 145 } 146 if (data.event == 'visible') { 147 if (!frameWasVisible) { 148 frameWasVisible = true; 149 TWidget.options.onVisible && TWidget.options.onVisible(); 150 } 151 PostMessage.send({event: 'visible_off'}); 152 } 153 else if (data.event == 'focus') { 154 TWidget.isFocused = data.has_focus; 155 triggerEvent(window, 'tg:focuschange'); 156 } 157 else if (data.event == 'set_options') { 158 triggerEvent(window, 'tg:optionschange', {detail: data.options}); 159 } 160 else if (data.event == 'visible') { 161 if (!frameWasVisible) { 162 frameWasVisible = true; 163 TWidget.options.onVisible && TWidget.options.onVisible(); 164 } 165 PostMessage.send({event: 'visible_off'}); 166 } 167 else if (data.event == 'callback') { 168 if (PostMessage._callbacks[data._cb]) { 169 PostMessage._callbacks[data._cb](data.value); 170 delete PostMessage._callbacks[data._cb]; 171 } else { 172 console.warn('Callback #' + data._cb + ' not found'); 173 } 174 } 175 } 176}; 177 178var TPopups = { 179 _list: [], 180 _lastId: 0, 181 _inited: false, 182 init: function() { 183 if (!TPopups._inited) { 184 TPopups._inited = true; 185 addEvent(document, 'keydown', function(e) { 186 if (e.keyCode == Keys.ESC && TPopups._list.length > 0) { 187 e.stopImmediatePropagation(); 188 e.preventDefault(); 189 TPopups.close(); 190 } 191 }); 192 } 193 }, 194 open: function(popup_el, options) { 195 TPopups.init(); 196 popup_el = ge1(popup_el); 197 if (!popup_el) { 198 return popup_el; 199 } 200 options = options || {}; 201 var popup_id = popup_el.__puid; 202 if (!popup_id) { 203 popup_id = ++TPopups._lastId; 204 popup_el.__puid = popup_id; 205 } 206 popup_el.__options = options; 207 var index = TPopups._list.indexOf(popup_id); 208 if (index >= 0) { 209 TPopups._list.splice(index, 1); 210 } 211 TPopups._list.push(popup_id); 212 document.body.style.overflow = 'hidden'; 213 document.body.appendChild(popup_el); 214 removeClass(popup_el, 'hide'); 215 TPopups.setPosition(popup_el); 216 if (document.activeElement) { 217 document.activeElement.blur(); 218 } 219 if (ge1('.js-popup_box', popup_el)) { 220 addEvent(popup_el, 'click', function(e) { 221 if (elInBody(e.target) && 222 !hasClass(e.target, 'js-popup_box') && 223 !gpeByClass(e.target, 'js-popup_box')) { 224 TPopups.close(popup_el); 225 } 226 }); 227 } 228 gec('.js-popup_close', function() { 229 addEvent(this, 'click', function() { 230 TPopups.close(popup_el); 231 }); 232 }, popup_el); 233 triggerEvent(popup_el, 'tg:popupopen'); 234 return popup_el; 235 }, 236 close: function(popup_el) { 237 if (!TPopups._list.length) return false; 238 var popup_id; 239 if (popup_el) { 240 popup_id = popup_el.__puid; 241 } else { 242 popup_id = TPopups._list.pop(); 243 gec('.js-popup_container', function() { 244 if (popup_id == this.__puid) { 245 popup_el = this; 246 return false; 247 } 248 }); 249 } 250 if (!popup_el) { 251 return false; 252 } 253 var options = popup_el.__options; 254 var index = TPopups._list.indexOf(popup_id); 255 if (index >= 0) { 256 TPopups._list.splice(index, 1); 257 } 258 if (!TPopups._list.length) { 259 document.body.style.overflow = ''; 260 } 261 removeEvent(popup_el, 'click'); 262 gec('.js-popup_close', function() { 263 removeEvent(this, 'click'); 264 }, popup_el); 265 addClass(popup_el, 'hide'); 266 triggerEvent(popup_el, 'tg:popupclose'); 267 }, 268 closeAll: function() { 269 while (TPopups._list.length) { 270 TPopups.close(); 271 } 272 }, 273 setPosition: function(popul_el) { 274 var popup_box = ge1('.js-popup_box', popul_el); 275 if (!popup_box) return; 276 getCoords(function(coords) { 277 var style = window.getComputedStyle(popul_el); 278 var contTop = parseInt(style.paddingTop); 279 var contBottom = parseInt(style.paddingBottom);
280 var marginMax = popul_el.offsetHeight - contTop - contBottom - coords.elHeight; 281 var frameTop = coords.frameTop || 0; 282 var deltaY = (coords.clientHeight - coords.elHeight) / 2; 283 var marginTop = deltaY - contTop - frameTop; 284 marginTop = Math.max(0, Math.min(marginMax, marginTop)); 285 popup_box.style.marginTop = marginTop + 'px'; 286 }, popup_box); 287 }, 288 show: function(html, buttons, options) { 289 options = options || {}; 290 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>'); 291 var text_el = ge1('.js-popup_text', popup_el); 292 var buttons_el = ge1('.js-popup_buttons', popup_el); 293 setHtml(text_el, html); 294 var enterBtn = null, onEnterPress = null; 295 for (var i = 0; i < buttons.length; i++) { 296 var btn = buttons[i]; 297 var button_el = newEl('div', 'tgme_popup_button' + (btn.close ? ' js-popup_close' : ''), btn.label); 298 btn.el = button_el; 299 buttons_el.appendChild(button_el); 300 if (btn.enter) { 301 enterBtn = button_el; 302 } 303 if (btn.onPress) { 304 addEvent(button_el, 'click', btn.onPress); 305 } 306 } 307 if (enterBtn) { 308 onEnterPress = function(e) { 309 if (e.keyCode == Keys.RETURN) { 310 e.stopImmediatePropagation(); 311 e.preventDefault(); 312 triggerEvent(enterBtn, 'click'); 313 } 314 }; 315 addEvent(document, 'keydown', onEnterPress); 316 } 317 var onPopupClose = function(e) { 318 if (enterBtn && onEnterPress) { 319 removeEvent(document, 'keydown', onEnterPress); 320 } 321 for (var i = 0; i < buttons.length; i++) { 322 var btn = buttons[i]; 323 if (btn.onPress) { 324 removeEvent(btn.el, 'click', btn.onPress); 325 } 326 } 327 removeEvent(popup_el, 'tg:popupclose', onPopupClose); 328 removeEl(popup_el); 329 }; 330 addEvent(popup_el, 'tg:popupclose', onPopupClose); 331 return TPopups.open(popup_el); 332 } 333}; 334 335function showAlert(html, onClose) { 336 return TPopups.show(html, [{ 337 label: l('WEB_CLOSE', 'Close'), 338 enter: true, 339 close: true 340 }]); 341} 342 343function showConfirm(html, onConfirm, confirm_btn) { 344 var popup_el = TPopups.show(html, [{ 345 label: l('WEB_CANCEL', 'Cancel'), 346 close: true 347 }, { 348 label: confirm_btn || l('WEB_OK', 'OK'), 349 onPress: function() { 350 onConfirm && onConfirm(popup_el); 351 TPopups.close(popup_el); 352 }, 353 enter: true 354 }]); 355 return popup_el; 356} 357 358function addEvent(el, event, handler) { 359 gec(el, function() { 360 var events = event.split(/\s+/); 361 for (var i = 0; i < events.length; i++) { 362 if (this.addEventListener) { 363 this.addEventListener(events[i], handler, false); 364 } else { 365 this.attachEvent('on' + events[i], handler); 366 } 367 } 368 }); 369} 370function removeEvent(el, event, handler) { 371 gec(el, function() { 372 var events = event.split(/\s+/); 373 for (var i = 0; i < events.length; i++) { 374 if (this.removeEventListener) { 375 this.removeEventListener(events[i], handler); 376 } else { 377 this.detachEvent('on' + events[i], handler); 378 } 379 } 380 }); 381} 382function triggerEvent(el, event_type, init_dict) { 383 gec(el, function() { 384 var event = new CustomEvent(event_type, init_dict); 385 this.dispatchEvent(event); 386 }); 387} 388 389function geById(el_or_id) { 390 if (typeof el_or_id == 'string' || el_or_id instanceof String) { 391 return document.getElementById(el_or_id); 392 } else if (el_or_id instanceof HTMLElement) { 393 return el_or_id; 394 } 395 return null; 396} 397 398function gec(el, callback, context) { 399 var list = ge(el, context); 400 for (var i = 0, l = list.length; i < l; i++) { 401 var result = callback.call(list[i], list[i], i, list); 402 if (result === false) { 403 break; 404 } 405 } 406} 407function ge(el, context) { 408 var list = []; 409 if (typeof el === 'string') { 410 list = (ge1(context) || document).querySelectorAll(el); 411 } else if (el instanceof Node || el instanceof Window) { 412 list = [el]; 413 } else if (Array.isArray(el)) { 414 list = el; 415 } else if (el) { 416 console.warn('unknown type of el', el); 417 return [el]; 418 } 419 if (list instanceof NodeList) { 420 list = Array.prototype.slice.call(list); 421 } 422 return list; 423} 424function ge1(el, context) { 425 if (typeof el === 'string') { 426 return (ge1(context) || document).querySelector(el); 427 } else if (el instanceof Node || el instanceof Window) { 428 return el; 429 } else if (el instanceof NodeList) { 430 return el.item(0); 431 } else if (el instanceof Array) { 432 return el[0]; 433 } else if (el) { 434 console.warn('unknown type of el', el); 435 return el; 436 } 437 return null; 438} 439function newEl(tag, cl, html, styles) { 440 var el = document.createElement((tag || 'DIV').toUpperCase()); 441 if (cl) el.className = cl; 442 if (styles) { 443 for (var k in styles) { 444 el.style[k] = styles[k]; 445 } 446 } 447 if (html) { 448 el.innerHTML = html; 449 } 450 return el; 451} 452function gpeByClass(el, cl) { 453 if (!el) return null; 454 while (el = el.parentNode) { 455 if (hasClass(el, cl)) break; 456 } 457 return el || null; 458} 459function elInBody(el) { 460 if (!el) return false; 461 while (el = el.parentNode) { 462 if (el === document.body) return true; 463 } 464 return false; 465} 466 467function getCoords(callback, el) { 468 var rect = {}; 469 if (el = ge1(el)) { 470 rect = el.getBoundingClientRect(); 471 } 472 var docEl = document.documentElement; 473 var coords = {}; 474 if (inFullFrame()) { 475 PostMessage.send({event: 'get_coords'}, function(coords) { 476 coords.inFrame = true; 477 if (el) { 478 coords.elTop = rect.top + coords.frameTop; 479 coords.elBottom = rect.bottom + coords.frameTop; 480 coords.elLeft = rect.left + coords.frameLeft; 481 coords.elRight = rect.right + coords.frameLeft; 482 coords.elWidth = rect.width; 483 coords.elHeight = rect.height; 484 } 485 callback && callback(coords);
486 }); 487 return; 488 } else { 489 if (el) { 490 coords.elTop = rect.top; 491 coords.elBottom = rect.bottom; 492 coords.elLeft = rect.left; 493 coords.elRight = rect.right; 494 coords.elWidth = rect.width; 495 coords.elHeight = rect.height; 496 } 497 coords.scrollTop = window.pageYOffset; 498 coords.scrollLeft = window.pageXOffset; 499 coords.clientWidth = docEl.clientWidth; 500 coords.clientHeight = docEl.clientHeight; 501 callback && callback(coords); 502 } 503} 504function scrollToY(y) { 505 if (inFullFrame()) { 506 PostMessage.send({event: 'scroll_to', y: y}); 507 } else { 508 window.scrollTo(0, y); 509 } 510} 511 512function addClass(el, cl) { 513 gec(el, function() { 514 var cls = cl.split(/\s+/); 515 for (var i = 0; i < cls.length; i++) { 516 this.classList.add(cls[i]); 517 } 518 }); 519} 520function removeClass(el, cl) { 521 gec(el, function() { 522 var cls = cl.split(/\s+/); 523 for (var i = 0; i < cls.length; i++) { 524 this.classList.remove(cls[i]); 525 } 526 }); 527} 528function toggleClass(el, cl, add) { 529 gec(el, function() { 530 var cls = cl.split(/\s+/); 531 for (var i = 0; i < cls.length; i++) { 532 cl = cls[i]; 533 var add_cl = (typeof add !== 'undefined') ? add : !hasClass(this, cl); 534 add_cl ? this.classList.add(cl) : this.classList.remove(cl); 535 } 536 }); 537} 538function hasClass(el, cl) { 539 var item = ge1(el); 540 return (item && item.classList && item.classList.contains(cl)); 541} 542function removeEl(el) { 543 gec(el, function() { 544 if (this && this.parentNode) { 545 this.parentNode.removeChild(this); 546 } 547 }); 548} 549function getHtml(el, context) { 550 var item = ge1(el, context); 551 return item ? item.innerHTML : null; 552} 553function setHtml(el, html) { 554 gec(el, function() { 555 if (this) { 556 this.innerHTML = html; 557 } 558 }); 559} 560function getAttr(el, attr) { 561 var item = ge1(el); 562 return item ? item.getAttribute(attr) : null; 563} 564function setAttr(el, attr, value) { 565 gec(el, function() { 566 if (this) { 567 this.setAttribute(attr, value); 568 } 569 }); 570} 571 572function isLSEnabled() { 573 try { 574 return window.localStorage ? true : false; 575 } catch (e) { 576 return false; 577 } 578} 579function parseHeaders(headers) { 580 var headers_strs = headers.replace(/^\s+|\s+$/g, '').split(/[\r\n]+/); 581 var headers_arr = []; 582 for (var i = 0; i < headers_strs.length; i++) { 583 var header_str = headers_strs[i]; 584 var parts = header_str.split(': '); 585 var name = parts.shift().toLowerCase(); 586 var value = parts.join(': '); 587 headers_arr.push({name: name, value: value}); 588 } 589 return headers_arr; 590} 591function setLS(xhr) { 592 if (!isLSEnabled()) return; 593 try { 594 var headers = parseHeaders(xhr.getAllResponseHeaders()); 595 for (var i = 0; i < headers.length; i++) { 596 var header = headers[i]; 597 if (header.name == 'x-set-local-storage') { 598 var arr = header.value.split('='); 599 var key = decodeURIComponent(arr[0]); 600 var val = decodeURIComponent(arr[1]); 601 if (val.length) { 602 localStorage.setItem(key, val); 603 } else { 604 localStorage.removeItem(key); 605 } 606 } 607 } 608 } catch (e) {} 609} 610function getLSString() { 611 if (!isLSEnabled()) return false; 612 var arr = []; 613 for (var i = 0; i < localStorage.length; i++) { 614 var key = localStorage.key(i); 615 arr.push(encodeURIComponent(key) + '=' + encodeURIComponent(localStorage[key])); 616 } 617 return arr.join('; '); 618} 619 620function getXHR() { 621 if (navigator.appName == "Microsoft Internet Explorer"){ 622 return new ActiveXObject("Microsoft.XMLHTTP"); 623 } else { 624 return new XMLHttpRequest(); 625 } 626} 627 628function xhrRequest(href, postdata, onCallback, retry_delay) { 629 var xhr = getXHR(), type = 'GET', data = null, ls_header; 630 if (postdata !== false) { 631 type = 'POST'; 632 var data_arr = []; 633 for (var field in postdata) { 634 data_arr.push(encodeURIComponent(field) + '=' + encodeURIComponent(postdata[field])); 635 } 636 data = data_arr.join('&'); 637 } 638 xhr.open(type, href); 639 if (postdata !== false) { 640 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 641 } 642 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 643 if (ls_header = getLSString()) { 644 xhr.setRequestHeader('X-Local-Storage', ls_header); 645 } 646 xhr.onerror = function() { 647 if (xhr._retried) return; 648 xhr._retried = true; 649 retry_delay = retry_delay || 1000; 650 if (retry_delay > 60000) { 651 onCallback && onCallback('Server unavailable'); 652 return; 653 } 654 setTimeout(function() { 655 xhrRequest(href, postdata, onCallback, retry_delay * 2); 656 }, retry_delay); 657 }; 658 xhr.onreadystatechange = function() { 659 if (xhr.readyState == 4) { 660 setLS(xhr); 661 if (typeof xhr.responseBody == 'undefined' && xhr.responseText) { 662 try { 663 var result = JSON.parse(xhr.responseText); 664 } catch(e) { 665 var result = {}; 666 } 667 if (xhr.status == 401) { // Unauthorized 668 TWidgetAuth.reload(); 669 return; 670 } 671 if (result.error && result.flood_wait) { 672 console.log('flood_wait', result.flood_wait); 673 setTimeout(function() { 674 xhrRequest(href, postdata, onCallback); 675 }, result.flood_wait * 1000); 676 return; 677 } 678 onCallback && onCallback(null, result); 679 } else { 680 xhr.onerror(); 681 } 682 } 683 }; 684 xhr.withCredentials = true; 685 xhr.send(data); 686 return xhr; 687} 688 689function xhrUploadRequest(href, params, onCallback, onProgress) { 690 var xhr = getXHR(), data = new FormData(), ls_header; 691 xhr.open('POST', href, true); 692 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 693 if (ls_header = getLSString()) { 694 xhr.setRequestHeader('X-Local-Storage', ls_header); 695 } 696 xhr.upload.addEventListener('progress', function(event) { 697 if (event.lengthComputable) { 698 onProgress && onProgress(event.loaded, event.total); 699 } 700 }); 701 xhr.onerror = function() { 702 onCallback && onCallback('Server unavailable'); 703 }; 704 xhr.onreadystatechange = function() { 705 if (xhr.readyState == 4) { 706 setLS(xhr); 707 if (typeof xhr.responseBody == 'undefined' && xhr.responseText) { 708 try { 709 var result = JSON.parse(xhr.responseText); 710 } catch(e) { 711 var result = {}; 712 } 713 if (result.error && result.flood_wait) { 714 console.log('flood_wait', result.flood_wait); 715 setTimeout(function() { 716 xhrUploadRequest(href, params, onCallback, onProgress); 717 }, result.flood_wait * 1000); 718 return; 719 } 720 onCallback && onCallback(null, result); 721 } else { 722 xhr.onerror(); 723 } 724 } 725 }; 726 for (var k in params) { 727 var value = params[k]; 728 if (value instanceof File) { 729 data.append(k, value, value.name); 730 } else { 731 data.append(k, value); 732 } 733 } 734 xhr.withCredentials = true; 735 xhr.send(data); 736 return xhr; 737} 738 739window.TWidgetAuth = { 740 init: function(options) { 741 options = options || {}; 742 TWidgetAuth.options = options; 743 }, 744 apiRequest: function(method, params, callback) { 745 var options = TWidgetAuth.options || {}; 746 if (!options.api_url) { 747 console.warn('API url not found'); 748 return null; 749 } 750 params.method = method; 751 return xhrRequest(options.api_url, params, callback); 752 }, 753 uploadRequest: function(params, onCallback, onProgress) { 754 var options = TWidgetAuth.options || {}; 755 if (!options.upload_url) { 756 console.warn('Upload url not found'); 757 return null; 758 } 759 return xhrUploadRequest(options.upload_url, params, onCallback, onProgress); 760 }, 761 logIn: function() { 762 var options = TWidgetAuth.options || {}; 763 if (!options.bot_id) { 764 console.warn('Bot id not found'); 765 return; 766 } 767 if (TWidgetAuth.isLoggedIn()) { 768 return; 769 } 770 Telegram.Login.auth({bot_id: options.bot_id, lang: 'en'}, function(user) { 771 if (user) { 772 xhrRequest('/auth', user, function(err, result) { 773 if (result.ok) { 774 TWidgetAuth.reload(result.host); 775 } else { 776 location.reload(); 777 } 778 }); 779 } 780 });
781 }, 782 reload: function(host, callback) { 783 var xhr = getXHR(), data = null, ls_header; 784 var url = location.href; 785 if (host) { 786 var a = newEl('a'); 787 a.href = url; a.hostname = host; url = a.href; 788 } 789 xhr.open('GET', url); 790 xhr.setRequestHeader('X-Requested-With', 'relogin'); 791 if (ls_header = getLSString()) { 792 xhr.setRequestHeader('X-Local-Storage', ls_header); 793 } 794 xhr.onreadystatechange = function() { 795 if (xhr.readyState == 4) { 796 setLS(xhr); 797 if (typeof xhr.responseBody == 'undefined' && xhr.responseText) { 798 document.open(); 799 document.write(xhr.responseText); 800 document.close(); 801 callback && callback(); 802 } else { 803 location.reload(); 804 } 805 } 806 }; 807 xhr.onerror = function() { 808 location.reload(); 809 }; 810 xhr.withCredentials = true; 811 xhr.send(); 812 }, 813 isLoggedIn: function() { 814 var options = TWidgetAuth.options || {}; 815 return options && !options.unauth; 816 } 817}; 818window.apiRequest = TWidgetAuth.apiRequest; 819window.uploadRequest = TWidgetAuth.uploadRequest; 820 821function loadImage(file, callback) { 822 var image = new Image(); 823 image.onload = function() { 824 var w = image.naturalWidth; 825 var h = image.naturalHeight; 826 callback && callback(null, { 827 url: image.src, 828 width: w, 829 height: h, 830 image: image 831 }); 832 }; 833 image.onerror = function() { 834 callback && callback('LOAD_FAILED'); 835 }; 836 image.src = URL.createObjectURL(file); 837} 838 839function initWidgetFrame(options) { 840 TWidget.options = options || {}; 841 if (window.devicePixelRatio >= 2) { 842 addClass(document.body, 'r2x'); 843 } 844 if (TWidget.options.auto_height || 845 TWidget.options.auto_width) { 846 addEvent(window, 'resize', checkFrameSize); 847 checkFrameSize(); 848 } 849 addEvent(window, 'message', PostMessage.onMessage); 850 addEvent(window, 'focus blur', function() { 851 triggerEvent(window, 'tg:focuschange'); 852 }); 853 PostMessage.send({event: 'ready'}); 854} 855 856var frameLastHeight = null, 857 frameLastWidth = null, 858 frameWasVisible = false; 859function checkFrameSize() { 860 var height, width, style; 861 if (document.body) { 862 if (window.getComputedStyle) { 863 style = window.getComputedStyle(document.body); 864 height = style.height; 865 if (height.substr(-2) == 'px') { 866 height = height.slice(0, -2); 867 } 868 width = style.width; 869 if (width.substr(-2) == 'px') { 870 width = width.slice(0, -2); 871 } 872 } else { 873 height = document.body.offsetHeight; 874 width = document.body.offsetWidth; 875 } 876 var data = {event: 'resize'}, resized = false; 877 if (TWidget.options.auto_height) { 878 height = Math.ceil(height); 879 if (height != frameLastHeight) { 880 frameLastHeight = height; 881 data.height = height; 882 resized = true; 883 } 884 } 885 if (TWidget.options.auto_width) { 886 width = Math.ceil(width); 887 if (width != frameLastWidth) { 888 frameLastWidth = width; 889 data.width = width; 890 resized = true; 891 } 892 } 893 if (resized) { 894 PostMessage.send(data); 895 } 896 } 897 requestAnimationFrame(checkFrameSize); 898} 899 900 901(function() { 902 var ua = navigator.userAgent.toLowerCase(); 903 var browser = { 904 opera: (/opera/i.test(ua) || /opr/i.test(ua)), 905 msie: (/msie/i.test(ua) && !/opera/i.test(ua) || /trident\//i.test(ua)) || /edge/i.test(ua), 906 msie_edge: (/edge/i.test(ua) && !/opera/i.test(ua)), 907 mozilla: /firefox/i.test(ua), 908 chrome: /chrome/i.test(ua) && !/edge/i.test(ua), 909 safari: (!(/chrome/i.test(ua)) && /webkit|safari|khtml/i.test(ua)), 910 iphone: /iphone/i.test(ua), 911 ipod: /ipod/i.test(ua), 912 ipad: /ipad/i.test(ua), 913 android: /android/i.test(ua), 914 mobile: /iphone|ipod|ipad|opera mini|opera mobi|iemobile|android/i.test(ua), 915 safari_mobile: /iphone|ipod|ipad/i.test(ua),
916 opera_mobile: /opera mini|opera mobi/i.test(ua), 917 opera_mini: /opera mini/i.test(ua), 918 mac: /mac/i.test(ua), 919 }; 920 var TBaseUrl = window.TBaseUrl || '//telegram.org/'; 921 922 function formatDateTime(datetime) { 923 var date = new Date(datetime); 924 var cur_date = new Date(); 925 if (cur_date.getFullYear() == date.getFullYear() && 926 cur_date.getMonth() == date.getMonth() && 927 cur_date.getDate() == date.getDate()) { 928 return formatTime(datetime); 929 } 930 return formatDate(datetime); 931 } 932 933 function formatDate(datetime) { 934 var date = new Date(datetime); 935 var cur_date = new Date(); 936 var j = date.getDate(); 937 var M = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][date.getMonth()]; 938 var Y = date.getFullYear(); 939 if (cur_date.getFullYear() == date.getFullYear()) { 940 return M + ' ' + j; 941 } 942 return M + ' ' + j + ', ' + Y; 943 } 944 945 function formatTime(datetime) { 946 var date = new Date(datetime); 947 var H = date.getHours(); 948 if (H < 10) H = '0' + H; 949 var i = date.getMinutes(); 950 if (i < 10) i = '0' + i; 951 return H + ':' + i; 952 } 953 954 function formatDuration(duration) { 955 duration = Math.floor(duration); 956 duration = Math.max(0, duration); 957 var duration_str = ''; 958 if (duration >= 3600) { 959 var hours = Math.floor(duration / 3600); 960 duration_str += hours + ':'; 961 var minutes = Math.floor((duration % 3600) / 60); 962 if (minutes < 10) minutes = '0' + minutes; 963 } else { 964 var minutes = Math.floor(duration / 60); 965 } 966 duration_str += minutes + ':'; 967 var seconds = duration % 60; 968 if (seconds < 10) seconds = '0' + seconds; 969 duration_str += seconds; 970 return duration_str; 971 } 972 973 function doesSupportEmoji() { 974 var context, smile, canvas = document.createElement('canvas'); 975 if (!canvas.getContext) return false; 976 context = canvas.getContext('2d'); 977 if (typeof context.fillText != 'function') return false; 978 smile = '#' + String.fromCharCode(65039) + String.fromCharCode(8419); 979 context.textBaseline = 'top'; 980 context.font = '32px Arial'; 981 context.fillText(smile, 0, 0); 982 if (context.getImageData(16, 16, 1, 1).data[0] === 0) return false; 983 var div = document.createElement('div'); 984 div.style.position = 'absolute'; 985 div.style.overflow = 'hidden'; 986 div.style.top = '-1000px'; 987 var span = document.createElement('span'); 988 div.style.fontSize = '16px'; 989 span.innerHTML = smile; 990 div.appendChild(span); 991 document.body.insertBefore(div, document.body.firstChild); 992 var width = span.offsetWidth; 993 document.body.removeChild(div); 994 if (width < 18) return false; 995 return true; 996 } 997 998 function cloneArr(arrLike) { 999 return Array.prototype.slice.apply(arrLike); 1000 } 1001 1002 var loadedLibs = {}; 1003 function loadLib(file, callback) { 1004 if (!loadedLibs[file]) { 1005 loadedLibs[file] = { 1006 loaded: null, 1007 callbacks: [callback] 1008 }; 1009 var script = document.createElement('script'); 1010 script.type = 'text/javascript'; 1011 script.async = true; 1012 script.src = file; 1013 script.onerror = function() { 1014 loadedLibs[file].loaded = false; 1015 applyCallbacks(loadedLibs[file].callbacks, loadedLibs[file].loaded); 1016 } 1017 script.onload = function() { 1018 loadedLibs[file].loaded = true; 1019 applyCallbacks(loadedLibs[file].callbacks, loadedLibs[file].loaded); 1020 } 1021 var head = document.getElementsByTagName('head')[0]; 1022 head.appendChild(script); 1023 return script; 1024 } else if (loadedLibs[file].loaded === null) { 1025 loadedLibs[file].callbacks.push(callback); 1026 } else { 1027 callback(loadedLibs[file].loaded); 1028 } 1029 }; 1030 1031 var webpNativeSupport = null, webpFallbackSupport = null, webpImage = null, webpCallbacks = []; 1032 function applyCallbacks(callbacks) { 1033 var args = cloneArr(arguments); args.shift(); 1034 for (var i = 0; i < callbacks.length; i++) { 1035 callbacks[i].apply(null, args); 1036 } 1037 } 1038 function doesSupportWebp(callback) { 1039 if (webpFallbackSupport !== null) { 1040 callback(webpNativeSupport, webpFallbackSupport); 1041 } else { 1042 webpCallbacks.push(callback); 1043 if (!webpImage) { 1044 webpImage = new Image(); 1045 webpImage.onerror = webpImage.onload = function() { 1046 if (this.width === 2 && this.height === 1) { 1047 webpNativeSupport = true; 1048 webpFallbackSupport = false; 1049 applyCallbacks(webpCallbacks, webpNativeSupport, webpFallbackSupport); 1050 } else { 1051 webpNativeSupport = false; 1052 var script = document.createElement('script'); 1053 script.type = 'text/javascript'; 1054 script.async = true; 1055 script.src = TBaseUrl + 'js/libwebp-0.2.0.js'; 1056 script.onerror = function() { 1057 webpFallbackSupport = false; 1058 applyCallbacks(webpCallbacks, webpNativeSupport, webpFallbackSupport); 1059 } 1060 script.onload = function() { 1061 webpFallbackSupport = true; 1062 applyCallbacks(webpCallbacks, webpNativeSupport, webpFallbackSupport); 1063 } 1064 var head = document.getElementsByTagName('head')[0]; 1065 head.appendChild(script); 1066 } 1067 } 1068 webpImage.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56
1068QAAAAA=='; 1069 } 1070 } 1071 } 1072 1073 function getPngDataUrlFromWebp(data) { 1074 var decoder = new WebPDecoder(); 1075 var config = decoder.WebPDecoderConfig; 1076 var buffer = config.j || config.output; 1077 var bitstream = config.input; 1078 if (!decoder.WebPInitDecoderConfig(config)) { 1079 throw new Error('[webpjs] Library version mismatch!'); 1080 } 1081 var StatusCode = decoder.VP8StatusCode; 1082 status = decoder.WebPGetFeatures(data, data.length, bitstream); 1083 if (status != (StatusCode.VP8_STATUS_OK || 0)) { 1084 throw new Error('[webpjs] status error'); 1085 } 1086 var mode = decoder.WEBP_CSP_MODE; 1087 buffer.colorspace = mode.MODE_RGBA; 1088 buffer.J = 4; 1089 try { 1090 status = decoder.WebPDecode(data, data.length, config); 1091 } catch (e) { 1092 status = e 1093 } 1094 var ok = (status == 0); 1095 if (!ok) { 1096 throw new Error('[webpjs] decoding failed'); 1097 } 1098 var bitmap = buffer.c.RGBA.ma; 1099 if (!bitmap) { 1100 throw new Error('[webpjs] bitmap error'); 1101 } 1102 var biHeight = buffer.height; 1103 var biWidth = buffer.width; 1104 var canvas = document.createElement('canvas'); 1105 var context = canvas.getContext('2d'); 1106 canvas.height = biHeight; 1107 canvas.width = biWidth; 1108 var output = context.createImageData(canvas.width, canvas.height); 1109 var outputData = output.data; 1110 for (var h = 0; h < biHeight; h++) { 1111 for (var w = 0; w < biWidth; w++) { 1112 outputData[0 + w * 4 + (biWidth * 4) * h] = bitmap[1 + w * 4 + (biWidth * 4) * h]; 1113 outputData[1 + w * 4 + (biWidth * 4) * h] = bitmap[2 + w * 4 + (biWidth * 4) * h]; 1114 outputData[2 + w * 4 + (biWidth * 4) * h] = bitmap[3 + w * 4 + (biWidth * 4) * h]; 1115 outputData[3 + w * 4 + (biWidth * 4) * h] = bitmap[0 + w * 4 + (biWidth * 4) * h]; 1116 } 1117 } 1118 context.putImageData(output, 0, 0); 1119 return canvas.toDataURL('image/png'); 1120 } 1121 1122 function proccessWebpImage(imgEl, failed_callback, success_callback) { 1123 var imgEl = geById(imgEl); 1124 if (!imgEl || imgEl.__inited) return; 1125 imgEl.__inited = true; 1126 failed_callback = failed_callback || function(){}; 1127 success_callback = success_callback || function(){}; 1128 doesSupportWebp(function(nativeSupport, fallbackSupport) { 1129 if (nativeSupport) { 1130 success_callback(); 1131 return; 1132 } else if (!fallbackSupport) { 1133 failed_callback(); 1134 return; 1135 } 1136 if (hasClass(imgEl, 'webp_sticker_done')) { 1137 success_callback(); 1138 return; 1139 } 1140 var isImage, src; 1141 if (imgEl.tagName && imgEl.tagName.toUpperCase() == 'IMG' && imgEl.src) { 1142 isImage = true; 1143 src = imgEl.src; 1144 } else { 1145 isImage = false; 1146 var bgImage; 1147 if (window.getComputedStyle) { 1148 bgImage = window.getComputedStyle(imgEl).backgroundImage; 1149 } else { 1150 bgImage = imgEl.style && imgEl.style.backgroundImage; 1151 } 1152 src = bgImage.slice(4, -1).replace(/["|']/g, ''); 1153 } 1154 if (!src) { 1155 failed_callback(); 1156 return; 1157 } 1158 var xhr = getXHR(); 1159 xhr.open('get', src); 1160 if (xhr.overrideMimeType) { 1161 xhr.overrideMimeType('text/plain; charset=x-user-defined'); 1162 } else { 1163 xhr.setRequestHeader('Accept-Charset', 'x-user-defined'); 1164 } 1165 xhr.onreadystatechange = function() { 1166 if (xhr.readyState == 4) { 1167 if (typeof xhr.responseBody == 'undefined' && xhr.responseText) { 1168 var rlen = xhr.responseText.length, uarr = new Uint8Array(rlen); 1169 for (var i = 0; i < rlen; i++) { 1170 uarr[i] = xhr.responseText.charCodeAt(i); 1171 } 1172 try { 1173 var src = getPngDataUrlFromWebp(uarr); 1174 if (isImage) { 1175 imgEl.src = src; 1176 } else { 1177 imgEl.style.backgroundImage = "url('" + src + "')"; 1178 } 1179 addClass(imgEl, 'webp_sticker_done'); 1180 success_callback(); 1181 } catch(e) { 1182 failed_callback(); 1183 } 1184 } else { 1185 failed_callback(); 1186 } 1187 } 1188 }; 1189 xhr.send(null); 1190 });
1191 } 1192 1193 function checkVideo(el, error_callback) { 1194 var timeout, eventAdded; 1195 if (!eventAdded) { 1196 function destroyCheck() { 1197 clearTimeout(timeout); 1198 removeEvent(el, 'canplay', onCanPlay); 1199 removeEvent(el, 'error', onError); 1200 } 1201 function onCanPlay() { 1202 destroyCheck(); 1203 } 1204 function onError() { 1205 destroyCheck(); 1206 error_callback(); 1207 } 1208 eventAdded = true; 1209 addEvent(el, 'canplay', onCanPlay); 1210 addEvent(el, 'error', onError); 1211 } 1212 if (el.readyState >= 2) { 1213 destroyCheck(); 1214 } else { 1215 timeout = setTimeout(function() { 1216 checkVideo(el, error_callback); 1217 }, 50); 1218 } 1219 } 1220 1221 window.TPost = { 1222 init: function(postEl, options) { 1223 postEl = geById(postEl); 1224 options = options || {}; 1225 if (!postEl || postEl.__inited) return; 1226 postEl.__inited = true; 1227 gec('time[datetime]', function() { 1228 var datetime = this.getAttribute('datetime'); 1229 if (datetime) { 1230 if (hasClass(this, 'datetime')) { 1231 this.innerHTML = formatDate(datetime) + ' at ' + formatTime(datetime); 1232 } else if (hasClass(this, 'time')) { 1233 this.innerHTML = formatTime(datetime); 1234 } else { 1235 this.innerHTML = formatDateTime(datetime); 1236 } 1237 } 1238 }, postEl); 1239 gec('.js-message_footer.compact', function() { 1240 var timeEl = ge1('time[datetime]', this) 1241 , textEl = this.previousElementSibling; 1242 if (textEl && !textEl.__inited && hasClass(textEl, 'js-message_text')) { 1243 var text_rect = textEl.getBoundingClientRect(); 1244 var tnode = textEl.firstChild; 1245 while (tnode && tnode.nodeType == tnode.ELEMENT_NODE) { 1246 tnode = tnode.firstChild; 1247 } 1248 if (tnode) { 1249 var r = document.createRange(); 1250 r.setStart(tnode, 0); 1251 r.setEnd(tnode, 1); 1252 var char_rect = r.getBoundingClientRect(); 1253 textEl.__inited = true; 1254 if (Math.abs(char_rect.right - text_rect.right) > 3) { 1255 var infoEl = ge1('.js-message_info', this); 1256 if (infoEl) { 1257 var shadowEl = document.createElement('span'); 1258 shadowEl.style.display = 'inline-block'; 1259 shadowEl.style.width = infoEl.offsetWidth + 'px'; 1260 textEl.appendChild(shadowEl); 1261 addClass(textEl, 'before_footer'); 1262 } 1263 } 1264 } 1265 } 1266 }, postEl); 1267 gec('.js-message_video_player', function() { 1268 TVideo.init(this); 1269 }, postEl); 1270 gec('.js-message_photo', function() { 1271 TPhoto.init(this); 1272 }, postEl); 1273 gec('.js-message_grouped_wrap', function() { 1274 TGrouped.init(this); 1275 }, postEl); 1276 gec('.js-message_roundvideo_player', function() { 1277 TRoundVideo.init(this); 1278 }, postEl); 1279 gec('.js-message_voice_player', function() { 1280 TVoice.init(this); 1281 }, postEl); 1282 gec('.js-sticker_image', function() { 1283 TSticker.init(this, function() { 1284 addClass(postEl, 'media_not_supported'); 1285 removeClass(postEl, 'no_bubble'); 1286 }); 1287 }, postEl); 1288 gec('.js-sticker_thumb', function() { 1289 TSticker.init(this); 1290 }, postEl); 1291 gec('.js-tgsticker_image', function() { 1292 if (options.tgs_workers_limit) { 1293 RLottie.WORKERS_LIMIT = options.tgs_workers_limit; 1294 } else if (options.frame) { 1295 RLottie.WORKERS_LIMIT = 1; 1296 } 1297 RLottie.init(this, { 1298 playOnce: this.hasAttribute('data-play-once') 1299 }); 1300 }, postEl); 1301 }, 1302 view: function(postEl) { 1303 postEl = geById(postEl); 1304 if (!postEl) return; 1305 var view = postEl.getAttribute('data-view'); 1306 if (view) { 1307 var xhr = getXHR(); 1308 xhr.open('get', '/v/?views=' + encodeURIComponent(view)); 1309 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 1310 xhr.send(null); 1311 } 1312 } 1313 }; 1314 1315 var TPhoto = window.TPhoto = { 1316 init: function(photoEl) { 1317 photoEl = geById(photoEl); 1318 if (!photoEl || photoEl.__inited) return; 1319 photoEl.__inited = true; 1320 var inGroup = hasClass(photoEl, 'grouped_media_wrap') 1321 , opened 1322 , overTo; 1323 if (inGroup) { 1324 addEvent(photoEl, 'click', function togglePhoto(e) { 1325 if (e.metaKey || e.ctrlKey) return true; 1326 e.stopPropagation(); 1327 if (!photoEl) return true; 1328 if (opened) { 1329 opened = false; 1330 removeClass(photoEl, 'active'); 1331 overTo = setTimeout(function() { 1332 removeClass(photoEl, 'over'); 1333 }, 200); 1334 } else { 1335 opened = true; 1336 clearTimeout(overTo); 1337 addClass(photoEl, 'over active'); 1338 } 1339 e.preventDefault(); 1340 return false; 1341 }); 1342 } 1343 } 1344 }; 1345 1346 var TVideo = window.TVideo = { 1347 init: function(playerEl) { 1348 playerEl = geById(playerEl); 1349 if (!playerEl || playerEl.__inited) return; 1350 playerEl.__inited = true; 1351 var videoEl = ge1('.js-message_video', playerEl) 1352 , videoBluredEl = ge1('.js-message_video_blured', playerEl) 1353 , playEl = ge1('.js-message_video_play', playerEl) 1354 , durationEl = ge1('.js-message_video_duration', playerEl) 1355 , inGroup = hasClass(playerEl, 'grouped_media_wrap') 1356 , looped 1357 , overTo; 1358 if (!videoEl) return; 1359 1360 looped = videoEl.hasAttribute('loop'); 1361 if (inGroup) { 1362 addEvent(playerEl, 'click', function videoToggleInGroup(e) { 1363 if (e.metaKey || e.ctrlKey) return true; 1364 if (hasClass(e.target, 'message_media_view_in_telegram')) return true; 1365 e.stopPropagation(); 1366 if (!playerEl) return true; 1367 if (hasClass(playerEl, 'active')) { 1368 removeClass(playerEl, 'active'); 1369 overTo = setTimeout(function() { 1370 removeClass(playerEl, 'over'); 1371 }, 200); 1372 } else { 1373 clearTimeout(overTo); 1374 addClass(playerEl, 'over active'); 1375 } 1376 e.preventDefault(); 1377 return false; 1378 }); 1379 } 1380 if (videoEl.hasAttribute('playsinline')) { 1381 enableInlineVideo(videoEl); 1382 if (videoBluredEl) { 1383 enableInlineVideo(videoBluredEl); 1384 } 1385 }
1386 function fixControls() { 1387 if (videoEl.controls) videoEl.controls = false; 1388 } 1389 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 1390 if (MutationObserver) { 1391 (new MutationObserver(fixControls)).observe(videoEl, {attributes: true}); 1392 } 1393 1394 checkVideo(videoEl, function() { 1395 addClass(playerEl, 'not_supported'); 1396 }); 1397 addEvent(videoEl, 'play', function() { 1398 fixControls(); 1399 addClass(playerEl, 'playing'); 1400 if (inGroup) { 1401 clearTimeout(overTo); 1402 addClass(playerEl, 'over active'); 1403 } 1404 if (videoBluredEl) { 1405 videoBluredEl.currentTime = videoEl.currentTime; 1406 if (!browser.mobile) { 1407 videoBluredEl.play(); 1408 } 1409 } 1410 if (!looped) { 1411 triggerEvent(videoEl, 'tg:play', {bubbles: true}); 1412 } 1413 }); 1414 addEvent(document, 'tg:play', function(e) { 1415 if (e.target === videoEl || looped) return true; 1416 if (!videoEl.paused) { 1417 videoEl.pause(); 1418 if (videoBluredEl) { 1419 videoBluredEl.pause(); 1420 } 1421 } 1422 }); 1423 addEvent(videoEl, 'pause', function() { 1424 fixControls(); 1425 removeClass(playerEl, 'playing'); 1426 if (inGroup) { 1427 removeClass(playerEl, 'active'); 1428 overTo = setTimeout(function() { 1429 removeClass(playerEl, 'over'); 1430 }, 200); 1431 } 1432 if (videoBluredEl) { 1433 videoBluredEl.currentTime = videoEl.currentTime; 1434 videoBluredEl.pause(); 1435 } 1436 if (looped) { 1437 videoEl.play(); 1438 } 1439 }); 1440 addEvent(videoEl, 'timeupdate', function(e) { 1441 fixControls(); 1442 if (videoBluredEl && videoBluredEl.currentTime != videoEl.currentTime) { 1443 videoBluredEl.currentTime = videoEl.currentTime; 1444 } 1445 if (durationEl && videoEl.duration) { 1446 var duration = Math.floor(videoEl.duration); 1447 durationEl.innerHTML = formatDuration(duration - videoEl.currentTime); 1448 } 1449 }); 1450 addEvent(videoEl, 'ended load', function(e) { 1451 fixControls(); 1452 if (durationEl && videoEl.duration) { 1453 var duration = Math.floor(videoEl.duration); 1454 durationEl.innerHTML = formatDuration(duration); 1455 } 1456 }); 1457 if (looped) { 1458 addEvent(document, 'touchstart', function(){ videoEl.play(); }); 1459 } else { 1460 addClass(playerEl, 'ready'); 1461 } 1462 if (playEl) { 1463 addEvent(playEl, 'click', function toggleVideo(e) { 1464 if (e.metaKey || e.ctrlKey) return true; 1465 e.stopPropagation(); 1466 if (!videoEl) return true; 1467 if (videoEl.paused) { 1468 videoEl.play(); 1469 if (videoBluredEl) { 1470 videoBluredEl.play(); 1471 } 1472 } else { 1473 videoEl.pause(); 1474 if (videoBluredEl) { 1475 videoBluredEl.pause(); 1476 } 1477 } 1478 e.preventDefault(); 1479 return false; 1480 }); 1481 } 1482 } 1483 }; 1484 1485 var TGrouped = window.TGrouped = { 1486 init: function(groupedWrapEl) { 1487 groupedWrapEl = geById(groupedWrapEl); 1488 if (!groupedWrapEl || groupedWrapEl.__inited) return; 1489 groupedWrapEl.__inited = true; 1490 var groupedEl = ge1('.js-message_grouped', groupedWrapEl) 1491 , groupedLayerEl = ge1('.js-message_grouped_layer', groupedEl) 1492 , thumbsEl = groupedLayerEl.children 1493 , margin_w = +groupedWrapEl.getAttribute('data-margin-w') || 2 1494 , margin_h = +groupedWrapEl.getAttribute('data-margin-h') || 2; 1495 if (!thumbsEl.length) { 1496 return false; 1497 } 1498 1499 addEvent(window, 'resize', function() { 1500 if (groupedLayerEl.offsetWidth != groupedEl.offsetWidth) { 1501 recalcGrouped(groupedWrapEl.offsetWidth); 1502 } 1503 }); 1504 recalcGrouped(groupedWrapEl.offsetWidth); 1505 1506 function updateThumb(thumbEl, x, y, width, height, th_width, th_height, position) { 1507 if (!thumbEl) return; 1508 var t = false, r = false, b = false, l = false; 1509 for (var i = 0; i < position.length; i++) { 1510 if (position[i] == 't') t = true; 1511 else if (position[i] == 'r') r = true; 1512 else if (position[i] == 'b') b = true; 1513 else if (position[i] == 'l') l = true; 1514 } 1515 thumbEl.style.left = x + 'px'; 1516 thumbEl.style.top = y + 'px'; 1517 thumbEl.style.width = width + 'px'; 1518 thumbEl.style.height = height + 'px'; 1519 thumbEl.style.marginRight = (!r ? margin_w : 0) + 'px'; 1520 thumbEl.style.marginBottom = (!b ? margin_h : 0) + 'px'; 1521 1522 var th_ratio = th_width / th_height; 1523 var ratio = +thumbEl.getAttribute('data-ratio') || 1.0; 1524 var mediaEl = ge1('.grouped_media', thumbEl); 1525 var helperEl = ge1('.grouped_media_helper', thumbEl); 1526 1527 if (mediaEl) {
1528 var media_height = Math.ceil(width / ratio); 1529 var media_tb = height - media_height; 1530 if (media_tb < 0) { 1531 var media_t = Math.floor(media_tb / 2); 1532 var media_b = media_tb - media_t; 1533 mediaEl.style.left = 0; 1534 mediaEl.style.right = 0; 1535 mediaEl.style.top = media_t + 'px'; 1536 mediaEl.style.bottom = media_b + 'px'; 1537 } else { 1538 var media_width = Math.ceil(height * ratio); 1539 var media_lr = width - media_width; 1540 var media_l = Math.floor(media_lr / 2); 1541 var media_r = media_lr - media_l; 1542 mediaEl.style.top = 0; 1543 mediaEl.style.bottom = 0; 1544 mediaEl.style.left = media_l + 'px'; 1545 mediaEl.style.right = media_r + 'px'; 1546 } 1547 } 1548 if (helperEl) { 1549 var helper_height = Math.floor(th_width / ratio); 1550 var helper_tb = th_height - helper_height; 1551 if (helper_tb > 0) { 1552 var helper_t = Math.floor(helper_tb / 2); 1553 var helper_b = helper_tb - helper_t; 1554 helperEl.style.left = 0; 1555 helperEl.style.right = 0; 1556 helperEl.style.top = helper_t + 'px'; 1557 helperEl.style.bottom = helper_b + 'px'; 1558 } else { 1559 var helper_width = Math.ceil(th_height * ratio); 1560 var helper_lr = th_width - helper_width; 1561 var helper_l = Math.floor(helper_lr / 2); 1562 var helper_r = helper_lr - helper_l; 1563 helperEl.style.top = 0; 1564 helperEl.style.bottom = 0; 1565 helperEl.style.left = helper_l + 'px'; 1566 helperEl.style.right = helper_r + 'px'; 1567 } 1568 } 1569 } 1570 1571 function recalcGrouped(max_w) { 1572 var orients = ''; 1573 var ratios = []; 1574 var cnt = thumbsEl.length; 1575 1576 var ratios_sum = 0; 1577 for (var i = 0; i < thumbsEl.length; i++) { 1578 var thumbEl = thumbsEl[i]; 1579 var ratio = +thumbEl.getAttribute('data-ratio') || 1.0; 1580 orients += ratio > 1.2 ? 'w' : (ratio < 0.8 ? 'n' : 'q'); 1581 ratios_sum += ratio; 1582 ratios.push(ratio); 1583 } 1584 1585 var avg_ratio = ratios.length ? ratios_sum / ratios.length : 1.0; 1586 var max_ratio = 0.75; 1587 var min_w = 75; 1588 var max_h = max_w / max_ratio; 1589 1590 var w, h, w0, w1, w2, h0, h1, h2, x, y, x1, x2, y1, y2, 1591 th_width, th_height; 1592 1593 if (cnt == 2) { 1594 if (orients == 'ww' && 1595 avg_ratio > 1.4 * max_ratio && 1596 (ratios[1] - ratios[0]) < 0.2) { 1597 // 2 wide pics are one below the other 1598 w = max_w; 1599 h = Math.min(w / ratios[0], Math.min(w / ratios[1], (max_h - margin_h) / 2.0)); 1600 th_width = max_w; 1601 th_height = 2 * h + margin_h; 1602 h0 = Math.floor(h); 1603 h1 = th_height - h0 - margin_h; 1604 y = h0 + margin_h; 1605 updateThumb(thumbsEl[0], 0, 0, w, h0, th_width, th_height, 'trl'); 1606 updateThumb(thumbsEl[1], 0, y, w, h1, th_width, th_height, 'rbl'); 1607 } 1608 else if (orients == 'ww' || orients == 'qq') { 1609 // 2 equal width pics 1610 w = (max_w - margin_w) / 2; 1611 h = Math.floor(Math.min(max_h, Math.min(w / ratios[0], w / ratios[1]))); 1612 th_width = max_w; 1613 th_height = h; 1614 w0 = Math.floor(w); 1615 w1 = max_w - w0 - margin_w; 1616 x = w0 + margin_w; 1617 updateThumb(thumbsEl[0], 0, 0, w0, h, th_width, th_height, 'tbl'); 1618 updateThumb(thumbsEl[1], x, 0, w1, h, th_width, th_height, 'trb'); 1619 } 1620 else { 1621 // so, we have one wide and one not wide (square or narrow) 1622 w0 = Math.floor((max_w - margin_w) / ratios[1] / (1 / ratios[0] + 1 / ratios[1])); 1623 w1 = max_w - w0 - margin_w; 1624 h = Math.floor(Math.min(max_h, Math.min(w0 / ratios[0], w1 / ratios[1]))); 1625 th_width = max_w; 1626 th_height = h; 1627 x = w0 + margin_w; 1628 updateThumb(thumbsEl[0], 0, 0, w0, h, th_width, th_height, 'tbl'); 1629 updateThumb(thumbsEl[1], x, 0, w1, h, th_width, th_height, 'trb'); 1630 } 1631 } 1632 else if (cnt == 3) { 1633 if (orients[0] == 'n') { 1634 // 2nd and 3rd photos are on the right part 1635 h0 = max_h; 1636 h2 = Math.floor(Math.min((max_h - margin_h) * 0.5, ratios[1] * (max_h - margin_h) / (ratios[2] + ratios[1]))); 1637 h1 = max_h - h2 - margin_h; 1638 w1 = Math.floor(Math.max(min_w, Math.min((max_w - margin_w) * 0.5, Math.min(h2 * ratios[2], h1 * ratios[1])))); 1639 w0 = Math.min(Math.floor(h0 * ratios[0]), (max_w - w1 - margin_w)); 1640 th_width = w0 + w1 + margin_w; 1641 th_height = max_h; 1642 x = w0 + margin_w; 1643 y = h1 + margin_h; 1644 updateThumb(thumbsEl[0], 0, 0, w0, h0, th_width, th_height, 'tbl'); 1645 updateThumb(thumbsEl[1], x, 0, w1, h1, th_width, th_height, 'tr'); 1646 updateThumb(thumbsEl[2], x, y, w1, h2, th_width, th_height, 'rb'); 1647 } 1648 else { 1649 // 2nd and 3rd photos are on the next line 1650 w0 = max_w; 1651 h0 = Math.floor(Math.min(w0 / ratios[0], (max_h - margin_h) * 0.66)); 1652 w = (max_w - margin_w) / 2; 1653 h = Math.floor(Math.min(max_h - h0 - margin_h, Math.min(w / ratios[1], w / ratios[2]))); 1654 th_width = max_w; 1655 th_height = h0 + h + margin_h; 1656 w1 = Math.floor(w); 1657 w2 = max_w - w1 - margin_w; 1658 x = w1 + margin_w; 1659 y = h0 + margin_h; 1660 updateThumb(thumbsEl[0], 0, 0, w0, h0, th_width, th_height, 'tlr'); 1661 updateThumb(thumbsEl[1], 0, y, w1, h, th_width, th_height, 'bl'); 1662 updateThumb(thumbsEl[2], x, y, w2, h, th_width, th_height, 'rb'); 1663 } 1664 } 1665 else if (cnt == 4) { 1666 if (orients == 'wwww' || orients[0] == 'w') { 1667 // 2nd, 3rd and 4th photos are on the next line 1668 w = max_w; 1669 h0 = Math.floor(Math.min(w / ratios[0], (max_h - margin_h) * 0.66)); 1670 h = (max_w - 2 * margin_w) / (ratios[1] + ratios[2] + ratios[3]); 1671 w0 = Math.floor(Math.max(min_w, Math.min((max_w - 2 * margin_w) * 0.4, h * ratios[1]))); 1672 w2 = Math.floor(Math.max(min_w, Math.min((max_w - 2 * margin_w) * 0.33, h * ratios[3]))); 1673 w1 = w - w0 - w2 - 2 * margin_w; 1674 h = Math.floor(Math.min(max_h - h0 - margin_h, h)); 1675 th_width = max_w; 1676 th_height = h0 + h + margin_h; 1677 y = h0 + margin_h; 1678 x1 = w0 + margin_w; 1679 x2 = x1 + w1 + margin_w; 1680 updateThumb(thumbsEl[0], 0, 0, w, h0, th_width, th_height, 'tlr'); 1681 updateThumb(thumbsEl[1], 0, y, w0, h, th_width, th_height, 'bl'); 1682 updateThumb(thumbsEl[2], x1, y, w1, h, th_width, th_height, 'b'); 1683 updateThumb(thumbsEl[3], x2, y, w2, h, th_width, th_height, 'rb'); 1684 } 1685 else { 1686 // 2nd, 3rd and 4th photos are on the right part 1687 h = max_h; 1688 w0 = Math.floor(Math.min(h * ratios[0], (max_w - margin_w) * 0.66)); 1689 w = Math.floor((max_h - 2 * margin_h) / (1 / ratios[1] + 1 / ratios[2] + 1 / ratios[3])); 1690 h0 = Math.floor(w / ratios[1]); 1691 h2 = Math.floor(w / ratios[3]); 1692 h1 = h - h0 - h2 - 2 * margin_h; 1693 w = Math.max(min_w, Math.min(max_w - w0 - margin_w, w)); 1694 th_width = w0 + w + margin_w; 1695 th_height = max_h; 1696 x = w0 + margin_w; 1697 y1 = h0 + margin_h; 1698 y2 = y1 + h1 + margin_h; 1699 updateThumb(thumbsEl[0], 0, 0, w0, h, th_width, th_height, 'tbl'); 1700 updateThumb(thumbsEl[1], x, 0, w, h0, th_width, th_height, 'tr'); 1701 updateThumb(thumbsEl[2], x, y1, w, h1, th_width, th_height, 'r'); 1702 updateThumb(thumbsEl[3], x, y2, w, h2, th_width, th_height, 'rb'); 1703 } 1704 } 1705 else { 1706 var ratios_cropped = []; 1707 for (var i = 0; i < ratios.length; i++) { 1708 var ratio = ratios[i]; 1709 if (avg_ratio > 1.1) { 1710 ratio_cropped = Math.max(1.0, ratio); 1711 } else { 1712 ratio_cropped = Math.min(1.0, ratio); 1713 } 1714 ratio_cropped = Math.max(0.66667, Math.min(1.7, ratio_cropped)); 1715 ratios_cropped.push(ratio_cropped); 1716 } 1717 1718 var multiHeight = function(ratios) { 1719 var ratios_sum = 0; 1720 for (var i = 0; i < ratios.length; i++) { 1721 var ratio = ratios[i]; 1722 ratios_sum += ratio; 1723 } 1724 return (max_w - (ratios.length - 1) * margin_w) / ratios_sum; 1725 }; 1726 1727 var tries = []; 1728 var first_line, second_line, third_line, fourth_line; 1729 // Two lines 1730 for (first_line = 1; first_line <= cnt - 1; first_line++) { 1731 second_line = cnt - first_line; 1732 if (first_line > 3 || 1733 second_line > 3) { 1734 continue; 1735 } 1736 tries.push([[first_line, second_line], [ 1737 multiHeight(ratios_cropped.slice(0, first_line)), 1738 multiHeight(ratios_cropped.slice(first_line)), 1739 ]]); 1740 } 1741 1742 // Three lines 1743 for (first_line = 1; first_line <= cnt - 2; first_line++) { 1744 for (second_line = 1; second_line <= cnt - first_line - 1; second_line++) { 1745 third_line = cnt - first_line - second_line; 1746 if (first_line > 3 || 1747 second_line > (avg_ratio < 0.85 ? 4 : 3) || 1748 third_line > 3) { 1749 continue; 1750 } 1751 tries.push([[first_line, second_line, third_line], [ 1752 multiHeight(ratios_cropped.slice(0, first_line)), 1753 multiHeight(ratios_cropped.slice(first_line, first_line + second_line)), 1754 multiHeight(ratios_cropped.slice(first_line + second_line)), 1755 ]]); 1756 } 1757 } 1758 1759 // Four lines 1760 for (first_line = 1; first_line <= cnt - 3; first_line++) { 1761 for (second_line = 1; second_line <= cnt - first_line - 2; second_line++) { 1762 for (third_line = 1; third_line <= cnt - first_line - second_line - 1; third_line++) { 1763 fourth_line = cnt - first_line - second_line - third_line; 1764 if (first_line > 3 || 1765 second_line > 3 || 1766 third_line > 3 || 1767 fourth_line > 3) { 1768 continue; 1769 } 1770 tries.push([[first_line, second_line, third_line, fourth_line], [ 1771 multiHeight(ratios_cropped.slice(0, first_line)), 1772 multiHeight(ratios_cropped.slice(first_line, first_line + second_line)), 1773 multiHeight(ratios_cropped.slice(first_line + second_line, first_line + second_line + third_line)), 1774 multiHeight(ratios_cropped.slice(first_line + second_line + third_line)), 1775 ]]); 1776 } 1777 } 1778 } 1779 1780 // Looking for minimum difference between thumbs block height and max_h (may probably be little over) 1781 var opt_i = false; 1782 var opt_conf = false; 1783 var opt_diff = false; 1784 var opt_h = false; 1785 for (var i = 0; i < tries.length; i++) { 1786 var conf_nums = tries[i][0]; 1787 var heights = tries[i][1]; 1788 var heights_sum = 0; 1789 var heights_min = Infinity; 1790 for (var j = 0; j < heights.length; j++) { 1791 heights_sum += heights[j];
1792 if (heights_min > heights[j]) { 1793 heights_min = heights[j]; 1794 } 1795 } 1796 var conf_h = Math.floor(heights_sum + margin_h * (heights.length - 1)); 1797 var conf_diff = Math.abs(conf_h - max_h); 1798 if (conf_nums.length > 1) { 1799 if (conf_nums[0] > conf_nums[1] || 1800 conf_nums[2] && conf_nums[1] > conf_nums[2] || 1801 conf_nums[3] && conf_nums[2] > conf_nums[3]) { 1802 conf_diff *= 1.5; 1803 } 1804 } 1805 if (heights_min < min_w) { 1806 conf_diff *= 1.5; 1807 } 1808 if (opt_conf === false || conf_diff < opt_diff) { 1809 opt_i = i; 1810 opt_conf = cloneArr(conf_nums); 1811 opt_diff = conf_diff; 1812 opt_h = conf_h; 1813 } 1814 } 1815 1816 // Generating optimal thumbs 1817 th_width = max_w; 1818 th_height = opt_h; 1819 var thumbs_remain = cloneArr(thumbsEl); 1820 var ratios_remain = cloneArr(ratios_cropped); 1821 var chunks = cloneArr(opt_conf); 1822 var opt_heights = cloneArr(tries[opt_i][1]); 1823 var chunks_num = chunks.length; 1824 var last_row = chunks_num - 1; 1825 var sy = 0; 1826 for (var i = 0; i < chunks.length; i++) { 1827 var line_chunks_num = chunks[i]; 1828 var line_thumbs = thumbs_remain.splice(0, line_chunks_num); 1829 var line_height = opt_heights.shift(); 1830 var last_column = line_thumbs.length - 1; 1831 var h = Math.floor(line_height); 1832 var sx = 0; 1833 var t = '', r = '', b = '', l = ''; 1834 if (i == 0) { 1835 t = 't'; 1836 } 1837 if (i == last_row) { 1838 b = 'b'; 1839 h = th_height - sy; 1840 } 1841 for (var j = 0; j < line_thumbs.length; j++) { 1842 var thumbEl = line_thumbs[j]; 1843 var thumb_ratio = ratios_remain.shift(); 1844 var w = Math.floor(thumb_ratio * h); 1845 if (j == 0) { 1846 l = 'l'; 1847 } 1848 if (j == last_column) { 1849 r = 'r'; 1850 w = th_width - sx; 1851 } 1852 updateThumb(thumbEl, sx, sy, w, h, th_width, th_height, t+r+b+l); 1853 sx += w + margin_w; 1854 } 1855 sy += h + margin_h; 1856 } 1857 } 1858 1859 groupedEl.style.paddingTop = (th_height / th_width * 100) + '%'; 1860 groupedLayerEl.style.width = th_width + 'px'; 1861 groupedLayerEl.style.height = th_height + 'px'; 1862 } 1863 } 1864 }; 1865 1866 var TRoundVideo = window.TRoundVideo = { 1867 init: function(playerEl) { 1868 playerEl = geById(playerEl); 1869 if (!playerEl || playerEl.__inited) return; 1870 playerEl.__inited = true; 1871 var videoEl = ge1('.js-message_roundvideo', playerEl) 1872 , playEl = ge1('.js-message_roundvideo_play', playerEl) 1873 , progressEl = ge1('.js-message_roundvideo_progress', playerEl) 1874 , durationEl = ge1('.js-message_roundvideo_duration', playerEl) 1875 , playing = false; 1876 if (!videoEl) return; 1877 1878 function autoplay() { 1879 if (!videoEl) return; 1880 removeEvent(document, 'touchstart', autoplay); 1881 removeClass(playerEl, 'playing'); 1882 playing = false; 1883 videoEl.muted = true; 1884 videoEl.loop = true; 1885 videoEl.currentTime = 0; 1886 play(); 1887 showProgress(); 1888 } 1889 function showProgress() { 1890 if (!videoEl) return; 1891 if (playing && !videoEl.paused) { 1892 requestAnimationFrame(function(){ showProgress(); }); 1893 } 1894 redrawProgress(); 1895 if (videoEl.duration) { 1896 var duration = Math.floor(videoEl.duration); 1897 durationEl.innerHTML = formatDuration(duration - videoEl.currentTime); 1898 } 1899 } 1900 function redrawProgress(updateSVG) { 1901 if (!videoEl) return; 1902 var progress; 1903 if (playing) { 1904 progress = videoEl.currentTime / videoEl.duration; 1905 } else { 1906 progress = 0; 1907 } 1908 progress = Math.max(0, Math.min(progress, 1)); 1909 var wrapWidth = playerEl.offsetWidth; 1910 if (wrapWidth) { 1911 var rd = progressEl.getAttribute('data-rd') || 3; 1912 var d = (wrapWidth - rd);
1913 var l = (d * Math.PI); 1914 progressEl.setAttribute('r', (d / 2)); 1915 progressEl.setAttribute('stroke-dasharray', l); 1916 progressEl.setAttribute('stroke-dashoffset', l * (1 - progress)); 1917 if (updateSVG) { 1918 progressEl.style.transform = !progressEl.style.transform ? 'rotateZ(270deg)' : ''; 1919 } 1920 } 1921 } 1922 function play() { 1923 if (!videoEl) return; 1924 var video = videoEl; 1925 var isPlaying = (video.currentTime > 0) && 1926 !video.paused && 1927 !video.ended && 1928 (video.readyState > 2); 1929 if (!isPlaying) { 1930 video.play(); 1931 if (playing) { 1932 triggerEvent(videoEl, 'tg:play', {bubbles: true}); 1933 } 1934 } 1935 } 1936 addEvent(document, 'tg:play', function(e) { 1937 if (e.target === videoEl || !playing) return true; 1938 if (videoEl.paused) { 1939 play(); 1940 showProgress(); 1941 } else { 1942 autoplay(); 1943 } 1944 }); 1945 function pause() { 1946 if (!videoEl) return; 1947 videoEl.pause(); 1948 } 1949 function toggle(e) { 1950 e.stopPropagation(); 1951 if (!playing) { 1952 redrawProgress(); 1953 addClass(playerEl, 'playing'); 1954 playing = true; 1955 videoEl.muted = false; 1956 videoEl.loop = false; 1957 videoEl.currentTime = 0; 1958 play(); 1959 showProgress(); 1960 } else { 1961 if (videoEl.paused) { 1962 play(); 1963 showProgress(); 1964 } else { 1965 pause(); 1966 } 1967 } 1968 } 1969 1970 enableInlineVideo(videoEl); 1971 1972 checkVideo(videoEl, function() { 1973 addClass(playerEl, 'not_supported'); 1974 }); 1975 autoplay(); 1976 addEvent(document, 'touchstart', autoplay); 1977 addEvent(videoEl, 'ended', function() { 1978 autoplay(); 1979 }); 1980 addEvent(window, 'resize', function() { 1981 redrawProgress(true) 1982 }); 1983 if (playEl) { 1984 addEvent(playEl, 'click', toggle); 1985 } 1986 } 1987 }; 1988 1989 var TVoice = window.TVoice = { 1990 init: function(playerEl) { 1991 playerEl = geById(playerEl); 1992 if (!playerEl || playerEl.__inited) return; 1993 playerEl.__inited = true; 1994 var audioEl = ge1('.js-message_voice', playerEl) 1995 , durationEl = ge1('.js-message_voice_duration', playerEl) 1996 , progressEl = ge1('.js-message_voice_progress', playerEl) 1997 , progressWrapEl = ge1('.js-message_voice_progress_wrap', playerEl) 1998 , player = null 1999 , isOGG = audioEl.hasAttribute('data-ogg') 2000 , seekTo = null 2001 , seeking = false 2002 , disableClick = false; 2003 if (!audioEl) return; 2004 2005 function initPlayer() { 2006 addClass(playerEl, 'ready'); 2007 addEvent(player, 'play', function() { 2008 addClass(playerEl, 'playing'); 2009 triggerEvent(playerEl, 'tg:play', {bubbles: true}); 2010 }); 2011 addEvent(player, 'pause', function() { 2012 removeClass(playerEl, 'playing'); 2013 }); 2014 addEvent(player, 'ended', function() { 2015 player.currentTime = 0; 2016 showProgress(); 2017 }); 2018 addEvent(player, 'loadedmetadata', function() { 2019 showProgress(); 2020 }); 2021 addEvent(playerEl, 'click', toggle); 2022 addEvent(progressWrapEl, 'mousedown touchstart', seekStart); 2023 addEvent(document, 'tg:play', stop); 2024 } 2025 function toggle(e) { 2026 e.stopPropagation(); 2027 if (!disableClick) { 2028 if (!player) return true; 2029 if (player.paused) { 2030 player.play(); 2031 showProgress(); 2032 } else { 2033 player.pause(); 2034 showProgress(); 2035 } 2036 } else { 2037 disableClick = false; 2038 } 2039 e.preventDefault(); 2040 return false; 2041 } 2042 function stop(e) { 2043 if (e.target === playerEl || !player) return true; 2044 if (!player.paused) { 2045 player.pause(); 2046 showProgress(); 2047 } 2048 return false; 2049 } 2050 function seekStart(e) { 2051 if (player && 2052 player.duration !== Infinity && 2053 (!player.paused || 2054 player.currentTime > 0 && player.currentTime < player.duration)) { 2055 e.preventDefault(); 2056 seeking = true; 2057 disableClick = false; 2058 player.pause(); 2059 addEvent(document, 'mousemove touchmove', seek); 2060 addEvent(document, 'mouseup mouseleave touchend touchcancel', seekEnd); 2061 seek(e); 2062 } 2063 } 2064 function seek(e) { 2065 if (!seeking) return; 2066 var px = e.pageX; 2067 var op = progressWrapEl; 2068 var x = op.offsetLeft; 2069 var w = op.offsetWidth; 2070 while (op = op.offsetParent) { 2071 x += op.offsetLeft; 2072 } 2073 var ct = Math.max(0, Math.min(px - x, w)) / w; 2074 seekTo = ct; 2075 showProgress(); 2076 } 2077 function seekEnd(e) { 2078 if (!seeking) return; 2079 seek(e); 2080 var duration = Math.floor(player.duration); 2081 player.currentTime = seekTo * duration; 2082 seekTo = null; 2083 seeking = false; 2084 if (e.type.substr(0, 5) == 'mouse') { 2085 disableClick = true; 2086 } 2087 player.play(); 2088 showProgress(); 2089 removeEvent(document, 'mousemove touchmove', seek); 2090 removeEvent(document, 'mouseup touchend', seekEnd); 2091 } 2092 function showProgress() { 2093 if (!player) return; 2094 if (!player.paused) { 2095 requestAnimationFrame(function(){ showProgress(); }); 2096 } 2097 if (player.duration && player.duration !== Infinity) { 2098 var duration = Math.floor(player.duration); 2099 if (seeking) { 2100 var currentTime = seekTo * duration; 2101 } else { 2102 var currentTime = Math.max(0, player.currentTime); 2103 } 2104 if (progressEl) { 2105 progressEl.style.width = Math.min(100, currentTime / duration * 100) + '%'; 2106 } 2107 if (durationEl) { 2108 durationEl.innerHTML = formatDuration(duration - currentTime); 2109 } 2110 } 2111 } 2112 function redrawProgress() { 2113 if (!audioEl) return; 2114 var ss = progressWrapEl.getElementsByTagName('S'); 2115 var ss_count = ss.length / 2; 2116 var waveform_str = audioEl.getAttribute('data-waveform') || ''; 2117 var waveform = waveform_str.split(','); 2118 var lines_cnt = Math.floor((progressWrapEl.offsetWidth + 2) / 6); 2119 var p = waveform.length / lines_cnt; 2120 var values = []; 2121 var max_value = 0; 2122 for (var i = 0; i < lines_cnt; i++) { 2123 var ws = i * p; 2124 var we = ws + p; 2125 var wsi = Math.floor(ws); 2126 var wei = Math.floor(we); 2127 if (wsi == wei) { 2128 var value = waveform[wsi] * (we - ws); 2129 } else { 2130 var value = 0; 2131 for (var j = wsi; j <= wei; j++) { 2132 var wv = +waveform[j] || 0; 2133 if (j == wsi) { 2134 value += wv * (j + 1 - ws); 2135 } else if (j == wei) { 2136 value += wv * (we - j); 2137 } else { 2138 value += wv; 2139 } 2140 } 2141 } 2142 value = value / p; 2143 max_value = Math.max(value, max_value); 2144 values.push(value); 2145 } 2146 for (var i = 0; i < ss.length; i++) { 2147 var li = i % ss_count; 2148 if (li < lines_cnt) { 2149 var height = (values[li] / max_value) * 100; 2150 ss[i].style.height = height + '%'; 2151 ss[i].style.display = ''; 2152 } else { 2153 ss[i].style.display = 'none'; 2154 } 2155 } 2156 } 2157 2158 loadLib(TBaseUrl + 'js/ogvjs/ogv-support.js', function(success) { 2159 if (!success) return; 2160 if (isOGG && 2161 OGVCompat.hasWebAudio() && 2162 OGVCompat.supported('OGVPlayer')) { 2163 loadLib(TBaseUrl + 'js/ogvjs/ogv.js', function(success) { 2164 if (!success) return; 2165 player = new OGVPlayer(); 2166 player.src = audioEl.src; 2167 initPlayer(); 2168 }); 2169 } else { 2170 player = audioEl; 2171 initPlayer(); 2172 } 2173 }); 2174 addEvent(window, 'resize', function(){ redrawProgress() }); 2175 redrawProgress(); 2176 } 2177 }; 2178 2179 var TSticker = window.TSticker = { 2180 init: proccessWebpImage 2181 }; 2182 2183 window.TWidgetPost = { 2184 init: function(options) { 2185 if (!doesSupportEmoji()) { 2186 removeClass(document.body, 'emoji_default'); 2187 addClass(document.body, 'emoji_image'); 2188 } 2189 options = options || {}; 2190 TWidgetPost.options = options; 2191 2192 gec('.js-widget_message', function() { 2193 TPost.init(this); 2194 addEvent(ge('.js-poll_option', this), 'click', TWidgetPost.eSelectPollOption); 2195 addEvent(ge('.js-poll_vote_btn', this), 'click', TWidgetPost.eSendVotes); 2196 }); 2197 initWidgetFrame({ 2198 auto_height: true, 2199 onVisible: function() { 2200 gec('.js-widget_message', function() { 2201 TPost.view(this); 2202 }); 2203 } 2204 }); 2205 addEvent(window, 'tg:optionschange', TWidgetPost.onOptionsChange); 2206 }, 2207 onOptionsChange: function(e) { 2208 var new_options = e.detail, transition_off = false; 2209 if (typeof new_options.dark !== undefined) { 2210 transition_off = true; 2211 addClass(document.body, 'no_transitions'); 2212 toggleClass(document.body, 'dark', !!new_options.dark); 2213 toggleClass(document.body, 'nodark', !new_options.dark); 2214 } 2215 if (transition_off) { 2216 setTimeout(function() { 2217 removeClass(document.body, 'no_transitions'); 2218 }, 100); 2219 } 2220 }, 2221 eSelectPollOption: function(e) { 2222 e.preventDefault(); 2223 if (!TWidgetAuth.isLoggedIn()) { 2224 return TWidgetAuth.logIn(); 2225 } 2226 var poll_el = gpeByClass(this, 'js-poll'); 2227 if (!poll_el) { 2228 return false; 2229 } 2230 toggleClass(this, 'selected'); 2231 toggleClass(poll_el, 'selected', ge('.js-poll_option.selected', poll_el).length > 0); 2232 if (!hasClass(poll_el, 'multiple')) { 2233 TWidgetPost.sendPollVote(poll_el, this); 2234 } 2235 }, 2236 eSendVotes: function(e) { 2237 e.preventDefault(); 2238 if (!TWidgetAuth.isLoggedIn()) { 2239 return TWidgetAuth.logIn(); 2240 } 2241 var poll_el = gpeByClass(this, 'js-poll'); 2242 if (!poll_el) { 2243 return false; 2244 } 2245 TWidgetPost.sendPollVote(poll_el, this); 2246 }, 2247 sendPollVote: function(poll_el, option_el) { 2248 if (!poll_el || hasClass(poll_el, 'sending')) { 2249 return false; 2250 } 2251 var option_els = ge('.js-poll_option.selected', poll_el); 2252 var options = TWidgetPost.options || {}; 2253 var post_el = gpeByClass(option_el, 'js-widget_message'); 2254 if (!post_el) { 2255 return false; 2256 } 2257 var peer = getAttr(post_el, 'data-peer'); 2258 var peer_hash = getAttr(post_el, 'data-peer-hash'); 2259 var post_id = getAttr(post_el, 'data-post-id'); 2260 if (!peer || !peer_hash || !post_id) { 2261 return false; 2262 } 2263 var poll_options = []; 2264 gec(option_els, function() { 2265 poll_options.push(getAttr(this, 'data-value')); 2266 }); 2267 removeClass(poll_el, 'selected'); 2268 addClass(poll_el, 'sending'); 2269 apiRequest('sendVote', { 2270 peer: peer, 2271 peer_hash: peer_hash, 2272 post_id: post_id, 2273 options: poll_options.join(';') 2274 }, function(err, result) { 2275 removeClass(poll_el, 'sending'); 2276 if (result.media_html) { 2277 var media_wrap = newEl('div', '', result.media_html); 2278 var media_html = getHtml('.js-poll', media_wrap); 2279 setHtml(poll_el, media_html); 2280 addEvent(ge('.js-poll_option', poll_el), 'click', TWidgetPost.eSelectPollOption); 2281 addEvent(ge('.js-poll_vote_btn', poll_el), 'click', TWidgetPost.eSendVotes); 2282 } 2283 toggleClass(poll_el, 'selected', ge('.js-poll_option.selected', poll_el).length > 0); 2284 }); 2285 } 2286 }; 2287 2288 var TWidgetLogin = { 2289 init: function(id, bot_id, params, init_auth, lang) { 2290 initWidgetFrame({ 2291 auto_height: true, 2292 auto_width: true 2293 }); 2294 TWidgetLogin.widgetEl = document.getElementById(id); 2295 TWidgetLogin.botId = bot_id; 2296 TWidgetLogin.params = params; 2297 TWidgetLogin.lang = lang; 2298 var params_encoded = '', params_arr = []; 2299 for (var k in params) { 2300 params_arr.push(encodeURIComponent(k) + '=' + encodeURIComponent(params[k])); 2301 } 2302 TWidgetLogin.paramsEncoded = params_arr.join('&'); 2303 if (init_auth) { 2304 TWidgetLogin.getAuth(true); 2305 } 2306 addEvent(window, 'message', function (event) { 2307 try { 2308 var data = JSON.parse(event.data); 2309 } catch(e) { 2310 var data = {}; 2311 } 2312 if (event.source !== TWidgetLogin.activePopup) return; 2313 if (data.event == 'auth_result') { 2314 TWidgetLogin.onAuth(data.origin, data.result); 2315 } 2316 }); 2317 }, 2318 auth: function() { 2319 var width = 550; 2320 var height = 470; 2321 var left = Math.max(0, (screen.width - width) / 2) + (screen.availLeft | 0), 2322 top = Math.max(0, (screen.height - height) / 2) + (screen.availTop | 0); 2323 function checkClose() { 2324 if (!TWidgetLogin.activePopup || TWidgetLogin.activePopup.closed) { 2325 return TWidgetLogin.onClose(); 2326 }
2327 setTimeout(checkClose, 100); 2328 } 2329 TWidgetLogin.activePopup = window.open('https://oauth.telegram.org/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'); 2330 TWidgetLogin.authFinished = false; 2331 if (TWidgetLogin.activePopup) { 2332 TWidgetLogin.activePopup.focus(); 2333 checkClose(); 2334 } 2335 }, 2336 getAuth: function(init) { 2337 var xhr = getXHR(); 2338 xhr.open('POST', 'https://oauth.telegram.org/auth/get?bot_id=' + TWidgetLogin.botId + (TWidgetLogin.lang ? '&lang=' + encodeURIComponent(TWidgetLogin.lang) : '')); 2339 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 2340 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 2341 xhr.onreadystatechange = function() { 2342 if (xhr.readyState == 4) { 2343 if (typeof xhr.responseBody == 'undefined' && xhr.responseText) { 2344 try { 2345 var result = JSON.parse(xhr.responseText); 2346 } catch(e) { 2347 var result = {}; 2348 } 2349 console.log(result); 2350 if (result.user) { 2351 TWidgetLogin.onAuth(result.origin, result.user, init); 2352 } else { 2353 TWidgetLogin.onAuth(result.origin, false, init); 2354 } 2355 } else { 2356 TWidgetLogin.onAuth('*', false, init); 2357 } 2358 } 2359 }; 2360 xhr.onerror = function() { 2361 TWidgetLogin.onAuth('*', false, init); 2362 }; 2363 xhr.withCredentials = true; 2364 xhr.send(TWidgetLogin.paramsEncoded); 2365 }, 2366 onAuth: function(origin, authData, init) { 2367 if (TWidgetLogin.authFinished) return; 2368 if (authData) { 2369 var data = {event: 'auth_user', auth_data: authData}; 2370 } else { 2371 var data = {event: 'unauthorized'}; 2372 } 2373 if (init) { 2374 data.init = true; 2375 } 2376 2377 //Arkadiy 2378 SloginTelegram.auth(data); 2379 2380 TWidgetLogin.authFinished = true; 2381 }, 2382 onClose: function() { 2383 TWidgetLogin.getAuth(); 2384 } 2385 }; 2386 window.TWidgetLogin = TWidgetLogin; 2387 2388 var TStats = { 2389 init: function () { 2390 if (!doesSupportEmoji()) { 2391 removeClass(document.body, 'emoji_default'); 2392 addClass(document.body, 'emoji_image'); 2393 } 2394 gec('.js-sticker_thumb', function() { 2395 TSticker.init(this); 2396 }); 2397 } 2398 } 2399 window.TStats = TStats; 2400 2401 window.TWidget = { 2402 initFrame: initWidgetFrame 2403 }; 2404 2405})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.