var bufferFiles = {}; //region [PROTOTYPES] Element.prototype.addClass = function (name) { this.classList.add(name) } Element.prototype.removeClass = function (name) { this.classList.remove(name) } Element.prototype.toggleClass = function (name) { if (this.classList.contains(name)) { this.classList.remove(name) } else { this.classList.add(name) } } Element.prototype.switchClasses = function (class1, class2) { if (this.classList.contains(class1)) { console.log(class1, class2); this.classList.remove(class1) this.classList.add(class2) } else if (this.classList.contains(class2)) { this.classList.remove(class2) this.classList.add(class1) } } Element.prototype.hasClass = function (className) { return this.classList.contains(className); } //endregion const all = (s, f) => { const elements = document.querySelectorAll(s); if (f) { elements.forEach(e => { f(e); }) } else { return elements; } }; /** @return Element **/ const one = (s, c) => { if (c) { let e = document.createElement('div'); e.className = s; c.appendChild(e); return e; } return document.querySelector(s); }; const appendElem = (t, c, p) => { let e = document.createElement(t); e.className = c + ' appear'; p.appendChild(e); setTimeout(t => { e.addClass('visible'); }, 10) return e; }; const prependElem = (t, c, p) => { let e = document.createElement(t); e.className = c; p.prepend(e); setTimeout(t => { e.addClass('visible'); }, 10) return e; }; const addImg = (c, p, src, type) => { let e = document.createElement('img'); e.className = c; e.src = '/get-img/' + src; if (type === 'prepend') { p.prepend(e); } else { p.appendChild(e); } e.addEventListener('load', function () { setTimeout(t => { e.addClass('visible'); }, 10) }); return e; }; const request = obj => { let serializer = d => { return Object.entries(d).map(([key, val]) => `${key}=${val}`).join('&'); }; obj.post = obj.post || ''; obj.get = obj.get ? '?' + serializer(obj.get) : ''; obj.url = obj.url || window.location.href; obj.dataType = obj.dataType || 'json'; obj.done = obj.done || null; const type = obj.post !== '' ? 'post' : 'get'; const xhr = new XMLHttpRequest(); xhr.open(type, obj.url + obj.get); if (!(obj.post instanceof FormData) && type === 'post') { xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); obj.post = serializer(obj.post); } xhr.upload.onprogress = function (e) { if (e.lengthComputable) { var percentage = Math.round((e.loaded / e.total) * 100); if (typeof obj.progress !== 'undefined') { obj.progress(percentage) } } }; xhr.onload = () => { //console.log(xhr.responseText) if (typeof obj.done !== 'undefined') { if (obj.dataType === 'json') { try { obj.done(JSON.parse(xhr.responseText)); } catch (e) { } } else { obj.done(xhr.responseText); } } }; xhr.send(obj.post); }; const error = (name, message) => { all('.error-bubble', function (e) { e.remove(); }); const element = one('[name="' + name + '"]'); element.parentNode.classList.add('form-error'); element.focus(); const elementYOffset = element.parentNode.offsetTop; window.scroll(0, elementYOffset - 100); console.log(elementYOffset); //window.pageYOffset = element.parentNode.offsetTop; const errorMsg = one('error-bubble', element.parentNode); errorMsg.innerText = message; setTimeout(() => { if (errorMsg) { errorMsg.remove(); } }, 5000); element.oninput = function () { if (errorMsg) { errorMsg.remove(); element.parentNode.classList.remove('form-error'); } } }; const errorElement = (element, message) => { all('.error-bubble', function (e) { e.remove(); }); element.parentNode.classList.add('form-error'); element.focus(); const elementYOffset = element.parentNode.offsetTop; window.scroll(0, elementYOffset - 100); console.log(elementYOffset); //window.pageYOffset = element.parentNode.offsetTop; const errorMsg = one('error-bubble', element.parentNode); errorMsg.innerText = message; setTimeout(() => { if (errorMsg) { errorMsg.remove(); } }, 5000); element.oninput = function () { if (errorMsg) { errorMsg.remove(); element.parentNode.classList.remove('form-error'); } } }; const ready = () => { all('form').forEach(e => { e.onsubmit = () => { if (e.dataset.type !== 'search') { event.preventDefault(); if (typeof CKEDITOR !== "undefined") { for (let instanceName in CKEDITOR.instances) { CKEDITOR.instances[instanceName].updateElement(); } } e.addClass('form-wait'); const waitingType = !one('.waiting-tape') ? one('waiting-tape', document.body) : null; const formData = new FormData(e); Object.keys(bufferFiles).forEach(f => { formData.append(f, bufferFiles[f]); }); request({ post: formData, done: data => { console.log(data); if (data.error) { error(data.field, data.message); } if (data.html) { const htmlContent = one('#html_content'); htmlContent.innerHTML = data.html; } if (data.redirect) { window.location.href = data.redirect; } if (data.reload) { window.location.reload(); } const smartRedirect = function (model_id) { const params = new URLSearchParams(window.location.search); if (params.get('back')) { window.location.href = atob(params.get('back')); } else { if (params.get('id')) { window.location.reload(); } else { window.location.href = `${window.location.href}&id=${model_id}` } } } console.log(data, 'test'); if (data.smart_redirect && data.model_id) { smartRedirect(data.model_id) } else { e.removeClass('form-wait'); if (waitingType) waitingType.remove() } } }); } else { event.preventDefault(); const formData = new FormData(e); const d = []; for (let key of formData.keys()) { const value = formData.get(key); if (value) { d.push(key + ':' + formData.get(key)) } } const queryStr = d.join('|'); if (queryStr) { window.location.href = '?q=' + d.join('|'); } else { window.location.href = window.location.href.split('?')[0]; } } } }); all('[data-image-name]', e => { setSingleFileImage(e); }); all('.historyButton', e => { setHistoryButton(e); }) all('.positionButton', e => { setPositionButton(e); }) dataFormat(); document.querySelectorAll('[data-pdf]').forEach(pdf => { pdf.classList.add('pointer'); pdf.addEventListener('click', () => { modal.modalFrame(pdf.dataset.pdf); }) }) document.querySelectorAll('[data-model-3d]').forEach(model3d => { model3d.classList.add('pointer'); model3d.addEventListener('click', () => { modal.modalFrame(model3d.getAttribute('data-model-3d')); }) }) }; window.getUri = function (query) { if (window.location.search) { return window.location.href + '&' + query; } else { return window.location.href + '?' + query; } } window.onload = ready; const modal = {}; modal.sessionLeft = (msg, time, resetLabel, ev, leftEv) => { const modalBackground = one('modal-background', document.body); const modal = one('modal', modalBackground); setTimeout(() => { modal.addClass('modal-open'); }, 0) const message = one('modal-message ct', modal); if (typeof msg === 'string' || msg instanceof String) { message.innerHTML = msg; } else { message.style.height = 'calc(100% - 40px)'; message.appendChild(msg); } const timer = document.createElement('span'); timer.innerHTML = time; const sec = document.createElement('span'); sec.innerHTML = ' сек.'; var timeOut; const timeRun = () => { let ct = parseInt(timer.innerHTML); timeOut = setTimeout(() => { ct--; if (ct === 0) { modal.removeClass('modal-open'); setTimeout(() => { modalBackground.remove(); }, 400) setTimeout(() => { modal.remove(); }, 1000); if (leftEv) { clearTimeout(timeOut) leftEv(); } } else { timer.innerHTML = ct; timeRun(); } }, 1000) } timeRun(); message.appendChild(timer) message.appendChild(sec) const modalButtons = one('modal-buttons ct', modal) const refresh = one('modal-button-confirm btn-ib btn-default', modalButtons) resetLabel = resetLabel || 'Обнови сесията' refresh.innerHTML = ' ' + resetLabel; refresh.addEventListener('click', () => { modal.removeClass('modal-open'); setTimeout(() => { modalBackground.remove(); }, 400) setTimeout(() => { modal.remove(); }, 1000); if (ev) { clearTimeout(timeOut) ev(); } }) } modal.confirm = (msg, yes, no, free, onload) => { const modalBackground = one('modal-background', document.body); const modal = one('modal', modalBackground); if (free) { Object.keys(free).forEach(key => { modal.style[key] = free[key]; }) } setTimeout(() => { modal.addClass('modal-open'); }, 0) const message = one('modal-message ct', modal); if (typeof msg === 'string' || msg instanceof String) { message.innerHTML = msg; } else { message.style.height = 'calc(100% - 40px)'; message.appendChild(msg); } const modalButtons = one('modal-buttons ct', modal) const cancel = one('modal-button-cancel btn-ib btn-default', modalButtons) const confirm = one('modal-button-confirm btn-ib btn-default', modalButtons) cancel.innerHTML = ' Отказ'; confirm.innerHTML = ' Потвърждение'; if (typeof onload !== 'undefined') { onload(); } addEventListener('keydown', e => { if (e.keyCode === 27) { modal.removeClass('modal-open'); setTimeout(() => { modalBackground.remove(); }, 400) if (no) { no(); } } }) cancel.onclick = () => { modal.removeClass('modal-open'); setTimeout(() => { modalBackground.remove(); }, 400) if (no) { no(); } }; confirm.onclick = () => { modal.removeClass('modal-open'); setTimeout(() => { modalBackground.remove(); }, 400) setTimeout(() => { modal.remove(); }, 1000); if (yes) { yes(); } } }; modal.player = (videoSrc) => { const modalBackground = one('modal-background', document.body); const modal = one('modal-video', modalBackground); const closeButton = one('modal-video-close', modal); closeButton.innerHTML = ''; setTimeout(function () { modal.addClass('modal-open'); }, 100) closeButton.addEventListener('click', () => { modal.removeClass('modal-open'); setTimeout(function () { modalBackground.remove(); }, 350) }) var video = document.createElement('video'); video.setAttribute('controls', true) // // First check for native browser HLS support // if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoSrc; // // If no native HLS support, check if HLS.js is supported // alert('application/vnd.apple.mpegurl') modal.appendChild(video); video.play(); } else if (Hls.isSupported()) { var hls = new Hls(); hls.loadSource(videoSrc); hls.attachMedia(video); modal.appendChild(video); video.play(); } } modal.modalFrame = (src) => { const modalBackground = one('modal-background', document.body); const modal = one('modal-video', modalBackground); modal.classList.add('frame') const closeButton = one('modal-video-close', modal); closeButton.innerHTML = ''; setTimeout(function () { modal.addClass('modal-open'); }, 100) closeButton.addEventListener('click', () => { modal.removeClass('modal-open'); setTimeout(function () { modalBackground.remove(); }, 350) }) var iframe = document.createElement('iframe'); iframe.setAttribute('style', 'border: 0; width: 100%; height: 100%') iframe.src = src modal.appendChild(iframe); } modal.modalPreview = (src) => { const modalBackground = one('modal-background', document.body); const modal = one('modal-video', modalBackground); modal.classList.add('modalImg') const closeButton = one('modal-video-close', modal); closeButton.innerHTML = ''; setTimeout(function () { modal.addClass('modal-open'); }, 100) closeButton.addEventListener('click', () => { modal.removeClass('modal-open'); setTimeout(function () { modalBackground.remove(); }, 350) }) var img = document.createElement('img'); img.setAttribute('style', 'height: 100%; display: block') img.src = src modal.appendChild(img); } modal.modalFrame = (src) => { const modalBackground = one('modal-background', document.body); const modal = one('modal-video', modalBackground); modal.classList.add('frame') const closeButton = one('modal-video-close', modal); closeButton.innerHTML = ''; document.body.classList.add('hideScrollbar'); setTimeout(function () { modal.classList.add('modal-open'); }, 100) closeButton.addEventListener('click', () => { modal.classList.remove('modal-open'); setTimeout(function () { modalBackground.remove(); document.body.classList.remove('hideScrollbar'); }, 350) }) var iframe = document.createElement('iframe'); iframe.setAttribute('style', 'border: 0; width: 100%; height: 100%') iframe.setAttribute('allow', 'autoplay; fullscreen') iframe.src = src modal.appendChild(iframe); } const flash = {}; flash.success = (msg, noTopScroll) => { if (!one('.flash')) { const flash = one('flash', document.body); flash.innerHTML = msg; setTimeout(() => { flash.addClass('success'); }, 10) if (noTopScroll === undefined) { setTimeout(() => { window.scroll(0, 0); }, 100) } setTimeout(() => { all('.flash').forEach(f => { f.removeClass('success'); setTimeout(() => { f.remove(); }, 500); }) }, 4000) } } flash.warning = msg => { if (!one('.flash')) { const flash = one('flash', document.body); flash.innerHTML = msg; setTimeout(() => { flash.addClass('warning'); }, 10) setTimeout(() => { all('.flash').forEach(f => { f.removeClass('warning'); setTimeout(() => { f.remove(); }, 500); }) }, 7000) } } flash.error = msg => { if (!one('.flash')) { const flash = one('flash', document.body); flash.innerHTML = msg; setTimeout(() => { flash.addClass('error'); }, 10) setTimeout(() => { all('.flash').forEach(f => { f.removeClass('warning'); setTimeout(() => { f.remove(); }, 500); }) }, 7000) } } const timeRange = (s, o) => { const createElement = (tag, className, appendTo) => { var element = document.createElement(tag) if (className) element.className = className; if (appendTo) appendTo.appendChild(element); return element; } const generate = e => { o = o || {} const dataset = e.dataset || {}, minH = parseInt(o.minH) || parseInt(dataset.minH) || 0, maxH = parseInt(o.maxH) || parseInt(dataset.maxH) || 23, minutesStep = parseInt(o.minutesStep) || parseInt(dataset.minutesStep) || 5, cnt = e.parentNode, hc = createElement('div', 'time-range', cnt), h1 = createElement('select', 'time-select', hc), sh1 = createElement('div', 'sh', hc), m1 = createElement('select', 'time-select', hc), d = createElement('div', 'd', hc), h2 = createElement('select', 'time-select', hc), sh2 = createElement('div', 'sh', hc), m2 = createElement('select', 'time-select', hc), updateValuesFromInput = () => { if (e.value) { let t1 = e.value.split('-')[0].split(':'); let t2 = e.value.split('-')[1].split(':'); h1.value = parseInt(t1[0]) m1.value = parseInt(t1[1]) h2.value = parseInt(t2[0]) m2.value = parseInt(t2[1]) check() } }, updateInput = (v) => { e.value = v }, check = () => { let vH1 = parseInt(h1.value), vM1 = parseInt(m1.value), vH2 = parseInt(h2.value), vM2 = parseInt(m2.value) if (vH1 === vH2 && vM1 >= vM2) m2.value = (vM1 + minutesStep).toString(); if (vH1 > vH2) h2.value = vH1.toString() if (h1.value && m1.value && h2.value && m2.value) { let vH1F = String(parseInt(h1.value)).padStart(2, '0'), vM1F = String(parseInt(m1.value)).padStart(2, '0'), vH2F = String(parseInt(h2.value)).padStart(2, '0'), vM2F = String(parseInt(m2.value)).padStart(2, '0') updateInput(`${vH1F}:${vM1F}-${vH2F}:${vM2F}`) cnt.classList.remove('form-error') } else { updateInput(''); } } createElement('option', null, h1).setAttribute('disabled', '') createElement('option', null, h2).setAttribute('disabled', '') createElement('option', null, m1).setAttribute('disabled', '') createElement('option', null, m2).setAttribute('disabled', '') for (let i = minH; i <= maxH; i++) { let opt1 = createElement('option', null, h1) opt1.innerHTML = String(i).padStart(2, '0') opt1.setAttribute('value', i) let opt2 = createElement('option', null, h2) opt2.innerHTML = String(i).padStart(2, '0') opt2.setAttribute('value', i) } for (let i = 0; i <= 59; i += minutesStep) { let opt1 = createElement('option', null, m1) opt1.innerHTML = String(i).padStart(2, '0') opt1.setAttribute('value', i) let opt2 = createElement('option', null, m2) opt2.innerHTML = String(i).padStart(2, '0') opt2.setAttribute('value', i); } h1.addEventListener('change', check) m1.addEventListener('change', check) h2.addEventListener('change', check) m2.addEventListener('change', check) updateValuesFromInput(); } document.querySelectorAll(s).forEach(e => generate(e)); } const dataFormat = () => { all('input[data-format]', e => { e.min = e.min || 0; const formatNumber = type => { var elem = null; e.addEventListener('focus', () => { e.select(); const elem_offset = document.getSelection().anchorOffset; elem = document.getSelection().anchorNode.childNodes[elem_offset]; }) e.addEventListener('keydown', () => { let kc = event.keyCode; if (e === elem) { e.value = ''; elem = null; } switch (true) { case kc > 47 && kc < 58 || kc === 8 || kc === 190: if (kc === 190 && type === 'integer') event.preventDefault(); if (kc !== 190 && kc !== 8 && e.value === '0') event.preventDefault() if (kc === 190 && e.value.indexOf('.') > -1) event.preventDefault() if (type === 'money' && kc !== 8 && e.value.charAt(e.value.length - 3) === '.') event.preventDefault(); break; case kc === 13: event.preventDefault(); blur(type); break; default: event.preventDefault(); } }) e.addEventListener('blur', () => { blur(type); }) e.addEventListener('keyup', (elem) => { //blur(type); if (e.dataset.max && type === 'integer') { if (e.value && parseInt(e.value) > parseInt(e.dataset.max)) { e.value = e.dataset.max } } }) } const blur = (type) => { if (type === 'money' && e.value) { let n = e.value.split('.'); if (n[1]) { e.value = n[0] + '.' + String(parseInt(n[1])).padEnd(2, '0') } else { e.value = n[0] + '.00'; } } e.blur(); } if (e.dataset && e.dataset.format) { if (['integer', 'double', 'money'].indexOf(e.dataset.format) > -1) formatNumber(e.dataset.format); } }) }