PageSourceSearch

https://www.o2.cz/osobni/-a257503?field=data&_linka=a1505087

js o2.cz collected 2026-10-01 10:37:08 UTC 11,762 bytes, 422 lines download raw bytes

1/*
2	Terminologie:
3	- `hourStatus` je stav daný otevíracími hodinami; rozlišuje se
4		- "ONLINE": fakticky online nebo busy, podle dostupnosti operátora
5		- "OFFLINE": stav, kdy je call centrum zavřené
6	- `operatorStatus` je stav daný dostupností online operátora; detekuje se jen když je CC otevřené a má hodnoty
7		- "ONLINE": online stav
8		- "NOT_ONLINE": busy stav (zahrnuje i chybové stavy, kdy se zkrátka nepodařilo ověřit, že je operátor k dispozici)
9	- `status` nebo "efektivní stav" je stav vypočtený z těchto dvou, tj. jedna z hodnot "ONLINE", "OFFLINE", "BUSY"
10*/
11(function() {
12	
13	const LOOKUP_SELECTOR   = '.js3-cmb:not(.js3-cmb--initialized)'; // dosud neinicializované CMB
14	const INITIALIZED_CLASS = 'js3-cmb--initialized';                // třída přidávaná k inicializovaným elementům
15	const DATASET_PREFIX    = 'cmb';
16
17	/*
18	 * Výchozí nastavení
19	 */
20	const defaultOptions = {
21
22		// Perioda kontroly `operatorStatus`
23		checkMs: 5000,
24		checkMsWait: 6000,
25
26		// Výchozí hodnoty stavů:
27		operatorStatus: "NOT_ONLINE",
28		hourStatus: "OFFLINE",
29
30		// Třídy indikující stav:
31/*
32		classOffline: "o2-cmb--offline",
33		classBusy: "o2-cmb--waiting",
34		classOnline: "o2-cmb--success",
35*/
36
37		// Výjimky pro busy stav:
38		forceBusy: false,    // BUSY stav vynucený z instance (tj. nastavený pro daný asset napevno)
39		treatAsBusy: false,  // BUSY stav detekovaný v prohlížeči (jen počáteční hodnota - mění se)
40		deviceBusy: false,   // BUSY stav v závislosti na zařízení (jen počáteční hodnota - mění se)
41
42		// Parametry ovlivňující logiku deviceBusy:
43		desktopBusy: false,  // BUSY stav bude vynucený pro desktop a tablet
44		mobileBusy: true     // BUSY stav bude vynucený pro mobil
45	};
46
47	const instancesById = {}; // Mapa identifikátorů elementů s CMB na instance CMB objektů
48	
49	const instancesByFormId = {}; // Mapa formId na seznamy instancí s daným formId
50
51	addEventListener("resize", function() {
52		for (let id in instancesById) {
53			instancesById[id].setMedia();
54		}
55	});
56
57	const CMB = function(elm) {
58		
59		this.elm = elm;
60		
61		// Zajistíme, aby element měl identifikátor
62		let elmId = elm.getAttribute('id');
63		if (!elmId) {
64			elmId = 'cmb' + Math.floor(Math.random() * 10000000);
65			elm.setAttribute('id', elmId);
66		}
67		
68		this.calculateOptions();
69		
70		instancesById[elmId] = this;
71
72		if (this.options.formId) {
73			instancesByFormId[this.options.formId] = this;
74		}
75
76		this.scanDom();
77		this.render();
78	};
79
80	CMB.prototype = {
81
82		setMedia: function() {
83			var o = this.options;
84			var isSS = (window.innerWidth < 1024);
85			this.$deviceHidden.value = (isSS ? "SS" : "BS");
86			if (isSS) {
87				// Platí pravidla pro "mobil"
88				if (o.mobileBusy !== this.deviceBusy) {
89					this.updateDeviceBusy(o.mobileBusy);
90				}
91			} else {
92				// Platí pravidla pro "desktop"
93				if (o.desktopBusy !== this.deviceBusy) {
94					this.updateDeviceBusy(o.desktopBusy);
95				}
96			}
97		},
98	
99		calculateOptions: function() {
100
101			const ds = this.elm.dataset;
102			const o = this.options = Object.assign({}, defaultOptions);
103			
104			for (let name in ds) {
105				if (name.startsWith(DATASET_PREFIX)) {
106					let key =
107						name.charAt(DATASET_PREFIX.length).toLowerCase() +
108						name.substring(DATASET_PREFIX.length + 1);
109						
110					let val = ds[name];
111					switch (true) {
112					case val == "true":
113						val = true;
114						break;
115					case val == "false":
116						val = false;
117						break;
118					}
119					o[key] = val;
120				}
121			}
122		},
123
124		scanDom: function() {
125
126			const o = this.options;
127			const elm = this.elm;
128
129			this.operatorStatus = o.operatorStatus;
130			this.hourStatus     = o.hourStatus;
131			this.forceBusy      = o.forceBusy;
132			this.treatAsBusy    = o.treatAsBusy;
133			this.deviceBusy     = o.deviceBusy;
134
135			/*
136				Status se zrcadlí do skrytého formulářového pole:
137			*/
138			this.$statusHidden = elm.querySelector('.js3-cmb-status-hidden');
139
140			/*
141				Device se zrcadlí do skrytého formulářového pole:
142			*/
143			this.$deviceHidden = elm.querySelector('.js3-cmb-device');
144
145			/*
146				V DOM jsou elementy, které reprezentují každé přepnutí stavu `hourStatus`
147				z ONLINE (tj. online/busy) do OFFLINE nebo naopak. Tyto elementy byly
148				vygenerované na serveru, zde se načtou ve strukturované podobě.
149			*/
150			var hourStatusChanges = this.hourStatusChanges = [];
151
152			elm.querySelectorAll(".js3-cmb-status-change").forEach(function($content) {
153				hourStatusChanges.push({
154					timeout: $content.dataset.cmbTimeout,
155					hourStatus: $content.dataset.cmbHourStatus,
156					$content: $content
157				});
158			});
159
160			this.hourStatusIndex = 0; // Ukazatel na nejbližší dosud nepoužitou položku v `hourStatusChanges`.
161			this.$content = this.elm; // Ukazatel na blok obsahu, ve kterém se mají hledat aktuální textace
162			if (this.hourStatus == "ONLINE") {
163				this.$content = this.$content.querySelector(".js3-cmb-status-now");
164			}
165
166			this.contentChanged = false; // Příznak toho, že při některé z operací se změnila hodnota this.$content
167		},
168
169		unrender: function() {
170			this.clearHourStatusTimeout();
171			this.unbindChecks(); 
172		},
173
174		bindChecks: function() {
175			this.unbindChecks();
176			this.checkInterval = window.setInterval(
177				this.checkOperatorStatus.bind(this),
178				this.options.checkMs
179			);
180		},
181
182		unbindChecks: function() {
183
184			if(this.waitTimeout) {
185				window.clearTimeout(this.waitTimeout);
186				this.waitTimeout = false;
187			}
188
189			if (this.checkInterval) {
190				window.clearInterval(this.checkInterval);
191				this.checkInterval = false;
192			}
193		},
194
195		checkOperatorStatusFailed: function() {
196			this.setOperatorStatus("NOT_ONLINE");
197		},
198
199		checkOperatorStatusResult: function(response) {
200			response.text().then((data) => {
201				switch (data.toLowerCase()) {
202				case "online":
203					this.setOperatorStatus("ONLINE");
204					break;
205				case "busy":
206				case "offline":
207				case "exception":
208				default:
209					this.setOperatorStatus("NOT_ONLINE");
210					break;
211				}
212			});
213		},
214
215		/*
216			Kontrola stavu operátora (AJAX call).
217		*/
218		checkOperatorStatus: function() {
219			this.setOperatorStatus("NOT_ONLINE");
220			return;
221		},
222
223		setOfflineStatus: function() {
224			var o = this.options;
225//			this.$elm.removeClass(o.classOnline).removeClass(o.classBusy).addClass(o.classOffline);
226			this.$statusHidden.value = "OFFLINE";
227			this.updateView(this.$content);
228		},
229
230		setBusyStatus: function() {
231			var o = this.options;
232//			this.$elm.removeClass(o.classOnline).removeClass(o.classOffline).addClass(o.classBusy);
233			this.$statusHidden.value = "BUSY";
234			this.updateView(this.$content.querySelector(".js3-cmb-busy"));
235		},
236
237		setOnlineStatus: function() {
238			var o = this.options;
239//			this.$elm.removeClass(o.classOffline).removeClass(o.classBusy).addClass(o.classOnline);
240			this.$statusHidden.value = "ONLINE";
241			this.updateView(this.$content.querySelector(".js3-cmb-online"));
242		},
243
244		updateView: function($tpl) {
245			var elm = this.elm;
246			$tpl.querySelectorAll(".js3-cmb-item").forEach(function($src) {
247				const $tgt = elm.querySelector('[data-cmb-match-of="' + $src.dataset.cmbMatch + '"]');
248				if ($tgt) {
249					var c = $src.dataset.cmbMatchClass;
250					switch (true) {
251					case !!c:
252						$tgt.className = c;
253						break;
254					case $tgt.matches('input'):
255						$tgt.setAttribute("placeholder", $src.getAttribute("placeholder"));
256						break;
257					default:
258						$tgt.innerHTML = $src.innerHTML;
259					}
260/*
261					$tgt.setAttribute("title", $src.getAttribute("title"));
262*/
263				}
264			});
265		},
266
267
268		/*
269			Aktualizace flagu `deviceBusy` a navázané akce.
270		*/
271		updateDeviceBusy: function(newValue) {
272			this.deviceBusy	= newValue;
273			if (this.hourStatus == "ONLINE") {
274				this.busyRecheck();
275			}
276		},
277
278		setHourStatusTimeout: function() {
279
280			var hourStatusChanges = this.hourStatusChanges;
281			
282			if (this.hourStatusIndex < hourStatusChanges.length) {
283				if (this.hourStatusTimeout) {
284					window.clearTimeout(this.hourStatusTimeout);
285				}
286				this.hourStatusTimeout = window.setTimeout(this.advanceHourStatus.bind(this), hourStatusChanges[this.hourStatusIndex].timeout);
287			}
288		},
289
290		/*
291			Akce prováděné při vstupu do `hourStatus` rovného `ONLINE` a při dalších akcích,
292			které mohou změnit efektivní force busy stav - tzn. při změně některého z busy flagů.
293		*/
294		busyRecheck: function() {
295			this.setOperatorStatus("NOT_ONLINE"); // dokud neproběhne check s kladným výsledkem, je operátor brán jako busy
296			if (this.forceBusy || this.treatAsBusy || this.deviceBusy) {
297				this.unbindChecks();
298			} else {
299				this.checkOperatorStatus();
300				this.bindChecks();
301			}
302		},
303
304		clearHourStatusTimeout: function() {
305			if (this.hourStatusTimeout) {
306				window.clearTimeout(this.hourStatusTimeout);
307				this.hourStatusTimeout = false;
308			}
309		},
310
311		/*
312			Posune hourStatus - použije nejbližší položku z pole změn a ukazatel posune
313			na další záznam v poli změn.
314		*/
315		advanceHourStatus: function() {
316			if (this.hourStatusIndex >= this.hourStatusChanges.length) {
317				return;
318			} 
319			var change = this.hourStatusChanges[this.hourStatusIndex];
320			this.setHourStatus(change.hourStatus, change.$content);
321			this.hourStatusIndex++;
322			this.setHourStatusTimeout();
323		},
324
325		/*
326			Aktualizuje hourStatus, ve výsledku včetně textace apod.
327		*/
328		setHourStatus: function(hourStatus, $content) {
329
330			this.$content = $content;
331			this.contentChanged = true;
332			this.hourStatus = hourStatus;
333
334			var o = this.options;
335
336			switch (hourStatus) {
337			case "ONLINE":
338				this.busyRecheck();
339				break;
340			case "OFFLINE":
341				this.unbindChecks();
342				this.setOfflineStatus();
343				break;
344			}
345		},
346
347		setOperatorStatus: function(operatorStatus) {
348			if (this.hourStatus == "ONLINE" && ((operatorStatus != this.operatorStatus) || this.contentChanged)) {
349				switch (operatorStatus) {
350				case "ONLINE":
351					this.setOnlineStatus();
352					break;
353				case "NOT_ONLINE":
354					this.setBusyStatus();
355					break;
356				}
357			}
358			this.operatorStatus = operatorStatus;
359			this.contentChanged = false;
360		},
361
362
363		render: function() {
364
365			const isSS = (window.innerWidth < 1024);
366			const o = this.options;
367
368			this.$deviceHidden.value = (isSS ? "SS" : "BS");
369
370			this.deviceBusy = (
371				isSS ?
372				o.mobileBusy :
373				o.desktopBusy
374			);
375
376			this.setHourStatusTimeout();
377
378			if (this.hourStatus == "ONLINE") {
379					this.checkOperatorStatus();
380					this.waitTimeout = window.setTimeout(() => {
381						this.bindChecks();
382						this.waitTimeout = false;
383					}, o.checkMsWait);
384			}
385		}
386	};
387
388	/*
389	 * Inicializace instance CMB na daném elementu
390	 */
391	const cmbInit = function(elm) {
392
393		elm.classList.add(INITIALIZED_CLASS); // označíme element jako inicializovaný
394
395		new CMB(elm);
396	};
397	
398	/*
399	 * Prohledání elementu a jeho potomků, inicializace všech nových CMB.
400	 */
401	const cmbLookup = function(node) {
402
403		if (!node || !node.querySelectorAll) { return; }
404
405		const cmbLs = node.querySelectorAll(LOOKUP_SELECTOR);
406		cmbLs.forEach(cmbInit);
407		
408		if (node.matches(LOOKUP_SELECTOR)) {
409			cmbInit(node);
410		}
411	};
412
413	// Dohledání CMB k inicializaci pouštíme nejprve v celém body, následně v každém elementu, který byl do DOM
414	// přidaný asynchronní aktualizací (která konvenčně volá událost `d3update`).
415
416	cmbLookup(document.body);
417
418	window.addEventListener('d3update', (event) => {
419	    cmbLookup(event.detail.new_node);
420	});
421	
422})();

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.