PageSourceSearch

https://www.polotv.pl/templates/polo/js/videoPlayer.js

js polotv.pl collected 2026-09-25 08:56:45 UTC 132,554 bytes, 4,452 lines download raw bytes

1/*
2 * DOM
3 */
4(function(window, document){
5	"use strict";
6
7	var getByClass = function(context, cl){
8			context = context || document;
9			if(context.getElementsByClassName) return context.getElementsByClassName(cl);
10			var node = context.getElementsByTagName('*') || context.all,
11				i = node.length,
12				e = [];
13
14			while(i--){
15				var clNms = node[i].className.split(' ');
16				var j = clNms.length;
17				while(j--){
18					if(clNms[j] == cl){
19						e.push(node[i]);
20						break;
21					}
22				}
23			}
24			return e;
25		},
26		getByAttr = function(context, attr){
27			context = context || document;
28			var attrs = attr.split("="),
29				node = context.getElementsByTagName('*') || context.all,
30				i = node.length,
31				e = [];
32
33			while(i--){
34				if(node[i].getAttribute(attrs[0]) == attrs[1]){
35					e.push(node[i]);
36				}
37			}
38			return e;
39		},
40		hasClass = function(el, cl){
41			return new RegExp('(\\s|^)' + cl + '(\\s|$)').test(el.className);
42		},
43		setEvent = function(el, e, cb){
44
45			el.evnts = el.evnts || {};
46
47			el.evnts[e[0]] = el.evnts[e[0]] || [];
48
49			var obj = [];
50			obj[0] = cb;
51			if(e[1]) obj[1] = e[1];
52
53			el.evnts[e[0]].push(obj);
54
55		},
56		bindEvent = function(el, event, cb){
57			var events = event.split(' ');
58
59			for(var i = 0, l = events.length; i < l; i++){
60				var e = events[i].split('.');
61
62				if(el.addEventListener){
63					el.addEventListener(e[0], cb, false);
64				}
65				else if(el.attachEvent){
66					el.attachEvent('on' + e[0], cb);
67				}
68
69				setEvent(el, e, cb);
70			}
71		},
72		unbindEvent = function(el, event){
73			var events = event.split(' ');
74			el.evnts = el.evnts || [];
75
76			for(var i = 0, l = events.length; i < l; i++){
77				var e = events[i].split('.');
78
79				if(!el.evnts[e[0]]) continue;
80
81				var ii = el.evnts[e[0]].length;
82				while(ii--){
83
84					if(e[1] && el.evnts[e[0]][ii][1] != e[1]) continue;
85
86					if(el.removeEventListener){
87						el.removeEventListener(e[0], el.evnts[e[0]][ii][0], false);
88					}
89					else if(el.detachEvent){
90						el.detachEvent('on' + e[0], el.evnts[e[0]][ii][0]);
91					}
92
93					el.evnts[e[0]].splice(ii, 1);
94
95				}
96
97			}
98		},
99		toHTML = function(html){
100			var a = document.createElement("div");
101
102			a.innerHTML = html;
103			
104			return a;
105		},
106		getAbsoluteUrl = function(url){
107			var el = document.createElement('div');
108			el.innerHTML = '<a></a>';
109			el.firstChild.href = url;
110			el.innerHTML = el.innerHTML;
111			return el.firstChild.href;
112		},
113		triggerLoadCache = function(uri, status){
114			for(var i = 0, item; item = DOM.load.cache[uri][i++]; ){
115				if(status === 'success' && typeof item.cb === "function") item.cb();
116				if(status === 'error' && typeof item.err === "function") item.err();
117			}
118			DOM.load.cache[uri] = status;
119		},
120		getXHR = function(){
121			if(window.XDomainRequest){
122				return new XDomainRequest();
123			}
124			if(window.XMLHttpRequest){
125				return new XMLHttpRequest();
126			}
127			try{
128				return new ActiveXObject('MSXML2.XMLHTTP.6.0');
129			}
130			catch(e){
131				try{
132					return new ActiveXObject('MSXML2.XMLHTTP.3.0');
133				}
134				catch(e){
135					throw new Error("This browser does not support XMLHttpRequest.");
136				}
137			}
138		};
139
140	var DOM = function(selector, context){
141		return new DOM.lets.init(selector, context);
142	}
143	DOM.lets = DOM.prototype = {
144		constructor: DOM,
145		init: function(selector, context){
146			context = context || document;
147
148			if(context instanceof DOM) context = context[0];
149
150			if(!selector){
151				return this;
152			}
153			else if(selector.nodeType || selector === window || selector === document){
154				this[0] = selector;
155				this.length = 1;
156			}
157			else if(typeof selector === "string"){
158
159				var s = selector.charAt(0),
160					el = [];
161
162				if(s == '#'){
163
164					var id = document.getElementById(selector.substr(1));
165					if(id) el[0] = id;
166
167				}
168				else{
169
170					if(/\s/.test(selector)){
171
172						var selectors = selector.split(/\s/);
173
174						var i = 0,
175							el = context;
176
177						while(i < selectors.length){
178							el = DOM(selectors[i++], el);
179						}
180
181					}
182					else{
183
184						if(s == '.'){
185							el = getByClass(context, selector.substr(1).replace(/\./g, ' '));
186						}
187						else if(s == '['){
188							el = getByAttr(context, selector.substr(1, selector.length - 2));
189						}
190						else{
191							el = context.getElementsByTagName(selector);
192						}
193
194					}
195
196				}
197
198				if(!el[0] && context.querySelectorAll){
199
200					try{
201						el = context.querySelectorAll(selector);
202					}
203					catch(e){}
204
205				}
206
207				el = this.slice.call(el);
208
209				if(el[0]){
210					this.length = el.length;
211					for(var i = 0, l = el.length; i < l; i++){
212						this[i] = el[i];
213					}
214				}
215
216			}
217
218			return (selector.constructor === DOM ? selector : this);
219		},
220		length: 0,
221		slice: [].slice,
222		splice: [].splice
223	}
224	DOM.lets.init.prototype = DOM.lets;
225
226	DOM.lets.eq = function(index){
227		return DOM(this[index]);
228	}
229	DOM.lets.find = function(selector){
230		return DOM(selector, this[0]);
231	}
232	DOM.lets.parent = function(){
233		return DOM(this[0].parentNode);
234	}
235	DOM.lets.on = function(type, cb){
236		for(var i = 0, l = this.length; i < l; i++){
237			bindEvent(this[i], type, cb);
238		}
239
240		return this;
241	}
242	DOM.lets.one = function(type, cb){
243		var orgCb = cb;
244		/* 
245		 * TODO
246		 * - add parsing type and adding random .namespace to func when doesnt include
247		 */
248		cb = function(event){
249			DOM(this).off(type);
250			return orgCb.apply(this, arguments);
251		}
252		for(var i = 0, l = this.length; i < l; i++){
253			bindEvent(this[i], type, cb);
254		}
255
256		return this;
257	}
258	DOM.lets.off = function(type){
259		for(var i = 0, l = this.length; i < l; i++){
260			unbindEvent(this[i], type);
261		}
262
263		return this;
264	}
265	DOM.lets.show = function(){
266		for(var i = 0, l = this.length; i < l; i++){
267			this[i].style.display = 'block';
268		}
269
270		return this;
271	}
272	DOM.lets.hide = function(){
273		for(var i = 0, l = this.length; i < l; i++){
274			this[i].style.display = 'none';
275		}
276
277		return this;
278	}
279	DOM.lets.focus = function(){
280		return DOM(this[0].focus());
281	}
282	DOM.lets.css = function(prop, value){
283		if(typeof prop === "Object"){
284
285		}
286		else if(prop && value){
287			for(var i = 0, l = this.length; i < l; i++){
288				this[i].style[prop] = value;
289			}
290		}
291		else if(prop && this.length == 1){
292			return this[0].style[prop];
293		}
294
295		return this;
296	}
297	DOM.lets.attr = function(attr, value){
298		if(typeof attr === "Object"){
299			// TODO
300		}
301		else if(attr && typeof value != "undefined"){
302			for(var i = 0, l = this.length; i < l; i++){
303				this[i].setAttribute(attr, value);
304			}
305		}
306		else if(typeof value == "undefined" && this[0]){
307			return this[0].getAttribute(attr);
308		}
309
310		return this;
311	}
312	DOM.lets.removeAttr = function(attr){
313		for(var i = 0, l = this.length; i < l; i++){
314			this[i].removeAttribute(attr);
315		}
316
317		return this;
318	}
319	DOM.lets.val = function(val){
320		if(val){
321			for(var i = 0, l = this.length; i < l; i++){
322				this[i].value = val;
323			}
324		}
325		else{
326			return this[0].value;
327		}
328
329		return this;
330	}
331	DOM.lets.hasClass = function(cl){
332		return hasClass(this[0], cl);
333	}
334	DOM.lets.addClass = function(cl){
335		var cl = cl.split(" ");
336		for(var i = 0, l = this.length; i < l; i++){
337			for(var ii = 0, ll = cl.length; ii < ll; ii++){
338				if(!hasClass(this[i], cl[ii])){
339					this[i].className += (this[i].className ? ' ' : '') + cl[ii];
340				}
341			}
342		}
343
344		return this;
345	}
346	DOM.lets.removeClass = function(cl){
347		for(var i = 0, l = this.length; i < l; i++){
348			if(cl){
349				var splitCl = cl.split(" ");
350				for(var j = 0, k = splitCl.length; j < k; j++){
351
352					if(hasClass(this[i], splitCl[j])){
353
354						var curCl = this[i].className.split(" ");
355						var filter = [];
356					
357						for(var ii = 0, ll = curCl.length; ii < ll; ii++){
358							if(splitCl[j] != curCl[ii] && curCl[ii] != ""){
359								filter.push(curCl[ii]);
360							}
361						}
362					
363						this[i].className = filter.join(" ");
364
365					}
366
367				}
368			}
369			else{
370				this[i].className = "";
371			}
372		}
373
374		return this;
375	}
376	DOM.lets.toggleClass = function(cl, check){
377		for(var i = 0, l = this.length; i < l; i++){
378			if(typeof check !== "undefinded"){
379				DOM(this[i])[(check ? "add" : "remove") + "Class"](cl);
380			}
381			else{
382
383				if(DOM(this[i]).hasClass(cl)){
384					DOM(this[i]).removeClass(cl);
385				}
386				else{
387					DOM(this[i]).addClass(cl);
388				}
389
390			}
391		}
392
393		return this;
394	}
395	DOM.lets.wrap = function(html){
396		var html = toHTML(html).firstChild;
397
398		for(var i = 0, l = this.length; i < l; i++){
399			var el = this[i];
400			
401			if(el.nextSibling){
402				el.parentNode.insertBefore(html, el.nextSibling);
403			}
404			else{
405				el.parentNode.appendChild(html);
406			}
407
408			html.appendChild(el);
409		}
410
411		return this;
412	}
413	DOM.lets.append = function(html){
414		for(var i = 0, l = this.length; i < l; i++){
415			var html = toHTML(html);
416			while(html.children.length > 0){
417				this[i].appendChild(html.children[0]);
418			}
419		}
420
421		return this;
422	}
423	DOM.lets.html = function(html){
424		var html = toHTML(html).innerHTML;
425
426		for(var i = 0, l = this.length; i < l; i++){
427			this[i].innerHTML = html;
428		}
429
430		return this;
431	}
432	DOM.lets.replaceWith = function(html){
433		var html = toHTML(html).firstChild;
434
435		for(var i = 0, l = this.length; i < l; i++){
436			var parent = this[i].parentNode;
437
438			parent.replaceChild(html, this[i]);
439		}
440
441		return this;
442	}
443	DOM.lets.remove = function(){
444		for(var i = 0, l = this.length; i < l; i++){
445			this[i].parentNode.removeChild(this[i]);
446		}
447	}
448	DOM.lets.scrollTop = function(val){
449		var el = this[0],
450			win = el === window;
451		if(val === undefined){
452			return win ?
453				("pageYOffset" in el) ?
454					el["pageYOffset"] :
455					el.document.documentElement["scrollTop"] :
456				el["scrollTop"];
457		}
458
459		if(win){
460			el.scrollTo(
461				DOM(el).scrollLeft(),
462				val
463			);
464		}
465		else{
466			el["scrollTop"] = val;
467		}
468	}
469	DOM.lets.scrollLeft = function(val){
470		var el = this[0],
471			win = el === window;
472		if(val === undefined){
473			return win ?
474				("pageXOffset" in el) ?
475					el["pageXOffset"] :
476					el.document.documentElement["scrollLeft"] :
477				el["scrollLeft"];
478		}
479
480		if(win){
481			el.scrollTo(
482				val,
483				DOM(el).scrollTop()
484			);
485		}
486		else{
487			el["scrollLeft"] = val;
488		}
489	}
490
491	DOM.extend = function(def, opt){
492		var ext = {};
493		var prop;
494		for(prop in def){
495			if(Object.prototype.hasOwnProperty.call(def, prop)){
496				ext[prop] = def[prop];
497			}
498		}
499		for(prop in opt){
500			if(Object.prototype.hasOwnProperty.call(opt, prop)){
501				ext[prop] = opt[prop];
502			}
503		}
504		return ext;
505	}
506	DOM.merge = function(first, second){
507		var i = first.length,
508			j = 0;
509
510		if(typeof second.length === "number"){
511			for(var l = second.length; j < l; j++){
512				first[i++] = second[j];
513			}
514		}
515		else{
516			while(second[j] !== undefined){
517				first[i++] = second[j++];
518			}
519		}
520
521		first.length = i;
522
523		return first;
524	}
525	DOM.inArray = function(val, arr){
526		for(var i = 0, l = arr.length; i < l; i++){
527			if(arr[i] === val){
528				return i;
529			}
530		}
531		return -1;
532	}
533	DOM.load = function(url, cb, err){
534		var uri = getAbsoluteUrl(url);
535
536		if(typeof DOM.load.cache[uri] === "undefined"){
537			var a,
538				b = document.getElementsByTagName('head')[0],
539				type=url.split('.').pop();
540
541			if(type == 'css'){
542				a = document.createElement('link');
543				a.rel = 'stylesheet';
544				a.type = 'text/css';
545			}
546			else if(type == 'js'){
547				a = document.createElement('script');
548				a.type = 'text/javascript';
549			}
550
551			DOM.load.cache[uri] = [];
552			DOM.load.cache[uri].push({
553				cb: cb,
554				err: err,
555			});
556
557			a.onload = function(){
558				triggerLoadCache(uri, 'success');
559			}
560			a.onreadystatechange = function(){
561				if(this.readyState == 'complete' || this.readyState == 'loaded'){
562					triggerLoadCache(uri, 'success');
563				}
564			}
565			a.onerror = function(e){
566				triggerLoadCache(uri, 'error');
567			}
568
569			a[type == 'css' ? "href" : "src"] = url;
570
571			b.appendChild(a);
572
573		} else {
574			if(typeof DOM.load.cache[uri] !== "string"){
575				DOM.load.cache[uri].push({
576					cb: cb,
577					err: err,
578				});
579			} else {
580				if(DOM.load.cache[uri] === "success" && typeof cb === "function") cb();
581				if(DOM.load.cache[uri] === "error" && typeof err === "function") err();
582			}
583		}
584			
585	}
586	DOM.load.cache = {};
587	DOM.xhr = function(opts){
588		var done = false, timer;
589		try{
590			var xhr = getXHR();
591			var async = typeof opts.async === "boolean" ? opts.async : true;
592			xhr.open(opts.method || "GET", opts.url, async);
593			xhr.onload = function(){
594				clearTimeout(timer);
595				if(done) return;
596				done = true;
597
598				if(typeof opts.onload == "function") opts.onload(xhr.responseText, xhr);
599				if(typeof opts.oncomplete == "function") opts.oncomplete(xhr);
600			}
601			xhr.onreadystatechange = function(){
602				if(this.readyState == 4 && !done) {
603					if(this.status == 200) {
604						xhr.onload.call(this);
605					} else {
606						xhr.onerror.call(this);
607					}
608				}
609			};
610			xhr.onerror = function(err){
611				clearTimeout(timer);
612				if(done) return;
613				done = true;
614
615				if(typeof opts.onerror == "function") opts.onerror(null, err || "error", this);
616				if(typeof opts.oncomplete == "function") opts.oncomplete(xhr);
617			};
618			xhr.ontimeout = function(){
619				xhr.onerror.call(this, "timeout");
620			};
621			xhr.onabort = function(){
622				xhr.onerror.call(this, "abort");
623			};
624			if(async) xhr.timeout = opts.timeout || 10000;
625			xhr.withCredentials = opts.credentials || false;
626			if(opts.data) {
627				xhr.setRequestHeader("Content-Type", opts.contentType || "application/x-www-form-urlencoded; charset=UTF-8");
628			}
629			xhr.send(opts.data || null);
630
631			timer = setTimeout(function(){
632				xhr.ontimeout.call(xhr);
633			}, xhr.timeout);
634		}
635		catch(e){
636			if(typeof opts.onerror == "function") opts.onerror(null, "trycatch");
637		}
638	}
639	DOM.getJSON = function(url, cb, opts){
640		DOM.xhr(DOM.extend({
641			url: url,
642			onload: function(data, xhr){
643				var status;
644
645				try{
646					data = JSON.parse(data);
647					status = "success";
648				}
649				catch(e){
650					status = "invalid JSON";
651				}
652
653				if(typeof cb == "function") cb(data, status, this);
654			},
655			onerror: cb
656		}, opts || {}));
657	}
658
659	window.DOM = DOM;
660
661})(window, document);
662
663if (!Function.prototype.bind) {
664	Function.prototype.bind = function(oThis) {
665		if (typeof this !== 'function') {
666			// closest thing possible to the ECMAScript 5
667			// internal IsCallable function
668			throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
669		}
670
671		var aArgs   = Array.prototype.slice.call(arguments, 1),
672				fToBind = this,
673				fNOP    = function() {},
674				fBound  = function() {
675					return fToBind.apply(this instanceof fNOP
676								 ? this
677								 : oThis,
678								 aArgs.concat(Array.prototype.slice.call(arguments)));
679				};
680
681		if (this.prototype) {
682			// Function.prototype doesn't have a prototype property
683			fNOP.prototype = this.prototype; 
684		}
685		fBound.prototype = new fNOP();
686
687		return fBound;
688	};
689}
690
691if (!Array.prototype.map) {
692  Array.prototype.map = function(callback/*, thisArg*/) {
693    var T, A, k;
694
695    if (this == null) {
696      throw new TypeError('this is null or not defined');
697    }
698
699    var O = Object(this);
700    var len = O.length >>> 0;
701
702    if (typeof callback !== 'function') {
703      throw new TypeError(callback + ' is not a function');
704    }
705
706    if (arguments.length > 1) {
707      T = arguments[1];
708    }
709
710    A = new Array(len);
711    k = 0;
712
713    while (k < len) {
714      var kValue, mappedValue;
715
716      if (k in O) {
717        kValue = O[k];
718        mappedValue = callback.call(T, kValue, k, O);
719        A[k] = mappedValue;
720      }
721      k++;
722    }
723
724    return A;
725  };
726}
727
728if (!Array.prototype.filter) {
729  Array.prototype.filter = function(fun /*, thisp*/)
730  {
731    var len = this.length;
732    if (typeof fun != "function")
733      throw new TypeError();
734
735    var res = new Array();
736    var thisp = arguments[1];
737    for (var i = 0; i < len; i++)
738    {
739      if (i in this)
740      {
741        var val = this[i]; // in case fun mutates this
742        if (fun.call(thisp, val, i, this))
743          res.push(val);
744      }
745    }
746
747    return res;
748  };
749}
750
751// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
752// MIT license
753!function(a,b,c){var f,d=0,e=["ms","moz","webkit","o"];for(f=0;f<e.length&&!a[b];++f)a[b]=a[e[f]+"RequestAnimationFrame"],a[c]=a[e[f]+"CancelAnimationFrame"]||a[e[f]+"CancelRequestAnimationFrame"];a[b]||(a[b]=function(b){var c=(new Date).getTime(),e=Math.max(0,16-(c-d)),f=a.setTimeout(function(){b(c+e)},e);return d=c+e,f}),a[c]||(a[c]=function(b){a.clearTimeout(b)})}(this,"requestAnimationFrame","cancelAnimationFrame");
754
755// uuidv4 - RFC4122 UUIDs
756// MIT license
757!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.uuidv4=r()}}(function(){return function r(e,n,t){function o(f,u){if(!n[f]){if(!e[f]){var a="function"==typeof require&&require;if(!u&&a)return a(f,!0);if(i)return i(f,!0);var d=new Error("Cannot find module '"+f+"'");throw d.code="MODULE_NOT_FOUND",d}var p=n[f]={exports:{}};e[f][0].call(p.exports,function(r){var n=e[f][1][r];return o(n?n:r)},p,p.exports,r,e,n,t)}return n[f].exports}for(var i="function"==typeof require&&require,f=0;f<t.length;f++)o(t[f]);return o}({1:[function(r,e,n){function t(r,e){var n=e||0,t=o;return t[r[n++]]+t[r[n++]]+t[r[n++]]+t[r[n++]]+"-"+t[r[n++]]+t[r[n++]]+"-"+t[r[n++]]+t[r[n++]]+"-"+t[r[n++]]+t[r[n++]]+"-"+t[r[n++]]+t[r[n++]]+t[r[n++]]+t[r[n++]]+t[r[n++]]+t[r[n++]]}for(var o=[],i=0;i<256;++i)o[i]=(i+256).toString(16).substr(1);e.exports=t},{}],2:[function(r,e,n){var t="undefined"!=typeof crypto&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&msCrypto.getRandomValues.bind(msCrypto);if(t){var o=new Uint8Array(16);e.exports=function(){return t(o),o}}else{var i=new Array(16);e.exports=function(){for(var r,e=0;e<16;e++)0===(3&e)&&(r=4294967296*Math.random()),i[e]=r>>>((3&e)<<3)&255;return i}}},{}],3:[function(r,e,n){function t(r,e,n){var t=e&&n||0;"string"==typeof r&&(e="binary"===r?new Array(16):null,r=null),r=r||{};var f=r.random||(r.rng||o)();if(f[6]=15&f[6]|64,f[8]=63&f[8]|128,e)for(var u=0;u<16;++u)e[t+u]=f[u];return e||i(f)}var o=r("./lib/rng"),i=r("./lib/bytesToUuid");e.exports=t},{"./lib/bytesToUuid":1,"./lib/rng":2}]},{},[3])(3)});
758
759// JavaScript MD5
760// MIT license
761!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],
7616,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);
762
763/*
764 * videoPlayer
765 */
766(function(api, $, window, document){
767	"use strict";
768
769	var defaults = {
770			enabled:		true,					/* if render videoPlayer */
771			debug:			false,					/* 1: debug in console.log 2: debug on screen */
772			selector:		".videoPlayer",			/* default selector to render video */
773			volume:			5,						/* default volume value in 0-10 range */
774			storage: {
775				enabled:	true,					/* if store values in localStorage */
776				key:		"videoPlayer_"			/* localStorage key suffix */
777			},
778			proportion:		"16:9",					/* default 16:9 - accept String format like example: "4:3" */
779			html:			"",						/* contains all html markup - setting later */
780			ads:			null,					/* url to json file with ads */
781			vast:			null,					/* url to vast file with ads */
782			duration:		null,					/* fallback video duration for vast */
783			gemius: {
784				debug:		true,					/* if debug gemius in console.log */
785				stream:		false,					/* object for gemius stream */
786				prism:		false,					/* object for gemius prism */
787				player:		false,					/* object for gemius player */
788			},
789			recommended:	[],						/* array of recommended videos */
790			recommendedCountdown: 10,				/* seconds to next video */
791			positionMemory: false,					/* position memory (true/false) */
792			positionMemoryLimit: 10,				/* position memory array limit */
793			diagnose:		null,					/* function to call when Diagnose button click */
794			diagnoseButton: "Wyślij raport techniczny...",
795			errorMsg:		"Przepraszamy, wystąpił problem z&nbsp;materiałem&nbsp;wideo.",
796			errorMsgTimeout: "Materiał nie&nbsp;mógł załadować&nbsp;się w&nbsp;określonym&nbsp;czasie. Sprawdź&nbsp;swoje&nbsp;połączenie&nbsp;internetowe.",
797			onInit:			null,					/* callback on init > function(videoPlayer, API){ videoPlayer - instance of object, API - functions to call } */
798			onEnded:		null,					/* callback on ended > function(videoPlayer){ videoPlayer - instance of object } */
799			onPlay:			null,					/* callback on play > function(videoPlayer){ videoPlayer - instance of object } */
800			onPause:		null,					/* callback on pause > function(videoPlayer){ videoPlayer - instance of object } */
801			onError:		function(video){		/* callback on error > function(videoPlayer){ videoPlayer - instance of object } */
802								var txt = video.mask.find('._'),
803									msg = txt[0].innerHTML,
804									geoISO = ["PL"],
805									msgGeo = "Przepraszamy, wideo nie jest dostępne na&nbsp;terenie&nbsp;Twojego&nbsp;kraju.",
806									errorGeo = null,
807									ip = null,
808									log = function(){
809										if(!canPlayAny || errorGeo) {
810											var button;
811											if((button = video.mask.find('.' + config.classes.button.diagnose)).length) {
812												button.remove();
813												video.skipDiagnose = true;
814											}
815										}
816										txt.html(msg);
817										video.errorGeo = errorGeo;
818										video.errorIp = ip;
819									};
820
821								var srcs = video.videoEl.container.find(video.videoEl.media).find('source'),
822									canPlayAny = false,
823									msgCanPlay = "Twoja przeglądarka nie obsługuje odtwarzacza&
823nbsp;materiałów&nbsp;wideo.";
824								for(var i = 0, source; source = srcs[i++]; ) {
825									var src = source.getAttribute('src'),
826										type = source.getAttribute('type') || 'video/' + src.split('.').pop(),
827										canPlay = video.videoEl.media.canPlayType(type);
828
829									if(canPlay.replace(/no/, '') != "") {
830										canPlayAny = true;
831									}
832								}
833
834								if(!canPlayAny) {
835									msg = msgCanPlay;
836									return log();
837								}
838
839								txt[0].innerHTML = '';
840
841								DOM.xhr({
842									url: video.videoEl.media.currentSrc,
843									method: 'HEAD',
844									oncomplete: function(xhr) {
845										if(xhr.status == 403) {
846											msg = msgGeo;
847											errorGeo = true;
848										}
849
850										log();
851									}
852								});
853
854							}
855		},
856		config = {
857			classes: {
858				container: 		"videoPlayer",
859				videoEl: {
860					container:	"videoPlayer__video",
861					media:		"videoPlayer__video--media",
862					ads:		"videoPlayer__video--ads"
863				},
864				mask:			"videoPlayer__mask",
865				adblock: {
866					container: 		"videoPlayer__adblock",
867					subclasses: {
868						"polsatsport.pl": "videoPlayer__adblock--lightblue",
869						"polsatnews.pl": "videoPlayer__adblock--orange",
870						"geekweek.pl": "videoPlayer__adblock--geekweek",
871						"poszkole.pl": "videoPlayer__adblock--poszkole",
872						default: "videoPlayer__adblock--lightblue",
873					},
874					container_640px:"videoPlayer__adblock--640px",
875					container_480px:"videoPlayer__adblock--480px",
876					container_mob_320px:"videoPlayer__adblock--mob-320px",
877					container_mob:	"videoPlayer__adblock--mob",
878					inner: 		"videoPlayer__adblock-inner",
879					inner2:		"videoPlayer__adblock-inner2",
880					header:		"videoPlayer__adblock-header",
881					info:		"videoPlayer__adblock-info",
882					color:		"videoPlayer__adblock-info-color",
883					button:		"videoPlayer__adblock-button",
884					arrow:		"videoPlayer__adblock-arrow",
885					info2:		"videoPlayer__adblock-info--info2",
886				},
887				adsUrl:			"videoPlayer__adsUrl",
888				controls: 		"videoPlayer__controls",
889				state: {
890					firstPlay:	"firstPlay",
891					playing:	"playing",
892					stopped:	"stopped",
893					ended:		"ended",
894					muted:		"muted",
895					fullscreen:	"fullscreen",
896					loading:	"loading",
897					loadingMetadata: "loading--metadata",
898					buffered:	"buffered",
899					hideControls: "hideControls",
900					vast:		"is--vast"
901				},
902				button: {
903					container:	"videoPlayer__buttons",
904					all:		"videoPlayer__button",
905					play:		"videoPlayer__button--play",
906					pause:		"videoPlayer__button--pause",
907					mute:		"videoPlayer__button--mute",
908					unmute:		"videoPlayer__button--unmute",
909					iconPlay:	"videoPlayer__button--iconPlay",
910					iconVolume:	"videoPlayer__button--iconVolume",
911					iconSettings: "videoPlayer__button--iconSettings",
912					enterFullscreen: "videoPlayer__button--enterFullscreen",
913					exitFullscreen: "videoPlayer__button--exitFullscreen",
914					iconFullscreen: "videoPlayer__button--iconFullscreen",
915					restore:	"videoPlayer__button--restore",
916					diagnose:	"videoPlayer__button--diagnose",
917				},
918				label: {
919					all:		"videoPlayer__label",
920					span:		"videoPlayer__label--span",
921					duration:	"videoPlayer__label--duration",
922					total:		"videoPlayer__label--total"
923				},
924				progress: {
925					container:	"videoPlayer__progress",
926					wrap:		"videoPlayer__progressWrap",
927					all:		"videoPlayer__progress--all",
928					seek:		"videoPlayer__progress--seek",
929					buffer:		"videoPlayer__progress--buffer",
930					bufferBg:	"videoPlayer__progress--bufferBg",
931					played:		"videoPlayer__progress--played",
932					volume:		"videoPlayer__progress--volume",
933					ads:		"videoPlayer__progress--ads"
934				},
935				more: {
936					container:	"videoPlayer__more",
937					volume: {
938						container:	"videoPlayer__volume",
939						wrap:		"videoPlayer__volumeWrap",
940						seek:		"videoPlayer__volume--seek"
941					},
942					settings: {
943						container:	"videoPlayer__settings",
944						items:		"videoPlayer__settings-items",
945						item:		"videoPlayer__settings-item",
946					},
947					fullscreen: {
948						container:	"videoPlayer__fullscreen"
949					}
950				},
951				recommended: {
952					container:	"videoPlayer__recommended",
953					list:		"videoPlayer__recommended-list",
954					item:		"videoPlayer__recommended-item",
955					title:		"videoPlayer__recommended-title",
956					img:		"videoPlayer__recommended-img",
957					progress:	"videoPlayer__recommended-progress",
958					svg:		"videoPlayer__recommended-svg",
959					counter:	"videoPlayer__recommended-counter",
960					seconds:	"videoPlayer__recommended-seconds",
961					cancel:		"videoPlayer__recommended-cancel"
962				},
963				placeholder:	"videoPlayer__placeholder",
964				vast: {
965					container:	"videoPlayer__vast"
966				}
967			}
968		};
969
970	defaults.html = (function(){
971		return [
972			'<div class="' + config.classes.mask + '"><span class="_"></span></div>',
973			'{recommended}',
974			'<div class="' + config.classes.controls + '">',
975				'<div class="' + config.classes.button.container + '">',
976					'<button class="' + config.classes.button.all + ' ' + config.classes.button.play + '"><span class="sr-only">Odtwórz</span></button>',
977					'<button class="' + config.classes.button.all + ' ' + config.classes.button.pause + '"><span class="sr-only">Wstrzymaj</span></button>',
978					'<div class="' + config.classes.button.all + ' ' + config.classes.button.iconPlay + '"><span class="_ _1"></span><span class="_ _2"></span><span class="_ _3"></span></div>',
979				'</div>',
980				'<div class="' + config.classes.progress.container + '">',
981					'<div class="' + config.classes.label.all + ' ' + config.classes.label.duration + '"><span class="sr-only">Aktualny czas</span><span class="' + config.classes.label.span + '">00:00</span></div>',
982					'<div class="' + config.classes.progress.wrap + '">',
983						'<label for="seek{id}" class="sr-only">Przewiń</label>',
984						'<input id="seek{id}" class="' + config.classes.progress.all + ' ' + config.classes.progress.seek + '" type="range" min="0" max="100" step="0.5" value="
9840">',
985						'<progress class="' + config.classes.progress.all + ' ' + config.classes.progress.played + '" max="100" value="0">',
986							'<div class="sr-only"><span>0</span>% odtworzone</div>',
987						'</progress>',
988						'<div class="' + config.classes.progress.all + ' ' + config.classes.progress.ads + '"></div>',
989						'<progress class="' + config.classes.progress.all + ' ' + config.classes.progress.buffer + '" max="100" value="0">',
990							'<div class="sr-only"><span>0</span>% załadowane</div>',
991						'</progress>',
992						'<div class="' + config.classes.progress.all + ' ' + config.classes.progress.bufferBg + '"></div>',
993					'</div>',
994					'<div class="' + config.classes.label.all + ' ' + config.classes.label.total + '"><span class="sr-only">Długość materiału</span><span class="' + config.classes.label.span + '">00:00</span></div>',
995				'</div>',
996				'<div class="' + config.classes.more.container + '">',
997					'<div class="' + config.classes.more.volume.container + '">',
998						'<input class="sr-only" id="mute{id}" type="checkbox">',
999						'<label for="mute{id}" class="' + config.classes.button.all + ' ' + config.classes.button.mute + '">',
1000							'<span class="sr-only">Wycisz</span>',
1001						'</label>',
1002						'<label for="mute{id}" class="' + config.classes.button.all + ' ' + config.classes.button.unmute + '">',
1003							'<span class="sr-only">Przywróć głośność</span>',
1004						'</label>',
1005						'<div class="' + config.classes.button.all + ' ' + config.classes.button.iconVolume + '"><span class="_ _1"></span><span class="_ _2"></span></div>',
1006						'<div class="' + config.classes.more.volume.wrap + '">',
1007							'<label for="volume{id}" class="sr-only">Głośność</label>',
1008							'<input id="volume{id}" class="' + config.classes.progress.all + ' ' + config.classes.more.volume.seek + '" type="range" min="0" max="10" step="0.5" value="' + defaults.volume + '">',
1009							'<progress class="' + config.classes.progress.all + ' ' + config.classes.progress.volume + '" max="100" value="0">',
1010								'<div class="sr-only"><span>0</span>% głośności</div>',
1011							'</progress>',
1012						'</div>',
1013					'</div>',
1014					'{settings}',
1015					'<div class="' + config.classes.more.fullscreen.container + '">',
1016						'<button class="' + config.classes.button.all + ' ' + config.classes.button.exitFullscreen + '"><span class="sr-only">Opuść tryb pełnoekranowy</span></button>',
1017						'<button class="' + config.classes.button.all + ' ' + config.classes.button.enterFullscreen + '"><span class="sr-only">Tryb pełnoekranowy</span></button>',
1018						'<div class="' + config.classes.button.all + ' ' + config.classes.button.iconFullscreen + '"></div>',
1019					'</div>',
1020				'</div>',
1021				'<a class="' + config.classes.adsUrl + '" target="_blank"></a>',
1022			'</div>'
1023		].join("\n");
1024	})();
1025
1026	/*
1027	 * Animate
1028	 */
1029	function Animate(options) {
1030		var self = this,
1031			defaults = {
1032				duration: 500,
1033				from: 0,
1034				to: 1,
1035				easing: Animate.easing.linear,
1036				onPlay: null,
1037				onPause: null,
1038				onUpdate: null,
1039				onStop: null
1040			};
1041
1042		self.config = $.extend(defaults, options);
1043		self._pause = null;
1044
1045		self.play = function() {
1046			self._start = Date.now() - self._pause;
1047			_call('onPlay', self._step);
1048			_update();
1049		}
1050
1051		self.pause = function() {
1052			cancelAnimationFrame(self._raf);
1053			self._pause = Date.now() - self._start;
1054			_call('onPause', self._step);
1055		}
1056
1057		self.stop = function() {
1058			cancelAnimationFrame(self._raf);
1059			_call('onStop');
1060			self._start = self._step = self._current = self._pause = null;
1061		}
1062
1063		function _update() {
1064			self._current = Date.now() - self._start;
1065			if(self._current < self.config.duration){
1066				self._raf = requestAnimationFrame(_update);
1067				self._step = self.config.easing(self._current, self.config.from, -self.config.from + self.config.to, self.config.duration);
1068			}
1069			else{
1070				self._step = self.config.to;
1071				requestAnimationFrame(self.stop);
1072			}
1073
1074			_call('onUpdate', self._step);
1075		}
1076
1077		function _call(fn, step) {
1078			if(typeof self.config[fn] === "function")
1079				self.config[fn].call(null, self, step);
1080		}
1081
1082		return self;
1083	}
1084
1085	Animate.easing = {
1086		linear: function(t, b, c, d) {
1087			return c * t / d + b;
1088		},
1089		easeOutCubic: function(t, b, c, d) {
1090			return c * (Math.pow(t / d - 1, 3) + 1) + b;
1091		},
1092		easeInOutCubic: function(t, b, c, d) {
1093			if ((t /= d / 2) < 1) {
1094				return c / 2 * Math.pow(t, 3) + b;
1095			}
1096			return c / 2 * (Math.pow(t - 2, 3) + 2) + b;
1097		}
1098	}
1099
1100	Animate.calculate = function(from, to, step) {
1101		return from + (to - from) * step;
1102	}
1103
1104	var ua = navigator.userAgent.toLowerCase();
1105	var an = navigator.appName.toLowerCase();
1106	var isIEMobile = ua.indexOf("iemobile") > -1;
1107	var isAndroid = ua.indexOf("android") > -1 && !isIEMobile;
1108	var isOldAndroid = (isAndroid && parseFloat(ua.slice(ua.indexOf("android") + 8)) < 3);
1109	var isiPad = ua.indexOf("ipad") > -1;
1110	var isiPhone = ua.indexOf("iphone") > -1 && !isIEMobile;
1111	var iOS = isiPad || isiPhone;
1112	var iOSVersion = parseFloat((ua.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || ['0'])[0].replace(/_/g, '.'));
1113	var isIE = ((an == "microsoft internet explorer") || ((an == "netscape") && (new RegExp("trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(ua) != null)));
1114	var isOpera = !!window.opera;
1115
1116	function hash(str) {
1117		var hash = 0, i, chr, l = str.length;
1118		if(l === 0) return hash;
1119		for(i = 0; i < l; i++) {
1120			chr   = str.charCodeAt(i);
1121			hash  = ((hash << 5) - hash) + chr;
1122			hash |= 0; // Convert to 32bit integer
1123		}
1124		return hash;
1125	}
1126
1127	function _hit(url){
1128		if(!url) return;
1129		new Image().src = url + '#' + Date.now();
1130	}
1131
1132	function _getPercentage(current, max){
1133		if(current === 0 || max === 0 || isNaN(current) || isNaN(max)){
1134			return 0;
1135		}
1136		return ((current / max) * 100).toFixed(2);
1137	}
1138
1139	function _isFullscreen(){
1140		return (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
1141	}
1142	function _requestFullscreen(element){
1143		
1144		if(element.requestFullscreen){
1145			element.requestFullscreen();
1146		}
1147		else if(element.msRequestFullscreen){
1148			element.msRequestFullscreen();
1149		}
1150		else if(element.mozRequestFullScreen){
1151			element.mozRequestFullScreen();
1152		}
1153		else if(element.webkitRequestFullscreen){
1154			element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
1155		}
1156
1157	}
1158	function _cancelFullscreen(){
1159
1160		if(document.exitFullscreen){
1161			document.exitFullscreen();
1162		}
1163		else if(document.msExitFullscreen){
1164			document.msExitFullscreen();
1165		}
1166		else if(document.mozCancelFullScreen){
1167			document.mozCancelFullScreen();
1168		}
1169		else if(document.webkitExitFullscreen){
1170			document.webkitExitFullscreen();
1171		}
1172
1173	}
1174
1175	function _canPlay(type){
1176		var v = document.createElement('video');
1177		return v.canPlayType('video/' + type).replace(/no/, '') != "" ? true : false;
1178	}
1179
1180	function VideoPlayer(container){
1181		
1182		var video = this;
1183		var cfg = $.extend({}, config);
1184
1185		video.container = container;
1186
1187		video.logs = [];
1188		var debugEl = false;
1189		function _log(text, state){
1190			if(cfg.debug){
1191				
1192				if(cfg.debug == 2){
1193					if(!debugEl){
1194						$(video.container).append('<div class="videoPlayer__debug"><div class="videoPlayer__debug--wrap"><div class="videoPlayer__debug--cont"></div></div></div>');
1195						debugEl = $(video.container).find('.videoPlayer__debug--cont');
1196					}
1197
1198					var log = _logStringify(text);
1199
1200					debugEl.append('<p class="log' + (state ? (' log--' + state) : '') + '">' + log.join(', ') + '</p>');
1201					debugEl.parent()[0].scrollTop = 1000000000;
1202				}
1203				else console[(state ? state : "log")](text);
1204
1205			}
1206
1207			var log = {};
1208			log[state || "log"] = _logStringify(text);
1209			video.logs.push(log);
1210		}
1211		function _logStringify(text) {
1212			var log = [text];
1213			if(typeof text === "object"){
1214				log = [];
1215				for(var i in text) {
1216					if(
1217						typeof text[i] !== "object"
1218					) {
1219						log.push(text[i]);
1220					}
1221				}
1222			}
1223			return log;
1224		}
1225
1226		function _prismDur(dur){
1227			var i = (dur / 60);
1228			if(i < 5){ return '0-5'; }
1229			else if(i < 10){ return '5-10'; }
1230			else if(i < 15){ return '10-15'; }
1231			else{ return '15'; }
1232		}
1233
1234		var cfgStats = cfg.stats || cfg.gemius;
1235
1236		var _stats = {
1237			stream: function(action, time){
1238
1239				if(window["gemiusStream"] && typeof cfgStats.stream == "object" && !video.isError){
1240
1241					if(!cfgStats.stream.id || !cfgStats.stream.materialId){
1242						_log("ERROR: Bad stream configuration (missing id or materialId)", 'error');
1243						return;
1244					}
1245
1246					if(action == 'newStream'){
1247						video.isNewStream = true;
1248
1249						cfgStats.stream.materialId = cfgStats.stream.materialId.replace(new RegExp(/[|*\n\t\r;=\/#]/g), " ");
1250
1251						_log("Stream: " + action, 'info');
1252
1253						window["gemiusStream"].newStream(video.uniq, cfgStats.stream.materialId, Math.ceil(video.videoEl.media.duration), cfgStats.stream.customPackage || [], cfgStats.stream.additionalPackage || [], cfgStats.stream.id, cfgStats.stream.hit, cfgStats.stream.treeId);
1254
1255						if(video.streamEventBuffer && video.streamEventBuffer.length){
1256							for(var i = 0, l = video.streamEventBuffer.length; i < l; i++){
1257								_stats.stream(video.streamEventBuffer[i][0], video.streamEventBuffer[i][1]);
1258							}
1259							video.streamEventBuffer = [];
1260						}
1261					}
1262					else if(!video.isNewStream){
1263						if(!video.streamEventBuffer) video.streamEventBuffer = [];
1264						video.streamEventBuffer.push([action, video.videoEl.media.currentTime]);
1265
1266						_log("Stream: " + action + " --buffered");
1267					}
1268					else{
1269						_log("Stream: " + action, 'info');
1270
1271						window["gemiusStream"].event(video.uniq, cfgStats.stream.materialId, Math.ceil(time || video.videoEl.media.currentTime), action);
1272					}
1273
1274				}
1275
1276			},
1277			prism: function(action, totalAd, currentAd){
1278
1279				if(window["gemius_event"] && typeof cfgStats.prism == "object" && !video.isError){
1280
1281					if(!cfgStats.prism.id || !cfgStats.prism.title){
1282						_log("ERROR: Bad prism configuration (missing id or title)", 'error');
1283						return;
1284					}
1285					if(action.indexOf("AdBlock") !== -1 ){
1286						(function(cb){
1287							if(isNaN(video.videoEl.media.duration)){
1288								video.videoEl.media.addEventListener('durationchange', cb)
1289							}else {
1290								cb();
1291							}
1292						})(function(){
1293							cfgStats.prism.duration = _prismDur(video.videoEl.media.duration);
1294							var ladb = video.supported.storage
1295								? (window.localStorage.getItem(cfg.storage.key+'ladb')==1)
1296									? 'Tak'
1297									: (window.localStorage.getItem(cfg.storage.key+'ladb')==0)
1298										? 'Nie'
1299										: ''
1300								: '';
1301							window["gemius_event"]('_action_', cfgStats.prism.id, 'g=' + action, 'GoalName=Odtwarzanie/' + action, 'm=' + cfgStats.prism.title, 'l=' + cfgStats.prism.duration, 'ladb='+ladb, 'adf=true');
1302							video.supported.storage && window.localStorage.setItem(cfg.storage.key+'ladb', action.indexOf('Tak')!==-1?1:0);
1303						});
1304						_log("Prism: " + action);
1305					}
1306					else if(action == 'Nowy_Materiał'){
1307						video.isNowyMaterial = true;
1308
1309						cfgStats.prism.title = cfgStats.prism.title.replace(new RegExp(/[ =&\+]/g), "_");
1310						cfgStats.prism.duration = _prismDur(video.videoEl.media.duration);
1311
1312						_log("Prism: " + action, 'info');
1313	
1314						window["gemius_event"]('_action_', cfgStats.prism.id, 'g=' + action, 'GoalName=Odtwarzanie/' + action, 'm=' + cfgStats.prism.title, 'l=' + cfgStats.prism.duration);
1315
1316						if(video.prismEventBuffer && video.prismEventBuffer.length){
1317							for(var i = 0, l = video.prismEventBuffer.length; i < l; i++){
1318								_stats.prism(video.prismEventBuffer[i][0], video.prismEventBuffer[i][1], video.prismEventBuffer[i][2]);
1319							}
1320							video.prismEventBuffer = [];
1321						}
1322					}
1323					else if(!video.isNowyMaterial){
1324						if(!video.prismEventBuffer) video.prismEventBuffer = [];
1325						video.prismEventBuffer.push([action, video.totalAdInBlock, video.currentAdInBlock]);
1326
1327						_log("Prism: " + action + " --buffered");
1328					}
1329					else{
1330
1331						_log("Prism: " + action + (video.isAds || totalAd ? (" :: ad [" + (currentAd || video.currentAdInBlock) + "/" + (totalAd || video.totalAdInBlock) + "]") : ""), 'info');
1332						
1333						if(!video.isAds && !totalAd) window["gemius_event"]('_action_', cfgStats.prism.id, 'g=' + action, 'GoalName=Odtwarzanie/' + action, 'm=' + cfgStats.prism.title, 'l=' + cfgStats.prism.duration);
1334						else window["gemius_event"]('_action_', cfgStats.prism.id, 'g=' + action, 'GoalName=Odtwarzanie/' + action, 'm=' + cfgStats.prism.title, 'l=' + cfgStats.prism.duration, 'an=' + (totalAd || video.totalAdInBlock), 'ap=' + (currentAd || video.currentAdInBlock));
1335
1336					}
1337
1338				}
1339			},
1340			player: function(action, ad, offset){
1341
1342				if(window["GemiusPlayer"] && typeof cfgStats.player == "object" && !video.isError){
1343
1344					if(!cfgStats.player.accountID || !cfgStats.player.programID){
1345						_log("ERROR: Bad gplayer configuration (missing accountID or programID)", 'error');
1346						return;
1347					}
1348
1349					if(action == 'newProgram'){
1350						video.GPlayerInstance = new GemiusPlayer(video.uniq, cfgStats.player.accountID, {});
1351						video.GPlayerInstance.setVideoObject(video.videoEl.media);
1352						cfgStats.player.additionalParameters.programDuration = video.videoEl.media.duration;
1353						cfgStats.player.additionalParameters.programName = cfgStats.player.additionalParameters.programName.replace(new RegExp(/[\n\t\r{}[\]()"'~`!@#$%^&*?;,:\/|=]/g), "").substr(0, 200);
1354						video.GPlayerInstance.newProgram(cfgStats.player.programID, cfgStats.player.additionalParameters);
1355
1356						_log("GPlayer: " + action, 'info');
1357	
1358						if(video.gPlayerEventBuffer && video.gPlayerEventBuffer.length){
1359							for(var i = 0, l = video.gPlayerEventBuffer.length; i < l; i++){
1360								_stats.player(video.gPlayerEventBuffer[i][0], video.gPlayerEventBuffer[i][1], video.gPlayerEventBuffer[i][2]);
1361							}
1362							video.gPlayerEventBuffer = [];
1363						}
1364					}
1365					else if(!video.GPlayerInstance){
1366						if(!video.gPlayerEventBuffer) video.gPlayerEventBuffer = [];
1367						video.gPlayerEventBuffer.push([action, video.isAds && {id: video.adsID, duration: video.videoEl.ads.duration}, video.videoEl.media.currentTime]);
1368
1369						_log("GPlayer: " + action + " --buffered");
1370					}
1371					else{
1372						
1373						var logEvent = "";
1374
1375						if(action == "newAd"){
1376							video.GPlayerInstance.newAd(ad && ad.id || video.adsID, {
1377								adDuration: ad && ad.duration || video.videoEl.ads.duration,
1378								BRN: cfgStats.player.additionalParameters.BRN || ''
1379							});
1380						}
1381						else if(ad || video.isAds){
1382							logEvent = "adEvent.";
1383							video.GPlayerInstance.adEvent(cfgStats.player.programID, ad && ad.id || video.adsID, offset || video.videoEl.media.currentTime, action);
1384						}
1385						else{
1386							logEvent = "programEvent.";
1387							var additional = {};
1388							if(action == "play"){
1389								additional = {
1390									autoPlay: !video.gpPlay && video.init.autoplay,
1391									partID: 1
1392								};
1393								video.gpPlay = true;
1394							}
1395							video.GPlayerInstance.programEvent(cfgStats.player.programID, offset || video.videoEl.media.currentTime, action, additional);
1396						}
1397
1398						_log("GPlayer: " + logEvent + action, 'info');
1399
1400					}
1401
1402				}
1403
1404			},
1405			redevents: function(action) {
1406
1407				if(typeof cfgStats.redevents == "object") {
1408
1409					var actions = this.redevents.actions || (this.redevents.actions = {
1410						'try': 't', // first play
1411						'begin preRoll': 'bp', 
1412						'begin': 'b',
1413						'cycle': 'c', // interval event
1414						'change quality': 'cq', // `qt` parameter
1415						'begin midRoll': 'bm', 
1416						'end midRoll': 'em',
1417						'seek': 'sk',
1418						'pause': 'p',
1419						'stop': 's',
1420						'end': 'e',
1421						'begin postRoll': 'br',
1422						'end postRoll': 'er',
1423						'error_adv': 'ea',
1424						'error_vod': 'ev'
1425					});
1426
1427					var time = _getRedEventsTime(),
1428							sc = Math.floor(((video.videoEl.media.currentTime || 0) / (video.redeventsVl || video.videoEl.media.duration || cfg.duration || 0)) * 100),
1429							uid, pl, cid, ct, vl;
1430
1431					var defaults = this.redevents.defaults || (
1432						uid = uuidv4(),
1433						pl = 'WWW',
1434						cid = cfgStats.redevents.hash,
1435						ct = 1 + '',
1436						video.redeventsVl = vl = Math.round(video.videoEl.media.duration || cfg.duration),
1437						this.redevents.defaults = {
1438							pr: cfgStats.redevents.portal,
1439							uid: uid,
1440							ct: ct,
1441							cid: cid,
1442							sh: 0,
1443							dc: 'PC',
1444							pl: pl,
1445							cl: api.version + '',
1446							ss: 2,
1447							ua: 'www_' + cfgStats.redevents.portal + '_html5',
1448							sid: md5(uid + pl + time + cid + ct),
1449							vl: vl
1450						}
1451					);
1452
1453					if(!video.redeventsTry) {
1454						video.redeventsTry = true;
1455						video.redeventsDuration = new RedeventsDuration();
1456
1457						_stats.redevents('try');
1458					}
1459
1460					var params = $.extend(defaults, {
1461						et: actions[action],
1462						sc: sc,
1463						dr: video.redeventsDrStore || Math.floor(video.redeventsDuration.get() / 1000),
1464						tm: time,
1465						qt: video.quality || '480p'
1466					});
1467
1468					if(action === 'try') {
1469						params.sc = params.dr = video.redeventsDrStore = null;
1470					} else if(action === 'begin') {
1471						video.redeventsDuration.play();
1472
1473						$(window).on('beforeunload.redevents', function(){
1474							_stats.redevents('stop');
1475						});
1476						$(video.videoEl.media).on('play.rd playing.rd pause.rd waiting.rd', function(e) {
1477							var playing = (e.type.indexOf('play') === 0);
1478							video.redeventsDuration[playing ? 'play' : 'pause']();
1479						});
1480					} else if(action === 'end') {
1481						video.redeventsDrStore = params.dr;
1482						video.redeventsDuration.reset();
1483						$(window).off('beforeunload.redevents');
1484						$(video.videoEl.media).off('play.rd playing.rd pause.rd waiting.rd');
1485					}
1486
1487					$.xhr({
1488						url: cfgStats.redevents.hit,
1489						method: 'POST',
1490						async: action !== 'stop',
1491						data: 'json=' + encodeURIComponent(JSON.stringify(params))
1492					});
1493
1494					_log("RedEvents: " + action, 'info');
1495
1496				}
1497			}
1498		}
1499
1500		function RedeventsDuration() {
1501			this.duration = 0;
1502			this.cycleTime = 0;
1503			this.play = function() {
1504				if(!this.going) {
1505					this.going = true;
1506					this.last = Date.now();
1507
1508					this.cycle();
1509				}
1510			};
1511			this.pause = function() {
1512				if(this.going) {
1513					this.going = false;
1514					this.duration = this.get();
1515					this.cycleTime = (this.lastCycle ? Date.now() - this.lastCycle : 0);
1516					this.last = null;
1517
1518					clearTimeout(video.redeventsInterval);
1519				}
1520			};
1521			this.reset = function() {
1522				clearTimeout(video.redeventsInterval);
1523				this.duration = 0;
1524				this.going = this.last = null;
1525			};
1526			this.get = function() {
1527				return this.duration + (this.last ? Date.now() - this.last : 0);
1528			};
1529			this.cycle = function() {
1530				var self = this;
1531				this.lastCycle = Date.now();
1532				clearTimeout(video.redeventsInterval);
1533				video.redeventsInterval = setTimeout(function() {
1534					_stats.redevents('cycle');
1535
1536					self.cycleTime = 0;
1537					self.cycle();
1538				}, cfgStats.redevents.interval * 1000 - this.cycleTime);
1539			};
1540
1541			return this;
1542		}
1543
1544		function _padLeft(x, n) {
1545			x = x.toString();
1546			n = typeof n !== 'undefined' ? n : 2;
1547			while(x.length < n) {
1548				x = '0' + x;
1549			}
1550			return x;
1551		}
1552		function _getRedEventsTime() {
1553			var date = new Date(),
1554					time = '';
1555
1556			time += date.getFullYear() + '-';
1557			time += _padLeft(date.getMonth() + 1) + '-';
1558			time += _padLeft(date.getDate()) + ' ';
1559			time += _padLeft(date.getHours()) + ':';
1560			time += _padLeft(date.getMinutes()) + ':';
1561			time += _padLeft(date.getSeconds()) + '.';
1562			time += _padLeft(date.getMilliseconds(), 3) + '000';
1563			time += date.getTimezoneOffset() < 0
1564							? '+' + _padLeft(Math.round(date.getTimezoneOffset() / -60))
1565							: '-' + _padLeft(Math.round(date.getTimezoneOffset() / 60))
1566
1567			return time;
1568		}
1569
1570		/* return Object from video.container context */
1571		function _getElements(selector){
1572			return $(video.container).find(selector);
1573		}
1574
1575		function _instance(){
1576			return video;
1577		}
1578
1579		var firstClick = false,
1580			preventLogOnAndroid = false;
1581
1582		function _play(){
1583
1584			if(!video.loadedmetadata) return;
1585
1586			for(var i = 0, vp; vp = videoPlayer.els[i++]; ) {
1587				var instance;
1588				if(!vp.isPaused() && video !== (instance = vp.instance())) {
1589					var w = $(window), scroll = w.off('scroll.pauseactive').one('scroll.pauseactive', function(){
1590						if(Date.now() - time < 1000) w.scrollTop(scroll);
1591					}).scrollTop(), time = Date.now();
1592
1593					vp.pause();
1594
1595					if(window.videoPlayer.persistent && window.videoPlayer.persistent.active === instance) {
1596						window.videoPlayer.persistent.active.container.removeClass('is--persistent');
1597						window.videoPlayer.persistent.active = null;
1598					}
1599
1600					break;
1601				}
1602			}
1603
1604			/* on Android cannot play without user interaction */
1605			if(!firstClick && isAndroid) {
1606				if((video.ads && video.ads["0"]) || (video.vast && video.vast.cuePoints.indexOf(0) > -1)) {
1607					firstClick = true;
1608					preventLogOnAndroid = true;
1609					video.videoEl.media.play();
1610					video.videoEl.media.pause();
1611					
1612					/* skip to next frame */
1613					setTimeout(function(){
1614						preventLogOnAndroid = false;
1615					});
1616				}
1617			}
1618
1619			if(video.vastActive) {
1620				video.vast.resume();
1621				return;
1622			}
1623
1624			video.media.play();
1625			
1626			if(!video.isAds && !video.isEnded){
1627				_stats.prism("Start");
1628			}
1629
1630			if(!video.isPreAdsFirstPlay){
1631				_stats.player("play");
1632			}
1633
1634			if(typeof cfg.onPlay == "function"){
1635				cfg.onPlay(video);
1636			}
1637
1638			setTimeout(function(){ video.buttons.pause.focus(); }, 100);
1639			_log(["Play", true]);
1640		}
1641
1642		function _pause(){
1643			if(video.vastActive) {
1644				video.vast.pause();
1645				return;
1646			}
1647
1648			video.media.pause();
1649
1650			if(!video.isAds){
1651				_stats.prism("Pauza");
1652				_stats.redevents("pause");
1653			}
1654
1655			_stats.player("pause");
1656
1657			if(typeof cfg.onPause == "function"){
1658				cfg.onPause(video);
1659			}
1660
1661			setTimeout(function(){ video.buttons.play.focus(); }, 100);
1662			_log(["Play", false]);
1663		}
1664
1665		function _toggle(){
1666			if(video.isAds){
1667				return _onClickAds();
1668			}
1669			video.media.paused ? _play() : _pause();
1670		}
1671
1672		function _hideControls(){
1673
1674			function hideControlsFn(event){
1675				
1676				$(video.container).removeClass(cfg.classes.state.hideControls);
1677				clearTimeout(video.timerFullscreen);
1678				video.timerFullscreen = setTimeout(function(){
1679
1680					$(video.container).addClass(cfg.classes.state.hideControls);
1681
1682					_log(["Fullscreen :: _hideControls", true]);
1683
1684				}, 4000);
1685
1686			}
1687
1688			$(video.container).on('mousemove.' + cfg.classes.state.hideControls, hideControlsFn);
1689			$(video.container).on('touchstart.' + cfg.classes.state.hideControls, hideControlsFn);
1690
1691			hideControlsFn();
1692
1693		}
1694		function _showControls(){
1695			
1696			clearTimeout(video.timerFullscreen);
1697			$(video.container).off('mousemove.' + cfg.classes.state.hideControls);
1698			$(video.container).off('touchstart.' + cfg.classes.state.hideControls);
1699			$(video.container).removeClass(cfg.classes.state.hideControls);
1700			
1701			_log(["Fullscreen :: _showControls", true]);
1702
1703		}
1704
1705		function _enterFullscreen(){
1706			_requestFullscreen(video.container[0]);
1707			setTimeout(function(){ video.buttons[!video.media.paused ? "pause" : "play"].focus(); }, 100);
1708
1709			_hideControls();
1710
1711			_log(["Fullscreen", true]);
1712		}
1713
1714		function _exitFullscreen(){
1715			_cancelFullscreen();
1716			setTimeout(function(){ video.buttons[!video.media.paused ? "pause" : "play"].focus(); }, 100);
1717
1718			_showControls();
1719
1720			_log(["Fullscreen", false]);
1721		}
1722
1723		function _toggleFullscreen(){
1724			_isFullscreen() === video.container[0] ? _exitFullscreen() : _enterFullscreen();
1725		}
1726
1727		function _seek(input){
1728
1729			if(video.isAds == true){
1730				_log(["Seek", false, "ads"]);
1731				return false;
1732			}
1733
1734			var targetTime = 0;
1735
1736			if(typeof input === "string" && input.slice(-1) == "%"){
1737				targetTime = video.media.duration * parseFloat(input) / 100;
1738			}
1739			else if(typeof input === "number"){
1740				targetTime = input;
1741			}
1742			else if(typeof input === "object" && (input.type === "change" || input.type === "input")){
1743				targetTime = ((input.target.value / input.target.max) * video.media.duration);
1744			}
1745
1746			if(targetTime < 0){
1747				targetTime = 0;
1748			}
1749			else if(targetTime > video.media.duration){
1750				targetTime = video.media.duration;
1751			}
1752
1753			try{
1754				video.media.currentTime = targetTime.toFixed(1);
1755				_log(["Seek", video.media.currentTime]);
1756			}
1757			catch(e){}
1758
1759			if(video.seekingStart){
1760				_stats.stream("seekingStarted");
1761				_stats.player("seek");
1762				_stats.prism("Przewijanie");
1763			}
1764
1765			if(typeof input === "object" && (input.type === "input" || input.type === "change" && isIE)){
1766				if(!video.isInput){
1767					video.isInput = true;
1768					_stats.stream("seekingStarted");
1769					_stats.player("seek");
1770					_stats.prism("Przewijanie");
1771				}
1772			}
1773			if(typeof input === "object" && input.type === "change"){
1774				video.isInput = false;
1775				if(!video.videoEl.media.paused){
1776					_stats.stream("playing");
1777					_stats.player("play");
1778					_stats.redevents("seek");
1779				}
1780			}
1781
1782		}
1783		function _progSeek(value) {
1784			_seek(value);
1785
1786			_stats.stream("seekingStarted");
1787			_stats.player("seek");
1788			_stats.prism("Przewijanie");
1789
1790			if(!video.videoEl.media.paused){
1791				_stats.stream("playing");
1792				_stats.player("play");
1793				_stats.redevents("seek");
1794			}
1795		}
1796
1797		function _setVolume(volume){
1798
1799			if(typeof volume === "undefined"){
1800				if(cfg.storage.enabled && video.supported.storage){
1801					volume = window.localStorage[cfg.storage.key + 'volume'] || cfg.volume;
1802				}
1803				else{
1804					volume = cfg.volume;
1805				}
1806			}
1807			else if(typeof volume === "string" && volume.slice(-1) == "%"){
1808				volume = 10 * parseFloat(volume) / 100;
1809			}
1810
1811			if(volume > 10){
1812				volume = 10;
1813			}
1814
1815			video.volume.seek[0].value = volume;
1816			var value = _getPercentage(volume, 10);
1817			
1818			if(video.supported.range){
1819				video.progress.volume[0].value = value;
1820			}
1821			else{
1822				video.progress.volume[0].style.width = value + "%";
1823			}
1824			video.progress.volumeSpan[0].innerHTML = value;
1825			
1826			video.media.volume = parseFloat(volume / 10);
1827
1828			_toggleMute(video.media.volume === 0);
1829
1830			if(video.vast) {
1831				video.vast.setVolumeState();
1832			}
1833
1834			if(cfg.storage.enabled && video.supported.storage){
1835				window.localStorage[cfg.storage.key + 'volume'] = volume;
1836			}
1837
1838			_log(["Volume", volume]);
1839
1840		}
1841
1842		function _toggleMute(muted){
1843		
1844			if(typeof muted === "undefined"){
1845				muted = !video.media.muted;
1846			}
1847
1848			if(video.supported.range){
1849				video.volume.checkbox[0].checked = muted;
1850			}
1851
1852			video.media.muted = muted;
1853
1854			if(video.vast) {
1855				video.vast.setVolumeState();
1856			}
1857			
1858			_checkMute();
1859
1860			_log(["Muted", muted]);
1861		
1862		}
1863
1864		function _checkPlaying(){
1865			$(video.container).toggleClass(cfg.classes.state.firstPlay, video.firstPlay);
1866			$(video.container).toggleClass(cfg.classes.state.playing, video.vast && video.isAds ? !video.vast.isPaused() : !video.media.paused);
1867			$(video.container).toggleClass(cfg.classes.state.stopped, video.vast && video.isAds ? video.vast.isPaused() : video.media.paused);
1868			$(video.container).toggleClass(cfg.classes.state.ended, video.isEnded);
1869		}
1870
1871		function _checkMute(){
1872			$(video.container).toggleClass(cfg.classes.state.muted, (video.media.volume === 0 || video.media.muted));
1873		}
1874
1875		function _checkFullscreen(){
1876			var fullscreenElement = _isFullscreen();
1877			for(var i = 0, el; el = videoPlayer.els[i++]; ){
1878				var container = el.instance().container;
1879				container.toggleClass(cfg.classes.state.fullscreen, fullscreenElement === container[0]);
1880			}
1881		}
1882
1883		function _checkLoading(event){
1884
1885			var loading = (event.type === "waiting" && !isIEMobile && video.firstPlay);
1886			
1887			_log(["Loading", loading]);
1888
1889			/* setTimeout to prevent setting class too fast */
1890			clearTimeout(video.loadingTimer);
1891			video.loadingTimer = setTimeout(function(){
1892
1893				if(!video.isInput){
1894					if(loading){
1895						_stats.stream("buffering");
1896						_stats.player("buffer");
1897					}
1898					if(video.loading == true && !loading && !video.videoEl.media.paused){
1899						_stats.stream("playing");
1900						_stats.player("play");
1901					}
1902				}
1903
1904				video.loading = loading;
1905				$(video.container).toggleClass(cfg.classes.state.loading, loading);
1906
1907			}, (loading ? 250 : 0));
1908
1909			/*
1910			 * try reload every 10 sec in half a minute
1911			 * if that fails, show error msg
1912			 */
1913			clearTimeout(video.loadingTimerReload);
1914			if(video.loadedmetadata && loading) {
1915				video.loadingTimerReload = setTimeout(function() {
1916					video.loadingTimerReloadCounter = video.loadingTimerReloadCounter || 0;
1917					if(video.loadingTimerReloadCounter < 3) {
1918						var media = video.videoEl.media,
1919							playing = !media.paused,
1920							current = media.currentTime;
1921
1922						if(playing) media.pause();
1923						$(media).off('error.buffer').on('error.buffer', _networkState);
1924						media.load();
1925						media.currentTime = current;
1926						if(playing) media.play();
1927
1928						video.loadingTimerReloadCounter++;
1929					} else if(video.videoEl.media.currentTime > 1) {
1930						_showError('timeout');
1931					}
1932				}, 20000);
1933			}
1934
1935		}
1936
1937		function _getBuffered(buffered, current){
1938			for(var i = 0, l = buffered.length; i < l; i++){
1939				if(buffered.start(i) <= current && buffered.end(i) > current) return buffered.end(i);
1940			}
1941			return buffered.end(buffered.length - 1);
1942		}
1943
1944		/* update progress, base on event from listener */
1945		function _updateProgress(event){
1946
1947			if(video.vast && video.isAds) return;
1948
1949			var progress = video.progress.played[0],
1950				text = video.progress.playedSpan[0],
1951				value = 0,
1952				ads = video.isAds || false,
1953				current = ads != true ? video.media.currentTime : video.time.ads.currentTime,
1954				duration = ads != true ? video.media.duration : video.time.ads.duration;
1955
1956			if(event){
1957				switch(event.type){
1958					case "timeupdate":
1959					case "seeking":
1960						value = _getPercentage(current, duration);
1961						if(event.type == "timeupdate"){
1962							video.progress.seek[0].value = value;
1963						}
1964
1965						if(!video.prismStart && current != 0){
1966							video.prismStart = true;
1967							_stats.prism("Start_Materiału_Głównego");
1968						}
1969						if(!video.prism90 && value >= 90){
1970							video.prism90 = true;
1971							_stats.prism("90_Procent");
1972						}
1973
1974						break;
1975
1976					case "change":
1977					case "input":
1978						value = event.target.value;
1979						break;
1980
1981					case "playing":
1982						if(!video.redeventsBegin) {
1983							video.redeventsBegin = true;
1984							_stats.redevents('begin');
1985						}
1986					case "progress":
1987						progress = video.progress.buffer[0];
1988						text = video.progress.bufferSpan[0];
1989						value = (function(){
1990									var buffered = video.media.buffered;
1991									if(buffered.length){
1992										return _getPercentage(_getBuffered(buffered, current), video.media.duration);
1993									}
1994									return 0;
1995								})();
1996
1997						$(video.container).toggleClass(cfg.classes.state.buffered, (value >= 100));
1998
1999						break;
2000				}
2001			}
2002
2003			if(video.supported.range){
2004				progress.value = value;
2005			}
2006			else{
2007				progress.style.width = value + "%";
2008			}
2009			text.innerHTML = value;
2010		}
2011
2012		/* return time in (0*)00:00 format */
2013		function _updateTimeDisplay(time){
2014			time = time || "";
2015
2016			var ads = video.isAds || false,
2017				getTime = (time || ads != true ?
2018					(time === "dur" ? video.videoEl.media.duration : video.videoEl.media.currentTime) :
2019					(video.time.ads.duration - (video.time.ads.currentTime = video.time.ads.duration - (video.time.ads.currentDuration - video.videoEl.ads.currentTime)))
2020				);
2021
2022			if(ads){
2023				time = "ads";
2024				getTime = Math.max(0, getTime);
2025			}
2026	
2027			video.time[time + "secs"] = ~~ (.5 + (getTime % 60));
2028			video.time[time + "mins"] = ~~ (getTime / 60);
2029	
2030			if(video.time[time + "secs"] == 60){
2031				video.time[time + "secs"] = 0;
2032				video.time[time + "mins"] += 1;
2033			}
2034
2035			video.time[time + "secs"] = (video.time[time + "secs"] < 10 ? "0" : "") + video.time[time + "secs"];
2036			video.time[time + "mins"] = (video.time[time + "mins"] < 10 ? "0" : "") + video.time[time + "mins"];
2037
2038			return video.time[time + "mins"] + ":" + video.time[time + "secs"];
2039
2040		}
2041
2042		function _timeUpdate(event){
2043			if(video.isAds) return;
2044			video.labels.durationSpan[0].innerHTML = _updateTimeDisplay();
2045			_updateProgress(event);
2046		}
2047
2048		function _durationUpdate(){
2049			video.labels.totalSpan[0].innerHTML = _updateTimeDisplay("dur");
2050		}
2051
2052		var checkingAdsOnTimeUpdate = false;
2053		function _checkAdsOnTimeUpdate(e){
2054			if(video.adsOnTimeupdate.length && !isNaN(e.target.duration)){
2055				var offset = video.adsOnTimeupdate[0].offset > 1 ? video.adsOnTimeupdate[0].offset : video.adsOnTimeupdate[0].offset * e.target.duration;
2056				if(e.target.currentTime >= offset){
2057					checkingAdsOnTimeUpdate = true;
2058
2059					_hit(video.adsOnTimeupdate[0].url);
2060					_log(["_hit :: onTimeupdate", video.adsOnTimeupdate[0].url]);
2061
2062					video.adsOnTimeupdate.shift();
2063					return _checkAdsOnTimeUpdate(e);
2064				}
2065			}
2066			checkingAdsOnTimeUpdate = false;
2067		}
2068
2069		function _adsTimeUpdate(e){
2070			video.mask.attr('data-time', _updateTimeDisplay());
2071			if(!checkingAdsOnTimeUpdate) _checkAdsOnTimeUpdate(e);
2072		}
2073
2074		function _vastUpdateTimeDisplay(time) {
2075			var getTime = Math.max(0, time || 0);
2076	
2077			time = "ads";
2078			video.time[time + "secs"] = ~~ (.5 + (getTime % 60));
2079			video.time[time + "mins"] = ~~ (getTime / 60);
2080	
2081			if(video.time[time + "secs"] == 60){
2082				video.time[time + "secs"] = 0;
2083				video.time[time + "mins"] += 1;
2084			}
2085
2086			video.time[time + "secs"] = (video.time[time + "secs"] < 10 ? "0" : "") + video.time[time + "secs"];
2087			video.time[time + "mins"] = (video.time[time + "mins"] < 10 ? "0" : "") + video.time[time + "mins"];
2088
2089			return video.time[time + "mins"] + ":" + video.time[time + "secs"];
2090		}
2091		function _vastTimeUpdate(time) {
2092			video.mask.attr('data-time', _vastUpdateTimeDisplay(time));
2093		}
2094
2095		function _drag(elem, event){
2096			var e = event || window.event;
2097
2098			var box = elem.getBoundingClientRect();
2099			
2100			var point = {
2101				x: (e.clientX - box.left),
2102				y: (e.clientY - box.top)
2103			}
2104			
2105			return Math.max(0, Math.min(100, _getPercentage(point.x, box.width)));
2106		}
2107
2108		function _showError(type){
2109			_log(["showError", type], "error");
2110
2111			video.isError = true;
2112
2113			$(video.container).addClass('noControls error');
2114			$(video.container).removeClass(cfg.classes.state.loading + " " + cfg.classes.state.loadingMetadata);
2115			$(video.media).off("waiting canplay seeked");
2116			$(video.videoEl.media).off("loadedmetadata.dur");
2117			$(video.videoEl.media).off("loadedmetadata waiting canplay seeked buffering");
2118			$(video.mask).off("click");
2119			$(video.mask).off("dblclick");
2120			$(video.container).off('touchstart.mobilesafari');
2121
2122			_pause();
2123
2124			try {
2125				$(video.adsUrl).remove();
2126				video.videoEl.ads.pause();
2127				$(video.videoEl.ads).remove();
2128				_toggleAds(false);
2129			} catch(e){}
2130
2131			$(video.mask).find('._').html(type === 'timeout' && cfg.errorMsgTimeout || cfg.errorMsg);
2132
2133			if(typeof cfg.diagnose === "function" && type !== 'timeout') {
2134				if(cfg.diagnoseButton) {
2135					var btn = video.mask
2136								.append('<button class="' + cfg.classes.button.all + ' ' + cfg.classes.button.diagnose + '">' + cfg.diagnoseButton + '</button>')
2137								.find('.' + cfg.classes.button.diagnose);
2138
2139					btn.on('click', function(event) {
2140						event.preventDefault();
2141						btn.addClass('is--loading');
2142						cfg.diagnose.call(this, video);
2143					});
2144				} else {
2145					cfg.diagnose.call(null, video);
2146				}
2147			}
2148
2149			if(typeof cfg.onError === "function") {
2150				cfg.onError(video);
2151			}
2152		}
2153
2154		/* checks if video can play > if not then show error log */
2155		function _networkState(event){
2156			if(video.videoEl.media.networkState == 0 || (video.videoEl.media.networkState == 3 && (event || isiPad || isAndroid)) || event === "error"){
2157				_log(["networkState", video.videoEl.media.networkState, (typeof event == "object" ? event.target.src : null)], "error");
2158				_showError('error');
2159			}
2160		}
2161
2162		/*
2163		 *	in Chrome can't seek when source is served by redcdn
2164		 *	so we fetch the source url
2165		 */
2166		function _fetchURL(callback){
2167
2168			setTimeout(function(){
2169
2170				callback = callback || function(){};
2171				
2172				if(window.fetch && video.videoEl.media.currentSrc){
2173					var url = video.videoEl.media.currentSrc;
2174					window.fetch(url, {
2175						method: 'head'
2176					}).then(function(response){
2177
2178						video.videoEl.media.src = response.url;
2179						_log(["_fetchURL"]);
2180						callback();
2181
2182					}).catch(function(e){
2183						
2184						_log(["_fetchURL :: error", url, e], "error");
2185						callback();
2186						
2187					});
2188
2189				}
2190				else{
2191					_log(["_fetchURL :: unsupported"]);
2192					callback();
2193				}
2194
2195			});
2196
2197		}
2198
2199		function _setupMedia(callback){
2200
2201			if(!video.media){
2202				return false;
2203			}
2204
2205			$(video.container).addClass(cfg.classes.state.stopped + " " + cfg.classes.state.loading + " " + cfg.classes.state.loadingMetadata);
2206
2207			if(!video.supported.range){
2208				$(video.container).addClass('noRangeSupported');
2209			}
2210			if(!video.supported.volume){
2211				$(video.container).addClass('noVolumeSupported');
2212			}
2213			if(!video.supported.fullscreen){
2214				$(video.container).addClass('noFullscreenSupported');
2215			}
2216			if(!video.supported.animation){
2217				$(video.container).addClass('noAnimationSupported');
2218			}
2219			if(!video.init.controls){
2220				$(video.container).addClass('noControls');
2221			}
2222
2223			_fetchURL(callback);
2224
2225		}
2226
2227		function _setupHTML(){
2228
2229			var i, attrs, html = cfg.html, toRemove = [];
2230
2231			html = html.replace(/\{id\}/g, video.uniq);
2232			html = html.replace(/\{recommended\}/g, _recommended(cfg.recommended));
2233			html = html.replace(/\{settings\}/g, _settings());
2234
2235			$(video.container)
2236				.wrap('<div />')[0]
2237				.insertAdjacentHTML("afterend", html);
2238
2239			/* remove and set all atributes from video to video.parent() */
2240			attrs = $(video.container)[0].attributes;
2241
2242			for(i = 0; i < attrs.length; i++){
2243				if($.inArray(attrs[i].name, ['poster', 'src', 'playsinline', 'muted', 'autoplay', 'data-autoplay', 'controls', 'preload']) !== -1) continue;
2244				else if(attrs[i].name == 'class'){
2245					$(video.container).parent().addClass(attrs[i].value);
2246					$(video.container).removeClass();
2247				}
2248				else{
2249					$(video.container).parent().attr(attrs[i].name, attrs[i].value);
2250					toRemove.push(attrs[i].name);
2251				}
2252			}
2253
2254			for(i = 0; i < toRemove.length; i++){
2255				$(video.container).removeAttr(toRemove[i]);
2256			}
2257
2258			/*
2259			 *	set video.container to video.parent()
2260			 *	set tabindex = -1 for video DOM, we dont want to Tab reach this element
2261			 */
2262			video.container = $(video.container).attr('tabindex', '-1').addClass(cfg.classes.videoEl.media).parent().addClass(cfg.classes.container + " " + cfg.classes.state.stopped);
2263
2264			var proportionStyle = _proportionStyle();
2265
2266			if(cfg.persistent) {
2267				var placeholder = document.createElement('div');
2268				placeholder.className = cfg.classes.placeholder;
2269
2270				video.persistent = {};
2271				video.persistent.placeholder = $(video.container[0].parentNode.insertBefore(placeholder, video.container[0].nextSibling));
2272
2273				var restore = document.createElement('button');
2274				restore.className = cfg.classes.button.all + ' ' + cfg.classes.button.restore;
2275				video.persistent.restore = $(video.container[0].appendChild(restore));
2276			}
2277
2278			$(video.media).wrap('<div class="' + cfg.classes.videoEl.container + '"' + (proportionStyle ? ' style="padding-top:' + proportionStyle + '"' : '') + ' />');
2279
2280			/* for iOS */
2281			if(isiPad || isiPhone){
2282				var webm = $(video.media).find('[type="video/webm"]');
2283				
2284				if(webm[0]){
2285					video.media.insertAdjacentHTML('afterbegin', _outerHTML(webm[0]));
2286					webm.remove();
2287				}
2288
2289				$(video.media).replaceWith(_outerHTML(video.media));
2290			}
2291
2292			video.media = _getElements("." + cfg.classes.videoEl.media)[0];
2293
2294			_log(["_setupHTML", video.container]);
2295
2296		}
2297
2298		function _outerHTML(el) {
2299			if('outerHTML' in el) {
2300				return el.outerHTML;
2301			}
2302
2303			var node, tmp;
2304			tmp = document.createElement('div');
2305			node = el.cloneNode(true);
2306			tmp.appendChild(node);
2307			return tmp.innerHTML;
2308		}
2309
2310		function _proportionStyle() {
2311			var proportion = '';
2312			if(cfg.proportion != "16:9" && (proportion = cfg.proportion.split(":")).length == 2){
2313				proportion = (proportion[1] / proportion[0] * 100).toFixed(2) + '%';
2314			}
2315
2316			return proportion;
2317		}
2318
2319		function _settings() {
2320			var html = '',
2321				container = $(video.container),
2322				qualities = container.find('source'),
2323				defaultSrc;
2324
2325			if(isIEMobile || isiPhone || (isiPad && iOSVersion < 10) || isOldAndroid) {
2326				return html;
2327			}
2328
2329			for(var i = 0, q; q = qualities[i++]; ) {
2330				var quality = q.getAttribute('data-quality'),
2331					contentType = q.getAttribute('type');
2332				
2333				if(!quality || contentType != 'video/mp4') continue;
2334
2335				video.qualities = video.qualities || [];
2336
2337				var src = q.getAttribute('src');
2338
2339				video.qualities.push({
2340					label: quality,
2341					src: src,
2342					isDefault: false
2343				});
2344
2345				if(!defaultSrc) {
2346					defaultSrc = src;
2347				}
2348			}
2349
2350			if(video.qualities && video.qualities.length > 1) {
2351				video.isSettings = true;
2352
2353				video.qualities.sort(function(a, b) {
2354					return parseInt(a.label) < parseInt(b.label);
2355				});
2356
2357				if(_is4G()) {
2358					var i = Math.max(0, video.qualities.length - 2);
2359					defaultSrc = video.qualities[i].src;
2360				}
2361
2362				video.qualities.unshift({
2363					label: 'auto',
2364					src: defaultSrc,
2365					isDefault: true
2366				});
2367
2368				html += '<div class="' + config.classes.more.settings.container + '">';
2369				html += '	<div class="' + config.classes.more.settings.items + '">';
2370				for(var i = 0, q; q = video.qualities[i++]; ) {
2371					html += '	<button class="' + config.classes.more.settings.item + (q.isDefault ? ' is--active' : '') + '">' + q.label + '</button>';
2372				}
2373				html += '	</div>';
2374				html += '	<div class="' + config.classes.button.all + ' ' + config.classes.button.iconSettings + '"><span class="_"></span></div>';
2375				html += '</div>';
2376
2377				container.addClass('is--settings');
2378			}
2379
2380			return html;
2381		}
2382
2383		function _recommended(recommended){
2384			var html = '';
2385
2386			if(recommended.length){
2387				video.isRecommended = true;
2388
2389				html = '<div class="' + cfg.classes.recommended.container + ' ' + cfg.classes.recommended.container + '--' + recommended.length + '">';
2390				html += '	<div class="' + cfg.classes.recommended.item + ' ' + cfg.classes.recommended.item + '--main">';
2391				html += '		<a href="' + recommended[0].url + '" class="' + cfg.classes.recommended.title + '">' + recommended[0].title + '</a>';
2392				html += '		<img src="' + recommended[0].img + '" alt="" class="' + cfg.classes.recommended.img + '">';
2393				html += '		<a href="' + recommended[0].url + '" class="' + cfg.classes.recommended.progress + '">'
2394				html += '			<svg class="' + cfg.classes.recommended.svg + '" version="1.1" viewBox="0 0 100 100" preserveAspectRatio="xMinYMin meet">';
2395				html += '				<circle cx="50" cy="50" r="47" stroke-width="6" stroke-dasharray="296" stroke-dashoffset="0" class="' + cfg.classes.recommended.svg + '-circle" />';
2396				html += '				<polygon points="35,25 72,50 35,75" class="' + cfg.classes.recommended.svg + '-play" />';
2397				html += '			</svg>';
2398				html += '		</a>';
2399				html += '		<span class="' + cfg.classes.recommended.counter + '">Następne wideo rozpocznie się za <span class="' + cfg.classes.recommended.seconds + '">-</span>
2399 sekund. <span class="' + cfg.classes.recommended.cancel + '">Anuluj</span></span>';
2400				html += '	</div>';
2401				html += '	<div class="' + cfg.classes.recommended.list + '">';
2402				for(var i = 1, l = recommended.length; i < l; i++){
2403					html += '	<a href="' + recommended[i].url + '" class="' + cfg.classes.recommended.item + '">';
2404					html += '		<span class="' + cfg.classes.recommended.title + '">' + recommended[i].title + '</span>';
2405					html += '		<img src="' + recommended[i].img + '" alt="" class="' + cfg.classes.recommended.img + '">';
2406					html += '	</a>';
2407				}
2408				html += '	</div>';
2409				html += '</div>';
2410			}
2411
2412			return html;
2413		}
2414		function _recommendedScroll(){
2415			requestAnimationFrame(function(){
2416				var wHeight = window.innerHeight;
2417
2418				for(var i = 0, el; el = videoPlayer.els[i++]; ){
2419					var el = el.instance();
2420
2421					if(!el.recommended.showing || el.recommended.isCancel) continue;
2422
2423					var rect = el.recommended.svg[0].getBoundingClientRect(),
2424						oTop = rect.top,
2425						oHeight = rect.height,
2426						pos = oTop + oHeight / 2;
2427
2428					if(el.recommended.scrollState !== (el.recommended.scrollState = pos > 0 && pos < wHeight)){
2429						if(window.videoPlayer.isBlur) continue;
2430
2431						if(el.recommended.scrollState){
2432							el.recommended.animate.play();
2433						}
2434						else{
2435							el.recommended.animate.pause();
2436						}
2437					}
2438				}
2439			});
2440		}
2441		function _recommendedFocusChange(el){
2442			if(!el.recommended.showing || el.recommended.isCancel) return;
2443
2444			if(window.videoPlayer.isBlur){
2445				el.recommended.animate.pause();
2446			}
2447			else if(el.recommended.scrollState){
2448				el.recommended.animate.play();
2449			}
2450		}
2451		function _prepareRecomended(){
2452			var secs = isiPhone || isIEMobile ? 0 : cfg.recommendedCountdown,
2453				second, stroke;
2454
2455			video.recommended.scrollState = null;
2456			video.recommended.showing = true;
2457			video.recommended.isCancel = !secs;
2458
2459			if(!video.recommended.isCancel){
2460				video.recommended.container.removeClass(cfg.classes.recommended.container + '--cancel');
2461				video.recommended.container.addClass(cfg.classes.recommended.container + '--pause');
2462				video.recommended.svg.attr('stroke-dashoffset', (stroke = parseInt(video.recommended.svg.attr('stroke-dasharray'))));
2463				video.recommended.seconds.html(secs);
2464
2465				video.recommended.animate = new Animate({
2466					duration: secs * 1000,
2467					onPlay: function(){
2468						video.recommended.isPause = false;
2469						video.recommended.container.removeClass(cfg.classes.recommended.container + '--pause');
2470					},
2471					onUpdate: function(anim, step){
2472						if(video.recommended.isPause)
2473							return;
2474
2475						if(!video.recommended.showing){
2476							video.recommended.animate.pause();
2477							return;
2478						}
2479
2480						if(second != (second = Math.round(Animate.calculate(secs, 0, step)))){
2481							video.recommended.seconds.html(second);
2482						}
2483
2484						video.recommended.svg.attr('stroke-dashoffset', Animate.calculate(stroke, 0, step));
2485					},
2486					onPause: function(){
2487						video.recommended.container.addClass(cfg.classes.recommended.container + '--pause');
2488						video.recommended.isPause = true;
2489						video.recommended.animate.stop();
2490					},
2491					onStop: function(){
2492						if(!video.recommended.isCancel && !video.recommended.isPause){
2493							var url = video.recommended.container.find('.' + cfg.classes.recommended.title).attr('href');
2494							window.location.assign(url);
2495						}
2496					}
2497				});
2498				
2499				_recommendedScroll();
2500			}
2501			else{
2502				video.recommended.container.addClass(cfg.classes.recommended.container + '--off');
2503			}
2504		}
2505		function _persistentClick() {
2506			window.videoPlayer.persistent.active = null;
2507			video.persistent.prevent = true;
2508			video.container.removeClass('is--persistent');
2509		}
2510		function _persistentScroll() {
2511			requestAnimationFrame(function(){
2512				var wHeight = window.innerHeight;
2513
2514				for(var i = 0, api; api = videoPlayer.els[i++]; ){
2515					var instance = api.instance();
2516
2517					if(!instance.persistent || instance.persistent.prevent || window.videoPlayer.persistent.active !== instance && api.isPaused()) continue;
2518
2519					window.videoPlayer.persistent.active = window.videoPlayer.persistent.active || instance;
2520
2521					var rect = window.videoPlayer.persistent.state ?
2522						instance.persistent.placeholder[0].getBoundingClientRect() :
2523						instance.container[0].getBoundingClientRect();
2524
2525					var top = rect.top > wHeight,
2526						bottom = rect.bottom < 0,
2527						width = rect.width,
2528						height = rect.height;
2529
2530					if(window.videoPlayer.persistent.state !== (window.videoPlayer.persistent.state = top || bottom)) {
2531						if(!window.videoPlayer.persistent.state) {
2532							instance.container.removeClass('is--persistent');
2533
2534							if(api.isPaused()) {
2535								window.videoPlayer.persistent.active = null;
2536							}
2537						} else {
2538							instance.persistent.placeholder[0].style.width = width + 'px';
2539							instance.persistent.placeholder[0].style.height = height + 'px';
2540							instance.container.addClass('is--persistent');
2541						}
2542					}
2543
2544					return;
2545				}
2546			});
2547		}
2548		function _getStorage(key, def) {
2549			try {
2550				return JSON.parse(window.localStorage[cfg.storage.key + key]) || def;
2551			} catch(e) {}
2552
2553			return def;
2554		}
2555		function _positionMemorySet() {
2556
2557			if(video.positionMemory) {
2558				var list = _getStorage('positionMemory', []);
2559
2560				for(var i = 0, item; item = list[i]; i++) {
2561					if(item[0] == video.uniq) {
2562						$(video.videoEl.media).one('play.positionMemorySet', function(){
2563							_progSeek(item[1]);
2564						});
2565						break;
2566					}
2567				}
2568			}
2569		}
2570		function _positionMemory() {
2571			var list = _getStorage('positionMemory', []),
2572				map = {};
2573
2574			for(var i = 0, item; item = list[i]; i++) {
2575				map[item[0]] = i;
2576			}
2577
2578			var toRemove = [];
2579			for(var i = 0, api; api = window.videoPlayer.els[i++]; ) {
2580				var instance = api.instance();
2581
2582				if(instance.positionMemory) {
2583					if(instance.videoEl.media.currentTime && !instance.isEnded) {
2584						var item = [instance.uniq, Math.round(instance.videoEl.media.currentTime)];
2585						if(instance.uniq in map) {
2586							list[map[instance.uniq]] = item;
2587						} else {
2588							list.unshift(item);
2589						}
2590					}
2591					else if(instance.isEnded) {
2592						toRemove.push(instance.uniq);
2593					}
2594				}
2595			}
2596
2597			for(var i = list.length, item; item = list[--i]; ) {
2598				for(var j = toRemove.length, remove; remove = toRemove[--j]; ) {
2599					if(item[0] == remove) {
2600						list.splice(i, 1);
2601						toRemove.splice(j, 1);
2602					}
2603				}
2604			}
2605
2606			if(list.length > cfg.positionMemoryLimit) {
2607				list.length = cfg.positionMemoryLimit;
2608			}
2609
2610			window.localStorage[cfg.storage.key + 'positionMemory'] = JSON.stringify(list);
2611		}
2612
2613		function _setupElements(){
2614
2615			video.videoEl				= {};
2616			video.videoEl.container		= _getElements("." + cfg.classes.videoEl.container);
2617			video.videoEl.media			= _getElements("." + cfg.classes.videoEl.media)[0];
2618
2619			video.mask					= _getElements("." + cfg.classes.mask);
2620			video.adsUrl				= _getElements("." + cfg.classes.adsUrl);
2621
2622			video.controls				= _getElements("." + cfg.classes.controls);
2623
2624			video.buttons				= {};
2625			video.buttons.all			= _getElements("." + cfg.classes.button.all);
2626			video.buttons.play			= _getElements("." + cfg.classes.button.play);
2627			video.buttons.pause			= _getElements("." + cfg.classes.button.pause);
2628			video.buttons.mute			= _getElements("." + cfg.classes.button.mute);
2629			video.buttons.unmute		= _getElements("." + cfg.classes.button.unmute);
2630			video.buttons.enterFullscreen = _getElements("." + cfg.classes.button.enterFullscreen);
2631			video.buttons.exitFullscreen = _getElements("." + cfg.classes.button.exitFullscreen);
2632
2633			video.labels				= {};
2634			video.labels.all			= _getElements("." + cfg.classes.label.all);
2635			video.labels.span			= _getElements("." + cfg.classes.label.span);
2636			video.labels.duration		= _getElements("." + cfg.classes.label.duration);
2637			video.labels.total			= _getElements("." + cfg.classes.label.total);
2638			video.labels.durationSpan	= _getElements("." + cfg.classes.label.duration + " ." + cfg.classes.label.span);
2639			video.labels.totalSpan		= _getElements("." + cfg.classes.label.total + " ." + cfg.classes.label.span);
2640
2641			video.progress				= {};
2642			video.progress.container	= _getElements("." + cfg.classes.progress.container);
2643			video.progress.all			= _getElements("." + cfg.classes.progress.all);
2644			video.progress.ads			= _getElements("." + cfg.classes.progress.ads);
2645			video.progress.seek			= _getElements("." + cfg.classes.progress.seek);
2646			video.progress.buffer		= _getElements("." + cfg.classes.progress.buffer);
2647			video.progress.bufferSpan	= _getElements("." + cfg.classes.progress.buffer + " span");
2648			video.progress.played		= _getElements("." + cfg.classes.progress.played);
2649			video.progress.playedSpan	= _getElements("." + cfg.classes.progress.played + " span");
2650			video.progress.volume		= _getElements("." + cfg.classes.progress.volume);
2651			video.progress.volumeSpan	= _getElements("." + cfg.classes.progress.volume + " span");
2652
2653			video.volume				= {};
2654			video.volume.container		= _getElements("." + cfg.classes.more.volume.container);
2655			video.volume.wrap			= _getElements("." + cfg.classes.more.volume.wrap);
2656			video.volume.checkbox		= _getElements("." + cfg.classes.more.volume.container + " [type=checkbox]");
2657			video.volume.seek			= _getElements("." + cfg.classes.more.volume.seek);
2658
2659			video.settings				= {};
2660			video.settings.container	= _getElements("." + cfg.classes.more.settings.container);
2661			video.settings.item			= _getElements("." + cfg.classes.more.settings.item);
2662
2663			video.fullscreen			= {};
2664			video.fullscreen.container	= _getElements("." + cfg.classes.more.fullscreen.container);
2665
2666			video.recommended			= {};
2667			video.recommended.container	= _getElements("." + cfg.classes.recommended.container);
2668			video.recommended.svg		= _getElements("." + cfg.classes.recommended.svg + "-circle");
2669			video.recommended.seconds	= _getElements("." + cfg.classes.recommended.seconds);
2670			video.recommended.cancel	= _getElements("." + cfg.classes.recommended.cancel);
2671
2672			_log(["_setupElements", video]);
2673
2674		}
2675
2676		function checkIfCanAutoplay(cb) {
2677			if(video.checkIfCanAutoplay) {
2678				cb(video.checkIfCanAutoplay);
2679				return;
2680			}
2681
2682			var promise = video.videoEl.media.play();
2683
2684			if(promise) {
2685				promise.then(function() {
2686					video.videoEl.media.pause();
2687					cb((video.checkIfCanAutoplay = {
2688						autoplayAllowed: true,
2689						autoplayRequiresMuted: false
2690					}));
2691				}).catch(function() {
2692					var _vol = video.videoEl.media.volume;
2693					_setVolume(0);
2694					
2695					video.videoEl.media.play().then(function() {
2696						video.videoEl.media.pause();
2697						cb((video.checkIfCanAutoplay = {
2698							autoplayAllowed: true,
2699							autoplayRequiresMuted: true
2700						}));
2701					}).catch(function() {
2702						_setVolume(_vol);
2703						
2704						cb((video.checkIfCanAutoplay = {
2705							autoplayAllowed: false,
2706							autoplayRequiresMuted: false
2707						}));
2708					});
2709				});
2710			} else {
2711				var playing = !video.videoEl.media.paused;
2712				video.videoEl.media.pause();
2713
2714				cb((video.checkIfCanAutoplay = {
2715					autoplayAllowed: playing,
2716					autoplayRequiresMuted: false
2717				}));
2718			}
2719		}
2720
2721		function _onLoadedMetadata(){
2722			_durationUpdate();
2723
2724			_stats.stream("newStream");
2725			_stats.prism("Nowy_Materiał");
2726			_stats.player("newProgram");
2727
2728			
2729			if(video.init.autoplay) {
2730				checkIfCanAutoplay(function(opts) {
2731					if(opts.autoplayAllowed) {
2732						_play();
2733					}
2734				});
2735			}
2736		}
2737
2738		function _loadedMetadata(event){
2739
2740			var dur = video.videoEl.media.duration,
2741				durArr = [0, 1, 100, 6000];
2742
2743			if((!event && isNaN(dur)) || video.loadedmetadata){
2744				// video.videoEl.media.load();
2745				return;
2746			}
2747
2748			_log(['loadedmetadata', !!event, dur]);
2749
2750			if(isAndroid || isiPhone || isiPad || dur){
2751
2752				clearTimeout(video.timerMetadata);
2753				video.loadedmetadata = true;
2754
2755				if($.inArray(dur, durArr) !== -1 || isNaN(dur)){
2756
2757					$(video.videoEl.media).on("durationchange.dur", function(e){
2758					
2759						if($.inArray(e.target.duration, durArr) === -1 && !isNaN(e.target.duration)){
2760							_onLoadedMetadata();
2761							$(video.videoEl.media).off("durationchange.dur");
2762						}
2763
2764					});
2765
2766				}
2767				else{
2768					_onLoadedMetadata();
2769				}
2770
2771
2772				$(video.container).off('touchstart.mobilesafari');
2773				$(video.videoEl.media).off("loadedmetadata.dur");
2774
2775				$(video.container).removeClass(cfg.classes.state.loading + " " + cfg.classes.state.loadingMetadata);
2776
2777			}
2778			else{
2779				setTimeout(function() {
2780					dur = video.videoEl.media.duration;
2781					if(($.inArray(dur, durArr) !== -1 || isNaN(dur)) && video.videoEl.media.networkState !== 2) {
2782						_showError('timeout');
2783					}
2784				}, 60000);
2785			}
2786
2787		}
2788
2789		function _is4G() {
2790			var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
2791			var type = (connection && connection.effectiveType || "").replace(/.*(\d)g/, function(a, b) {
2792				return b;
2793			});
2794
2795			return type > 3;
2796		}
2797
2798		function _changeSource(src, label) {
2799			var time = video.videoEl.media.currentTime,
2800				paused = video.videoEl.media.paused;
2801
2802			video.container.addClass('loading loading--quality');
2803			video.videoEl.media.src = src;
2804			video.videoEl.media.load();
2805			video.videoEl.media.currentTime = time;
2806			$(video.videoEl.media).one('loadeddata', function() {
2807				video.container.removeClass('loading loading--quality');
2808
2809				if(!paused) {
2810					video.videoEl.media.play();
2811				}
2812				
2813				video.quality = label === 'auto' ? '480p' : label;
2814					
2815				if(video.redeventsBegin)
2816					_stats.redevents("change quality");
2817
2818			});
2819		}
2820
2821		function _listeners(){
2822
2823			$(video.mask).on("click", _toggle);
2824			$(video.buttons.play).on("click", _play);
2825			$(video.buttons.pause).on("click", _pause);
2826
2827			if(video.supported.fullscreen){
2828				$(video.mask).on("dblclick", _toggleFullscreen);
2829				$(video.buttons.enterFullscreen).on("click", _enterFullscreen);
2830				$(video.buttons.exitFullscreen).on("click", _exitFullscreen);
2831			}
2832		
2833			$(video.volume.seek).on("change input", function(){
2834				_setVolume(this.value);
2835			});
2836
2837			$(video.progress.seek).on("change input", _seek);
2838
2839			if(!video.supported.range){
2840
2841				video.progress.seek.replaceWith('<div class="' + cfg.classes.progress.all + ' ' + cfg.classes.progress.seek + ' ' + cfg.classes.progress.all + '--fallback"></div>');
2842				video.progress.seek = _getElements("." + cfg.classes.progress.seek);
2843
2844				video.volume.seek.replaceWith('<div class="' + cfg.classes.progress.all + ' ' + cfg.classes.more.volume.seek + ' ' + cfg.classes.progress.all + '--fallback"></div>');
2845				video.volume.seek = _getElements("." + cfg.classes.more.volume.seek);
2846
2847
2848				var startDrag = false;
2849				_getElements("." + cfg.classes.progress.all + "--fallback").on("mousedown.range", function(e){
2850					var elem = this,
2851						elemIsProgress = $(this).hasClass(cfg.classes.progress.seek),
2852						value = _drag(elem, e) + "%";
2853
2854					startDrag = true;
2855					video.isInput = true;
2856
2857					if(elemIsProgress){
2858						video.seekingStart = true;
2859						_seek(value);
2860						video.seekingStart = false;
2861					}
2862					else{
2863						_setVolume(value);
2864					}
2865
2866					$(document).on("mousemove.range", function(e){
2867						if(!startDrag) return;
2868
2869						value = _drag(elem, e) + "%";
2870
2871						if(elemIsProgress){
2872							_seek(value);
2873						}
2874						else{
2875							_setVolume(value);
2876						}
2877					});
2878
2879					$(document).one("mouseup.range", function(){
2880
2881						if(elemIsProgress && !video.videoEl.media.paused){
2882							_stats.stream("playing");
2883							_stats.player("play");
2884						}
2885
2886						startDrag = false;
2887						video.isInput = false;
2888						$(document).off("mousemove.range");
2889
2890					});
2891				});
2892
2893			}
2894
2895			$(video.volume.checkbox).on("change", function(){
2896				_toggleMute(this.checked);
2897			});
2898
2899			if(video.isSettings) {
2900				video.settings.item.on('click', function(event) {
2901					event.preventDefault();
2902					
2903					var t = $(this),
2904						index = Array.prototype.slice.call(this.parentElement.children).indexOf(this);
2905
2906					if(t.hasClass('is--active'))
2907						return;
2908
2909					t.parent().find('.is--active').removeClass('is--active');
2910					t.addClass('is--active');
2911					
2912					var q = video.qualities[index];
2913
2914					_changeSource(q.src, q.label);
2915
2916					try{
2917						if(q.label == 'auto') {
2918							window.localStorage.removeItem(cfg.storage.key + 'quality');
2919						} else {
2920							window.localStorage[cfg.storage.key + 'quality'] = JSON.stringify(q.label);
2921						}
2922					} catch(e) {}
2923				});
2924
2925				var storageQuality = _getStorage('quality', false);
2926				if(storageQuality) {
2927					for(var i = 0, q; q = video.qualities[i]; i++) {
2928						if(q.label == storageQuality) {
2929							video.settings.item[i].click();
2930							break;
2931						}
2932					}
2933				} else if(_is4G()) {
2934					var i = Math.max(1, video.qualities.length - 2);
2935					_changeSource(video.qualities[i].src, video.qualities[i].label);
2936				}
2937
2938			}
2939
2940			if(cfg.persistent) {
2941				video.persistent.restore.on('click.persistent', _persistentClick);
2942			
2943				if(!window.videoPlayer.persistent) {
2944					window.videoPlayer.persistent = {};
2945					$(window).on('scroll.persistent', _persistentScroll);
2946				}
2947			}
2948
2949			if(cfg.positionMemory && cfg.storage.enabled && video.supported.storage) {
2950				video.positionMemory = true;
2951
2952				if(!window.videoPlayer.positionMemory) {
2953					window.videoPlayer.positionMemory = {};
2954
2955					window.onbeforeunload = _positionMemory;
2956				}
2957			}
2958
2959			video.recommended.cancel.on("click", function(){
2960				video.recommended.container.addClass(cfg.classes.recommended.container + '--cancel');
2961				video.recommended.isCancel = true;
2962				video.recommended.animate.pause();
2963			});
2964
2965			$(video.media).on("volumechange", _checkMute);
2966
2967			$(video.media).on("play pause", _checkPlaying);
2968			$(video.videoEl.media).on("ended", function(){
2969				if(video.isEnded) return;
2970
2971				/* fix for IE */
2972				if(isIE) video.media.pause();
2973
2974				function _logEnd() {
2975					_stats.stream("complete");
2976					_stats.prism("Koniec_Materiału");
2977					_stats.player("complete");
2978					_stats.redevents("end");
2979
2980					_log('end');
2981				}
2982
2983				function _ended() {
2984					video.isEnded = true;
2985					_checkPlaying();
2986
2987					if(video.isRecommended) {
2988						_prepareRecomended();
2989					}
2990
2991					if(typeof cfg.onEnded == "function") {
2992						cfg.onEnded(video);
2993					}
2994
2995					$(video.progress.seek).one("change.afterend input.afterend", function() {
2996						$(video.container).removeClass(cfg.classes.state.ended);
2997						if(video.isRecommended) {
2998							video.recommended.showing = false;
2999							if(video.recommended.animate) video.recommended.animate.pause();
3000						}
3001					});
3002
3003					_log('ended');
3004				}
3005
3006				if(video.vast && video.isAds) {
3007					return;
3008				}
3009				
3010				_logEnd();
3011
3012				if(video.vast) {
3013					video.vast.contentComplete(_ended);
3014				} else {
3015					_ended();
3016				}
3017
3018			});
3019			$(video.videoEl.media).on("play pause", function(e){
3020				if(e.target.ended || preventLogOnAndroid) return;
3021
3022				if(e.type == "play" && video.isEnded){
3023
3024					_stats.stream("newStream");
3025					_stats.prism("Nowy_Materiał");
3026					_stats.prism("Start");
3027					_stats.redevents("try");
3028					_stats.redevents("begin");
3029
3030					video.isEnded = 
3031					video.prismStart = 
3032					video.prism90 = 
3033					video.recommended.showing = false;
3034
3035					_checkPlaying();
3036				}
3037
3038				var state = e.type == "play" ? "playing" : "paused";
3039				_stats.stream(state);
3040			});
3041
3042			$(video.videoEl.media).on("waiting canplay seeked buffering", _checkLoading);
3043
3044			if(!video.fullscreenListener) {
3045				$(document).on('webkitfullscreenchange mozfullscreenchange MSFullscreenChange fullscreenchange', _checkFullscreen);
3046				video.fullscreenListener = true;
3047			}
3048
3049			video.videoEl.media.addEventListener("error", _networkState, true);
3050			//if(isAndroid || isiPad) _networkState();
3051
3052			$(video.media).on("progress", _updateProgress);
3053
3054			$(video.media).on("playing", _updateProgress);
3055
3056			video.timerMetadata = setTimeout(function(){
3057				if(isAndroid || isiPhone || isiPad) _loadedMetadata(true);
3058			}, 3000);
3059
3060			$(video.videoEl.media).on("loadedmetadata.dur", _loadedMetadata);
3061			_loadedMetadata();
3062			
3063			if(!isAndroid){
3064
3065				video.videoEl.media.load();
3066
3067				if(isiPad || isiPhone){
3068
3069					$(video.container).removeClass(cfg.classes.state.loadingMetadata);
3070					$(video.container).on('touchstart.mobilesafari', function(){
3071						video.videoEl.media.load();
3072					});
3073
3074				}
3075			}
3076
3077			$(video.videoEl.media).on("timeupdate seeking", _timeUpdate);
3078
3079			if(!window.videoPlayer.focusChange){
3080				window.videoPlayer.focusChange = true;
3081				$(window).on('focus.videoPlayer blur.videoPlayer', _focusChange);
3082			}
3083
3084			if(video.isRecommended && !window.videoPlayer.recommendedScroll){
3085				window.videoPlayer.recommendedScroll = true;
3086				$(window).on('scroll.videoPlayer', _recommendedScroll);
3087			}
3088		}
3089
3090		function _toggleAds(ads){
3091			$(video.container).toggleClass('ads', ads);
3092			video.isAds = ads;
3093			if(ads) video.mask.attr('data-time', '--:--');
3094		}
3095
3096		function _isAds(){
3097			return video.isAds;
3098		}
3099
3100		function _onClickAds(){
3101
3102			if(!video.loadedmetadata || $(video.adsUrl).attr('href') == "") return;
3103			if(video.vast && video.vast.isPaused()) {
3104				_play();
3105			} else if(!video.videoEl.ads.paused){
3106
3107				_hit(video.adsOnClicked);
3108
3109				try{
3110					$(video.adsUrl)[0].click();
3111				}
3112				catch(e){
3113					window.open($(video.adsUrl)[0].href, '_blank');
3114				}
3115
3116				_log(["_hit :: onClicked", video.adsOnClicked]);
3117
3118			}
3119			else{
3120				_play();
3121			}
3122
3123		}
3124
3125		function _onEndedPREAds(e, row){
3126
3127			/*if(!row){
3128				_hit(video.adsOnEmitted);
3129				_log(["_hit :: onEmitted", video.adsOnEmitted]);
3130			}*/
3131
3132			if(e) _stats.player("complete");
3133
3134			video.time.ads.currentDuration -= row && row["duration"] || video.videoEl.ads.duration;
3135
3136			var row;
3137			if(row = video.ads["0"]["items"].shift()){
3138
3139				video.currentAdInBlock++;
3140
3141				_stats.prism("PreRoll");
3142
3143				video.videoEl.ads.src = _getSource(row.src);
3144				video.videoEl.ads.load();
3145				video.adsUrl[0].href = row.url;
3146				video.adsID = row.id;
3147				video.adsOnClicked = row.events.on_clicked;
3148				video.adsOnEmitted = row.events.on_emitted;
3149				video.adsOnTimeupdate = row.events.on_timeupdate;
3150
3151				_stats.player("newAd");
3152				//$(video.videoEl.ads).one('playing', function(){
3153				//	_gemius.player("play");
3154				//});
3155
3156				_hit(video.adsOnEmitted);
3157				_log(["_hit :: onEmitted", video.adsOnEmitted]);
3158
3159			}
3160			else{
3161
3162				_stats.prism("PreRoll_KoniecBloku");
3163
3164				/* unbind */
3165				$(video.videoEl.ads).off("ended.ads");
3166				$(video.videoEl.ads).off("error.ads");
3167
3168				video.media = video.videoEl.media;
3169
3170				_toggleAds(false);
3171				
3172				_setVolume();
3173
3174				_checkBeforeBegin();
3175
3176				video.currentAdInBlock = 0;
3177				video.totalAdInBlock = 0;
3178
3179				/* fix for iOS Mobile - the next ad has start time from previous one */
3180				if(isiPad || isiPhone){
3181					video.videoEl.ads.currentTime = 0.1;
3182					$(video.container).removeClass(cfg.classes.state.ended);
3183				}
3184
3185				if(video.ads["offsets"].length){
3186
3187					_setupAdsMID();
3188
3189				}
3190				else{
3191					$(video.adsUrl).remove();
3192					$(video.videoEl.ads).remove();
3193				}
3194
3195			}
3196
3197			if(e || video.init.autoplay) _play();
3198
3199		}
3200
3201		function _listenersAds(){
3202
3203			$(video.videoEl.ads).one("playing", function(){
3204				_toggleAds(true);
3205				
3206				_stats.prism("PreRoll_StartBloku");
3207				_stats.prism("PreRoll");
3208				_stats.redevents("begin preRoll");
3209
3210				_focusChange();
3211			});
3212
3213			$(video.videoEl.ads).on("play pause", _checkPlaying);
3214
3215			video.media = video.videoEl.ads;
3216
3217			$(video.videoEl.ads).on("ended.ads", _onEndedPREAds);
3218			$(video.videoEl.ads).on("timeupdate.ads", _adsTimeUpdate);
3219
3220		}
3221
3222		function _onEndedMIDAds(evntId, list, row){
3223
3224			/*if(!row){
3225				_hit(video.adsOnEmitted);
3226				_log(["_hit :: onEmitted", video.adsOnEmitted]);
3227			}*/
3228
3229			video.time.ads.currentDuration -= row && row["duration"] || video.videoEl.ads.duration;
3230			
3231			if(list["items"].length){
3232
3233				video.currentAdInBlock++;
3234
3235				_stats.prism("MidRoll");
3236
3237				var row = list["items"].shift();
3238
3239				video.videoEl.ads.src = _getSource(row.src);
3240				video.videoEl.ads.load();
3241				video.adsUrl[0].href = row.url;
3242				video.adsID = row.id;
3243				video.adsOnClicked = row.events.on_clicked;
3244				video.adsOnEmitted = row.events.on_emitted;
3245				video.adsOnTimeupdate = row.events.on_timeupdate;
3246
3247				_stats.player("newAd");
3248				//$(video.videoEl.ads).one('playing', function(){
3249				//	_gemius.player("play");
3250				//});
3251
3252				_hit(video.adsOnEmitted);
3253				_log(["_hit :: onEmitted", video.adsOnEmitted]);
3254
3255				$(video.videoEl.ads).one("error.ads", function(){
3256					_onEndedMIDAds(evntId, list, row);
3257				});
3258
3259			}
3260			else{
3261
3262				_stats.prism("MidRoll_KoniecBloku");
3263				_stats.redevents("end midRoll");
3264
3265				/* unbind */
3266				$(video.videoEl.ads).off("error.ads");
3267				$(video.videoEl.ads).off("ended.id" + evntId);
3268
3269				video.media = video.videoEl.media;
3270
3271				_toggleAds(false);
3272
3273				_setVolume();
3274
3275				video.currentAdInBlock = 0;
3276				video.totalAdInBlock = 0;
3277
3278				/* fix for iOS Mobile - the next ad has start time from previous one */
3279				if(isiPad || isiPhone) video.videoEl.ads.currentTime = 0.1;
3280				
3281				$('#ads' + video.uniq + '_' + evntId).remove();
3282
3283				var offset;
3284				if(offset = video.ads["offsets"].shift()){
3285
3286					_setAdsListener(offset);
3287
3288				}
3289				else{
3290					$(video.adsUrl).remove();
3291					$(video.videoEl.ads).remove();
3292				}
3293
3294			}
3295
3296			_play();
3297
3298		}
3299
3300		function _setAdsListener(offset){
3301
3302			var evntId = parseInt(offset * 100),
3303				time = offset * video.media.duration,
3304				counter = 0;
3305
3306			$(video.media).on("timeupdate.id" + evntId, function(e){
3307				if(e.target.currentTime >= time){
3308
3309					$(video.media).off("timeupdate.id" + evntId);
3310
3311					var pause = video.media.paused;
3312
3313					video.media.pause();
3314					_stats.player("break");
3315
3316					var mid = video.ads["mid"],
3317						list = video.ads[offset];
3318
3319					_toggleAds(true);
3320
3321					video.time.ads = {
3322						currentTime: 0,
3323						currentDuration: list["total"],
3324						duration: list["total"]
3325					};
3326
3327					video.currentAdInBlock = 1;
3328					video.totalAdInBlock = list["items"].length;
3329
3330					var row = list["items"].shift();
3331
3332					video.videoEl.ads.src = _getSource(row.src);
3333					video.videoEl.ads.load();
3334					video.adsUrl[0].href = row.url;
3335					video.adsID = row.id;
3336					video.adsOnClicked = row.events.on_clicked;
3337					video.adsOnEmitted = row.events.on_emitted;
3338					video.adsOnTimeupdate = row.events.on_timeupdate;
3339
3340					_hit(video.adsOnEmitted);
3341					_log(["_hit :: onEmitted", video.adsOnEmitted]);
3342
3343					video.media = video.videoEl.ads;
3344
3345					_setVolume();
3346
3347					if(!pause){
3348						video.videoEl.ads.play();
3349
3350						_focusChange();
3351					}
3352
3353					/* skip to next frame */
3354					setTimeout(function(){
3355						_stats.prism("MidRoll_StartBloku");
3356						_stats.prism("MidRoll");
3357						_stats.player("newAd");
3358						_stats.redevents("begin midRoll");
3359
3360						$(video.videoEl.ads).one('playing', function(){
3361							_stats.player("play");
3362						});
3363					});
3364
3365					$(video.videoEl.ads).one("error.ads", function(){
3366						_onEndedMIDAds(evntId, list, row);
3367					});
3368
3369					$(video.videoEl.ads).on("ended.id" + evntId, function(e){
3370
3371						_stats.player("complete");
3372						_onEndedMIDAds(evntId, list);
3373
3374					});
3375
3376				}
3377
3378			});
3379
3380		}
3381
3382		function _getSource(source){
3383			return source[(_canPlay('mp4') ? (video.container[0].clientWidth <= 360 ? "mobile" : "mp4") : "webm")];
3384		}
3385
3386		function _isPaused(){
3387			if(video.vast && video.isAds) {
3388				return video.vast.isPaused();
3389			}
3390			return video.media.paused;
3391		}
3392
3393		function _shouldPlay(val){
3394			if(typeof val !== "undefined") return video.shouldPlay = val;
3395			return video.shouldPlay;
3396		}
3397
3398		function _focusChange(e){
3399			setTimeout(function(){
3400				var blur = !document.hasFocus();
3401				window.videoPlayer.isBlur = blur;
3402
3403				for(var i = 0, el; el = videoPlayer.els[i++]; ){
3404					var instance = el.instance();
3405
3406					if(el.isAds()){
3407						if(blur) el.shouldPlay(instance.vast ? !instance.vast.isPaused() : !el.isPaused());
3408						if(el.shouldPlay() || video.vastIsIMAClicked) blur ? el.pause() : (el.play(), video.vastIsIMAClicked = null);
3409					}
3410
3411					if(instance.isRecommended){
3412						_recommendedFocusChange(instance);
3413					}
3414				}
3415			});
3416		}
3417
3418		function _setupAds(){
3419
3420			$(video.videoEl.container).append('<video class="' + cfg.classes.videoEl.ads + '" tabindex="-1" />');
3421			video.videoEl.ads = _getElements("." + cfg.classes.videoEl.ads)[0];
3422
3423			$(video.videoEl.ads).on("play.prism pause.prism", function(e){
3424				if(e.target.ended || e.target.currentTime == 0) return;
3425				var state = e.type == "play" ? "Start" : "Pauza";
3426				_stats.prism(state);
3427			});
3428
3429			if(video.ads["0"]){
3430
3431				_setupAdsPRE();
3432
3433			}
3434			else if(video.ads["offsets"].length){
3435
3436				_setupAdsMID();
3437
3438			}
3439
3440			_log(["ADS", video.ads]);
3441
3442		}
3443
3444		function _setupAdsPRE(){
3445
3446			var row,
3447				pre = video.ads["0"];
3448
3449			video.time.ads = {
3450				currentTime: 0,
3451				currentDuration: pre["total"],
3452				duration: pre["total"]
3453			};
3454
3455			video.currentAdInBlock = 1;
3456			video.totalAdInBlock = pre["items"].length;
3457			
3458			_listenersAds();
3459
3460			if(row = pre["items"].shift()){
3461
3462				$(video.videoEl.ads).on("error.ads", function(){
3463					_onEndedPREAds(false, row);
3464				});
3465				
3466				_setVolume();
3467
3468				video.videoEl.ads.src = _getSource(row.src);
3469				video.videoEl.ads.load();
3470				video.adsUrl[0].href = row.url;
3471				video.adsID = row.id;
3472				video.adsOnClicked = row.events.on_clicked;
3473				video.adsOnEmitted = row.events.on_emitted;
3474				video.adsOnTimeupdate = row.events.on_timeupdate;
3475				
3476				video.isPreAdsFirstPlay = true;
3477
3478				$(video.videoEl.ads).one("play.firstPlayAdsEmitted", function(){
3479					_toggleAds(true);
3480					_stats.player("newAd");
3481					_stats.player("play");
3482
3483					video.isPreAdsFirstPlay = false;
3484
3485					_hit(video.adsOnEmitted);
3486					_log(["_hit :: onEmitted", video.adsOnEmitted]);
3487				});
3488
3489			}
3490
3491		}
3492
3493		function _setCuePoints(points) {
3494			var adsHtml = "";
3495
3496			for(var i = 0, l = points.length; i < l; i++){
3497				var left = (points[i] * 100);
3498				adsHtml += '<i style="left:' + left + '%" id="ads' + video.uniq + '_' + parseInt(left) + '"></i>';
3499			}
3500
3501			$(video.progress.ads).html(adsHtml);
3502		}
3503		function _clearCuePoints(offset) {
3504			video.tmpCuePoints = video.tmpCuePoints || video.vast && video.vast.cuePoints.filter(function(point) {
3505				return point > 0;
3506			}) || [];
3507
3508			if(!video.tmpCuePoints.length) return;
3509
3510			video.tmpCuePoints = video.tmpCuePoints.filter(function(point) {
3511				if(!offset || point == offset) {
3512					var left = (point / video.videoEl.media.duration) * 100;
3513					$('#ads' + video.uniq + '_' + parseInt(left)).remove();
3514				} else {
3515					return point;
3516				}
3517			});
3518		}
3519
3520		function _setupAdsMID(){
3521
3522			/* skip mid_roll ads - on iPad main video is freezing after ad's end */
3523			if(isiPad){
3524				video.firstPlay = true;
3525				return;
3526			}
3527
3528			var mid = video.ads["offsets"];
3529			_setCuePoints(mid);
3530
3531			video.firstPlay = true;
3532
3533			$(video.videoEl.ads).on("play pause", _checkPlaying);
3534			$(video.videoEl.ads).on("timeupdate.ads", _adsTimeUpdate);
3535
3536			var dur = video.videoEl.media.duration,
3537				durArr = [0, 1, 100, 6000];
3538
3539			if($.inArray(dur, durArr) !== -1 || isNaN(dur)){
3540
3541				$(video.videoEl.media).on("durationchange.durAds", function(e){
3542				
3543					if($.inArray(e.target.duration, durArr) === -1 && !isNaN(e.target.duration)){
3544
3545						_setAdsListener(mid.shift());
3546
3547						$(video.videoEl.media).off("durationchange.durAds");
3548					}
3549
3550				});
3551
3552			}
3553			else{
3554				_setAdsListener(mid.shift());
3555			}
3556
3557		}
3558
3559		function _checkAfterAds(){
3560
3561			if(video.init.muted/* || video.init.autoplay && isAndroid*/) {
3562				video.media.muted = false;
3563				_toggleMute(true);
3564			}
3565
3566			_positionMemorySet();
3567
3568		}
3569		function _checkBeforeBegin(){
3570
3571			video.firstPlay = true;
3572
3573		}
3574		function _setupListeners(){
3575			/* setup listeners */
3576			_listeners();
3577
3578			_checkAfterAds();
3579			_checkBeforeBegin();
3580		}
3581
3582		/**
3583		 * private init of videoPlayer
3584		 * returns API for later use
3585		 * API is stored in emitter DOM Object
3586		 * @return {Object}
3587		 *  - media:		video DOM element
3588		 *  - play:			play video
3589		 *  - pause:		pause video
3590		 *  - toggle:		toggle play/pause video
3591		 *  - seek:			seek { Number (seconds) || String (percent: "35%") }
3592		 *  - volume:		volume { Number (0-10) || String (percent: "35%") }
3593		 *  - toggleMute:	toggle mute
3594		 *  - toggleFullscreen: toggle fullscreen
3595		 */
3596		function _init(){
3597
3598			video.media = $(video.container)[0];
3599
3600			/* store init values */
3601			video.init = {};
3602			/* strange behavior on Chrome - muted returns false even if attr is defined */
3603			video.init.muted = video.media.muted || video.media.getAttribute('muted') != null;
3604			video.init.controls = video.media.controls;
3605			video.init.autoplay = video.media.autoplay || ($(video.media).attr('data-autoplay') == "true");
3606
3607			/* store time values */
3608			video.time = {};
3609
3610			video.supported = api.supported();
3611
3612			if(!video.supported.video){
3613				return false;
3614			}
3615
3616			/* get uniq || random value for labels */
3617			var tmpmedia;
3618			video.uniq = (tmpmedia = $(video.media)).attr('data-id') || video.media.id || hash(tmpmedia.find('source').attr('src')) || -Math.floor(Math.random() * 10000);
3619
3620			/*
3621			 *	sets controls and autoplay to false, and preload to only metadata
3622			 *	autoplay will be set again later > ado Object
3623			 */
3624			video.media.controls = video.media.autoplay = false;
3625			video.media.preload = 'metadata';
3626
3627
3628			/* setup all HTML markup */
3629			_setupHTML();
3630
3631			/* setup elements for interial use */
3632			_setupElements();
3633
3634			/* setup volume from localStorage */
3635			_setVolume();
3636
3637			/* setup classes */
3638			_setupMedia(function(){
3639
3640				if(isOldAndroid) {
3641					//cfg.vast = iOSVersion >= 10 ? cfg.vast || false;
3642					cfg.ads = false;
3643				}
3644				if(isIEMobile) {
3645					cfg.ads = cfg.vast = false;
3646				}
3647
3648				if(cfg.vast) {
3649
3650					new Vast(function(vast) {
3651
3652						video.vast = vast;
3653
3654						_setCuePoints(vast.cuePoints.filter(function(point) {
3655							return point > 0;
3656						}).map(function(point) {
3657							return point / video.videoEl.media.duration;
3658						}));
3659
3660						video.vastActive = true || vast.cuePoints.filter(function(point) {
3661							return point === 0;
3662						}).length > 0;
3663
3664						_setVolume();
3665
3666						/* setup listeners */
3667						_listeners();
3668
3669						video.firstPlay = true;
3670
3671						_checkAfterAds();
3672
3673						if(!vast.cuePoints.length) {
3674							_checkBeforeBegin();
3675						}
3676
3677						_stats.prism("AdBlock/Nie");
3678						
3679					}, !config.adblockInfoFile ? _setupListeners : function(){
3680						var domain = window.location.href,
3681						domain = domain.replace(/(http:\/\/|https:\/\/)|(www\.)/g, "").split("/")[0],
3682						subclass = config.classes.adblock.subclasses[domain] || config.classes.adblock.subclasses.default;
3683
3684						video.videoEl.container[0].insertAdjacentHTML('afterend', [
3685								'<div class="'+config.classes.adblock.container+ (subclass?' '+subclass:'')+'">',
3686									'<div class="'+config.classes.adblock.inner+'">',
3687										'<div class="'+config.classes.adblock.inner2+'">',
3688											'<p class="'+config.classes.adblock.header+'">Wyłącz oprogramowanie do blokowania reklam, aby obejrzeć ten materiał</p>',
3689											'<p class="'+config.classes.adblock.info+'">Dzięki reklamom wszystkie nasze materiały możesz oglądać za darmo. <a href="'+config.adblockInfoFile+'" class="'+config.classes.adblock.color+'">Sprawdź jak wyłączyć blokowanie reklam</a></p>',
3690											'<a href="javascript:window.location.reload(true)" class="'+config.classes.adblock.button+'">
3690Spróbuj ponownie<span class="'+config.classes.adblock.arrow+'"></span></a>',
3691											'<p class="'+config.classes.adblock.info, config.classes.adblock.info2+'">Nie używasz oprogramowania do blokowania reklam, lecz nadal nie możesz odtworzyć materiału? Sprawdź połączenie z Internetem i spróbuj ponownie</p>',
3692										'</div>',
3693									'</div>',
3694								'</div>'
3695							].join("\n")
3696						);
3697
3698						var adblock 			= {};
3699						adblock.container		= _getElements("." + cfg.classes.adblock.container);
3700						adblock.container_640px = cfg.classes.adblock.container_640px;
3701						adblock.container_480px = cfg.classes.adblock.container_480px;
3702						adblock.container_mob_320px = cfg.classes.adblock.container_mob_320px;
3703						adblock.container_mob 	= cfg.classes.adblock.container_mob;
3704
3705						function _resizeAdblock(){
3706							var adblockContainer = $(adblock.container);
3707							var adblockContainerWidth = $(adblock.container)[0].offsetWidth;
3708							adblockContainer.removeClass(adblock.container_640px)
3709								.removeClass(adblock.container_480px)
3710								.removeClass(adblock.container_mob_320px)
3711								.removeClass(adblock.container_mob);
3712			
3713							if(adblockContainerWidth>=640) adblockContainer.addClass(adblock.container_640px);
3714							else if(adblockContainerWidth>=480) adblockContainer.addClass(adblock.container_480px);
3715							else if(adblockContainerWidth>=325) adblockContainer.addClass(adblock.container_mob_320px);
3716							else adblockContainer.addClass(adblock.container_mob);
3717						}
3718
3719						_resizeAdblock();
3720			
3721						function debounce(func, wait, immediate) {
3722							var timeout;
3723							return function() {
3724								var context = this, args = arguments;
3725								var later = function() {
3726									timeout = null;
3727									if (!immediate) func.apply(context, args);
3728								};
3729								var callNow = immediate && !timeout;
3730								clearTimeout(timeout);
3731								timeout = setTimeout(later, wait);
3732								if (callNow) func.apply(context, args);
3733							};
3734						};
3735
3736						$(window).on("resize", debounce(_resizeAdblock, 250));
3737
3738						_stats.prism("AdBlock/Tak");
3739					}); 
3740
3741				} else if(cfg.ads) {
3742
3743					$.getJSON(cfg.ads, function(data, status, xhr){
3744
3745						if(status == "success"){
3746
3747							var ads = { "offsets" : [] }, key;
3748
3749							for(var i in data){
3750								
3751								key = data[i]["offset"];
3752
3753								if(!ads[key]){
3754									
3755									ads[key] = { "items" : [] , "total" : 0 };
3756
3757								}
3758
3759								ads[key]["items"].push({
3760									"id": i,
3761									"duration" : data[i]["dur"],
3762									"offset" : data[i]["offset"],
3763									"url" : data[i]["url"],
3764									"events" : {
3765										"on_emitted" : data[i]["on_emitted"],
3766										"on_clicked" : data[i]["on_clicked"],
3767										"on_timeupdate" : data[i]["on_timeupdate"] || []
3768									},
3769									"src" : {
3770										"webm" : data[i]["srcreq"] && data[i]["srcreq"][0]["url"] || "",
3771										"mp4" : data[i]["srcreq"] && data[i]["srcreq"][1]["url"] || "",
3772										"mobile" : data[i]["srcreq"] && data[i]["srcreq"][2]["url"] || ""
3773									}
3774								});
3775								ads[key]["total"] += parseInt(data[i]["dur"]);
3776
3777								if(key != 0 && $.inArray(key, ads["offsets"]) === -1) ads["offsets"].push(key);
3778
3779							}
3780
3781							video.ads = ads;
3782
3783							/* setup listeners */
3784							_listeners();
3785
3786							/* setup listeners */
3787							if(!video.isError) _setupAds();
3788
3789							_checkAfterAds();
3790
3791							if(!ads[0] && !ads["offsets"].length){
3792								_checkBeforeBegin();
3793							}
3794
3795						} else {
3796							_setupListeners();
3797						}
3798
3799					}, {credentials: true});
3800
3801				} else {
3802
3803					/*
3804					 * setup listeners
3805					 * skip frame - iPad
3806					 */
3807					setTimeout(_setupListeners);
3808
3809				}
3810
3811				/* callback onInit */
3812				if(typeof cfg.onInit === "function"){
3813					setTimeout(function(){
3814						cfg.onInit(video, returnApi);
3815					}, 200);
3816				}
3817
3818				_log(["_init", video]);
3819
3820			});
3821
3822			return true;
3823
3824		}
3825
3826		function Vast(success, error) {
3827
3828			var self = this,
3829				ended = false,
3830				autostart = null,
3831				firstPlay = false,
3832				isInit = false,
3833				videoContentEl = video.videoEl.media,
3834				duration = videoContentEl.duration || cfg.duration,
3835				adContainerEl,
3836				adContainer,
3837				adLoader,
3838				adRequest,
3839				adManager,
3840				AD,
3841				ADisPaused,
3842				interval,
3843				errorTimeout,
3844				_ = {
3845					leftAdsDuration: 0,
3846					name: null,
3847					size: 0,
3848					offset: 0
3849				};
3850
3851			function initUI() {
3852				adContainerEl = document.createElement('div');
3853				adContainerEl.className = cfg.classes.vast.container;
3854				video.videoEl.container[0].appendChild(adContainerEl);
3855
3856				video.container.addClass(cfg.classes.state.vast);
3857			}
3858
3859			function destroyUI() {
3860				video.videoEl.container[0].removeChild(adContainerEl);
3861				video.container.removeClass(cfg.classes.state.vast);
3862				_clearCuePoints();
3863			}
3864
3865			function destroy() {
3866				adManager && adManager.destroy();
3867				adContainer && adContainer.destroy();
3868				destroyUI();
3869			}
3870
3871			function initIMA(vast) {
3872				autostart = video.init.autoplay;
3873				ended = false;
3874
3875				// clean up
3876				adContainer && destroy();
3877
3878				initUI();
3879
3880				google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);
3881				google.ima.settings.setLocale('pl');
3882				
3883				adContainer = new google.ima.AdDisplayContainer(adContainerEl, videoContentEl);
3884
3885				adLoader = new google.ima.AdsLoader(adContainer);
3886				
3887				adRequest = new google.ima.AdsRequest();
3888				adRequest.adsResponse = vast;
3889
3890				adLoader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function(e) {
3891					_log(['VAST :: adLoader: ' + e.getError()], 'error');
3892					destroy();
3893					error(e);
3894				}, false);
3895
3896				adLoader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function(event) {
3897					success(initManager(event));
3898				}, false);
3899
3900				function request(opts) {
3901					if(opts) {
3902						adRequest.setAdWillAutoPlay(opts.autoplayAllowed);
3903						adRequest.setAdWillPlayMuted(opts.autoplayRequiresMuted);
3904					}
3905
3906					adLoader.requestAds(adRequest);
3907				}
3908
3909				if(autostart) {
3910					checkIfCanAutoplay(request);
3911				} else {
3912					request();
3913				}
3914			}
3915
3916			function initManager(event) {
3917				var adsRenderingSettings = new google.ima.AdsRenderingSettings();
3918				adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
3919  
3920				adManager = event.getAdsManager(videoContentEl, adsRenderingSettings);
3921
3922				setListeners(adManager);
3923				setVolumeState(true);
3924
3925				self.cuePoints = adManager.getCuePoints();
3926
3927				return self;
3928			}
3929
3930			function startRemainingTime() {
3931				interval = setInterval(function() {
3932					if(AD) {
3933						var remaining = adManager.getRemainingTime(),
3934							timeLeft = _.leftAdsDuration + remaining;
3935
3936						_vastTimeUpdate(timeLeft);
3937					}
3938				}, 300);
3939			}
3940
3941			function stopRemainingTime() {
3942				clearInterval(interval);
3943			}
3944
3945			function setVolumeState(init) {
3946				if(!init && autostart && !firstPlay) {
3947					return;
3948				}
3949
3950				adManager && adManager.setVolume(
3951					video.videoEl.media.muted
3952						? 0
3953						: video.videoEl.media.volume
3954				);
3955			}
3956
3957			function setListeners(manager) {
3958
3959				if(isiPhone) {
3960					video.videoEl.media.addEventListener('webkitendfullscreen', function() {
3961						var fs = document.fullScreenElement || document.webkitIsFullScreen == true || document.mozFullScreen || document.msFullscreenElement;
3962						if(!fs) {
3963							video.container.off('touchstart.iosFs').on('touchstart.iosFs', function() {
3964								video.videoEl.media.webkitEnterFullscreen();
3965							});
3966						}
3967					}, false);
3968				}
3969
3970				manager.addEventListener(google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, function(event) {
3971					video.vastActive = false;
3972					_toggleAds(false);
3973
3974					if(_.name) {
3975						_stats.prism(_.name + "Roll_KoniecBloku", _.size, _.current - 1);
3976						if(_.name !== "Pre") _stats.redevents("end " + _.name.toLowerCase() + "Roll");
3977					}
3978
3979					if(!video.videoEl.media.ended) {
3980						_play();
3981						_checkPlaying();
3982					}
3983
3984					stopRemainingTime();
3985				});
3986
3987				manager.addEventListener(google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, function(event) {
3988					AD = event.getAd();
3989					var pod = AD.getAdPodInfo(),
3990						offset = pod.getTimeOffset(),
3991						adType = function() {
3992							switch(offset) {
3993								case -1:
3994									return "Post";
3995								case 0:
3996									return "Pre";
3997								default:
3998									return "Mid"
3999							}
4000						}();
4001
4002					_.id = AD.getAdId();
4003					_.leftAdsDuration = pod.getMaxDuration();
4004					_.duration = AD.getDuration();
4005					_.name = adType;
4006					_.size = pod.getTotalAds();
4007					_.offset = offset === -1 ? duration : offset;
4008					_.current = 1;
4009
4010					if(offset > 0) {
4011						videoContentEl.pause();
4012						_clearCuePoints(_.offset);
4013						_stats.player("break");
4014					}
4015
4016					_toggleAds(true);
4017					_checkPlaying();
4018					video.vastActive = true;
4019
4020					_stats.prism(_.name + "Roll_StartBloku", _.size, _.current);
4021					_stats.redevents("begin " + _.name.toLowerCase() + "Roll");
4022				});
4023
4024				manager.addEventListener(google.ima.AdEvent.Type.CLICK, function(event) {
4025					video.vastIsIMAClicked = true;
4026				});
4027
4028				manager.addEventListener(google.ima.AdEvent.Type.STARTED, function(event) {
4029
4030					firstPlay = true;
4031					ADisPaused = false;
4032					AD = event.getAd();
4033					var pod = AD.getAdPodInfo(),
4034						offset = pod.getTimeOffset();
4035					
4036					_.id = AD.getAdId();
4037					_.duration = AD.getDuration();
4038					_.leftAdsDuration = _.leftAdsDuration - _.duration;
4039
4040					setVolumeState();
4041					startRemainingTime();
4042					_focusChange();
4043
4044					_stats.prism(_.name + "Roll", _.size, _.current++);
4045					_stats.player("newAd", {id: _.id, duration: _.duration}, _.offset);
4046					_stats.player("play", {id: _.id, duration: _.duration}, _.offset);
4047
4048					if(isiPhone && video.videoEl.media.poster) {
4049						video.videoEl.media.removeAttribute('poster');
4050					}
4051				});
4052
4053				manager.addEventListener(google.ima.AdEvent.Type.PAUSED, function(e) {
4054
4055					ADisPaused = true;
4056					_checkPlaying();
4057
4058					_stats.prism("Pauza", _.size, _.current - 1);
4059					_stats.player("pause", {id: _.id, duration: _.duration}, _.offset);
4060				});
4061
4062				manager.addEventListener(google.ima.AdEvent.Type.COMPLETE, function(e) {
4063					stopRemainingTime();
4064
4065					_stats.player("complete", {id: _.id, duration: _.duration}, _.offset);
4066				});
4067
4068				manager.addEventListener(google.ima.AdEvent.Type.RESUMED, function(e) {
4069					ADisPaused = false;
4070					_checkPlaying();
4071
4072					_stats.prism("Start", _.size, _.current - 1);
4073					_stats.player("play", {id: _.id, duration: _.duration}, _.offset);
4074				});
4075
4076				// manager.addEventListener(google.ima.AdEvent.Type.VOLUME_CHANGED, function(t) {
4077				// 	currentTime: _.offset,
4078				// 	volume: manager.getVolume()
4079				// });
4080
4081				manager.addEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, function(e) {
4082					ended = true;
4083					_clearCuePoints();
4084				});
4085
4086				manager.addEventListener(google.ima.AdEvent.Type.CLICK, function() {
4087					manager.pause();
4088				});
4089
4090				manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function(e) {
4091					_log(['VAST :: adManager: ' + e.getError()], 'error');
4092					destroy();
4093					_toggleAds(false);
4094					video.vastActive = false;
4095					video.vast = null;
4096					_pause();
4097					_checkPlaying();
4098				});
4099			}
4100
4101			function loadIMAScript(success, error) {
4102				function onSuccess() {
4103					loadVAST(success, error);
4104				}
4105				function onError(e) {
4106					ended = true;
4107					error && error();
4108				}
4109				DOM.load('//imasdk.googleapis.com/js/sdkloader/ima3.js', onSuccess, onError);
4110			}
4111
4112			function loadVAST(success, error) {
4113				DOM.xhr({
4114					url: cfg.vast,
4115					credentials: true,
4116					onload: function(_, xhr) {
4117						function _init() {
4118							clearTimeout(errorTimeout);
4119							success(createVMAP(xhr.responseXML, xhr.responseText));
4120						}
4121
4122						duration = videoContentEl.duration || cfg.duration;
4123
4124						if(duration) {
4125							_init();
4126						} else {
4127							$(videoContentEl).one('loadedmetadata.vast', _init);
4128							errorTimeout = setTimeout(function() {
4129								$(videoContentEl).off('loadedmetadata.vast');
4130								_init();
4131								_log('VAST :: loadVast > timeout', 'error');
4132							}, 5000);
4133						}
4134					},
4135					onerror: error
4136				})
4137			}
4138
4139			function createVMAP(xml, text) {
4140				if(xml && xml.firstChild.tagName !== 'VAST') {
4141					return text;
4142				}
4143
4144				var vast = $(xml).find('VAST'),
4145					ads = vast.find('Ad');
4146
4147				function _wraper(ads) {
4148					return '<vmap:VMAP xmlns:vmap="http://www.iab.net/videosuite/vmap" version="1.0">' + ads + '</vmap:VMAP>';
4149				}
4150				function _adbreak(ads) {
4151					return ads.map(function(ad) {
4152						return [
4153							'<vmap:AdBreak timeOffset="' + ad.offset + '" breakType="linear">',
4154							'	<vmap:AdSource allowMultipleAds="true" followRedirects="true">',
4155							'		<vmap:VASTAdData>',
4156							'			<VAST version="3.0">' + ad.data + '</VAST>',
4157							'		</vmap:VASTAdData>',
4158							'	</vmap:AdSource>',
4159							'</vmap:AdBreak>'
4160						].join("\n");
4161					}).join("\n");
4162				}
4163
4164				function _pad(x) {
4165					return (x < 10 ? "0" : "") + x;
4166				}
4167				function _getOffset(ad) {
4168					var offset = (ad.attributes.offset || {value: '0%'}).value;
4169					switch(offset) {
4170						case '0%':
4171							return 'start';
4172						case '100%':
4173							return 'end';
4174						default:
4175							var floatOffset = duration * (parseInt(offset) / 100);
4176
4177							if(!duration) {
4178								return 'skip';
4179							}
4180
4181							var s = floatOffset % 60,
4182								m = Math.floor(floatOffset / 60),
4183								h = Math.floor(floatOffset / 3600);
4184
4185							return _pad(h) + ':' + _pad(m) + ':' + _pad(s.toFixed(3));
4186					}
4187				}
4188				function _offset(ad) {
4189					switch((ad.attributes.block || {}).value) {
4190						case '0':
4191							return 'start';
4192						case '1':
4193							return 'end';
4194						default:
4195							return _getOffset(ad);
4196					}
4197				}
4198				function _findAdBreakByOffset(breaks, offset) {
4199					for(var i = 0, block; block = breaks[i]; i++) {
4200						if(block.offset === offset) return i;
4201					}
4202
4203					return -1;
4204				}
4205				function _ads(ads) {
4206					var breaks = [];
4207
4208					if('XMLSerializer' in window) {
4209						var XMLS = new XMLSerializer();
4210
4211						for(var i = 0, ad; ad = ads[i++]; ) {
4212							var offset = _offset(ad);
4213							
4214							if(offset == 'skip') continue;
4215
4216							var _id = _findAdBreakByOffset(breaks, offset),
4217								id = _id !== -1 ? _id : breaks.length,
4218								html = XMLS.serializeToString(ad);
4219
4220							if(breaks[id]) {
4221								breaks[id].data += html;
4222							} else {
4223								breaks.push({
4224									offset: offset,
4225									data: html
4226								});
4227							}
4228						}
4229					}
4230
4231					return breaks;
4232				}
4233
4234				return _wraper(_adbreak(_ads(ads)));
4235			}
4236
4237			function init() {
4238				loadIMAScript(initIMA, error);
4239			}
4240
4241			init();
4242
4243			this.pause = function() {
4244				adManager && adManager.pause();
4245			}
4246
4247			this.resume = function() {
4248				if(adManager) {
4249					if(ADisPaused) {
4250						adManager.resume();
4251					} else if (!isInit) {
4252						videoContentEl.load();
4253						adContainer.initialize();
4254
4255						try {
4256							adManager.init('100%', '100%', google.ima.ViewMode.NORMAL);
4257							adManager.start();
4258							isInit = true;
4259						} catch(e) {
4260							videoContentEl.play();
4261						}
4262					}
4263				}
4264			}
4265
4266			this.setVolumeState = setVolumeState;
4267
4268			this.isPaused = function() {
4269				return ADisPaused;
4270			}
4271
4272			this.contentComplete = function(callback) {
4273				if(ended) {
4274					callback();
4275				} else if(adManager) {
4276					var cb = function cbt() {
4277						ended = true;
4278						adManager.removeEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, cbt);
4279						callback();
4280					};
4281					adLoader.contentComplete();
4282					adManager.addEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, cb);
4283				} else {
4284					callback();
4285				}
4286			}
4287		}
4288
4289		if(!_init()){
4290			return false;
4291		}
4292
4293		var returnApi = {
4294			media:				video.media,
4295			isAds:				_isAds,
4296			isPaused:			_isPaused,
4297			shouldPlay:			_shouldPlay,
4298			instance:			_instance,
4299			play:				_play,
4300			pause:				_pause,
4301			toggle:				_toggle,
4302			seek:				_progSeek,
4303			volume:				_setVolume,
4304			toggleMute:			_toggleMute,
4305			toggleFullscreen:	_toggleFullscreen
4306		};
4307
4308		return returnApi;
4309
4310	}
4311
4312
4313	/**
4314	 * Check if supported
4315	 * @return {Object}
4316	 *  - range:		input[type=range]
4317	 *  - video:		video.canPlayType
4318	 *  - fullscreen:	requestFullscreen
4319	 *  - storage:		localStorage
4320	 */
4321	api.supported = function(){
4322		
4323		var range =		(function(){
4324							var i = document.createElement("input");
4325							i.setAttribute("type", "range");
4326							return i.type !== "text";
4327						})(),
4328			progress =	(document.createElement('progress').max !== undefined),
4329			video =		!!document.createElement("video").canPlayType,
4330			volume =	(function(){
4331							/* test for iOS which cannot set volume */
4332							var a = document.createElement('audio');
4333							a.volume = .5;
4334							return (a.volume == .5);
4335						})(),
4336			fullscreen = (document.fullscreenEnabled || 
4337							document.webkitFullscreenEnabled || 
4338							document.msFullscreenEnabled ||
4339							document.mozFullScreenEnabled) && (function(){
4340								var d = document.createElement("div");
4341								return ("requestFullscreen" in d
4342									|| "msRequestFullscreen" in d
4343									|| "mozRequestFullScreen" in d
4344									|| "webkitRequestFullScreen" in d);
4345						})(),
4346			storage =	(function(){
4347							try{
4348								if("localStorage" in window && window.localStorage != null){
4349									window.localStorage.setItem('localStorage', 1);
4350									window.localStorage.removeItem('localStorage');
4351									return true;
4352								}
4353								else return false;
4354							}
4355							catch(e){return false;}
4356						})(),
4357			animation = (function(){
4358							var animation = false,
4359								animationstring = 'animation',
4360								keyframeprefix = '',
4361								domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
4362								pfx  = '',
4363								elm = document.createElement('div');
4364
4365							if( elm.style.animationName !== undefined ) { animation = true; }    
4366
4367							if( animation === false ) {
4368								for( var i = 0; i < domPrefixes.length; i++ ) {
4369									if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
4370										pfx = domPrefixes[ i ];
4371										animationstring = pfx + 'Animation';
4372										keyframeprefix = '-' + pfx.toLowerCase() + '-';
4373										animation = true;
4374										break;
4375									}
4376								}
4377							}
4378
4379							return animation;
4380						})();
4381
4382		return {
4383			video: video,
4384			range: (range && progress && !isOpera),
4385			volume: volume,
4386			fullscreen: fullscreen,
4387			storage: storage,
4388			animation: animation
4389		};
4390
4391	}
4392
4393	/**
4394	 * Init videoPlayer
4395	 * @param {Object} options
4396	 * @return {Object} videoPlayer
4397	 */
4398	api.init = function(options){
4399
4400		config = $.extend(config, $.extend(defaults, $.extend(options, api.config)));
4401
4402		if(!config.enabled){
4403			return false;
4404		}
4405
4406		var elements	= $(config.selector),
4407			videos		= [];
4408
4409		for(var i = 0, l = elements.length; i < l; i++){
4410
4411			var el = elements[i];
4412
4413			if(typeof el.videoPlayer === "undefined"){
4414				/*
4415				 *	if vp == true
4416				 *		means videoPlayer successfully init,
4417				 *		means video has parentNode
4418				 *	  so return API to this parentNode
4419				 *  else
4420				 *		return false to el
4421				 */
4422
4423				var vp = new VideoPlayer(el);
4424				el = vp ? vp.media.parentNode.parentNode : el;
4425				el.videoPlayer = vp;
4426				api.els.push(vp);
4427			}
4428
4429			videos.push(el.videoPlayer);
4430
4431		}
4432
4433		return videos;
4434
4435	}
4436
4437	api.version = 2.4;
4438
4439	/* array of videoPlayers on current page */
4440	api.els = api.els || [];
4441
4442
4443	var returnEl = [];
4444	for(var i = 0, l = (api.buffer || []).length; i < l; i++){
4445		returnEl.push(api.init(api.buffer[i]));
4446	}
4447
4448	delete api.buffer;
4449
4450	return returnEl;
4451
4452}(this.videoPlayer = this.videoPlayer || {}, DOM, window, document));

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.