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.