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