PageSourceSearch

https://bgtime.tv/app/js/app.js?v=0.14

js bgtime.tv collected 2026-10-02 01:09:22 UTC 125,689 bytes, 3,796 lines download raw bytes

1function MyTV_App() {
2	var _self = this;
3	var oThis = this;
4	var local_storage = localStorage;
5	var storage_settings = JSON.parse(local_storage.getItem('settings')) || {};
6	var mytv_api = (new MyTV_API());
7	
8	var video_interfaces = {};
9	var last_video;
10	var minute_size = 4;
11	var player_seek_added = 0;
12	
13	var time_in_bg = 7200000;
14	var time_sync = 0;
15	var local_time_gmt_offset	= (new Date()).getTimezoneOffset ? (new Date()).getTimezoneOffset() : 0;
16	var local_time_offset		= local_time_gmt_offset * 60000;
17	
18	var oneHourWidth			= 240;
19	
20	var user_info;
21	var profile_info;
22	var simple_slider;
23	
24	var screenshot_ajax_lock = {};
25	var ajax_last_ref;
26	var blob_screen_last;
27	var clientX_last = 0;
28	var prev_images = new Array();
29	
30	var mouse_css = '';
31	var lock_fullscreen_doblclick = false;
32	var timers 		= {};
33	var timeouts 	= {};
34	var __cache = (new CacheClass()).init();
35	var _tv_program_width_cache = 0;
36	var _window_width_cache = 0;
37	var _tv_left_width_cache = 0;
38	var _calendar;
39	
40	var drag_last_x		= 0;
41	var drag_is_active	= false;
42	var currentPos 		= [];
43	var currLeftPos 	= 0;
44	var scrollLeftBegin	= 0;
45	var transition_event= transitionEndEventName();
46	var animating		= false;
47
48	var adv_seeking 	= false;
49	
50	var main_menu = {
51		menu: null,
52		index: 0
53	};
54	
55	var menu_container,
56		items_container,
57		player_container;
58	
59	var vinterface;
60	var first_load = false;
61	var repeats_hidden = true;
62	var seasen_selected = null;
63	
64	var slow_cpu_image_stack = new Array();
65	
66	this.version = window.SITE_SETTINGS['APPLICATION_VERSION'];
67	
68	this.init = function () {
69		menu_container = $('#menu-container').get(0);
70		items_container = $('#items-container').get(0);
71		player_container = $('#player-container').get(0);
72		
73		this.bind();
74		
75		_window_width_cache = $(window).width();
76		
77		this.state_manager.init('/app/');
78		
79		if(!mytv_api.init(local_storage)) {
80			
81		} else {
82			mytv_api.set_error_handler(function(identifier, msg, number) {
83				_self.show_error(identifier, msg);
84			});
85
86			mytv_api.set_complete_handler(function(res) {
87				if(res && res['title_prev']) {
88					document.title = res['title_prev'] + ' - ' + window.SITE_SETTINGS['SITE_NAME'];
89				}
90			});
91			
92			// Взимаме настройките за url-ите първо
93			mytv_api.settings_urls(function () {
94				// Взимаме данните за потребителя
95				mytv_api.settings_info(function (res) {
96					if(res && res['data']) {
97						// Проверяваме дали има get_profile_key
98						// Ако няма показваме страницата за избор на профил
99						// Ако има проверяваме дали е съвпада с някой от профилите на усера.
100						// Може да е изтрит или да се е логнал друг усер
101						user_info = res['data'];
102						
103						var current_profile_key = mytv_api.get_profile_key();
104						var show_profile_page = false;
105						
106						if(current_profile_key.length) {
107							if(user_info['profiles'] && user_info['profiles'].length) {
108								show_profile_page = true;
109								
110								for(var i=0; i<user_info['profiles'].length; i++) {
111									if(user_info['profiles'][i]['key'] == current_profile_key) {
112										profile_info = user_info['profiles'][i];
113										show_profile_page = false;
114										break;
115									}
116								}
117							}
118						} else {
119							if(user_info['profiles']) {
120								// Показваме екрана за избор на профил
121								show_profile_page = true;
122							}
123						}
124						
125						// Ако няма нужда да покаваме екрана за пфилите рендим стандартно
126						if(!show_profile_page) {
127							_self.menu_main_load(function () {
128								// Зареждаме Intercom
129								_self.loadIntercom();
130								
131								if(main_menu['menu'].length > 8) {
132									return _self.state_manager.switch_page('menu', 'menu/home');
133								} else {
134									return _self.state_manager.switch_page('menu', 'menu/livetv_alternative/ts0');
135								}
136							});
137						} else {
138							// Показваме екрана за избор на профил
139							_self.profile_select_load(user_info['profiles'], true);
140						}
141						
142					} else {
143						return _self.state_manager.switch_page('login', {});
144					}
145				});
146			});
147		}
148		
149		return this;
150	}
151	
152	
153	
154	this.bind = function() {
155		// 
156		$(window).on('resize', function() {
157			_window_width_cache = $(window).width();
158		});
159
160		// Падащите менюта
161		var menu_hide = true;
162		$('body').on('click', '.open .main-nav, .show, *[data-action=seasons-show], *[data-action=more-menu-show], *[data-action=account-menu-show]', function() {
163			menu_hide = false;
164		});
165		
166		$('body').on('click', function() {
167			if(menu_hide) {
168				$('.show').toggleClass('show', false);
169				$('.open').toggleClass('open', false);
170			}
171			
172			menu_hide = true;
173		});
174		
175		$('body').on('click', '#main-nav-btn', function() {
176			$('#menu-container').toggleClass('open');
177			
178			menu_hide = !$('#menu-container').hasClass('open');
179		});
180		
181		$('body').on('click', '.btn-back, .close-popup', function() {
182			if(!$('.fullscreen-panel:visible').length) {
183				if(_self.state_manager['queue'].length) {
184					history.back();
185				}
186			} else {
187				var popup = _self.state_manager['popups'].pop();
188				popup.close();
189			}
190		});
191		
192		var stop_click = false;
193		$('body').on('click', '#tv-program-inner *[data-action]', function(e) {
194			e.pageX = parseInt(e.pageX);
195			e.pageY = parseInt(e.pageY);
196			
197			if(e.pageX != drag_last_x) {
198				stop_click = true;
199				return false;
200			}
201			
202			if(drag_is_active) {
203				stop_click = true;
204				return false;
205			}
206			
207			var action = $(this).attr('data-action');
208			var key = $(this).attr('data-key');
209			var clear_queue = $(this).attr('clear-queue');
210			
211			if(clear_queue) {
212				_self.state_manager.clear_queue();
213			}
214			
215			return _self.state_manager.switch_page(action, key);
216		});
217		
218		$('body').on('click', '*[data-action]', function(e) {
219			if(stop_click == true) {
220				stop_click = false;
221				return false;
222			}
223			
224			var action = $(this).attr('data-action');
225			var key = $(this).attr('data-key');
226			var clear_queue = $(this).attr('clear-queue');
227			
228			if(clear_queue) {
229				_self.state_manager.clear_queue();
230			}
231			
232			return _self.state_manager.switch_page(action, key);
233		});
234
235		// Скорост
236		$('body')
237			.on('click.'+this.id, '.speed a[data-speed]', function () {
238				var speed = parseFloat($(this).attr('data-speed'));
239				_self.vinterface.setSpeed(speed);
240			});
241
242		// Реклами
243		$('body')
244			.on('click.'+this.id, '.adv a[data-adv="on"]', function () {
245				storage_settings['adv'] = 'on';
246				localStorage.setItem('settings', JSON.stringify(storage_settings));
247				_self.player_ui.renderAdv();
248			})
249			.on('click.'+this.id, '.adv a[data-adv="off"]', function () {
250				storage_settings['adv'] = 'off';
251				localStorage.setItem('settings', JSON.stringify(storage_settings));
252				_self.player_ui.renderAdv();
253			});
254		
255		
256		// Search
257		$(document)
258			.on('keyup',function (e) {
259				if(e.target &&
260				   (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA')) {
261					
262					if($(e.target).parents('#search-form').length) {
263						// На 3 символа пускаме търсенето
264						var search_term = $(e.target).val();
265						
266						if(search_term.length > 2) {
267							if(timers['search']) {
268								clearInterval(timers['search']);
269								timers['search'] = null;
270							}
271							
272							timers['search'] = setTimeout(function() {
273								mytv_api.search(search_term, function(res) {
274									_self.search_render_result(res);
275								});
276							}, 300);
277						}
278					}
279				}
280			});
281		
282		
283		// Program
284		/* Firefox SUCSSSSSSSSSSSSSSSSSSS !!!!!!!!!!!!!!!!!!!!!!!! */
285		$(window)
286			.on('scroll', function() {
287				var topScrollPosition = parseInt($(document).scrollTop());
288				
289				if(topScrollPosition < 0) {
290					topScrollPosition = 0;
291				}
292				
293				var diff = $('#menu-container').height() - topScrollPosition;
294				var fuck_setTimeout = setTimeout(function() {
295					if (diff <= 0) {
296						$('#time-line-wrapper').css({
297							position:'fixed',
298							top: '0px'
299						});
300						
301						$('.return-to-top').show(200);
302					} else {
303						$('#time-line-wrapper').css({
304							position:'fixed',
305							top: diff+'px'
306						});
307						$('.return-to-top').hide(200);
308					}
309				}, 0);
310			});
311		
312		$(window)
313			.on('mouseup touchend', function (e) {
314				if(timers['scrollInterval']) {
315					// Приключило е сктролване с мишката
316					clearInterval(timers['scrollInterval']);
317					timers['scrollInterval'] = null;
318				}
319				
320				if(_self.player_ui['is_active'] && drag_is_active) {
321					var evnt = e.originalEvent ? e.originalEvent : e;
322					var posx = evnt.clientX ? evnt.clientX : (evnt.touches && evnt.touches.length ? evnt.touches[0].clientX : (evnt.changedTouches && evnt.changedTouches.length ? evnt.changedTouches[0].clientX : 0));
323					
324					var percent = (posx - $('.proggress-bar').offset().left) / $(".proggress-bar-inner").width();
325					var mouse_time = Math.floor(percent * _self.player_ui.media['duration']);
326					_self.player_ui.media['last_time'] = mouse_time;
327					_self.vinterface.seek(mouse_time);
328				}
329				
330				drag_is_active = false;
331			});
332		
333		$(document).on('dragstart', 'img, a', function(e) {
334			return false;
335		});
336		
337		$('body')
338			.on('mousedown touchstart', '.tv-program-inner, .time-line-cont, .proggress-bar-inner', function (e) {
339				if(items_container.className == 'tv-program'
340					|| _self.player_ui['is_active']) {
341					if(e.which == 1 || e.type == 'touchstart') {
342						drag_is_active = true;
343						
344						var evnt = e.originalEvent ? e.originalEvent : e;
345						var posx = evnt.clientX ? evnt.clientX : (evnt.touches ? evnt.touches[0].clientX : 0);
346						
347						drag_last_x = posx;
348					};
349				}
350			});
351
352		$(document).on('mousemove touchmove', function (e) {
353			if (!drag_is_active) {
354				return;
355			}
356			
357			if(_self.player_ui['is_active']) {
358				// Драгване на скръбера
359				// fuck touch events!!!!!!!!!!!!!!!!
360				var evnt = e.originalEvent ? e.originalEvent : e;
361				var posx = evnt.clientX ? evnt.clientX : (evnt.touches ? evnt.touches[0].clientX : 0);
362				
363				if(posx > 0 ) {
364					var percent = (posx - $('.proggress-bar').offset().left) / $(".proggress-bar-inner").width();
365					var mouse_time = Math.floor(percent * _self.player_ui.media['duration']);
366					_self.player_ui.media['last_time'] = mouse_time;
367					
368					_self.player_ui.scrubberMouseUpdate(posx);
369					_self.player_ui.scrubberTimesUpdate(_self.player_ui.media);
370				}
371			} else if(items_container.className == 'tv-program') {
372				// Ако е през тъч не пипаме нищо.
373				var evnt = e.originalEvent ? e.originalEvent : e;
374				if(typeof(evnt['touches']) !== 'undefined') {
375					return;
376				}
377
378				var posx = evnt.clientX ? evnt.clientX : (evnt.touches ? evnt.touches[0].clientX : 0);
379				var pagex = parseInt(evnt.pageX ? evnt.pageX : (evnt.touches ? evnt.touches[0].pageX : 0));
380				var pagey = parseInt(evnt.pageY ? evnt.pageY : (evnt.touches ? evnt.touches[0].pageY : 0));
381
382				if (pagex !== currentPos[0] && pagey !== currentPos[1]) {
383					currentPos = [pagex, pagey];
384					prevent_click_when_drag = true;
385
386					var pixels_to_move = drag_last_x - posx;
387					
388					drag_last_x = posx;
389					
390					if(pixels_to_move < 0) {
391						_self.program_scrollDirection({
392							'direction'	: 'left',
393							'pixels'	: Math.abs(pixels_to_move),
394							'animate'	: false
395						});
396					} else if(pixels_to_move != 0) {
397						_self.program_scrollDirection({
398							'direction'	: 'right',
399							'pixels'	: Math.abs(pixels_to_move),
400							'animate'	: false
401						});
402					}
403				}
404			}
405		});
406		
407		$(document)
408			.on('keydown',function (e) {
409				if(e.target &&
410				   (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA')) {
411					return true;
412				}
413				
414				if(_self.player_ui['is_active']) {
415					if (e.which == 37 || e.which == 39) {
416						e.preventDefault && e.preventDefault();
417						e.stopPropagation && e.stopPropagation();
418						
419						var clss = $('.proggress-bar').attr('class');
420						if(clss.indexOf('disabled') >= 0){
421							return false;
422						}
423						
424						if(timeouts['seek_time']){
425							clearTimeout(timeouts['seek_time']);
426						}
427						
428						if(e.which == 37) {
429							player_seek_added -= 10
430						} else {
431							player_seek_added += 10;
432						}
433						
434						var seek_to_time = Math.floor(_self.player_ui.media['currentTime']) + player_seek_added;
435						_self.player_ui.media['last_time'] = seek_to_time;
436						_self.player_ui.toggleScreenshot(seek_to_time / _self.player_ui.media['duration'], seek_to_time);
437						$('.mouse_time').html(_self.player_ui.hh_mm(seek_to_time));
438						
439						timeouts['seek_time'] = setTimeout(
440							function(){
441								_self.player_ui.media['last_time'] = seek_to_time;
442								player_seek_added = 0;
443								_self.vinterface.seek(seek_to_time);
444							}, 1500);
445					}
446				} else if(items_container.className == 'tv-program') {
447					if (e.which  == 37 || e.which  == 39) {
448						//left btn          //right btn
449						e.preventDefault();
450						if(!timers['scrollInterval']) {
451							var key_code = e.which;
452							timers['scrollInterval'] = setInterval(function() {
453								_self.program_scrollDirection({
454									direction: (key_code == 37 ? 'left' : 'right')
455								});
456							}, 350);
457							
458							// Пускаме вднага веднъж, ако само един път е натиснато
459							_self.program_scrollDirection({
460								direction: (key_code == 37 ? 'left' : 'right')
461							});
462						}
463					}
464				}
465			})
466			.on('keyup',function (e) {
467				if(e.target &&
468				   (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA')) {
469					return true;
470				}
471				
472				if(items_container.className == 'tv-program') {
473					if(e.which  == 37 || e.which  == 39) {
474						// Приключило е сктролване със стрелките
475						if(timers['scrollInterval']) {
476							clearInterval(timers['scrollInterval']);
477							timers['scrollInterval'] = null;
478						}
479					}
480				}
481			});
482		
483		if(transition_event !== undefined) {
484			$('body')
485				.on(transition_event, '#tv-program-inner', function () {
486					animating = false;
487				});
488		}
489		
490		$('body').on('click', '.tv-calendar', function () {
491			$(this).toggleClass('opened');
492		});
493		
494		$('body')
495			.on('mousedown', '.time-line-buttons .btn-prev, .time-line-buttons .btn-next', function (e) {
496				e.preventDefault();
497				if(!timers['scrollInterval']) {
498					var direction = $(this).hasClass('btn-prev') ? 'left' : 'right';
499					timers['scrollInterval'] = setInterval(function() {
500						_self.program_scrollDirection({
501							'direction': direction
502						});
503					}, 350);
504					
505					// Пускаме вднага веднъж, ако само един път е натиснато
506					_self.program_scrollDirection({
507						'direction': direction
508					});
509				}
510			})
511			.on('mouseup', '.time-line-buttons .btn-prev, .time-line-buttons .btn-next', function (e) {
512				if(timers['scrollInterval']) {
513					clearInterval(timers['scrollInterval']);
514					timers['scrollInterval'] = null;
515				}
516			})
517			.on('mousedown', '.btn-now',function () {
518				var goToDate = new Date((new Date()).getTime() - time_sync);
519				oThis.calendar_load_dt(goToDate);
520				oThis.calendar_select_dt(goToDate);
521			});
522		
523		//favorite
524		simple_slider = (new SimpleSliderNew({ item_selector: ".tv-show" })).init();
525		
526		// Video интерфейси
527		for(var i=0; i<mytv_video_interfaces.length; i++) {
528			// Всеки видео интерфейс извършва тест за съвместимост
529			try {
530				var _interface =
531						(new window[mytv_video_interfaces[i]]).init(_self.player_ui, {
532							'width': '100%',
533							'height': 'auto',
534							'bgcolor': 'rgba(0, 0, 0, 0.7)',
535							'external_controls': true
536						});
537				video_interfaces[mytv_video_interfaces[i]] = _interface;
538			} catch(e) {
539				console.log(e);
540			}
541			
542			try {
543				log(_interface.constructor.name, _interface.is_supported);
544			} catch(e) {
545			}
546		}
547		
548		
549		// Video player
550		$('body').on('click.'+this.id, '.nav-btn', function () {
551			$(this).toggleClass('expanded');
552		});
553		
554		$('body')
555			.on('mousemove', '.player-ui.fullscreen', function() {
556				_self.player_ui.fullScreenControlsShow();
557			})
558			.on('click', '.full-screen', function (e) {
559				if(!lock_fullscreen_doblclick) {
560					_self.player_ui.enterFullscreen();
561					_self.player_ui.fullScreenControlsShow();
562				}
563			});
564		
565		$(document).on('webkitfullscreenchange mozfullscreenchange MSFullscreenChange msfullscreenchange fullscreenchange', function (e) {
566			is_full_screen = document.webkitFullscreenElement || document.mozFullScreen || document.msFullscreenElement != null || document.fullscreenElement != null;
567			if(is_full_screen) {
568				$('#intercom-container').hide();
569				$('html').toggleClass('fullscreen', true);
570				$('.player-ui').toggleClass('fullscreen', true);
571				_self.player_ui.fullScreenControlsShow();
572			} else {
573				$('#intercom-container').show();
574				$('html').toggleClass('fullscreen', false);
575				$('.player-ui').toggleClass('fullscreen', false);
576				
577				_self.player_ui.fullScreenControlsHide();
578			}
579			
580			var fuck_settimeout = setTimeout(function () { lock_fullscreen_doblclick = false;}, 500);
581		});
582		
583		// PLAY PAUSE
584		$(document).on('keydown.'+this.id, function (e) {
585			if(!_self.player_ui['is_active']) {
586				return true;
587			}
588			
589			var code = e.keyCode || e.which;
590			if(code === 32) {
591				if(!(e.target && e.target.nodeName == 'INPUT') && !(e.target && e.target.nodeName == 'TEXTAREA')) {
592					e.preventDefault();
593					
594					if(_self.player_ui['state'] != 'playing') {
595						_self.vinterface.play();
596					} else {
597						_self.vinterface.pause();
598					}
599					
600					return false;
601				}
602			}
603			
604			if(code == 13){
605				if(!lock_fullscreen_doblclick) {
606					_self.player_ui.enterFullscreen();
607					_self.player_ui.fullScreenControlsShow();
608				}
609			}
610			
611			return true;
612		});
613		
614		$('body')
615			.on('click.'+this.id, '.nav-btn.sm-el', function() {
616				setTimeout(function () {$('.sm-hide').toggleClass('open_');});
617			})
618			.on('click.'+this.id, '.play-pause', function (e) {
619				if(!_self.player_ui['is_active']) {
620					return true;
621				}
622				
623				if(_self.player_ui['state'] != 'playing') {
624					_self.vinterface.play();
625				} else {
626					_self.vinterface.pause();
627				}
628			});
629		// PLAY PAUSE END
630		
631		
632		
633		// VOLUME
634		var volume_drag = false;
635		$('body')
636			.on('click.'+this.id, '.volume-controler-cont', function (e) {
637				e.stopPropagation();
638				e.preventDefault();
639				
640				return false;
641			})
642			.on('click.'+this.id, '.volume-cont', function (e) {
643				if(_self.player_ui['muted']) {
644					_self.player_ui['muted'] = false;
645					_self.vinterface.setVolume(_self.player_ui['current_volume']);
646				} else {
647					_self.player_ui['muted'] = true;
648					_self.vinterface.setVolume(0);
649				}
650				
651				$(this).toggleClass('expanded', true);
652				
653				e.stopPropagation();
654				e.preventDefault();
655				
656				return false;
657			})
658			.on('mouseenter.'+this.id, '.volume-cont', function (e) {
659				if(timeouts['volume_hide']) {
660					clearTimeout(timeouts['volume_hide']);
661				}
662				$(this).toggleClass('expanded', true);
663			})
664			.on('mouseleave.'+this.id, '.volume-cont', function (e) {
665				var self = $(this);
666				if(timeouts['volume_hide']) {
667					clearTimeout(timeouts['volume_hide']);
668				}
669				
670				timeouts['volume_hide'] = setTimeout(function () {
671					self.toggleClass('expanded', false);
672				}, 1000);
673			})
674			.on('mousedown.'+this.id, '.volum_controler', function (e) {
675				var volume 	= _self.player_ui.calVolume(e.clientY);
676				
677				volume_drag = true;
678				
679				_self.player_ui['muted'] = false;
680				_self.vinterface.setVolume(volume);
681				
682				e.stopPropagation();
683				e.preventDefault();
684
685				return false;
686			});
687
688		$(window)
689			.on('mouseup.'+this.id, function (e) {
690				volume_drag = false;
691			})
692			.on('mousemove.'+this.id, function (e) {
693				if(!volume_drag) return true;
694				
695				var volume = _self.player_ui.calVolume(e.clientY);
696				volume_drag = true;
697				_self.player_ui['muted'] = false;
698				
699				_self.vinterface.setVolume(volume);
700				
701				e.stopPropagation();
702				e.preventDefault();
703
704				return false;
705			});
706
707		$(document)
708			.on('keydown.'+this.id, function (e) {
709				if(!_self.player_ui['is_active']) {
710					return true;
711				}
712				
713				var code = e.keyCode || e.which;
714				
715				if(code === 38 || code ===40) {
716					_self.player_ui.fullScreenControlsShow();
717					
718					if(timeouts['volume_change']) { clearTimeout(timeouts['volume_change']); }
719					if(timeouts['volume_hide']) { clearTimeout(timeouts['volume_hide']); }
720					
721					$('.volume-cont').toggleClass('expanded', true);
722					
723					if(code == 38 ){
724						_self.player_ui['current_volume'] += 2;
725					} else {
726						_self.player_ui['current_volume'] -= 2;
727					}
728					
729					_self.player_ui['current_volume'] = _self.player_ui['current_volume'] >= 100 ? 100:  _self.player_ui['current_volume'];
730					_self.player_ui['current_volume'] = _self.player_ui['current_volume'] <= 0 ? 0 : _self.player_ui['current_volume'];
731					
732					_self.vinterface.setVolume(_self.player_ui['current_volume']);
733					
734					return false;
735				}
736			})
737			.on('keyup.'+this.id,  function (e){
738				if(!_self.player_ui['is_active']) {
739					return true;
740				}
741				
742				var code = e.keyCode || e.which;
743				
744				if(code == 38 || code ==40) {
745					if(timeouts['volume_hide']) {
746						clearTimeout(timeouts['volume_hide']);
747					}
748					
749					timeouts['volume_hide'] =  setTimeout(function () {
750						$('.volume-cont').toggleClass('expanded', false);
751					}, 1500);
752					
753					return false;
754				}
755			});
756		// VOLUME END
757		
758		
759		// SCRUBBER
760		$('body')
761			.on('click.'+this.id, '.proggress-bar', function (e) {
762				// Seek
763				var percent = (e.clientX - $('.proggress-bar').offset().left) / $(".proggress-bar-inner").width();
764				
765				var mouse_time = Math.floor(percent * _self.player_ui.media['duration']);
766				_self.player_ui.media['last_time'] = mouse_time;
767				_self.vinterface.seek(mouse_time);
768			})
769			.on('mouseleave', '.proggress-bar', function (e) {
770				$('.proggress-bar .time_moved').toggleClass('hidden', false);
771				$('.proggress-bar .time_duration').toggleClass('hidden', false);
772				$('.player-ui .navigation').toggleClass('show_times', false);
773			})
774			.on('mousemove mouseenter touchmove', '.proggress-bar', function (e) {
775				var evnt = e.originalEvent ? e.originalEvent : e;
776				var posx = evnt.clientX ? evnt.clientX : (evnt.touches ? evnt.touches[0].clientX : 0);
777				
778				_self.player_ui.scrubberMouseUpdate(posx);
779			});
780			
781		// SCRUBBER END
782		
783		
784		// QUALITY SWITCH
785		$('body')
786			.on('click.'+this.id, '.nav-btn.quality ul li a', function (e) {
787				$(".nav-btn.quality .quality").toggleClass("rotating", true);
788				_self.vinterface.setBitrate($(this).data('quality'));
789			});
790		// QUALITY SWITCH END
791		
792		
793		// REPORTS
794		var is_unload_executed = false;
795		$(window).on('beforeunload.'+this.id+', unload.'+this.id, function () {
796			if(!is_unload_executed && _self.player_ui['is_active']) {
797				_self.player_ui.report_playback_progress('stop');
798			}
799			
800			is_unload_executed = true;
801		});
802		// REPORTS END
803	}
804	
805	
806	function pagestate(action, key, scrollTop) {
807		this.action		= action;
808		this.key		= key;
809		this.scrollTop	= scrollTop;
810	}
811	
812	this.state_manager = {
813		'queue': [],
814		'popups': [],
815		'base_path': '',
816		
817		'init': function(base_path) {
818			this.base_path = '/' + base_path.trim_simbol('/') + '/';
819			
820			window.onpopstate = function(state) {
821				_self.state_manager.pop();
822			}
823		},
824		
825		'get_url': function(key) {
826			var url = this.base_path + key;
827
828			// Оправяме url-а да няма параметри в get-a
829			try {
830				var link = document.createElement('a');
831    			link.href = url;
832				url = link.pathname;
833			} catch(e){
834				console.error(e);
835			}
836			
837			return url;
838		},
839		
840		'clear_queue': function() {
841			this.queue = [];
842		},
843		
844		'push': function(state) {
845			this.queue.push(state);
846			
847			var url = this.get_url(state['key']);
848			history.pushState(state, '', url);
849			
850			// За новата страница ресетваме скролинга
851			$(items_container).scrollTop(0);
852			$('html').scrollTop(0);
853		},
854		
855		'pop': function() {
856			var current_state = this.queue.pop();
857			
858			$('#profiles-panel').hide();
859			$('#main-bnt-back').toggleClass('btn-back', false);
860			
861			if(_self.player_ui['is_active']) {
862				_self.player_ui.stop();
863			}
864			
865			if(this.queue.length) {
866				var state = this.queue[this.queue.length - 1];
867				this.switch_page(state['action'], state['key'], [function() {
868					if(typeof(current_state['scrollTop']) != 'undefined') {
869						$(items_container).scrollTop(current_state['scrollTop']);
870						$('html').scrollTop(current_state['scrollTop']);
871					} else {
872						$(items_container).scrollTop(0);
873						$('html').scrollTop(0);
874					}
875				}]);
876			} else {
877				// Ако опашката е празна мапрваме url-a
878				_self.map_url();
879			}
880		},
881		
882		'popup_add': function(page, close_func) {
883			this.popups.push({
884				'page': page,
885				'close': close_func
886			});
887		},
888		
889		'check_add_state': function(action, key, scrollTop) {
890			var dot_add_to_queue = this.queue.length && this.queue[this.queue.length-1]['key'] == key;
891			if(!dot_add_to_queue) {
892				var state = new pagestate(action, key, scrollTop);
893				this.push(state);
894			}
895			
896			$('#main-bnt-back').toggleClass('btn-back', this.queue.length > 1);
897		},
898		
899		'switch_page': function(action, data, after_render) {
900			after_render = !after_render ? [] : after_render;
901
902			// Изтриваме таймери ако има
903			for(tmr in timers) {
904				clearInterval(timers[tmr]);
905			}
906			
907			var css_class = (typeof(data) == 'string' ? ' ' + data.replace(/\//g, '_') : action.replace(/\//g, '_'));
908			$('html')[0].className = css_class;
909			
910			timers = {};
911			
912			var scrollTop = items_container.scrollTop || $('html').scrollTop();
913			switch(action) {
914				case 'login':
915					_self.login_render();
916				break;
917				
918				case 'logout':
919					mytv_api.logout(function () {
920						mytv_api.clear_saved_data();
921						user_info = null;
922						
923						if(_self.player_ui['is_active']) {
924							_self.player_ui.stop();
925						}
926						
927						location.reload(true);
928					});
929					
930					return false;
931				break;
932				
933				case 'more-menu-show':
934					$('.menu-more').toggleClass('show');
935				break;
936				
937				case 'account-menu-show':
938					$('.account-sub-menu ul').toggleClass('show');
939				break;
940				
941				case 'close-msg':
942				case 'close-error':
943					$('#errors-container').hide();
944				break;
945
946				case 'seasons-select':
947					if(data == 'all') {
948						$('.tv-show').toggleClass('hidden', false);
949					} else {
950						$('.tv-show').toggleClass('hidden', true);
951						$('.tv-show[data-season='+data+']').toggleClass('hidden', false);
952					}
953
954					$('.sesons-btn').html($('*[data-action=seasons-select]').parent().find('a[data-key='+data+']').html());
955					$('.seasons-panel').toggleClass('show');
956				break;
957
958				case 'seasons-show':
959					$('.seasons-panel').toggleClass('show');
960				break;
961
962				case 'repeats-btn':
963					repeats_hidden = !repeats_hidden;
964					
965					removeClass(items_container, 'episodes-hidden');
966					if(repeats_hidden) {
967						addClass(items_container, 'episodes-hidden');
968					}
969				break;
970				
971				case 'favorite-add':
972					mytv_api.favorite_add_remove(data, function(res) {
973						if(res['st'] == 'saved') {
974							$('#watchlist_cnt').html(parseInt($('#watchlist_cnt').html()) + 1);
975						} else {
976							$('#watchlist_cnt').html(parseInt($('#watchlist_cnt').html()) - 1);
977						}
978
979						$('#menu-container a[data-key2=menu_watchlist]').toggleClass('blink', true);
980						setTimeout(function() { $('#menu-container a[data-key2=menu_watchlist]').toggleClass('blink', false); }, 300);
981
982						$('*[data-key="'+data+'"]').toggleClass('saved', res['st'] == 'saved');
983					});
984					
985					return false;
986				break;
987				
988				case 'close-popup':
989					var popup = _self.state_manager['popups'].pop();
990					popup.close();
991				break;
992				
993				case 'select_avatar':
994					$('#avatars_panel').hide();
995					$('#profile-edit_selected_avatar').attr('src', $('*[data-key='+data+']').attr('data-src'));
996					document.getElementsByName('avatar_key')[0].value = data;
997				break;
998				
999				case 'change_avatar':
1000					$('#avatars_panel').show();
1001				break;
1002				
1003				case 'delete_profile':
1004					_self.show_profile_delte_confirm();
1005				break;
1006				
1007				case 'add_profile':
1008					_self.profile_edit();
1009					
1010					return false;
1011				break;
1012				
1013				case 'edit_profile':
1014					var _profile_info_edit;
1015					
1016					if(user_info['profiles'] && user_info['profiles'].length) {
1017						for(var i=0; i<user_info['profiles'].length; i++) {
1018							if(user_info['profiles'][i]['key'] == data) {
1019								_profile_info_edit = user_info['profiles'][i];
1020								show_profile_page = false;
1021								break;
1022							}
1023						}
1024					}
1025					
1026					_self.profile_edit(_profile_info_edit);
1027					
1028					return false;
1029				break;
1030				
1031				
1032				case 'select_profile':
1033					mytv_api.set_profile_key(data);
1034					location.reload(true);
1035				break;
1036				
1037				
1038				case 'play_video':
1039					_self.player_load(data);
1040				break;
1041				
1042				
1043				case 'menu':
1044					switch(data) {
1045						case 'search':
1046							_self.search_render();
1047						break;
1048						
1049						case 'profile-select':
1050							_self.profile_select_load(user_info['profiles']);
1051						break;
1052						
1053						case 'menu/home':
1054							after_render.push(function() {
1055								_self.state_manager.check_add_state(action, data, scrollTop);
1056							})
1057							_self.menu_home_load(after_render);
1058						break;
1059						
1060						case 'menu/tvguide':
1061							after_render.push(function() {
1062								_self.state_manager.check_add_state(action, data, scrollTop);
1063							})
1064							_self.menu_general_load(data, after_render);
1065						break;
1066						
1067						case 'menu/news':
1068							_self.menu_news_load(after_render);
1069						break;
1070						
1071						default:
1072							// Ресетваме индекса за бутоните в заглавието и селектния сезон
1073							seasen_selected = null;
1074							repeats_hidden = true;
1075
1076							if(data.match(/menu\/program/ig)) {
1077								after_render.push(function() {
1078									_self.state_manager.check_add_state(action, data, scrollTop);
1079								})
1080								_self.menu_general_load(data, after_render);
1081							} else {
1082								after_render.push(function() {
1083									_self.state_manager.check_add_state(action, data, scrollTop);
1084								})
1085								_self.menu_general_load(data, after_render);
1086							}
1087						break;
1088					}
1089				break;
1090				
1091				default:
1092					// Дефолтна страница
1093				break;
1094			}
1095		}
1096	}
1097	
1098	
1099	this.show_error = function(id, msg) {
1100		if(id == 'subscription_required') {
1101			location.href = '/plans';
1102			return;
1103		}
1104		
1105		var error_container = document.getElementById('errors-container');
1106		
1107		_self.innerHTML(error_container, '\
1108			<div class="error-inner">\
1109				<h1>' + msg + '</h1>\
1110				<button data-action="close-error" class="active btn green">OK</button>\
1111			</div>'
1112		);
1113		
1114		$(error_container).show();
1115	}
1116	
1117	
1118	this.loadIntercom = function() {
1119		if(!user_info['no_intercom']) {
1120			window.intercomSettings = {
1121				email: user_info['email'],
1122				name: user_info['name'],
1123				user_hash: user_info['intercom_hash_web'],
1124				app_id: "f179ba5331e96357fa2ea7f02e6c3bc1bff7a271"
1125			};
1126			
1127			$(function () {
1128				(function(){
1129					var w=window;
1130					var ic=w.Intercom;
1131					
1132					if(typeof ic==="function") {
1133						ic('reattach_activator');
1134						ic('update',intercomSettings);
1135					} else {
1136						var d=document;
1137						var i=function(){
1138								i.c(arguments)
1139							};
1140						
1141						i.q=[];
1142						i.c=function(args){
1143							i.q.push(args)
1144						};
1145						w.Intercom=i;
1146						
1147						function l(){
1148							var s=d.createElement('script');
1149							s.type='text/javascript';
1150							s.async=true;
1151							s.src='https://static.intercomcdn.com/intercom.v1.js';
1152							var x=d.getElementsByTagName('script')[0];
1153							x.parentNode.insertBefore(s,x);
1154						}
1155						
1156						l();
1157					};
1158				})();
1159			});
1160		}
1161	}
1162	
1163	
1164	this.map_url = function(url) {
1165		url = url ? url : location.pathname;
1166		
1167		var page = url.replace(/app\//ig, '').trim_simbol('/');
1168
1169		if(page == '' || page == '/') {
1170			page = 'menu/home';
1171		}
1172		
1173		if(page.indexOf('menu') > -1) {
1174			_self.state_manager.switch_page('menu', page);
1175		} else {
1176			_self.state_manager.switch_page(page);
1177		}
1178	}
1179	
1180	
1181	this.menu_general_load = function (key, after_render) {
1182		this.show_loader();
1183		
1184		mytv_api.menu(key, function (res) {
1185			if(!res)  {
1186				_self.show_error(MyTV.ERRORS['invalid_data']);
1187				return;
1188			}
1189			
1190			if(res['msg']) {
1191				_self.show_error('generic_error', res['msg']);
1192				return;
1193			}
1194
1195			if(res['menu']) {
1196				if(key.indexOf('menu/program_v2') >= 0) {
1197					_self.program_render(res);
1198					after_render && after_render.forEach(function(fn) { fn(); });
1199				} else if(key == 'menu/news') {
1200				} else if(key.indexOf('menu/tvguide') >= 0) {
1201					_self.tvguide_render(res);
1202					after_render && after_render.forEach(function(fn) { fn(); });
1203				} else {
1204					items_container.scrollTop_cached = items_container.scrollTop = 0;
1205					_self.general_render(key, res);
1206					after_render && after_render.forEach(function(fn) { fn(); });
1207				}
1208			} else if(res['type'] == 'item') {
1209				_self.state_manager.switch_page('play_video', res);
1210			} else {
1211				
1212			}
1213		}, function () {
1214			_self.hide_loader();
1215		}, lock = true);
1216	}
1217	
1218	
1219	this.menu_main_load = function(onloaded) {
1220		_self.show_loader();
1221		
1222		mytv_api.menu('', function (res) {
1223			if(!res)  {
1224				_self.show_error(MyTV.ERRORS['invalid_data']);
1225				return;
1226			}
1227			
1228			if(!res['menu']) {
1229				// Ако е празноменюто
1230				location.reload(true);
1231			}
1232			
1233			if(user_info && user_info['email'] == 'lgtv_test'
1234			   || !user_info) {
1235			}
1236			
1237			_self.main_menu_render(res);
1238			
1239			if(onloaded) {
1240				onloaded();
1241			}
1242		}, function () {
1243			_self.hide_loader();
1244		}, false);
1245	}
1246	
1247	
1248	this.main_menu_render = function (items) {
1249		if(items && items['menu']) {
1250			// Нещо не е наред релоадваме
1251			main_menu['menu'] = items['menu'];
1252			
1253			var sel = '',
1254				html = '<a id="main-nav-btn"></a><div class="menu-inner"><ul class="main-nav">',
1255				title = '',
1256				sep = '',
1257				item_coint = '',
1258				css = ''
1259				watch_cnt = 0;
1260			
1261			for(var i=0; i < main_menu['menu'].length; i++) {
1262				if(main_menu['menu'][i]['key'] == 'menu/watchlist/favourites') {
1263					watch_cnt = main_menu['menu'][i]['notification']['savedItemsCount'];
1264					continue;
1265				}
1266				
1267				sep = main_menu['menu'][i]['separator'] ? ' class="separator"' : '';
1268				
1269				if(main_menu['menu'][i]['thumb']) {
1270					thumb = '<img src="' + main_menu['menu'][i]['thumb'] + '" alt="" />';
1271					css = ' have-thumb';
1272				} else {
1273					css = '';
1274					thumb = '';
1275				}
1276				
1277				if(main_menu['menu'][i]['notification'] && main_menu['menu'][i]['notification']['savedItemsCount']) {
1278					item_coint = '<span>' + main_menu['menu'][i]['notification']['savedItemsCount'] + '</span>';
1279				} else {
1280					item_coint = '';
1281				}
1282				
1283				title = window['_LANG'] == 'en' ? main_menu['menu'][i]['title_en'] : main_menu['menu'][i]['title'];
1284				
1285				if(i == 5) {
1286					html += '<li><a data-action="more-menu-show">Още<span class="icon"></span></a><ul class="menu-more">';
1287				}
1288				
1289				html += '<li' + sep + '><a data-action="menu" clear-queue="true" data-key2="' + main_menu['menu'][i]['key'].replace('/', '_') + '" data-key="' + main_menu['menu'][i]['key'] + '"' + sel + '>' + thumb + title + item_coint + '</a></li>';
1290			}
1291			
1292			html += '</li></ul></ul>';
1293			
1294			var user_sub_menu = '';
1295			
1296			if(user_info && user_info['profiles'] && user_info['profiles'].length) {
1297				for(var i=0; i<user_info['profiles'].length; i++) {
1298					user_sub_menu += '<li><a data-action="select_profile" data-key="'+user_info['profiles'][i]['key']+'"><img src="'+user_info['profiles'][i]['avatar']+'"/> '+user_info['profiles'][i]['name']+'</a></li>';
1299				}
1300				
1301				user_sub_menu += '<li><a data-action="menu" data-key="profile-select">Управление на профили</a></li>';
1302				user_sub_menu += '<li class="sep"></li>';
1303				user_sub_menu += '<li><a href="/settings" target="_blank">Настройки</a></li>';
1304				user_sub_menu += '<li><a href="/subscription" target="_blank">Абонамент</a></li>';
1305				user_sub_menu += '<li><a data-action="logout">Изход</a></li>';
1306			}
1307			
1308			html += '<div class="account-sub-menu"><a data-action="menu" data-key="search"><span class="icon"></span></a><a data-action="menu" data-key="menu/watchlist/favourites" data-key2="menu_watchlist"><span id="watchlist_cnt">'+watch_cnt+'</span></a><a data-action="account-menu-show"><img src="' + profile_info['avatar'] + '" /><span class="icon"></span></a><ul>'+user_sub_menu+'</ul></div></div>';
1309			
1310			_self.innerHTML(menu_container, html);
1311		}
1312	}
1313	
1314	
1315	////////////////////////////////////
1316	// Login страница
1317	////////////////////////////////////
1318	
1319	this.login_render = function () {
1320		this.hide_loader();
1321		
1322		var container = document.getElementById('login-form'),
1323		form = document.createElement('form');
1324		form.setAttribute('id', 'login-form-form');
1325		
1326		form.onsubmit = function (event) {
1327			try {
1328				var usr = document.getElementsByName('usr')[0].value,
1329					pwd = document.getElementsByName('pwd')[0].value;
1330				
1331				_self.show_loader();
1332				
1333				mytv_api.login(usr, pwd, function (res) {
1334					if(res['token']) {
1335						mytv_api.set_token(res['token']);
1336						location.reload(true);
1337					}
1338				}, function () {
1339					_self.hide_loader();
1340				});
1341			} catch(e) {
1342				console.log(e);
1343			}
1344			
1345			return false;
1346		}
1347
1348		window.FB_login_result = function() {
1349			FB.getLoginStatus(function(response) {
1350				if (response.authResponse) {
1351					mytv_api.login_facebook(response["authResponse"]["accessToken"],
1352						function (res) {
1353							mytv_api.set_token(res['token']);
1354						},
1355						function () {
1356							location.reload(true);
1357						});
1358				}
1359			});
1360		}
1361			
1362		_self.innerHTML(form, '\
1363			<img src="/app/res/logo_color2.svg" class="logo" alt="">\
1364				<label>\
1365					'+window['lang'][window['_LANG']]['email']+'\
1366					<input id="login_0" class="active" type="text" name="usr" value="" />\
1367				</label>\
1368				<label>\
1369					'+window['lang'][window['_LANG']]['pass']+'\
1370					<input id="login_1" type="password" name="pwd" value="" />\
1371				</label>\
1372				<button type="submit" class="btn green '+mouse_css+'" value="Вход" id="login_2" name="login-btn">'+window['lang'][window['_LANG']]['login']+'</button>\
1373				<div class="fb-btn">\
1374					<div class="fb-login-button loading" data-max-rows="1" data-size="large" onlogin="try {FB_login_result();} catch(e) {top.FB_login_result();}" data-scope="public_profile,email" data-button-type="login_with" data-show-faces="false" data-auto-logout-link="false" data-use-continue-as="false"></div>\
1375				</div>'
1376		);
1377		
1378		_self.innerHTML(container, '');
1379		container.appendChild(form);
1380		container.style.display = 'block';
1381	}
1382	
1383	
1384	
1385	////////////////////////////////////
1386	// general страница START
1387	////////////////////////////////////
1388	this.general_render = function (key, items, season) {
1389		var sub_page_key = '';
1390		var season_filter = '';
1391		var is_epidodes_hidden = '';
1392
1393		items_container.className = '';
1394		document.getElementById('main-frame').className = '';
1395		
1396		if(key) {
1397			var css_arr = key.trim_simbol('/').split('/');
1398			var rest = css_arr.splice(2);
1399			
1400			sub_page_key = css_arr.join('_');
1401			items_container.className = sub_page_key;
1402		}
1403		
1404		if(items && items['menu']) {
1405			var html = '';
1406			if(typeof(items['title_prev']) != 'undefined') {
1407				// Слагаме загалвието
1408				var is_saved = items['is_saved'] ? ' saved' : '';
1409				var title = window['_LANG'] == 'en' && items['title_prev_en'] ? items['title_prev_en'] : items['title_prev'];
1410				var have_repeat = false;
1411
1412				is_epidodes_hidden = repeats_hidden ? ' episodes-hidden' : '';
1413				
1414				if(items['saveable']) {
1415					for(var i=0; i<items['menu'].length; i++) {
1416						have_repeat = items['menu'][i]['is_repeat'];
1417						if(have_repeat) {
1418							break;
1419						}
1420					}
1421
1422					// Проверяваме дали има сезони за печатане
1423					var seasons_btn = '';
1424					var seasons_panel = '';
1425					if(items['meta_info'] && items['meta_info']['seasons'] && items['meta_info']['seasons'].length) {
1426						seasons_panel = '<div class="seasons-panel">\
1427							<a data-action="seasons-select" data-key="all">Всички епизоди</a>';
1428						for(var i=0; i<items['meta_info']['seasons'].length; i++) {
1429							if(typeof(season) !== 'undefined' && i == season) {
1430								seasen_selected = season;
1431								season_filter = items['meta_info']['seasons'][i]['season_number'];
1432
1433								seasons_btn = '<a class="sesons-btn" data-action="seasons-show">'+items['meta_info']['seasons'][i]['title']+'</a>';
1434							}
1435
1436							seasons_panel += '<a data-action="seasons-select" data-key="'+items['meta_info']['seasons'][i]['season_number']+'">'+items['meta_info']['seasons'][i]['title']+'</a>';
1437						}
1438						seasons_panel += '</div>';
1439
1440						if(seasons_btn.length == 0) {
1441							// Няма избран сезон
1442							seasons_btn += '<a class="sesons-btn" data-action="seasons-show">Всички епизоди</a>';
1443						}
1444					}
1445					
1446					html += '<h2 class="'+(seasons_btn ? '' : 'no-seasons')+'">' + title + '\
1447						<div class="buttons-header">\
1448							<a data-key="' + key + '" data-action="favorite-add" class="favorite' + is_saved + '"></a>\
1449							'+(have_repeat ? '<a data-action="repeats-btn" class="repeat-btn"></a>' : '')+'\
1450							'+seasons_btn+'\
1451							'+seasons_panel+'\
1452						</h2>';
1453				} else {
1454					html += '<h2 class="no-seasons">' + title + '</h2>';
1455				}
1456			}
1457			
1458			removeClass(items_container, 'have-desc');
1459			removeClass(items_container, 'episodes-hidden');
1460
1461			if(is_epidodes_hidden) {
1462				addClass(items_container, 'episodes-hidden');
1463			}
1464			
1465			for(var i=0; i<items['menu'].length; i++) {
1466				html += this.item_render(items['menu'][i], sub_page_key == 'menu_livetv_alternative');
1467			}
1468			
1469			_self.innerHTML(items_container, html);
1470			this.item_post_render();
1471		}
1472	}
1473	////////////////////////////////////
1474	// general страница END
1475	////////////////////////////////////
1476	
1477	this.player_ui = {
1478		'current_volume': 100,
1479		'state': '',
1480		'media': {},
1481		'report_interval': null,
1482		'is_active': false,
1483		'is_controls_visible': true,
1484		'blob_loading': false,
1485		
1486		'report_playback_progress': function(action) {
1487			action = !action ? 'start' : action;
1488			var adskip = 0; //
1489			var report_data = {
1490				'key'				: last_video['tracking_key'],
1491				'time'				: this['media']['currentTime'],
1492				'duration'			: this['media']['duration'],
1493				'current_time'		: this['media']['currentTime'],
1494				'stream_started'	: this['media']['stream_started'],
1495				'profile_key'		: mytv_api.get_profile_key(),
1496				'action'			: action,
1497				'adskip'            : adskip
1498			};
1499			
1500			mytv_api.report_playback(report_data);
1501		},
1502		
1503		'stop': function() {
1504			this.state = 'stoped';
1505			
1506			_self.vinterface.stop && _self.vinterface.stop();
1507			_self.vinterface.destroy && _self.vinterface.destroy();
1508			
1509			this.is_active = false;
1510			
1511			if(this.report_interval) {
1512				clearInterval(this.report_interval);
1513				this.report_interval = null;
1514			}
1515			
1516			$(player_container).hide();
1517			$('html')[0].className = '';
1518			
1519			this.report_playback_progress('stop');
1520		},
1521		
1522		'onPlayerLoaded': function() {
1523			if(storage_settings && typeof storage_settings['vol'] === 'number' ){
1524				_self.vinterface.setVolume(storage_settings['vol']);
1525				this.setVolume(storage_settings['vol']);
1526			} else {
1527				this.setVolume(_self.vinterface.getVolume());
1528			}
1529
1530			_self.vinterface.setSpeed(1);
1531
1532			if(last_video['is_live']) {
1533				$('.player-ui').toggleClass('have-speed', false);
1534			} else {
1535				$('.player-ui').toggleClass('have-speed', true);
1536			}
1537		},
1538
1539		'onSetSpeed': function(e) {
1540			_self.player_ui.renderSpeed();
1541			e = e.toString().replace(/\./,'\\.');
1542			$('.nav-btn.speed ul li a[data-speed='+e+']').addClass('sel');
1543		},
1544		
1545		'onStreamsWitched': function(e) {
1546			if(e['label'] || e['title']) {
1547				var label = e['label'] ? e['label'] : e['title'];
1548				
1549				$('.nav-btn.quality ul li a').removeClass('sel');
1550				$('.nav-btn.quality ul li a[data-quality=' + label + ']').addClass('sel');
1551				$('.nav-btn.quality .quality').toggleClass('rotating', false);
1552				
1553				$('.nav-btn.quality .quality_icon').remove();
1554				$('<span class="quality_icon">'+ label + (e['resolution'] ? '<br>' + e['resolution'] : '') + '</span>').prependTo($('.nav-btn.quality .icon')).toggleClass(label, true);
1555			}
1556		},
1557		
1558		'onLoadedMetaData': function(media_info) {
1559			first_load = true;
1560			this.is_active = true;
1561			
1562			this.media['stream_started'] = Math.ceil((new Date()).getTime() / 1000);
1563			this.report_playback_progress('start');
1564			
1565			this.report_interval = setInterval(function () {
1566				// Упдейтваме прогреса
1567				_self.player_ui.report_playback_progress('progress');
1568			}, 1000 * 90); // 1.5 минути
1569		},
1570		
1571		'onTimeUpdate': function(media_info) {
1572			if(media_info && media_info['media']) {
1573				this.is_active = true;
1574				
1575				this.media['currentTime'] = media_info['media']['currentTime'];
1576				this.media['duration'] = media_info['media']['duration'];
1577			}
1578			
1579			try {
1580				var fuck_setTimeout = setTimeout(function() {
1581					_self.player_ui.scrubberTimesUpdate(media_info['media']);
1582				}, 0);
1583			} catch(e) {
1584			}
1585
1586			if(last_video['adv']) {
1587				if(this.media['currentTime']
1588				   && !adv_seeking && storage_settings['adv'] && storage_settings['adv'] == 'on') {
1589					// Гледаме за реклами
1590					// Калкулираме текущото време
1591					last_video['adv']
1592					
1593					var time_fix = last_video['time_offset_fix'];
1594					var curren_time_fixed = parseInt(last_video['time_from'] + this.media['currentTime'] - time_fix);
1595					var drift = _self.player_ui.getDrift(curren_time_fixed, last_video['time_from'] - time_fix);
1596					var adv = last_video['adv'];
1597					var dt_start_hash = Math.floor(curren_time_fixed / 600);
1598
1599					if(drift != 0) {
1600						curren_time_fixed -= drift;
1601						dt_start_hash = Math.floor(curren_time_fixed / 600);
1602					}
1603
1604					if(adv[dt_start_hash]) {
1605						// Има реклами в тези 10 минути
1606						// Изцикляме отзат напред, за да можем да взмем ако има несъбрани реклами на едно
1607						for(var i=adv[dt_start_hash].length - 1; i>=0; i--) {
1608							// Ако в края на периода на рекламата има дрифт предварително го вадим от рейнджа
1609							var drift_check = _self.player_ui.getDrift(adv[dt_start_hash][i]['e'], last_video['time_from'] - time_fix) - drift;
1610
1611							if(curren_time_fixed >= (adv[dt_start_hash][i]['s'] - 2)
1612							&& curren_time_fixed <= (adv[dt_start_hash][i]['e'] - drift_check - 4)) {
1613								// Трябва да сметнем релативното време
1614								var seek_to = parseInt(this.media['currentTime'] + adv[dt_start_hash][i]['e'] - 1 - curren_time_fixed + drift_check);
1615
1616								// Поне 10 секунди да има реклама, че се получават бъгове при превъртането
1617								if((seek_to - this.media['currentTime']) > 10) {
1618									$('#player-container').toggleClass('adv-seeking', true);
1619
1620									adv_seeking = true;
1621
1622									(function(player_time) {
1623										if(timeouts['adv_seeking']) {
1624											clearTimeout(timeouts['adv_seeking']);
1625										}
1626
1627										timeouts['adv_seeking'] = setTimeout(function () {
1628											if(adv_seeking) {
1629												_self.vinterface.seek(player_time);
1630											}
1631										}, 2000);
1632									})(seek_to);
1633								}
1634
1635								break;
1636							}
1637						}
1638					}
1639				}
1640			}
1641		},
1642		
1643		'onPlay': function() {
1644			$('.play-pause .text').html('Pause');
1645			$('.play-pause .icon').toggleClass('play',true);
1646			
1647			this.media['last_time'] = 0;
1648			this.state = 'playing';
1649		},
1650		
1651		'onPause': function() {
1652			$('.play-pause .text').html('Play');
1653			$('.play-pause .icon').toggleClass('play',false);
1654			
1655			this.state = 'paused';
1656		},
1657		
1658		'onSeekStart': function() {
1659			
1660		},
1661		
1662		'onSeekEnd': function() {
1663			adv_seeking = false;
1664			$('#player-container').toggleClass('adv-seeking', false);
1665			
1666			player_seek_added = 0;
1667			this.report_playback_progress('seek');
1668			
1669			this.media['last_time'] = 0;
1670		},
1671		
1672		'onBuffering': function (data) {
1673			this.state = 'buffering';
1674		},
1675		
1676		'onBufferProgress': function(media_info) {
1677			var bufferEnd = (media_info.media.duration - media_info.media.bufferEnd) / media_info.media.duration * 100;
1678			bufferEnd = bufferEnd < 0 ? 0 : bufferEnd;
1679			
1680			$('.proggress-bar .buffer').css({right:bufferEnd + '%'});
1681		},
1682		
1683		'onVolumeChange': function(volume) {
1684			this.setVolume(volume);
1685		},
1686		
1687		'onError': function(data) {
1688			this.state = 'error';
1689		},
1690		
1691		'onStop': function() {
1692			this.state = 'stoped';
1693		},
1694		
1695		'onDestroy': function() {
1696			this.state = 'stoped';
1697		},
1698		
1699		'enterFullscreen': function() {
1700			lock_fullscreen_doblclick = true;
1701			
1702			var is_full_screen = document.webkitFullscreenElement || document.mozFullScreen || document.msFullscreenElement != null || document.fullscreenElement != null;
1703			var container = $('.player-ui').get(0);
1704			if(!is_full_screen) {
1705				try {
1706					var fullscreenApi =
1707							container.requestFullscreen ||
1708							container.mozRequestFullScreen ||
1709							container.webkitRequestFullscreen ||
1710							container.msRequestFullscreen;
1711					fullscreenApi.call(container);
1712				} catch(e) {
1713					alert('Yor browser dosn\'t support Fullscreen API!');
1714				}
1715			} else {
1716				try {
1717					var fullscreenApi =
1718							document.exitFullscreen ||
1719							document.mozCancelFullScreen ||
1720							document.webkitExitFullscreen ||
1721							document.msExitFullscreen;
1722					fullscreenApi.call(document);
1723				} catch(e) {
1724					alert('Yor browser dosn\'t support Fullscreen API!');
1725				}
1726				
1727				$('#intercom-container').show();
1728				$('html').toggleClass('fullscreen', false);
1729			}
1730		},
1731		
1732		'fullScreenControlsShow': function() {
1733			if(timeouts['fullscreen_controls']) {
1734				clearTimeout(timeouts['fullscreen_controls']);
1735				delete timeouts['fullscreen_controls'];
1736			}
1737			
1738			this.is_controls_visible = true;
1739			$('.player-ui.fullscreen').toggleClass('show-controls', true);
1740			
1741			timeouts['fullscreen_controls'] = setTimeout(function() {
1742				this.is_controls_visible = false;
1743				$('.player-ui.fullscreen').toggleClass('show-controls', false);
1744			}, 2000);
1745		},
1746		
1747		'fullScreenControlsHide': function () {
1748			if(timeouts['fullscreen_controls']) {
1749				clearTimeout(timeouts['fullscreen_controls']);
1750			}
1751			
1752			this.is_controls_visible = true;
1753			$('.player-ui.fullscreen').toggleClass('no-mouse', false);
1754		},
1755		
1756		'setVolume': function (vol) {
1757			if(vol > 0) {
1758				_self.player_ui['current_volume'] = vol;
1759			}
1760			
1761			var total = 100 - vol;
1762			
1763			$('.volum_progres') .css({ 'height': total+'%' });
1764			$('.volume-cont .icon').toggleClass('max mid low mute', false);
1765			
1766			if (total == 100) {
1767				state = 'mute';
1768			} else {
1769				if (total < 100 && total >= 66) {
1770					state = 'low';
1771				}else if(total < 66 && total >= 33) {
1772					state = 'mid';
1773				}else{
1774					state = 'max';
1775				}
1776			}
1777			
1778			storage_settings['vol'] = vol;
1779			local_storage.setItem('settings', JSON.stringify(storage_settings));
1780			
1781			$('.volume-cont .icon').toggleClass(state, true);
1782		},
1783		
1784		
1785		'hh_mm': function(currentTime) {
1786			var hours 	= Math.floor(currentTime / 3600);
1787			var minutes = Math.floor((currentTime - hours * 3600) / 60);
1788			var sec		= Math.floor(currentTime % 60);
1789			
1790			if(hours > 0) {
1791				return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' + ('0' + sec).slice(-2);
1792			} else {
1793				return ('0' + minutes).slice(-2) + ':' + ('0' + sec).slice(-2);
1794			}
1795		},
1796		
1797		
1798		'calVolume': function(clientY) {
1799			var volume = 100 - parseInt((clientY - $(".volum_controler").offset().top + $(document).scrollTop()) * 100 / 152);
1800			
1801			volume = volume < 0 ? 0 : volume;
1802			volume = volume > 100 ? 100 : volume;
1803			return volume;
1804		},
1805		
1806		'scrubberMouseUpdate': function (clientX) {
1807			clientX = !clientX ? clientX_last : clientX;
1808			
1809			var left_px			= clientX - $('.proggress-bar').offset().left;
1810			var progress_width	= $(".proggress-bar-inner").width();
1811			var percent 		= left_px / progress_width;
1812			var mouse_time		= Math.floor(percent * _self.player_ui.media['duration']);
1813			var currentTime		= (_self.player_ui.media.currentTime / _self.player_ui.media.duration) * progress_width;
1814			var moved_width		= $('.proggress-bar .time_moved').width();
1815			var duration_width	= $('.proggress-bar .time_duration').width();
1816			
1817			$('.mouse_time').html(this.hh_mm(mouse_time));
1818			
1819			_self.player_ui.toggleScreenshot(percent, mouse_time, left_px);
1820			
1821			if(currentTime > (progress_width - moved_width - duration_width)) {
1822				$('.proggress-bar .time_duration').toggleClass('hidden', true);
1823			} else {
1824				$('.proggress-bar .time_duration').toggleClass('hidden', false);
1825			}
1826		},
1827		
1828		'scrubberTimesUpdate': function (media) {
1829			if(!media) return;
1830			
1831			var currentTime		= this['media'].last_time ? this['media'].last_time : media.currentTime;
1832			var delta 			= currentTime / media.duration;
1833			var progress_width	= $('.proggress-bar-inner').width();
1834			var left_px 		= delta * progress_width;
1835			var percent 		= (delta * 100 > 100 ? 100 : delta * 100);
1836			var moved_width		= $('.proggress-bar .time_moved').width();
1837			var duration_width	= $('.proggress-bar .time_duration').width();
1838			
1839			// Упдейтваме и квадчето от което е пуснато видеото
1840			if(last_video && last_video['time_to']) {
1841				try {
1842					var percent_real = parseInt(currentTime * 100 / (last_video['time_to'] - last_video['time_from']));
1843					percent_real = percent_real > 100 ? 100 : percent_real;
1844					percent_real = percent_real < 1 ? 1 : percent_real;
1845					
1846					if(!$('*[data-key="' + last_video['video_key'] + '"] .progress div').length) {
1847						$('*[data-key="' + last_video['video_key'] + '"] .img').append('<div class="progress"><div style="width:1%;"></div></div>');
1848					}
1849					
1850					$('*[data-key="' + last_video['video_key'] + '"] .progress div').css({width: percent_real + '%'});
1851				} catch(e) {
1852				}
1853			}
1854			
1855			$('.proggress-bar .inner_progress').css({width: percent + '%'});
1856			$('.proggress-bar .progress-time').css({left: percent + '%'});
1857			$('.proggress-bar .time_duration').html(this.hh_mm(media.duration));
1858			
1859			if(percent >= 100) {
1860				$('.proggress-bar .proggress-bar-inner').toggleClass('full', true);
1861			} else {
1862				$('.proggress-bar .proggress-bar-inner').toggleClass('full', false);
1863			}
1864			
1865			if(left_px > (moved_width / 2)) {
1866				$('.proggress-bar .time_moved').html(this.hh_mm(currentTime)).css({
1867					'left'			: percent + '%',
1868					'margin-left'	: -parseInt(moved_width / 2) + 'px'
1869				});
1870				$('.proggress-bar .time_forward').css({
1871					'left'			: percent + '%',
1872					'margin-left'	: parseInt(moved_width / 2 + 10) + 'px'
1873				});
1874				if(left_px > (progress_width - moved_width - duration_width)) {
1875					$('.proggress-bar .time_duration').toggleClass('hidden', true);
1876				}
1877			} else {
1878				$('.proggress-bar .time_moved').html(this.hh_mm(currentTime)).css({left: '5px'});
1879				$('.proggress-bar .time_forward').css({left: '5px'});
1880			}
1881		},
1882		
1883
1884		'showScreenShot': function(img_src, bg_css) {
1885			var current_src	= $('.proggress-bar .screenshot').data('current_src');
1886			var timeout = 0;
1887			
1888			function switch_src() {
1889				if(timeouts['screenshot_show_background_circle']) {
1890					clearTimeout(timeouts['screenshot_show_background_circle']);
1891					timeouts['screenshot_show_background_circle'] = null;
1892				}
1893				
1894				if(timeouts['screenshot_show_background']) {
1895					clearTimeout(timeouts['screenshot_show_background']);
1896					timeouts['screenshot_show_background'] = null;
1897				}
1898				
1899				$('.proggress-bar .screenshot').data('current_src', img_src);
1900				
1901				bg_css = bg_css || {};
1902				bg_css['background-image'] = 'url(' + img_src + ')';
1903				
1904				$('.proggress-bar .screenshot').toggleClass('loading', false).css(bg_css);
1905			}
1906			
1907			if(current_src != img_src) {
1908				if(timeouts['screenshot_show_background_circle']) {
1909					clearTimeout(timeouts['screenshot_show_background_circle']);
1910					timeouts['screenshot_show_background_circle'] = null;
1911				}
1912				
1913				timeouts['screenshot_show_background_circle'] = setTimeout(function() {
1914					$('.proggress-bar .screenshot').toggleClass('loading', true).data('current_src', 'loader.gif');
1915				}, 30);
1916				
1917				// Прелоадваме картинката
1918				var img = new Image();
1919				
1920				img.onload = function () {
1921					switch_src();
1922				}
1923				img.src = img_src;
1924				timeout = 1000;
1925				prev_images.push(img);
1926			}
1927			
1928			if(timeouts['screenshot_show_background']) {
1929				clearTimeout(timeouts['screenshot_show_background']);
1930				timeouts['screenshot_show_background'] = null;
1931			}
1932	
1933			if(timeout == 0) {
1934				switch_src();
1935			} else {
1936				timeouts['screenshot_show_background'] = setTimeout(function() {
1937					switch_src();
1938				}, timeout);
1939			}
1940	
1941			if(prev_images.length > 1) {
1942				while(prev_images.length > 1) {
1943					var img_to_del = prev_images.shift();
1944	
1945					if(!img_to_del) {
1946						// Fuck js?!!!
1947						continue;
1948					}
1949	
1950					img_to_del.src = '';
1951					delete img_to_del;
1952				}
1953			}
1954		},
1955		
1956		'getDrift': function(curren_time_fixed, start_time_fixed) {
1957			var drifts;
1958			try {
1959				drifts = last_video['drifts'];
1960			} catch(e) {
1961				return 0;
1962			}
1963			
1964			var drift = 0;
1965			var dt_drifts_hash = Math.floor(start_time_fixed / 600);
1966			var dt_start_hash = Math.floor(curren_time_fixed / 600);
1967			do {
1968				if(drifts && drifts[dt_drifts_hash]) {
1969					for(var i in drifts[dt_drifts_hash]) {
1970						if(i < curren_time_fixed) {
1971							drift += drifts[dt_drifts_hash][i];
1972						}
1973					}
1974				}
1975				
1976				dt_drifts_hash++;
1977			} while(dt_drifts_hash <= dt_start_hash);
1978			
1979			return drift;
1980		},
1981		
1982		
1983		'load_blobs': function() {
1984			if(timeouts['blob_loading']) {
1985				clearTimeout(timeouts['blob_loading']);
1986			}
1987			
1988			if(this.blob_loading) {
1989				timeouts['blob_loading'] = setTimeout(function() {
1990					_self.player_ui.load_blobs();
1991				}, 2000);
1992				
1993				return;
1994			}
1995			
1996			// Зареждаме ги последователно
1997			var blobs = last_video['blobs_data']['blobs'];
1998			var blob;
1999			for(var i in blobs) {
2000				if(!blobs[i]['is_loaded'] && !blobs[i]['is_loading']) {
2001					blob = blobs[i];
2002					
2003					this.load_blob(blob);
2004					return;
2005				}
2006			}
2007		},
2008		
2009		'load_blob': function(blob) {
2010			if(blob['is_loading']
2011			   || blob['is_loaded']
2012			   || blob['loading_error']) {
2013				// Може да се получат паралелни рекуести
2014				return;
2015			}
2016			
2017			this.blob_loading = true;
2018			
2019			blob['is_loading'] = true;
2020			blob['loading_error'] = false;
2021			
2022			var xhr = new XMLHttpRequest();
2023			xhr.onreadystatechange = function(){
2024				if (this.readyState == 4) {
2025					if(this.status == 200) {
2026						blob['data'] = this.response;
2027						blob['is_loaded'] = true;
2028					}
2029					
2030					_self.player_ui.blob_loading = false;
2031					_self.player_ui.load_blobs();
2032				}
2033			}
2034	
2035			xhr.onabort = xhr.onerror = function() {
2036				blob['is_loaded'] = true;
2037				blob['loading_error'] = true;
2038				_self.player_ui.blob_loading = false;
2039				_self.player_ui.load_blobs();
2040			}
2041			
2042			xhr.open('GET', blob['url_high']);
2043			xhr.responseType = 'blob';
2044			xhr.send();
2045		},
2046		
2047		
2048		'toggleScreenshot': function (percent, mouse_time, left_px) {
2049			if(isNaN(mouse_time)) {
2050				return;
2051			}
2052			
2053			if(!last_video['is_live'] || last_video['is_sliding']) {
2054				if(typeof(left_px) !== 'undefined') {
2055					if(left_px < 125) { left_px = 125; }
2056					if(left_px + 180 > _window_width_cache) { left_px = _window_width_cache - 125; }
2057					
2058					$('.proggress-bar .screenshot').css({ 'width': '', 'height': '', 'left': left_px + 'px'});
2059				} else {
2060					$('.proggress-bar .screenshot').css({ 'width': '', 'height': '', 'left': (percent * 100) + '%'});
2061				}
2062				
2063				$('.player-ui .navigation').toggleClass('show_times', true);
2064				
2065				if(timeouts['screenshot_hide_timeout']) {
2066					clearTimeout(timeouts['screenshot_hide_timeout']);
2067					timeouts['screenshot_hide_timeout'] = null;
2068				}
2069				
2070				timeouts['screenshot_hide_timeout'] = setTimeout(function () {
2071					$('.player-ui .navigation').toggleClass('show_times', false);
2072				}, 4000);
2073				
2074				var clip;
2075				var time_fix		= 0;
2076				var drift 			= 0;
2077				var from_time 		= 0;
2078				
2079				try {
2080					clip = last_video;
2081				} catch(e){
2082				}
2083				
2084				if(!clip) {
2085					return;
2086				}
2087				
2088				try {
2089					time_fix = parseInt(clip['time_offset_fix']);
2090				} catch(e){
2091				}
2092				
2093				try {
2094					from_time = clip['time_from'] + parseInt(mouse_time) - time_fix;
2095					drift = _self.player_ui.getDrift(from_time, clip['time_from'] - time_fix);
2096				} catch(e) {
2097				}
2098				
2099				from_time -= drift;
2100				
2101				var from_time_fixed = from_time;
2102				var from_time_ajax = (from_time - from_time % 600);
2103				var force_old_logic = false;
2104				if(clip['blobs_data']) {
2105					var dt_hash = Math.floor(from_time_fixed / 600) - 1;
2106					
2107					if(clip['blobs_data']['screen_dt'][dt_hash]) {
2108						// Циклим, за да намерим точната позиция в блоба
2109						var positions = clip['blobs_data']['screen_dt'][dt_hash];
2110						var positions_2 = clip['blobs_data']['screen_dt'][dt_hash + 1] ? clip['blobs_data']['screen_dt'][dt_hash + 1] : new Array();
2111						var found_index = false;
2112						
2113						positions = positions.concat(positions_2);
2114						
2115						for(var i=0; i<positions.length; i++) {
2116							if((positions[i]['dt'] - 30 <= from_time_fixed)
2117							   && from_time_fixed <= (positions[i]['dt'])) {
2118								found_index = i;
2119								break;
2120							}
2121						}
2122						
2123						force_old_logic = found_index === false;
2124						
2125						if(!force_old_logic) {
2126							found_index = found_index < 0 ? 0 : found_index;
2127							
2128							var blob_id = positions[found_index]['bid'];
2129							
2130							if(clip['blobs_data']['blobs'][blob_id]['is_loaded'] && clip['blobs_data']['blobs'][blob_id]['data']) {
2131								var pos_low = positions[found_index]['posh'];
2132								var pos_next_low = positions[found_index + 1] ? positions[found_index + 1]['posh'] : 0;
2133								var url = window.URL || window.webkitURL;
2134								var blob_data = clip['blobs_data']['blobs'][blob_id]['data'];
2135								var image_blob = pos_next_low > 0 ? blob_data.slice(pos_low, pos_next_low, 'image/jpeg') : blob_data.slice(pos_low, blob_data.size, 'image/jpeg');
2136								var img_src = url.createObjectURL(image_blob);
2137								var current_src	= $('.proggress-bar .screenshot').data('current_src');
2138								
2139								if(img_src == current_src) {
2140									return;
2141								}
2142								
2143								$('.proggress-bar .screenshot').toggleClass('loading', false).data('current_src', img_src);
2144								
2145								if(blob_screen_last) {
2146									delete blob_screen_last;
2147								}
2148								
2149								if(timeouts['screenshot_show_last']) {
2150									clearTimeout(timeouts['screenshot_show_last']);
2151									timeouts['screenshot_show_last'] = null;
2152								}
2153								
2154								// Тротле трябва да се направи иначе прекалано много картинките се пускат към рендера
2155								timeouts['screenshot_show_last'] = setTimeout(function() {
2156									blob_screen_last = new Image();
2157									blob_screen_last.onload = function () {
2158										$('.proggress-bar .screenshot').toggleClass('loading', false).css({
2159											'background-image': 'url(' + img_src + ')'
2160										});
2161									}
2162									blob_screen_last.src = img_src;
2163								}, 0);
2164							} else if(clip['blobs_data']['blobs'][blob_id]['is_loaded'] && clip['blobs_data']['blobs'][blob_id]['loading_error']) {
2165								force_old_logic = true;
2166							} else {
2167								// Чакаме да се зареди и пускаме форсиран лоадинг
2168								var current_src	= $('.proggress-bar .screenshot').data('current_src');
2169								if(current_src == 'loader.gif') {
2170									return;
2171								}
2172								
2173								_self.player_ui.load_blob(clip['blobs_data']['blobs'][blob_id]);
2174
2175								if(timeouts['screenshot_show_background_circle']) {
2176									clearTimeout(timeouts['screenshot_show_background_circle']);
2177									timeouts['screenshot_show_background_circle'] = null;
2178								}
2179								
2180								timeouts['screenshot_show_background_circle'] = setTimeout(function() {
2181									$('.proggress-bar .screenshot').toggleClass('loading', true).data('current_src', 'loader.gif');
2182								}, 30);
2183								
2184								timeouts['screenshot_show_last'] = setTimeout(function() {
2185									_self.player_ui.toggleScreenshot(percent, mouse_time, left_px);
2186								}, 1000);
2187							}
2188						}
2189					} else {
2190						force_old_logic = true;
2191					}
2192				}
2193				
2194				if((force_old_logic || !clip['blobs_data']) && last_video['screenshot']) {
2195					$('html').toggleClass('animate-screens', false);
2196					
2197					from_time = (from_time - from_time % 30);
2198					
2199					var img_src	= last_video['screenshot']['url'] + from_time + '.jpeg';
2200					if(screenshot_ajax_lock[from_time_ajax]) {
2201						// Ако чакаме да се зареди извикваме със settimeout да опита да покаже последната позиция след малко
2202						if(timeouts['screenshot_show_last']) {
2203							clearTimeout(timeouts['screenshot_show_last']);
2204							timeouts['screenshot_show_last'] = null;
2205						}
2206						
2207						timeouts['screenshot_show_last'] = setTimeout(function () {
2208							_self.player_ui.toggleScreenshot(percent, mouse_time, left_px);
2209						}, 200);
2210					} else {
2211						var cache_key = 'sst_' + last_video['video_key'] + '_' + from_time_ajax;
2212						var res = __cache.get(cache_key);
2213						
2214						var select_screenshot = function(res) {
2215							for(var i=res.length - 1; i>=0; i--) {
2216								if(res[i]['dt_start'] <= from_time_fixed) {
2217									// тук е шота
2218									_self.player_ui.showScreenShot(res[i]['img'], {});
2219									
2220									return true;
2221								}
2222							}
2223							
2224							return false;
2225						}
2226						
2227						if(res) {
2228							if(!select_screenshot(res)) {	
2229								_self.player_ui.showScreenShot(img_src);
2230							}
2231							
2232							return;
2233						}
2234						
2235						screenshot_ajax_lock[from_time_ajax] = true;
2236						
2237						var img_src_ajax = last_video['screenshot']['url'] + from_time_ajax + '.jpeg';
2238						if(ajax_last_ref && ajax_last_ref.abort) {
2239							ajax_last_ref.abort();
2240						}
2241						
2242						ajax_last_ref = $.ajax({
2243							type: "GET",
2244							url: img_src_ajax + '?json',
2245							dataType: "json",
2246							complete: function() {
2247								delete screenshot_ajax_lock[from_time_ajax];
2248							},
2249							success: function(res) {
2250								if(res && $.isArray(res)) {
2251									__cache.set(cache_key, res, 600);
2252									
2253									if(!select_screenshot(res)) {
2254										_self.player_ui.showScreenShot(img_src);
2255									}
2256								} else {
2257									_self.player_ui.showScreenShot(img_src);
2258								}
2259							}
2260						});
2261					}
2262				} else if(force_old_logic || !clip['blobs_data']) {
2263					$('.proggress-bar .screenshot').remove();
2264				}
2265			} else {
2266				$('.proggress-bar .screenshot').remove();
2267			}
2268		},
2269
2270
2271		'renderSpeed': function () {
2272			$('.nav-btn.speed ul li').remove();
2273			
2274			var title = '';
2275			var speeds = [0.5, 1, 1.25, 1.5, 2]
2276			for(var i=0; i<speeds.length; i+=1) {
2277				title = speeds[i] == 1 ? 'normal' : speeds[i];
2278				$('<li><a data-speed="'+speeds[i]+'"><span>'+title+'</span></a></li>').appendTo($('.nav-btn.speed ul'));
2279			}
2280		},
2281		
2282		
2283		'renderQuality': function(quality_urls, selected_quality) {
2284			if(quality_urls) {
2285				$('.nav-btn.quality ul li').remove();
2286				
2287				for(var i=0; i<quality_urls.length; i++) {
2288					$('<li><a data-quality="'+quality_urls[i]['title']+'" data-label="'+quality_urls[i]['title']+'"><span>'+quality_urls[i]['title']+'</span></a></li>').appendTo($('.nav-btn.quality ul'));
2289				}
2290			}
2291		},
2292		
2293		
2294		'renderQuickLists': function(quick_lists) {
2295			var html = '';
2296			
2297			if(quick_lists && quick_lists.length) {
2298				for(var j=0; j<quick_lists.length; j++) {
2299					html += '\
2300					<div class="video-recomended ' + quick_lists[j]['template'] + '">\
2301						<div class="pane-scroll have_prev have_next">\
2302							<div class="pane-inner">\
2303								<div class="pane-scroller">';
2304					
2305					for(var i=0; i<quick_lists[j]['items'].length; i++) {
2306						html += _self.item_render(quick_lists[j]['items'][i], quick_lists[j]['template'] == 'live_tv');
2307					}
2308					
2309					html += '\
2310								</div>\
2311							</div>\
2312							<a data-dir="right" class="pane-right-arrow"></a>\
2313							<a data-dir="left" class="pane-left-arrow"></a>\
2314						</div>\
2315					</div>';
2316				}
2317				
2318				$('.player-ui-bottom-sliders').html(html);
2319				
2320				_self.item_post_render();
2321				
2322				removeClass(items_container, 'have-desc');
2323				
2324				setTimeout(function() {
2325					simple_slider.update();
2326					
2327					var elm = $('*[data-timefrom="' + last_video['time_from'] + '"]');
2328					if(elm.length) {
2329						var scroll_cont = elm.parents('.pane-scroll');
2330						var cnt = elm.prevAll().length;
2331						
2332						simple_slider.scroll_to(scroll_cont, 'right', cnt - 1);
2333						elm.toggleClass('watching');
2334					}
2335				}, 500);
2336			} else {
2337				$('.player-ui').toggleClass('.no-recomended');
2338			}
2339		},
2340
2341		'renderAdv': function (advs) {
2342			if(typeof(storage_settings['adv']) == 'undefined') {
2343				storage_settings['adv'] = 'off';
2344			}
2345	
2346			$('.nav-btn.adv a').toggleClass('sel', false);
2347			$('.nav-btn.adv a[data-adv="'+storage_settings['adv']+'"]').toggleClass('sel', true);
2348			$('.nav-btn.adv .text').html('' + (storage_settings['adv'] == 'on' ? 'превър. реклами' : 'показ. реклами'));
2349			$('.nav-btn.adv').attr('title', (storage_settings['adv'] == 'on' ? 'Превъртане на рекламите включено' : 'Превъртане на рекламите изключено'));
2350
2351			if(advs) {
2352				$('.player-ui').toggleClass('have-adv', true);
2353			}
2354		},
2355		
2356		'render': function(container) {
2357			$(container).html('\
2358				<div class="player-container player-ui">\
2359					<div class="player-ui-controls-overlay">\
2360						<div class="btn-back"></div>\
2361						<div class="video-info player_info"></div>\
2362						<div class="player-ui-controls">\
2363							<div class="navigation">\
2364								<div class="proggress-bar">\
2365									<div class="proggress-bar-inner">\
2366										<div class="buffer"></div>\
2367										<div class="inner_progress"></div>\
2368										<div class="progress-time"></div>\
2369										<div class="screenshot"><div class="mouse_time"></div></div>\
2370									</div>\
2371									<div class="time_forward"></div>\
2372									<div class="time_moved"></div>\
2373									<div class="time_duration"></div>\
2374								</div>\
2375								<div class="buttons-cont">\
2376									<div class="nav-btn play-pause" tabindex="10">\
2377										<div class="icon">\
2378											<svg class="play-svg" viewBox="19 20 30 30">\
2379												<path xmlns="http://www.w3.org/2000/svg" d="M 27.40 23.40 C 29.05 22.63 30.05 23.79 31.25 24.71 C 33.94 26.68 36.75 28.54 39.36 30.63 C 40.88 31.62 42.59 32.74 43.79 34.09 C 44.69 36.01 42.92 36.68 41.76 37.71 C 38.44 40.05 35.15 42.59 31.92 44.80 C 30.66 45.60 29.65 47.06 28.00 46.83 C 26.57 46.63 26.90 44.02 26.85 43.00 C 26.85 37.33 26.85 31.67 26.85 26.00 C 26.78 25.00 26.97 24.14 27.40 23.40 Z" fill="currentColor" />\
2380											</svg>\
2381											<svg class="pause-svg" viewBox="90 20 30 30">\
2382												<path xmlns="http://www.w3.org/2000/svg" d="M 103.00 26.00 C 103.00 31.33 103.00 36.67 103.00 42.00 C 102.86 43.65 103.54 45.71 101.82 46.72 C 100.03 47.13 96.33 47.64 96.02 45.00 C 95.97 38.67 96.01 32.33 96.00 26.00 C 94.98 21.81 104.02 21.81 103.00 26.00 Z" fill="currentColor" />\
2383												<path xmlns="http://www.w3.org/2000/svg" d="M 115.00 26.00 C 114.99 32.33 115.03 38.67 114.98 45.00 C 114.68 47.63 110.95 47.14 109.17 46.72 C 107.33 45.72 108.21 42.75 108.00 41.00 C 108.00 36.00 108.00 31.00 108.00 26.00 C 106.98 21.81 116.02 21.81 115.00 26.00 Z" fill="currentColor" />\
2384											</svg>\
2385											&nbsp;\
2386										</div>\
2387										<span class="text">Пусни</span>\
2388									</div>\
2389									<div class="nav-btn volume-cont" tabindex="11">\
2390										<div class="icon">\
2391											<svg viewBox="158 19 34 33" class="volume-max">\
2392												<path xmlns="http://www.w3.org/2000/svg" d="M 173.34 22.36 C 174.90 21.72 175.92 22.25 175.90 24.00 C 175.90 31.33 175.90 38.67 175.90 46.00 C 175.90 47.75 174.94 48.26 173.37 47.62 C 170.73 45.59 168.11 43.61 165.67 41.34 C 163.49 40.41 160.61 41.54 158.43 40.57 C 157.92 37.63 157.87 32.37 158.46 29.46 C 160.63 28.50 163.52 29.66 165.65 28.65 C 168.08 26.36 170.70 24.39 173.34 22.36 Z" fill="currentColor" />\
2393												<path xmlns="http://www.w3.org/2000/svg" d="M 180.00 31.05 C 182.34 31.43 181.56 35.37 181.58 37.00 C 181.68 38.28 179.44 39.90 179.00 38.00 C 179.02 37.00 179.08 36.00 179.17 35.00 C 179.37 33.92 178.19 31.06 180.00 31.05 Z" fill="currentColor" />\
2394												<path xmlns="http://www.w3.org/2000/svg" d="M 183.26 28.28 C 184.97 27.44 185.75 29.76 186.03 31.00 C 187.14 33.81 186.87 37.16 185.70 39.92 C 185.03 40.97 184.90 42.24 183.31 41.67 C 182.94 41.02 183.01 40.32 
2394183.54 39.54 C 184.27 36.77 184.55 33.26 183.45 30.57 C 183.00 29.70 182.93 28.94 183.26 28.28 Z" fill="currentColor" />\
2395												<path xmlns="http://www.w3.org/2000/svg" d="M 187.89 24.22 C 192.97 29.90 193.00 38.62 188.71 44.80 C 188.28 45.82 186.13 46.69 186.16 45.00 C 186.97 43.28 187.98 41.68 188.66 39.85 C 189.88 35.20 189.47 30.13 186.77 26.07 C 185.80 24.83 186.00 23.46 187.89 24.22 Z" fill="currentColor" />\
2396											</svg>\
2397											<svg viewBox="158 19 34 33" class="volume-mid">\
2398												<path xmlns="http://www.w3.org/2000/svg" d="M 173.34 22.36 C 174.90 21.72 175.92 22.25 175.90 24.00 C 175.90 31.33 175.90 38.67 175.90 46.00 C 175.90 47.75 174.94 48.26 173.37 47.62 C 170.73 45.59 168.11 43.61 165.67 41.34 C 163.49 40.41 160.61 41.54 158.43 40.57 C 157.92 37.63 157.87 32.37 158.46 29.46 C 160.63 28.50 163.52 29.66 165.65 28.65 C 168.08 26.36 170.70 24.39 173.34 22.36 Z" fill="currentColor" />\
2399												<path xmlns="http://www.w3.org/2000/svg" d="M 180.00 31.05 C 182.34 31.43 181.56 35.37 181.58 37.00 C 181.68 38.28 179.44 39.90 179.00 38.00 C 179.02 37.00 179.08 36.00 179.17 35.00 C 179.37 33.92 178.19 31.06 180.00 31.05 Z" fill="currentColor" />\
2400												<path xmlns="http://www.w3.org/2000/svg" d="M 183.26 28.28 C 184.97 27.44 185.75 29.76 186.03 31.00 C 187.14 33.81 186.87 37.16 185.70 39.92 C 185.03 40.97 184.90 42.24 183.31 41.67 C 182.94 41.02 183.01 40.32 183.54 39.54 C 184.27 36.77 184.55 33.26 183.45 30.57 C 183.00 29.70 182.93 28.94 183.26 28.28 Z" fill="currentColor" />\
2401											</svg>\
2402											<svg viewBox="158 19 34 33" class="volume-low">\
2403												<path xmlns="http://www.w3.org/2000/svg" d="M 173.34 22.36 C 174.90 21.72 175.92 22.25 175.90 24.00 C 175.90 31.33 175.90 38.67 175.90 46.00 C 175.90 47.75 174.94 48.26 173.37 47.62 C 170.73 45.59 168.11 43.61 165.67 41.34 C 163.49 40.41 160.61 41.54 158.43 40.57 C 157.92 37.63 157.87 32.37 158.46 29.46 C 160.63 28.50 163.52 29.66 165.65 28.65 C 168.08 26.36 170.70 24.39 173.34 22.36 Z" fill="currentColor" />\
2404												<path xmlns="http://www.w3.org/2000/svg" d="M 180.00 31.05 C 182.34 31.43 181.56 35.37 181.58 37.00 C 181.68 38.28 179.44 39.90 179.00 38.00 C 179.02 37.00 179.08 36.00 179.17 35.00 C 179.37 33.92 178.19 31.06 180.00 31.05 Z" fill="currentColor" />\
2405											</svg>\
2406											<svg viewBox="159 509 34 33" class="volume-mute">\
2407												<path xmlns="http://www.w3.org/2000/svg" d="M 176.54 512.46 C 176.86 520.72 176.86 529.28 176.54 537.54 C 174.75 538.52 173.97 537.36 172.68 536.34 C 170.41 534.96 168.65 533.07 166.60 531.41 C 164.45 530.39 161.55 531.49 159.35 530.65 C 158.85 527.46 158.78 522.55 159.40 519.39 C 161.57 518.54 164.50 519.69 166.57 518.57 C 168.62 516.94 170.39 515.04 172.61 513.61 C 173.96 512.63 174.73 511.44 176.54 512.46 Z" fill="currentColor" />\
2408												<path xmlns="http://www.w3.org/2000/svg" d="M 183.00 519.85 C 184.80 519.98 184.96 522.30 186.84 521.80 C 187.91 521.02 188.47 519.58 190.00 519.90 C 190.60 520.30 191.15 520.79 191.64 521.36 C 191.81 523.14 188.67 523.74 189.46 525.54 C 190.11 526.22 190.80 526.86 191.54 527.46 C 192.18 529.33 189.12 531.19 187.87 529.14 C 186.44 527.47 185.68 527.91 184.37 529.37 C 183.20 530.93 181.29 529.41 181.09 528.00 C 181.34 526.70 182.91 526.36 183.17 525.00 C 182.92 523.36 180.51 523.06 181.25 521.23 C 181.74 520.60 182.32 520.14 183.00 519.85 Z" fill="currentColor" />\
2409											</svg>\
2410											&nbsp;\
2411										</div>\
2412										<span class="text">Звук</span>\
2413										<div class="volume-controler-cont">\
2414											<div class="volum_controler">\
2415												<div class="volum_progres"></div>\
2416											</div>\
2417											<div class="volume-arrow"></div>\
2418										</div>\
2419									</div>\
2420									<div class="more-video-settings sm-hide">\
2421										<div class="center-content">\
2422											<div class="nav-btn adv" title="Преъртане на рекламите" tabindex="20">\
2423												<div class="icon">&nbsp;</div>\
2424												<span class="text">Реклама</span>\
2425												<div class="sub-menu"><ul><li><a data-adv="on"><span>On</span></a></li><li><a class="sel" data-adv="off"><span>Off</span></a></li></ul></div>\
2426											</div>\
2427											<div class="nav-btn picture-size" tabindex="22">\
2428												<div class="icon"><span class="placeholder original"></span></div>\
2429												<span class="text">Картина</span>\
2430												<div class="sub-menu"><ul></ul></div>\
2431											</div>\
2432											<div class="nav-btn speed" title="Скорост" tabindex="18">\
2433												<div class="icon"><svg viewBox="0 0 24 24">
2433<path fill="currentColor" stroke="currentColor" stroke-width="0.7" d="M10,8v8l6-4L10,8L10,8z M6.3,5L5.7,4.2C7.2,3,9,2.2,11,2l0.1,1C9.3,3.2,7.7,3.9,6.3,5z            M5,6.3L4.2,5.7C3,7.2,2.2,9,2,11 l1,.1C3.2,9.3,3.9,7.7,5,6.3z            M5,17.7c-1.1-1.4-1.8-3.1-2-4.8L2,13c0.2,2,1,3.8,2.2,5.4L5,17.7z            M11.1,21c-1.8-0.2-3.4-0.9-4.8-2 l-0.6,.8C7.2,21,9,21.8,11,22L11.1,21z            M22,12c0-5.2-3.9-9.4-9-10l-0.1,1c4.6,.5,8.1,4.3,8.1,9s-3.5,8.5-8.1,9l0.1,1 C18.2,21.5,22,17.2,22,12z"></path></svg></div>\
2434												<span class="text">Скорост</span>\
2435												<div class="sub-menu"><ul><li><a data-speed="0.5"><span>0.5</span></a></li><li><a class="sel" data-speed="1"><span>normal</span></a></li><li><a data-speed="1.5"><span>1.5</span></a></li></ul></div>\
2436											</div>\
2437											<div class="nav-btn quality" tabindex="23">\
2438												<div class="icon"><span class="quality_icon">–</span></div>\
2439												<span class="text">Качество</span>\
2440												<div class="sub-menu"><ul></ul></div>\
2441											</div>\
2442										</div>\
2443									</div>\
2444									<div class="nav-btn sm-el" tabindex="22">\
2445										<div class="more-video-settings-btn for-menu_2">\
2446											<svg viewBox="-2 -3 32 32">\
2447												<path transform="translate(-1288.97 -51)" fill="currentColor" d="M1288.98,50.986h26.01V54h-26.01V50.986Zm0,7.985h26.01v3.054h-26.01V58.972Zm0,7.993h26.01V70h-26.01V66.965Z" />\
2448											</svg>\
2449										</div>\
2450									</div>\
2451									<div class="nav-btn full-screen" tabindex="24">\
2452										<div class="icon">\
2453											<svg viewBox="370 20 31 31">\
2454												<path fill-rule="evenodd" fill="currentColor" d="M 373.00 22.03 C 381.33 21.98 389.67 21.98 398.00 22.02 C 399.54 22.28 400.12 23.54 400.00 25.00 C 399.98 32.00 400.03 39.00 399.98 46.00 C 399.73 47.55 398.46 48.12 397.00 48.00 C 389.00 47.99 381.00 48.03 373.00 47.98 C 371.45 47.72 370.88 46.46 371.00 45.00 C 371.00 39.67 371.00 34.33 371.00 29.00 C 371.32 26.87 369.92 22.44 373.00 22.03 Z M 384.67 36.30 C 385.17 38.49 380.97 39.79 381.23 41.84 C 381.92 42.48 382.13 43.12 381.86 43.75 C 380.25 44.29 377.91 44.41 376.15 44.69 C 375.28 43.28 376.22 40.64 376.29 39.00 C 376.30 38.40 376.75 38.18 377.66 38.35 C 380.19 41.35 381.84 33.90 384.67 36.30 Z M 395.54 25.46 C 394.98 27.35 395.07 29.10 394.69 31.00 C 394.41 32.58 392.74 30.73 392.00 30.66 C 390.00 31.27 388.78 35.15 386.37 33.63 C 385.74 31.87 388.90 30.18 389.77 28.82 C 389.49 27.81 389.28 26.93 389.14 26.19 C 390.94 25.52 393.73 24.56 395.54 25.46 Z" />\
2455											</svg>\
2456											&nbsp;\
2457										</div>\
2458										<span class="text">Цял екран</span>\
2459									</div>\
2460								</div>\
2461							</div>\
2462						</div>\
2463						<div class="player-ui-bottom-sliders">\
2464						</div>\
2465					</div>\
2466					<div class="player-ui-video"></div>\
2467				</div>');
2468			
2469			if(!$('.adv-seek-notice').length) {
2470				$('<div class="adv-seek-notice">Превъртане на реклама</div>').appendTo('.player-ui-video');
2471			}
2472		}
2473	}
2474	
2475	
2476	////////////////////////////////////
2477	// Video страница START
2478	////////////////////////////////////
2479	this.player_load = function(video_info, force_player) {
2480		last_video = video_info;
2481		first_load = false;
2482		
2483		force_player = force_player ? force_player : '';
2484		
2485		_self.vinterface && _self.vinterface.destroy();
2486		_self.vinterface = null;
2487		
2488		if((!_self.vinterface || force_player == 'MediaSourceHLSInterface')
2489		   && video_interfaces['MediaSourceHLSInterface']
2490		   && video_interfaces['MediaSourceHLSInterface'].is_supported) {
2491			_self.vinterface = video_interfaces['MediaSourceHLSInterface'];
2492		}
2493		
2494		if((!_self.vinterface || force_player == 'HTML5Interface')
2495		   && (is_android || is_ios || is_smarttv || is_tizen || is_edge) 
2496		   && video_interfaces['HTML5Interface']
2497		   && video_interfaces['HTML5Interface'].is_supported) {
2498			_self.vinterface = video_interfaces['HTML5Interface'];
2499		}
2500		
2501		if(_self.vinterface) {
2502			var config = {};
2503			var bitrates = [];
2504
2505			if(video_info['quality_urls']) {
2506				for(var i=0; i<video_info['quality_urls'].length; i++) {
2507					bitrates.push({
2508						'url'	: video_info['quality_urls'][i]['key'],
2509						'title'	: video_info['quality_urls'][i]['title'],
2510						'bitrate': video_info['quality_urls'][i]['title']
2511					});
2512				}
2513			}
2514
2515			_self.player_ui.render(player_container);
2516			_self.player_ui.renderQuality(video_info['quality_urls']);
2517			_self.player_ui.renderSpeed();
2518			_self.player_ui.renderQuickLists(video_info['quick_lists']);
2519
2520			if(video_info['adv']) {
2521				_self.player_ui.renderAdv(video_info['adv']);
2522			}
2523			
2524			config['container'] = $(player_container).find('.player-ui-video')[0];
2525			config['bitrates'] = bitrates;
2526			config['player_settings'] = {
2527				'clip': {
2528					'url': video_info['key'],
2529					'start': video_info['resume_time_sec'] > 0 ? video_info['resume_time_sec'] : -1
2530				}
2531			};
2532			
2533			if(video_info['resume_time_sec']) {
2534				config['player_settings']['clip']['start'] = video_info['resume_time_sec'];
2535			}
2536			
2537			$(player_container).show();
2538			
2539			_self.state_manager.popup_add('video-player', function() {
2540				try { _self.player_ui.stop(); } catch(e) {}
2541				
2542				$(player_container).hide();
2543				
2544				$('#main-bnt-back').toggleClass('btn-back', _self.state_manager['queue'].length > 1);
2545			});
2546
2547			_self.vinterface.loadMedia(config);
2548		}
2549	}
2550	////////////////////////////////////
2551	// Video страница END
2552	////////////////////////////////////
2553	
2554	
2555	
2556	////////////////////////////////////
2557	// HOME страница START
2558	////////////////////////////////////
2559	this.menu_home_load = function(after_render) {
2560		this.show_loader();
2561		
2562		mytv_api.menu('home', function (res) {
2563			if(!res)  {
2564				_self.show_error(MyTV.ERRORS['invalid_data']);
2565				return;
2566			}
2567			
2568			if(res['msg']) {
2569				_self.show_error('generic_error', res['msg']);
2570				return;
2571			}
2572
2573			// Рендим страницата
2574			_self.home_render(res);
2575			
2576			after_render && after_render.forEach(function(fn) { fn(); });
2577		}, function () {
2578			_self.hide_loader();
2579		}, lock = true);
2580	}
2581	
2582		this.home_render = function (items) {
2583			this.main_menu_hide();
2584			items_container.className = 'home';
2585			document.getElementById('main-frame').className = '';
2586			
2587			var html = '';
2588			var title = '';
2589			
2590			if(items && items['toptv']) {
2591				//<h6>' + items['toptv'][0]['title'] + '</h6>
2592				html += '<div class="category-panel toptv pr100"><div class="pane-scroll have_prev have_next"><div class="pane-inner"><div class="pane-scroller">';
2593				
2594				var program_key = 'menu/program_v2';
2595				
2596				html += '<div data-action="menu" data-key="' + program_key + '" class="tv-show btn green">Програма</div>';
2597				
2598				for(var i=0; i<items['toptv'][0]['items'].length; i++) {
2599					items['toptv'][0]['items'][i]['title'] = '';
2600					html += this.item_render(items['toptv'][0]['items'][i], true);
2601				}
2602				
2603				html += '</div></div><a data-dir="right" class="pane-right-arrow"></a><a data-dir="left" class="pane-left-arrow"></a></div></div>';
2604			}
2605			
2606			var have_desc = '';
2607			if(items && items['menu']) {
2608				for(var i=0; i<items['menu'].length; i++) {
2609					if(!items['menu'][i]['items']) {
2610						continue;
2611					}
2612					
2613					title = window['_LANG'] == 'en' && items['menu'][i]['title_en'] ? items['menu'][i]['title_en'] : items['menu'][i]['title'];
2614
2615					have_desc = items['menu'][i]['template'] == 'usertop' ? ' have-desc' : '';
2616					
2617					html += '<div class="category-panel pr100 '+items['menu'][i]['template']+'  '+have_desc+'"><h6>' + title + '</h6><div class="pane-scroll have_prev have_next"><div class="pane-inner"><div class="pane-scroller">';
2618					
2619					for(var j=0; j<items['menu'][i]['items'].length; j++) {
2620						html += this.item_render(items['menu'][i]['items'][j])
2621					}
2622					
2623					html += '</div></div><a data-dir="right" class="pane-right-arrow"></a><a data-dir="left" class="pane-left-arrow"></a></div></div>';
2624				}
2625				
2626				removeClass(items_container, 'have-desc');
2627				_self.innerHTML(items_container, html);
2628				
2629				this.item_post_render();
2630			}
2631		}
2632	////////////////////////////////////
2633	// HOME страница END
2634	////////////////////////////////////
2635	
2636	
2637	////////////////////////////////////
2638	// News страница START
2639	////////////////////////////////////
2640	this.menu_news_load = function(after_render) {
2641		this.show_loader();
2642		
2643		mytv_api.menu('news', function (res) {
2644			if(!res)  {
2645				_self.show_error(MyTV.ERRORS['invalid_data']);
2646				return;
2647			}
2648			
2649			if(res['msg']) {
2650				_self.show_error('generic_error', res['msg']);
2651				return;
2652			}
2653			
2654			// Рендим страницата
2655			_self.home_render(res);
2656			$(items_container).toggleClass('have-desc', true);
2657			
2658			after_render && after_render.forEach(function(fn) { fn(); });
2659		}, function () {
2660			_self.hide_loader();
2661		}, lock = true);
2662	}
2663	////////////////////////////////////
2664	// News страница EDN
2665	////////////////////////////////////
2666	
2667	
2668	
2669	////////////////////////////////////
2670	// Избор на профил START
2671	////////////////////////////////////
2672	this.profile_select_load = function(res, forced) {
2673		this.hide_loader();
2674		
2675		forced = !!forced;
2676		
2677		var html = '';
2678		var cnt = 0;
2679		
2680		for(var i=0; i<res.length; i++) {
2681			html += '<div data-action="select_profile" data-key="' + res[i]['key'] + '" class="profile-item"><img src="' + res[i]['avatar'] + '" alt="" /><span>'+res[i]['name']+'</span><a id="profile-select_' + (i + 10)  + '" data-action="edit_profile" data-index="' + i + '" data-key="' + res[i]['key'] + '" class="edit-button"></a></div>';
2682			cnt++;
2683		}
2684		
2685		if(cnt < 5) {
2686			// Слагаме бутон за добавяне на профил
2687			html += '<div data-action="add_profile" class="profile-item"><img src="' + _self.state_manager.base_path + 'res/add_profile.png" alt="" /><span></span></div>';
2688			cnt++;
2689		}
2690		
2691		var container = document.getElementById('profiles-panel');
2692		
2693		_self.innerHTML(container, '\
2694			<div class="pop-inner">\
2695				<br><br>\
2696				<h1>' + window['lang'][window['_LANG']]['profile_select_msg'] + '</h1>\
2697				' + html + '\
2698			</div>'
2699		);
2700		
2701		addClass(container, 'show');
2702		removeClass(document.getElementById('main-bnt-back'), 'btn-back');
2703		
2704		if(!forced) {
2705			addClass(document.getElementById('main-bnt-back'), 'btn-back');
2706		}
2707		
2708		if(!_self.state_manager.popups.length || _self.state_manager.popups[_self.state_manager.popups.length-1]['page'] != 'profile-select') {
2709			_self.state_manager.popup_add('profile-select', function() {
2710				$(container).hide();
2711				$('#main-bnt-back').toggleClass('btn-back', _self.state_manager['queue'].length > 1);
2712			});
2713		}
2714	}
2715	////////////////////////////////////
2716	// Избор на профил END
2717	////////////////////////////////////
2718	
2719	
2720	
2721	////////////////////////////////////
2722	// Справочник START
2723	////////////////////////////////////
2724	this.tvguide_render = function(items) {
2725		this.main_menu_hide();
2726		
2727		items_container.className = 'menu_tvguide';
2728		document.getElementById('main-frame').className = '';
2729		
2730		if(items && items['menu']) {
2731			// Махаме маркера за активен елемент
2732			var html = '';
2733			
2734			if(typeof(items['title_prev']) != 'undefined') {
2735				// Слагаме загалвието
2736				var title = window['_LANG'] == 'en' && items['title_prev_en'] ? items['title_prev_en'] : items['title_prev'];
2737				html += '<h2>' + title + '</h2>';
2738			}
2739			
2740			removeClass(items_container, 'have-desc');
2741			
2742			if(items['menu']['tv_filter'] && items['menu']['tv_filter'].length) {
2743				html += '<div class="pane-scroll"><div class="pane-inner"><div class="pane-scroller">';
2744				
2745				for(var j=1; j<items['menu']['tv_filter'].length; j++) {
2746					html += this.item_render_small(items['menu']['tv_filter'][j]);
2747				}
2748				
2749				html += '</div></div><a data-dir="right" class="pane-right-arrow"></a><a data-dir="left" class="pane-left-arrow"></a></div>';
2750			}
2751			
2752			if(items['menu']['tv_program'] && items['menu']['tv_program'].length) {
2753				html += '<div id="tvguide-main-slider" class="tvguide-main-slider"><div class="tvguide-main-slider-inner" style="width: ' + (450 * items['menu']['tv_program'].length) + 'px">';
2754				
2755				for(var i=0; i<items['menu']['tv_program'].length; i++) {						
2756					if(items['menu']['tv_program'][i]['menu']) {
2757						html += '\
2758						<div class="tvguide-list">\
2759							<h2>' + items['menu']['tv_program'][i]['title'] + '</h2>';
2760						
2761						html += '<div class="tvguide-slider"><div class="tvguide-slider-inner">';
2762						for(var j=0; j<items['menu']['tv_program'][i]['menu'].length; j++) {
2763							html += this.item_render_tvguide(items['menu']['tv_program'][i]['menu'][j]);
2764						}
2765						
2766						html += '</div></div></div>';
2767					}
2768				}
2769				
2770				html += '</div></div>';
2771			}
2772			
2773			_self.innerHTML(items_container, html);
2774			
2775			this.item_post_render();
2776		}
2777	}
2778	////////////////////////////////////
2779	// Справочник END
2780	////////////////////////////////////
2781	
2782	
2783	
2784	
2785	
2786	
2787	////////////////////////////////////
2788	// Програма Start
2789	////////////////////////////////////
2790	this.program_render_current_time = function(min_time, max_time, selected_date) {
2791		var left_side = (new Date(min_time * 1000)).getTime();
2792		var right_side = (new Date(max_time * 1000)).getTime();
2793		var now = (new Date()).getTime();
2794		var program_inner = document.getElementById('tv-program-inner');
2795		var time_line_inner = document.getElementById('time-line-inner');
2796		
2797		selected_date = selected_date * 1000;
2798		
2799		// добавяме поитъра само ако сме на текущия ден
2800		if(now > left_side && now < right_side) {
2801			var timePointerLeft = Math.ceil((now - selected_date) / 60000 * minute_size) - 4 + minute_size;
2802			
2803			var timePointer = document.createElement('div');
2804			timePointer['style']['left'] = timePointerLeft + 'px';
2805			
2806			program_inner.appendChild(timePointer);
2807			addClass(timePointer, 'timePointer');
2808			
2809			var timeFixer = document.createElement('div');
2810			timeFixer['style']['left'] = timePointerLeft + 'px';
2811			
2812			time_line_inner.appendChild(timeFixer);
2813			addClass(timeFixer, 'timePointer_fixer');
2814			
2815			timeFixer.innerHTML = date_format(new Date(now + local_time_offset), { 'format': 'only_hour'});
2816		}
2817		
2818		
2819		
2820		for(var from = (new Date(left_side)).setHours(0, 0, 0, 0); from <= right_side; from += 4 * 60 * 60 * 1000){
2821			var timePointerLeft = Math.ceil((from - selected_date) / 60000 * minute_size) - 4 + minute_size;
2822			var dt_from = new Date(from + local_time_offset);
2823			
2824			if(dt_from.getHours() == 0) {
2825				var timePointer = document.createElement('div');
2826				timePointer['style']['left'] = timePointerLeft + 'px';
2827				
2828				program_inner.appendChild(timePointer);
2829				addClass(timePointer, 'timePointer endday');
2830			}
2831			
2832			//
2833			var timeFixer = document.createElement('div');
2834			timeFixer['style']['left'] = timePointerLeft +'px';
2835			
2836			time_line_inner.appendChild(timeFixer);
2837			addClass(timeFixer, 'timePointer_fixer endday');
2838			
2839			timeFixer.innerHTML = '<span>' + date_format(new Date(from + local_time_offset)) + '</span>';
2840		}
2841	}
2842	
2843	this.program_render_timeline = function(min_time, max_time, selected_date) {
2844		var current_time = new Date(min_time * 1000);
2845		
2846		current_time.setMinutes(0);
2847		current_time.setSeconds(0);
2848		
2849		current_time = current_time.getTime() / 1000;
2850		
2851		var timeline_cont = document.getElementById('time-line-cont');
2852		var left = 0;
2853		var now = parseInt((new Date(selected_date * 1000)).getTime() / 1000);
2854		var html = '';
2855		
2856		var index = 0;
2857		do {
2858			left = parseInt((current_time - now) / 60 * minute_size) + 10;
2859			html += '<div class="ts" style="left: '+left+'px;"><div class="time">'+time_format(new Date(current_time * 1000 + local_time_offset))+'</div></div>';
2860			
2861			current_time += 3600;
2862			index++;
2863		} while(current_time < max_time);
2864		
2865		html = '<div id="time-line-holder"><div id="time-line-inner" class="time-line-inner">'+html+'</div></div>';
2866		$('#time-line-cont').html(html);
2867	}
2868	
2869	
2870	this.program_render_event = function(now, selected_date, event) {
2871		var event_time = parseInt(event['s']);
2872		var event_length = parseInt(event['l']);
2873		var left =Math.round((event_time - selected_date) / 60) * minute_size + 1;
2874		var width = event_length / 60 * minute_size - 2;
2875		var tma = now < event_time ? ' tma' : '';
2876		var time_hm	= time_format(new Date(event_time * 1000 + local_time_offset));
2877		var current_bg = '';
2878		var current_css = '';
2879		var html_program = '';
2880
2881		if(now > event_time && (event_time + event_length) > now) {
2882			//width -= 1;
2883			current_bg = 'background:rgb('+event['tv_color2']+') !important;';
2884			current_css = ' curr';
2885		}
2886		
2887		if(width < 70) {
2888			html_program = '<div data-action="menu" data-key="'+ event['k'] +'" class="inPrTv'+tma+current_css+'" style="left:'+left+'px;width:'+width+'px;">\
2889				<div class="in" style="'+current_bg+'"></div>\
2890			</div>';
2891		} else if(width < 90) {
2892			html_program = '<div data-action="menu" data-key="'+ event['k'] +'" class="inPrTv'+tma+current_css+'" style="left:'+left+'px;width:'+width+'px;">\
2893				<div class="in" style="'+current_bg+'">\
2894					<span class="strSwT">' + time_hm + '</span>\
2895				</div>\
2896			</div>';
2897		} else {
2898			html_program = '<div data-action="menu" data-key="'+ event['k'] +'" class="inPrTv'+tma+current_css+'" style="left:'+left+'px;width:'+width+'px;">\
2899				<div class="in" style="'+current_bg+'">\
2900					<span class="strSwT">' + time_hm + '</span>\
2901					<span class="ntShow">' + event['t'] + '</span>\
2902				</div>\
2903			</div>';
2904		}
2905		
2906		return html_program;
2907	}
2908	
2909	
2910	this.calendar_init = function () {
2911		var now = (new Date()).getTime() - time_sync;
2912
2913		_calendar = $('.calendar-dropdown .calendar-main').datepicker({
2914			dateFormat: 'yy-mm-dd',
2915			showOtherMonths: true,
2916			hideIfNoPrevNext: true,
2917			setDate: new Date(now),
2918			maxDate: new Date(now + 10 * 24 * 3600 * 1000),
2919			minDate: new Date(now - 30 * 24 * 3600 * 1000),
2920			beforeShowDay: function(date) {
2921				var diff_days = Math.floor((now - date.getTime()) / 1000 / 86400);
2922				if(diff_days >= 0 && diff_days <= 30) {
2923					return [true, 'have-dvr', ''];
2924				}
2925
2926				if(diff_days > -7) {
2927					return [true, '', ''];
2928				}
2929
2930				return [false, '', ''];
2931			},
2932			onSelect: function(dateText) {
2933				try {$('.tv-calendar').toggleClass('opened', false);} catch(e) {}
2934				try {oThis.calendar_select_dt(null, dateText);} catch(e) {}
2935				
2936				// Превъртаме до текущоия час на избрания ден от календара
2937				var now = new Date((new Date()).getTime() - time_sync);
2938				oThis.calendar_load_dt(new Date(_calendar.datepicker('getDate').getTime() + now.getHours() * 3600 * 1000 + now.getMinutes() * 60 * 1000));
2939			}
2940		});
2941	};
2942
2943	this.calendar_select_dt = function (dt, dt_text) {
2944		if(!dt_text) {
2945			dt_text = date_format(dt, {'format': 'day_month'});
2946		}
2947		
2948		$('.tv-calendar .txt').html(dt_text);
2949		
2950		if(_calendar && _calendar.datepicker && dt) {
2951			_calendar.datepicker('setDate', dt);
2952		}
2953	}
2954	
2955	this.calendar_load_dt = function (dt) {
2956		// Трябва да презаредим през календара.
2957		// Сменяме началната дата, че иначе много ще отместваме по X
2958		var start_date = new Date(dt.getTime());
2959		var end_date = 0;
2960		var now = new Date();
2961		var selected_date = new Date(dt.getTime());
2962		
2963		start_date.setHours(0, 0, 0);
2964		start_date = Math.ceil(start_date / 1000) - 3600 * 12;
2965		end_date = start_date + 3600 * 48;
2966		
2967		selected_date.setHours(now.getHours(), now.getMinutes());
2968		
2969		var key = 'menu/program_v2?date_start='+start_date+'&date_end='+end_date;
2970		mytv_api.menu(key, function (res) {
2971			if(!res)  {
2972				_self.show_error(MyTV.ERRORS['invalid_data']);
2973				return;
2974			}
2975			
2976			if(res['msg']) {
2977				_self.show_error('generic_error', res['msg']);
2978				return;
2979			}
2980			
2981			if(res['menu']) {
2982				_self.program_render(res, selected_date.getTime());
2983			}
2984		}, function () {
2985			_self.hide_loader();
2986		}, lock = true);
2987	}
2988	
2989	
2990	this.checkScrollBehaviorSuport = function () {
2991		return !is_lgtv && document.documentElement && document.documentElement['style'] && ('scrollBehavior' in document.documentElement['style']) ? true : false;
2992	}
2993	
2994	this.program_scrollDirection = function (params) {
2995		params['animate'] = typeof(params['animate']) !== 'undefined' ? params['animate'] : true;
2996		
2997		if(params['animate'] && !(this.checkScrollBehaviorSuport()))  {
2998			if(animating) {
2999				return;
3000			}
3001			
3002			$('#tv-program-inner').toggleClass('noanimation', false);
3003			$('#time-line-holder').toggleClass('noanimation', false);
3004			
3005			animating = true;
3006			
3007			if(transition_event === undefined) {
3008				timers['animation'] = setTimeout(function () {
3009					animating = true;
3010				}, animatonTime);
3011			}
3012		} else {
3013			$('#tv-program-inner').toggleClass('noanimation', true);
3014			$('#time-line-holder').toggleClass('noanimation', true);
3015		}
3016		
3017		params['pixels'] = params['pixels'] ? params['pixels'] : oneHourWidth * 2;
3018		
3019		switch (params['direction']){
3020			default: case 'left' :
3021				currLeftPos += params['pixels'];
3022				
3023				if(this.checkScrollBehaviorSuport()) {
3024					var scroll_opt = { 'left' : scrollLeftBegin - currLeftPos };
3025					if(params['animate']) {
3026						scroll_opt['behavior'] = 'smooth';
3027					}
3028					
3029					$('#tv-program-main')[0].scrollTo(scroll_opt);
3030				} else {
3031					$('#tv-program-inner').css({left:(currLeftPos)+'px'});
3032					$('#time-line-holder').css({left:(currLeftPos)+'px'});
3033				}
3034			break;
3035			
3036			case 'right' :
3037				currLeftPos -= params['pixels'];
3038				
3039				if(this.checkScrollBehaviorSuport()) {
3040					var scroll_opt = { 'left' : scrollLeftBegin - currLeftPos};
3041					if(params['animate']) {
3042						scroll_opt['behavior'] = 'smooth';
3043					}
3044					
3045					$('#tv-program-main')[0].scrollTo(scroll_opt);
3046				} else {
3047					$('#tv-program-inner').css({left:(currLeftPos)+'px'});
3048					$('#time-line-holder').css({left:(currLeftPos)+'px'});
3049				}
3050			break;
3051		}
3052	}
3053	
3054	
3055	this.program_render = function (items, selected_date) {
3056		if(timers['program_refresh']) {
3057			clearInterval(timers['program_refresh']);
3058			timers['program_refresh'] = null;
3059		}
3060		
3061		timers['program_refresh'] = setInterval(function() {
3062			// Рефрешваме само ако сме на тази страница!!!
3063			_self.program_render(items, selected_date);
3064		}, 180000);
3065		
3066		this.main_menu_hide();
3067		items_container.className = 'tv-program';
3068		
3069		if(items && items['menu']) {
3070			if(items['time_in_bg'] && items['time_in_bg'] > 0) {
3071				time_in_bg 				= items['time_in_bg'];
3072				local_time_gmt_offset	= (new Date()).getTimezoneOffset ? (new Date()).getTimezoneOffset() : 0
3073				local_time_offset 		= local_time_gmt_offset * 60000 + time_in_bg;
3074			}
3075			
3076			var _selected_date_ms = parseInt((!selected_date ? (new Date()).getTime() : selected_date));
3077			var _selected_date = parseInt(_selected_date_ms / 1000);
3078
3079			var html_program = '';
3080			var html_channels = '';
3081			var min_time = parseInt((new Date(_selected_date_ms)).getTime() / 1000);
3082			var max_time = min_time;
3083			var now = parseInt((new Date()).getTime() / 1000);
3084			var row = 0;
3085			var el_height = 66;
3086			
3087			var html = '\
3088			<div id="tv-program-frame" class="tv-program-frame">\
3089				<div id="time-line-wrapper">\
3090					<div class="time-line-scrubber"><div id="time-line-cont"></div></div>\
3091					<div class="tv-calendar">\
3092						<span class="tv-order-edit slow-animation" title="Промяна на подредбата на каналите"></span>\
3093						<span class="txt"><b>21</b> Фев</span>\
3094						<span class="calendar-btn" title="Избери дата на програмата"></span>\
3095						<div class="calendar-dropdown">\
3096							<div class="calendar-main"></div>\
3097							<div class="calendar-bottom">\
3098								<span class="f" >30 дни Time Shifting</span>\
3099								<span class="s" ></span>\
3100							</div>\
3101						</div>\
3102						<div class="tv-edit-container">\
3103							<svg class="tv-edit-cancel" aria-hidden="true" data-prefix="fas" data-icon="times" class="svg-inline--fa fa-times fa-w-11" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path class="slow-animation" fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg>\
3104							<span>Запази</span>\
3105							<svg aria-hidden="true" data-prefix="fas" data-icon="check" class="svg-inline--fa fa-check fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">												<path class="slow-animation" fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg>\
3106						</div>\
3107					</div>\
3108					<div class="time-line-buttons"><a class="btn-prev"></a><a class="btn-next"></a><a class="btn-now"></a></div>\
3109				</div>\
3110				<div class="tv-channels-inner">'+html_channels+'</div>\
3111				<div id="tv-program-main"><div id="tv-program-inner" class="tv-program-inner">'+html_program+'</div></div>\
3112				<a data-dir="left" class="arrow-handle left"></a><a data-dir="right" class="arrow-handle right"></a>\
3113			</div>';
3114			
3115			_self.innerHTML(items_container, html);
3116			
3117			_tv_program_width_cache = $('#tv-program-inner').width();
3118			_tv_left_width_cache = $('.tv-channels-inner').width();
3119			
3120			var time_start = (new Date()).getTime();
3121			var factor = 0.8;
3122			
3123			for(i=0; i<items['menu'].length; i++) {
3124				var tv_info = items['menu'][i];
3125				var red = (tv_info['c'] >> 16);
3126				var green = (tv_info['c'] >> 8) & parseInt('11111111', 2);
3127				var blue = tv_info['c'] & parseInt('11111111', 2);
3128				var tv_color = Math.round(red * factor) +',' + Math.round(green * factor) + ',' + Math.round(blue * factor);
3129				var tv_color2 = Math.round(red * factor / 2) +',' + Math.round(green * factor / 2) + ',' + Math.round(blue * factor / 2);
3130				var tv_css = tv_info['have_fhd'] ? ' fhd' : (tv_info['have_hd'] ? ' hd' : '');
3131				var event_time = 0;
3132				
3133				if(!tv_info['have_dvr']) {
3134					tv_css += ' channel-no-dvr';
3135				}
3136				
3137				if(tv_info['t'] == 'bgnews'
3138				   || tv_info['t'] == 'bgvideo'
3139				   || tv_info['k'] == '') {
3140					continue;
3141				}
3142				
3143				var top = row * el_height + 41;
3144				
3145				//style="top:'+top+'px"
3146				html_channels += '<div class="tv-box'+tv_css+'" data-action="menu" data-key="'+tv_info['k']+'" style="top:'+(top 
3146- 1)+'px;background-color:rgb('+tv_color+');"><img src="' + tv_info['p'] +'" /><span class="playBtnHover"></span></div>';
3147				html_program += '<div class="tv-row ' + tv_css + '">';
3148				
3149				if(tv_info['s'].length) {
3150					// Циклим всички елементи
3151					for(j=0; j<tv_info['s'].length; j++) {
3152						var event = tv_info['s'][j];
3153						event['tv_color2'] = tv_color2;
3154						
3155						html_program += _self.program_render_event(now, _selected_date, event);
3156						
3157						event_time = parseInt(event['s']);
3158						
3159						min_time = min_time > event_time ? event_time : min_time;
3160						max_time = max_time < event_time ? event_time : max_time;
3161					}
3162				} else {
3163					// Канамл само на живо
3164					var event = {
3165						's': now - 3600,
3166						'l': 3600 * 4,
3167						'k': tv_info['k'],
3168						'tv_color2': tv_color2,
3169						't': 'Само на живо'
3170					};
3171					
3172					html_program += _self.program_render_event(now, _selected_date, event);
3173					
3174					event_time = parseInt(event['s']);
3175					
3176					min_time = min_time > event_time ? event_time : min_time;
3177					max_time = max_time < event_time ? event_time : max_time;
3178				}
3179				
3180				html_program += '</div>';
3181				
3182				row++;
3183			}
3184			
3185			var html = '\
3186			<div id="tv-program-frame" class="tv-program-frame">\
3187				<div id="time-line-wrapper">\
3188					<div class="time-line-scrubber"><div id="time-line-cont"></div></div>\
3189					<div class="tv-calendar">\
3190						<span class="tv-order-edit slow-animation" title="Промяна на подредбата на каналите"></span>\
3191						<span class="txt"><b>21</b> Фев</span>\
3192						<span class="calendar-btn" title="Избери дата на програмата"></span>\
3193						<div class="calendar-dropdown">\
3194							<div class="calendar-main"></div>\
3195							<div class="calendar-bottom">\
3196								<span class="f" >30 дни Time Shifting</span>\
3197								<span class="s" ></span>\
3198							</div>\
3199						</div>\
3200						<div class="tv-edit-container">\
3201							<svg class="tv-edit-cancel" aria-hidden="true" data-prefix="fas" data-icon="times" class="svg-inline--fa fa-times fa-w-11" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path class="slow-animation" fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg>\
3202							<span>Запази</span>\
3203							<svg aria-hidden="true" data-prefix="fas" data-icon="check" class="svg-inline--fa fa-check fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">												<path class="slow-animation" fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg>\
3204						</div>\
3205					</div>\
3206					<div class="time-line-buttons"><a class="btn-prev"></a><a class="btn-next"></a><a class="btn-now"></a></div>\
3207				</div>\
3208				<div class="tv-channels-inner">'+html_channels+'</div>\
3209				<div id="tv-program-main"><div id="tv-program-inner" class="tv-program-inner">'+html_program+'</div></div>\
3210			</div>';
3211			
3212			setTimeout(function() {
3213				_self.innerHTML(items_container, html);
3214				document.getElementById('tv-program-frame').style['height'] = (top + el_height * 2 + 70) + 'px';
3215				_self.item_post_render();
3216				_self.calendar_init();
3217				_self.calendar_select_dt(new Date(_selected_date_ms));
3218				
3219				$('#tv-program-main').on('scroll', function () {
3220					// Трябва да сметнем currLeftPos
3221					var currentScroll = $('#tv-program-main').scrollLeft();
3222					$('#time-line-cont').scrollLeft(currentScroll);
3223				});
3224			});
3225			
3226			setTimeout(function() {
3227				_self.program_render_timeline(min_time, max_time, _selected_date);
3228				_self.program_render_current_time(min_time, max_time, _selected_date);
3229				
3230				scrollLeftBegin = parseInt((_tv_program_width_cache - _window_width_cache - _tv_left_width_cache) / 2);
3231				$('#tv-program-main')[0].scrollLeft = scrollLeftBegin;
3232			});
3233		}
3234	}
3235	
3236	////////////////////////////////////
3237	// Програма END
3238	////////////////////////////////////
3239	
3240	
3241	
3242	
3243	
3244	////////////////////////////////////
3245	// Profiles START
3246	////////////////////////////////////
3247	this.profile_edit = function(_profile_info) {
3248		_self.show_loader();
3249		
3250		avatar_panel_hidden = true;
3251		
3252		mytv_api.profiles_avatars(function(res) {
3253			_self.hide_loader();
3254			
3255			var container = document.getElementById('profiles-panel');
3256			
3257			var html = '';
3258			var cnt = 0;
3259			var selected_avatar;
3260			var active = '';
3261			
3262			if(res['avatars']) {
3263				var avatar_info;
3264				
3265				for(var i=0; i<res['avatars'].length; i++) {
3266					if(window['_LANG'] == 'en') {
3267						html += '<div class="slider have_right"><div class="slider-inner">';
3268					} else {
3269						html += '<h2>'+res['avatars'][i]['name']+'</h2><div class="slider have_right"><div class="slider-inner">';
3270					}
3271					
3272					for(var j=0; j<res['avatars'][i]['list'].length; j++) {
3273						avatar_info = res['avatars'][i]['list'][j];
3274						
3275						if(!selected_avatar) {
3276							selected_avatar = avatar_info;
3277						}
3278						
3279						if(_profile_info && avatar_info['key'] == _profile_info['avatar_key']) {
3280							selected_avatar = avatar_info;
3281							active = 'active';
3282						} else {
3283							active = '';
3284						}
3285						
3286						html += '<div data-action="select_avatar" data-key="'+avatar_info['key']+'" data-src="' + avatar_info['avatar'] + '" class="profile-item ' + active + ' ' + mouse_css +'"><img src="' + avatar_info['avatar'] + '" alt="" /></div>';
3287						cnt++;
3288					}
3289					
3290					html += '</div><a data-dir="left" class="arrow-handle showing left"></a><a data-dir="right" class="arrow-handle showing right"></a></div>';
3291				}
3292			}
3293			
3294			_self.innerHTML(container, '\
3295				<div class="pop-inner profile-add">\
3296					<h1>' + window['lang'][window['_LANG']]['profile_edit_header'] + '</h1>\
3297					<form id="profile_edit_form" onsubmit="return false;">\
3298						<div id="avatars_panel" style="display:none;"><div class="pop-inner">' + html + '</div></div>\
3299						<div class="profile-item"><img id="profile-edit_selected_avatar" src="' + selected_avatar['avatar'] + '" alt="" /></div>\
3300						<a data-action="change_avatar" class="active btn green">' + window['lang'][window['_LANG']]['avatar_select'] + '</a>\
3301						<input type="hidden" name="avatar_key" value="' + selected_avatar['key'] + '" />\
3302						<label>' + window['lang'][window['_LANG']]['profile_name'] + '</label>\
3303						<input  type="text" name="profile_name" value="' + (_profile_info ? _profile_info['name'] : '') + '" /><br><br>\
3304						<button type="submit" class="btn green">' + (_profile_info ? window['lang'][window['_LANG']]['save_change'] : window['lang'][window['_LANG']]['profile_add_btn'] )+ '</button>&nbsp;&nbsp;&nbsp;\
3305						<button data-action="close-popup" type="button" class="btn white">' + window['lang'][window['_LANG']]['cancel'] + '</button><br>\
3306						'+(_profile_info ? '<a data-action="delete_profile" class="btn delete-profile"><img src="//srv1.mytv.bg/i/ic/avt/delete_profile.png" alt="" />' + window['lang'][window['_LANG']]['profile_delete'] + '</a>' : '') + '\
3307					</form>\
3308				</div>'
3309			);
3310			
3311			var form = document.getElementById('profile_edit_form');
3312			form.onsubmit = function () {
3313				_self.show_loader();
3314				
3315				if(_profile_info) {
3316					var data = {
3317						'key'		: _profile_info['key'],
3318						'name'		: document.getElementsByName('profile_name')[0].value,
3319						'avatar'	: document.getElementsByName('avatar_key')[0].value
3320					};
3321					
3322					mytv_api.profile_update(data, function(res) {
3323						if(res && res['profiles']) {
3324							user_info['profiles'] = res['profiles'];
3325						}
3326						
3327						_self.hide_loader();
3328						
3329						_self.state_manager.switch_page('close-popup');
3330						_self.state_manager.switch_page('menu', 'profile-select');
3331					});
3332				} else {
3333					var data = {
3334						'name'		: document.getElementsByName('profile_name')[0].value,
3335						'avatar'	: document.getElementsByName('avatar_key')[0].value
3336					};
3337					
3338					mytv_api.profile_add(data, function(res) {
3339						if(res && res['profiles']) {
3340							user_info['profiles'] = res['profiles'];
3341						}
3342						
3343						_self.hide_loader();
3344						
3345						_self.state_manager.switch_page('close-popup');
3346						_self.state_manager.switch_page('menu', 'profile-select');
3347					});
3348				}
3349				
3350				return false;
3351			}
3352			
3353			_self.state_manager.popup_add('profile-edit', function() {
3354				_self.state_manager.switch_page('menu', 'profile-select');
3355			});
3356		});
3357		
3358		addClass(document.getElementById('main-bnt-back'), 'btn-back');
3359	}
3360	
3361	
3362	
3363	this.show_profile_delte_confirm = function() {
3364		var error_container = document.getElementById('errors-container');
3365		
3366		_self.innerHTML(error_container, '\
3367			<div class="error-inner">\
3368				<h1>' + window['lang'][window['_LANG']]['profile_delete'] + '</h1>\
3369				<button data-action="delete-profile-confirm" class="btn green">' + window['lang'][window['_LANG']]['logout_yes'] + '</button>\
3370				<button data-action="close-msg" class="btn white">' + window['lang'][window['_LANG']]['logout_no'] + '</button>\
3371			</div>'
3372		);
3373		
3374		$(error_container).show();
3375	}
3376	
3377	
3378	////////////////////////////////////
3379	// Profiles END
3380	////////////////////////////////////
3381	
3382	
3383	
3384	
3385	////////////////////////////////////
3386	// Search START
3387	////////////////////////////////////
3388	this.search_render_result = function(items) {
3389		var container = $('.search-result'),
3390			html = '',
3391			first_episode = false;
3392		
3393		container.html('');
3394
3395		if(!items || !items['menu']) {
3396			return;
3397		}
3398
3399		for(var i=0; i<items['menu'].length; i++) {
3400			if(!first_episode) {
3401				if(items['menu'][i]['saveable'] == 'no') {
3402					first_episode = true;
3403					
3404					if(i > 0) {
3405						html += '<br />';
3406					}
3407				}
3408			}
3409			html += this.item_render(items['menu'][i], false, items['menu'][i]['saveable'] != 'no' ? 'close-popup' : '');
3410		}
3411		
3412		container.html(html);
3413		this.item_post_render();
3414	}
3415	
3416	this.search_render = function() {
3417		var container = document.getElementById('search-form');
3418		
3419		_self.innerHTML(container, '\
3420			<div class="pop-inner">\
3421				<a class="btn-back"></a>\
3422				<form class="" onsubmit="return false;">\
3423					<h1>Търсене</h1>\
3424					<input type="text" />\
3425				</form>\
3426				<div class="search-result have-desc"></div>\
3427			</div>\
3428		');
3429		
3430		$(container).show();
3431		$(container).find('input[type=text]').focus();
3432		
3433		_self.state_manager.popup_add('search', function() {
3434			$(container).hide();
3435		});
3436	}
3437	////////////////////////////////////
3438	// Search END
3439	////////////////////////////////////
3440	
3441	
3442	
3443	
3444	
3445	
3446	this.innerHTML = function (el, html) {
3447		el.innerHTML = html;
3448	}
3449	
3450	this.show_loader = function() {
3451		$('#loader-container').show();
3452	}
3453	
3454	this.hide_loader = function() {
3455		$('#loader-container').hide();
3456	}
3457	
3458	this.main_menu_show = function () {
3459		
3460	}
3461	
3462	this.main_menu_hide = function (no_animation) {
3463		
3464	}
3465	
3466	
3467	////////////////////////////////////
3468	// Item Render
3469	////////////////////////////////////
3470	this.item_render = function (sub_item, add_bg_color, add_css) {
3471		add_bg_color = !!add_bg_color;
3472		add_css = add_css ? add_css : '';
3473		
3474		var bg_color = sub_item['bg_color'] && add_bg_color ? ' style="background-color:#' + ('000000' + sub_item['bg_color'].toString(16)).substr(-6) + '"' : '';
3475		var desc = sub_item['desc'] || '';
3476		var progress = '';
3477		
3478		var is_saveble = sub_item['saveable'] && sub_item['saveable'] == 'show';
3479		var is_repeat = sub_item['is_repeat'] ? ' repeat' : '';
3480		var is_watched = typeof(sub_item['is_watched']) != 'undefined' && sub_item['is_watched'] ? ' <span class="watched">гледано</span>' : '';
3481		var hour_bg = typeof(sub_item['hour_bg']) != 'undefined' ? '<div class="hour-bg">' + sub_item['hour_bg'] + '</div>' : '';
3482		var title = sub_item['title'].split("\n");
3483		var fav_btn = is_saveble ? '<strong title="Добави / премахни от моя списъÐ
3483º" data-key="'+ sub_item['key'] +'" data-action="favorite-add"  class="favorites ' + (sub_item['is_saved'] ? ' saved' : '') + '"></strong>' : '';
3484		var have_subs = sub_item['have_subs'] ? '<span class="icon-subs"></span>' : '';
3485		var css = (sub_item['new_episode'] ? ' new-episode' : '') + (add_css ? ' ' + add_css : '');
3486		var time_from = sub_item['time_from'] ? ' data-timefrom="' + sub_item['time_from'] + '"' : '';
3487		var season_number = sub_item['season_number'] ? ' data-season="' + sub_item['season_number'] + '" ' : '';
3488		
3489		if(hour_bg != '') {
3490			is_watched = '';
3491		}
3492		
3493		desc = (title.length > 1 ? title[1] : (sub_item['desc'] ? sub_item['desc'] : ''));
3494		
3495		if(desc != '') {
3496			removeClass(items_container, 'have-desc');
3497			addClass(items_container, 'have-desc');
3498		}
3499		
3500		if(sub_item['progress']) {
3501			progress = '<div class="progress"><div style="width:'+sub_item['progress']+'%;"></div></div>';
3502		}
3503		
3504		if(sub_item['percent_watched']) {
3505			is_watched = '';
3506			progress = '<div class="progress"><div style="width:'+sub_item['percent_watched']+'%;"></div></div>';
3507		}
3508		
3509		return '<div data-action="menu" ' + season_number + ' data-key="'+ sub_item['key'] +'" class="tv-show' + css + is_repeat + '"' + time_from + '>\
3510			<div class="img"' + bg_color + '><img src="' + sub_item['thumb'] + '" />' + progress + have_subs +'</div>\
3511			' + hour_bg + '\
3512			<div class="title">' + title[0] + '<div class="desc">' +  desc + '</div>' + is_watched + '</div>\
3513			' + fav_btn + '\
3514		</div>';
3515	}
3516	
3517	
3518	this.item_render_tvguide = function (sub_item) {
3519		var bg_color = sub_item['bg_color'] ? ' style="background-color:#' + ('000000' + sub_item['bg_color'].toString(16)).substr(-6) + '"' : '';
3520		var desc = sub_item['desc'] || '';
3521		var hour_bg = typeof(sub_item['time_start']) != 'undefined' ? '' + sub_item['time_start'] + '' : '';
3522		var title = sub_item['title'].split("\n");
3523		var cat_img = sub_item['cat_thumb'] ? '<img src="' + sub_item['cat_thumb'] + '" />' : '';
3524		var is_saved = sub_item['is_saved'] ? ' saved' : '';
3525		
3526		desc = (title.length > 1 ? title[1] : (sub_item['desc'] ? sub_item['desc'] : ''));
3527		
3528		return '\
3529		<div data-key="'+ sub_item['key'] +'" class="tvguide-row ' + is_saved + '">\
3530			<span class="img">' + cat_img + '</span>\
3531			<span class="hour">' + hour_bg + '</span>\
3532			<span class="title">' + title[0] + '&nbsp;<i></i></span>\
3533		</div>';
3534	}
3535	
3536	
3537	this.item_render_small = function (sub_item) {
3538		var bg_color = sub_item['bg_color'] ? 'background-color:#' + ('000000' + sub_item['bg_color'].toString(16)).substr(-6) + ';' : '';
3539		var desc = sub_item['desc'] || '';
3540		var progress = '';
3541		
3542		var is_watched = typeof(sub_item['is_watched']) != 'undefined' && sub_item['is_watched'] ? ' <span class="watched">гледано</span>' : '';
3543		var hour_bg = typeof(sub_item['hour_bg']) != 'undefined' ? '<div class="hour-bg">' + sub_item['hour_bg'] + '</div>' : '';
3544		var title = sub_item['title'].split("\n");
3545		
3546		if(hour_bg != '') {
3547			is_watched = '';
3548		}
3549		
3550		desc = (title.length > 1 ? title[1] : (sub_item['desc'] ? sub_item['desc'] : ''));
3551		
3552		if(desc != '') {
3553			removeClass(items_container, 'have-desc');
3554			addClass(items_container, 'have-desc');
3555		}
3556		
3557		if(sub_item['progress']) {
3558			progress = '<div class="progress"><div style="width:'+sub_item['progress']+'%;"></div></div>';
3559		}
3560		
3561		if(sub_item['percent_watched']) {
3562			is_watched = '';
3563			progress = '<div class="progress"><div style="width:'+sub_item['percent_watched']+'%;"></div></div>';
3564		}
3565		
3566		return '<div data-action="menu" data-key="'+ sub_item['key'] +'" class="tv-show">\
3567			<div class="img" style="' + bg_color + '"><div class="img-bg" style="background-image: url(' + sub_item['thumb'] + ');"></div>' + progress +'</div>\
3568			' + hour_bg + '\
3569			<div class="title">' + title[0] + '&nbsp; <div class="desc">' +  desc + '&nbsp;</div>' + is_watched + '</div>\
3570		</div>';
3571	}
3572	
3573	
3574	this.process_image_stack = function (max_simultanios_downloads) {
3575		if(!slow_cpu_image_stack.length) {
3576			return;
3577		}
3578		
3579		for(var i=0; i<max_simultanios_downloads; i++) {
3580			if(!slow_cpu_image_stack.length) {
3581				return;
3582			}
3583			
3584			var img_pop = slow_cpu_image_stack.shift();
3585
3586			(function(img_el, src1) {
3587				// Ако екрана го няма вече не сваляме картинката!!!
3588				if(!img_el.parentNode) {
3589					img_el.src = '';
3590					delete img_el;
3591					return;
3592				}
3593				
3594				var img = document.createElement('img');				
3595				img.src = src1;
3596				
3597				if(img.complete == 1) {
3598					// Взелоя е от шибани кеш!!!!!!!!!!!!!!!
3599					if(!img_el.parentNode) {
3600						img.src = '';
3601						delete img;
3602						return;
3603					}
3604					
3605					img_el.parentNode.insertBefore(img, img_el);
3606					
3607					var rm;
3608					if(img_el.parentNode.deleteChild) {
3609						var rm = img_el.parentNode.deleteChild(img_el);
3610					} else {
3611						var rm = img_el.parentNode.removeChild(img_el);
3612					}
3613					
3614					try { if(rm) { delete rm; } } catch(e) {}
3615					
3616					_self.process_image_stack(1);
3617				} else {
3618					img.onload = function () {
3619						if(!img_el.parentNode) {
3620							img.src = '';
3621							delete img;
3622							return;
3623						}
3624						
3625						img_el.parentNode.insertBefore(img, img_el);
3626						
3627						if(img_el.parentNode.deleteChild) {
3628							img_el.parentNode.deleteChild(img_el);
3629						} else {
3630							var rm = img_el.parentNode.removeChild(img_el);
3631						}
3632						
3633						_self.process_image_stack(1);
3634					}
3635					
3636					img.onerror = function(e) {
3637						img.src = null;
3638						img.onload = null;
3639						img.onerror = null;
3640						delete img;
3641						
3642						if(img_el.parentNode && (typeof(img_el.retry) == 'undefined' || img_el.retry < 1)) {
3643							if(typeof(img_el.retry) == 'undefined') {
3644								img_el.retry = 0;
3645							}
3646							
3647							img_el.retry++;
3648							
3649							slow_cpu_image_stack.unshift({
3650								'src': src1,
3651								'el': img_el
3652							});
3653						} else {
3654							delete img_el;
3655						}
3656						
3657						_self.process_image_stack(1);
3658					}
3659				}
3660				
3661				
3662			})(img_pop['el'], img_pop['src']);
3663		}
3664		
3665		
3666	}
3667	
3668	this.item_post_render = function () {
3669		//
3670		simple_slider.update();
3671		
3672		//
3673		$('.show').toggleClass('show', false);
3674		$('.open').toggleClass('open', false);
3675		
3676		var images_first;
3677		var images_late;
3678		
3679		try {
3680			var cont = document.getElementById('player-container');
3681			images_first = cont.getElementsByTagName('img');
3682			
3683			var cont = document.getElementById('main-frame');
3684			images_late = cont.getElementsByTagName('img');
3685		} catch(e) {
3686			images_first = document.getElementsByTagName('img');
3687		}
3688		
3689		slow_cpu_image_stack = new Array();
3690		
3691		for(var i=0; i<images_first.length; i++) {
3692			var src = images_first[i].getAttribute('src1');
3693			
3694			if(src) {
3695				slow_cpu_image_stack.push({
3696					'src': src,
3697					'el': images_first[i]
3698				});
3699			}
3700		}
3701		
3702		if(images_late && images_late.length) {
3703			for(var i=0; i<images_late.length; i++) {
3704				var src = images_late[i].getAttribute('src1');
3705				
3706				if(src) {
3707					slow_cpu_image_stack.push({
3708						'src': src,
3709						'el': images_late[i]
3710					});
3711				}
3712			}
3713		}
3714
3715		_self.process_image_stack(10);
3716	}
3717	////////////////////////////////////
3718	// Item Render END
3719	////////////////////////////////////
3720}
3721
3722
3723
3724
3725
3726function date_format(dt, settings) {
3727	var monthNames = ['Яну','Фев','Мар','Апр','Май','Юни', 'Юли','Авг','Сеп','Окт','Нов','Дек'];
3728	var hour_min = ('0' + dt.getHours()).slice(-2) + ':' + ('0' + dt.getMinutes()).slice(-2);
3729	var dayNamesShort = ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'];
3730	
3731	if(settings) {
3732		switch(settings['format']) {
3733			case 'only_hour':
3734				return hour_min;
3735			break;
3736			
3737			case 'day_month':
3738				return '<b>' + dt.getDate() + '</b> ' + monthNames[dt.getMonth()] ;
3739			break;
3740		}
3741	}
3742	
3743	return dt.getDate() + ' ' + monthNames[dt.getMonth()] + ' ' + (dt.getYear() + 1900) + '<br>' + hour_min;
3744}
3745
3746
3747function time_format(dt, only_hour) {
3748	var time_start_h	= ('0' + dt.getHours()).slice(-2);
3749	var time_start_m	= '00';
3750	
3751	if(!only_hour) {
3752		time_start_m	= ('0' + dt.getMinutes()).slice(-2);
3753	}
3754	
3755	return time_start_h + ':' + time_start_m;
3756}
3757
3758
3759function removeClass(el, classname) {
3760	if(!el) {
3761		return;
3762	}
3763	
3764	var regexp = new RegExp('\\s*' + RegExp.quote(classname), 'gi');
3765	el.className = el.className.replace(regexp, '');
3766}
3767
3768
3769function addClass(el, classname) {
3770	if(!el) {
3771		return;
3772	}
3773	
3774	el.className +=  ' ' + classname;
3775}
3776
3777function transitionEndEventName() {
3778	var i,
3779		undefined,
3780		el = document.createElement('div'),
3781		transitions = {
3782			'transition':'transitionend',
3783			'OTransition':'otransitionend',  // oTransitionEnd in very old Opera
3784			'MozTransition':'transitionend',
3785			'WebkitTransition':'webkitTransitionEnd'
3786		};
3787
3788	for (i in transitions) {
3789		if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) {
3790			return transitions[i];
3791		}
3792	}
3793
3794	//TODO: throw 'TransitionEnd event is not supported in this browser';
3795	return undefined;
3796}

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.