Initial import

This commit is contained in:
Admin Nasledstvo
2026-05-01 20:52:04 +03:00
commit ac168868ee
10028 changed files with 2337954 additions and 0 deletions
@@ -0,0 +1,131 @@
export class Base {
set() {
self = this;
self.form();
}
setAttrEvents(e, attributes, events) {
attributes = attributes || {}
events = events || {}
Object.keys(attributes).forEach(key => {
switch (key) {
case 'tag':
break;
case 'content':
e.innerHTML = attributes[key]
break;
case 'parent':
attributes[key].appendChild(e)
break;
default:
e.setAttribute(key, attributes[key]);
}
})
Object.keys(events).forEach(key => {
e.addEventListener(key, events[key])
})
return e;
}
element(attributes, events) {
let e = document.createElement(attributes.tag || 'div')
return self.setAttrEvents(e, attributes, events)
}
get(s, events, attributes) {
events = events || {}
attributes = attributes || {}
let e = document.querySelector(s);
self.setAttrEvents(e, attributes, events)
return e;
}
getAll(s, loop) {
let elements = document.querySelectorAll(s);
elements.forEach((e, i) => {
loop(e, i);
})
return elements;
}
collectData(s, data) {
let objectData = {};
this.getAll(s + ' [name]', e => {
if (e.getAttribute('type') === 'checkbox') {
objectData[e.getAttribute('name')] = e.checked
} else {
objectData[e.getAttribute('name')] = e.value;
}
})
if (data) data(objectData)
return objectData
}
toggleClass(element, addClass, removeClass) {
element.classList.remove(removeClass);
element.classList.add(addClass);
}
request(data, done) {
data = data || {};
data.url = data.url || window.location.href
data.method = data.method || 'post'
data.data = data.data || {};
let xhr = new XMLHttpRequest()
xhr.responseType = data.contentType || 'json'
xhr.open(data.method, data.url)
xhr.onload = function () {
if (done) done(xhr.response);
}
xhr.send(JSON.stringify(data.data))
}
getOffset(el) {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
setError(dataKey, message, findBySelector) {
let rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove()
let selector = findBySelector === true ? `iframe[title=${dataKey}]` : `[name="${dataKey}"]`
let input = this.get(selector, {
keypress: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
change: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
}),
rec = this.getOffset(input),
element = self.element({
class: 'error-bubble',
content: message,
id: `bubble-${dataKey}`,
style: `top:${rec.top}px; left:${rec.left}px`,
parent: document.body
})
//if(dataKey !== 'g-recaptcha')
input.classList.add('error-input')
input.focus()
window.addEventListener('resize', () => {
if (element) {
rec = this.getOffset(input)
element.setAttribute('style', `top:${rec.top}px; left:${rec.left}px`)
}
})
setTimeout(() => {
element.remove()
}, 4000)
}
}
@@ -0,0 +1,110 @@
class Booking {
default(lg) {
this.locale = lg;
}
getCalc(e, val) {
let id = e.dataset.relateBtn
let counter = document.querySelector(`[data-relate-counter="${id}"]`)
let calc = parseInt(counter.dataset.counter) + val
return {calc, counter}
}
countIncrease(e) {
let ca = this.getCalc(e, 1)
if (ca.calc < 101) {
ca.counter.setAttribute('data-counter', ca.calc)
ca.counter.innerText = ca.calc
this.calculate(e)
}
}
countDecrease(e) {
let ca = this.getCalc(e, -1)
if (ca.calc > -1) {
ca.counter.setAttribute('data-counter', ca.calc)
ca.counter.innerText = ca.calc
this.calculate(e)
}
}
calculate(e) {
let id = e.dataset.relateBtn
let counter = self.get(`[data-relate-counter="${id}"]`)
let singlePrice = document.querySelector(`[data-relate-price="${id}"]`)
let amount = document.querySelector(`[data-realte-amount="${id}"]`)
let total = document.querySelector('[data-total]');
let totalAmount = 0;
let singlePriceVal = singlePrice.dataset.price;
let calculateAmount = singlePriceVal * counter.dataset.counter;
amount.setAttribute('data-amount', calculateAmount)
amount.querySelector('span').innerHTML = calculateAmount.toFixed(2);
document.querySelectorAll('[data-amount]').forEach(a => {
totalAmount += parseInt(a.dataset.amount)
})
total.setAttribute('data-total', totalAmount)
total.querySelector('span').innerHTML = totalAmount.toFixed(2);
}
pay(b, webviewMode) {
b.classList.add('disabled');
let tickets = [];
document.querySelectorAll('[data-counter]').forEach(c => {
for (let i = 0; i < c.dataset.counter; i++) {
tickets.push(c.dataset.cart);
}
})
let selectDate = document.querySelector('#select-date')
let selectTime = document.querySelector('#select-time')
if (selectDate.value && selectTime.value) {
let
date = document.querySelector('#select-date').value,
time = document.querySelector('#select-time').value,
event_id = document.querySelector('#event_id')
if (tickets.length > 0) {
self.request({
url: `/${this.locale}/user/add-booking-to-cart/`,
data: {
tickets: tickets.join(','),
date_time: `${date} ${time}:00`
}
}, res => {
b.classList.remove('disabled');
if(webviewMode) {
window.location.href = `/${this.locale}/user/cart/?webview_mode=true`
} else {
window.location.href = `/${this.locale}/user/cart/`
}
});
} else {
modal.alert(document.querySelector('#error-msg-1').value + '.');
b.classList.remove('disabled');
}
} else {
modal.alert(document.querySelector('#error-msg-2').value + '.')
b.classList.remove('disabled');
}
}
request(data, done) {
data = data || {};
data.url = data.url || window.location.href
data.method = data.method || 'post'
data.data = data.data || {};
let xhr = new XMLHttpRequest()
xhr.responseType = data.contentType || 'json'
xhr.open(data.method, data.url)
xhr.onload = function () {
if (done) done(xhr.response);
}
xhr.send(JSON.stringify(data.data))
}
}
@@ -0,0 +1,456 @@
class CartBase {
constructor() {
self = this;
}
setAttrEvents(e, attributes, events) {
attributes = attributes || {}
events = events || {}
Object.keys(attributes).forEach(key => {
switch (key) {
case 'tag':
break;
case 'content':
e.innerHTML = attributes[key]
break;
case 'parent':
attributes[key].appendChild(e)
break;
default:
e.setAttribute(key, attributes[key]);
}
})
Object.keys(events).forEach(key => {
e.addEventListener(key, events[key])
})
return e;
}
element(attributes, events) {
let e = document.createElement(attributes.tag || 'div')
return self.setAttrEvents(e, attributes, events)
}
get(s, events, attributes) {
events = events || {}
attributes = attributes || {}
let e = document.querySelector(s);
self.setAttrEvents(e, attributes, events)
return e;
}
getAll(s, loop) {
let elements = document.querySelectorAll(s);
elements.forEach((e, i) => {
loop(e, i);
})
return elements;
}
collectData(s, data) {
let objectData = {};
this.getAll(s + ' [name]', e => {
if (e.getAttribute('type') === 'checkbox') {
objectData[e.getAttribute('name')] = e.checked
} else {
objectData[e.getAttribute('name')] = e.value;
}
})
if (data) data(objectData)
return objectData
}
toggleClass(element, addClass, removeClass) {
element.classList.remove(removeClass);
element.classList.add(addClass);
}
request(data, done) {
data = data || {};
data.url = data.url || window.location.href
data.method = data.method || 'post'
data.data = data.data || {};
let xhr = new XMLHttpRequest()
xhr.responseType = data.contentType || 'json'
xhr.open(data.method, data.url)
xhr.onload = function () {
if (done) done(xhr.response);
}
xhr.send(JSON.stringify(data.data))
}
getOffset(el) {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
setError(dataKey, message, findBySelector) {
let rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove()
let selector = findBySelector === true ? `iframe[title=${dataKey}]` : `[name="${dataKey}"]`
let input = this.get(selector, {
keypress: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
change: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
}),
rec = this.getOffset(input),
element = self.element({
class: 'error-bubble',
content: message,
id: `bubble-${dataKey}`,
style: `top:${rec.top}px; left:${rec.left}px`,
parent: document.body
})
//if(dataKey !== 'g-recaptcha')
input.classList.add('error-input')
input.focus()
window.addEventListener('resize', () => {
if (element) {
rec = this.getOffset(input)
element.setAttribute('style', `top:${rec.top}px; left:${rec.left}px`)
}
})
setTimeout(() => {
element.remove()
}, 4000)
}
setCookie(cName, cValue, expDays) {
let date = new Date();
date.setTime(date.getTime() + (expDays * 24 * 60 * 60 * 1000));
const expires = "expires=" + date.toUTCString();
document.cookie = cName + "=" + cValue + "; " + expires + "; path=/";
}
getCookie(cName) {
const name = cName + "=";
const cDecoded = decodeURIComponent(document.cookie); //to be careful
const cArr = cDecoded.split('; ');
let res;
cArr.forEach(val => {
if (val.indexOf(name) === 0) res = val.substring(name.length);
})
return res;
}
}
class Cart extends CartBase {
locale
setCart(lg) {
this.locale = lg;
let count = self.getCookieData().length
let cart = self.element({
class: 'cart',
parent: document.body,
content: `<i class="la la-shopping-cart"></i><span>${count}</span>`
}, {
click: () => {
window.location.href = `/${lg}/user/cart/`;
}
})
if (count > 0 && window.location.href !== `${window.origin}/${lg}/user/cart/`) {
let pathnameParts = window.location.pathname.split('/')
if (pathnameParts[2] && pathnameParts[2] === 'partnjor' || pathnameParts[2] === 'partner')
return;
setTimeout(() => {
cart.classList.add('open')
}, 500)
}
}
remove(e, callback) {
self.request({url: `/${this.locale}/user/remove-from-cart/`, data: {cart: e.dataset.cart}}, res => {
let cart = self.get('.cart')
if (self.getCookieData().length > 0) {
let cartCount = self.get('.cart span')
cartCount.innerHTML = self.getCookieData().length
cart.classList.add('open')
} else {
cart.classList.remove('open')
}
if (callback) callback(e)
});
}
removeFromCart(e) {
self.request({url: `/${this.locale}/user/remove-from-cart/`, data: {cart: e.dataset.cart}}, res => {
let cart = self.get('.cart')
let cartItem = e.parentNode;
cartItem.remove();
let cartList = document.querySelectorAll('.cart-list');
let noCartData = self.get('.no-cart-data');
if (cartList.length === 0) {
noCartData.classList.add('show')
} else {
noCartData.classList.remove('show')
}
let total = 0;
self.getAll('.q-changer', s => {
total += (s.value * s.dataset.price);
});
if (total === 0) {
let cartContinue = self.get('.cart-continue');
cartContinue.classList.add('disabled');
self.get('#total-price').innerHTML = '0.00';
} else {
self.get('#total-price').innerHTML = total.toFixed();
}
});
}
add(e, callback, type) {
let max = e.dataset.max || null;
const addType = type ? `?type=${type}` : '';
self.request({url: `/${this.locale}/user/add-to-cart/${addType}`, data: {cart: e.dataset.cart, max: max}}, res => {
if (res.error) {
let cartLabel = this.locale === 'en' ? 'Go to cart' : 'Към количката';
modal.alert(res.message, {
href: `/${this.locale}/user/cart/`,
content: `<i class="la la-shopping-cart"></i> ${cartLabel}`
});
} else {
if (self.getCookieData().length > 0) {
let cart = self.get('.cart')
let cartCount = self.get('.cart span')
cartCount.innerHTML = self.getCookieData().length
cart.classList.add('open')
}
if (callback) callback(e)
}
});
}
updateQuantity(e) {
let total = 0;
self.getAll('.q-changer', s => {
total += (s.value * s.dataset.price);
});
self.request({
url: `/${this.locale}/user/update-cart-quantity/`,
data: {cart: e.dataset.cart, quantity: e.value}
}, res => {
self.get('#total-price').innerHTML = total.toFixed(2);
});
}
updateSubscriptions(e, mode) {
switch (mode) {
case 'add':
e.classList.remove('visible-option')
self.getAll('.subscription-button.visible-option', (btn) => {
btn.classList.add('disabled')
})
let optionSelected = e.parentNode.querySelector('.subscribe-selected');
if (optionSelected) optionSelected.classList.add('visible-option')
let bodySub = e.parentNode.parentNode;
if (bodySub) bodySub.classList.add('selected')
break
case 'remove':
self.getAll('.subscription-button.visible-option.disabled', (btn) => {
btn.classList.remove('disabled')
})
let subscribeSelected = e.parentNode;
if (subscribeSelected) {
subscribeSelected.classList.remove('visible-option')
let subscriptionButton = subscribeSelected.parentNode.querySelector('.subscription-button');
if (subscriptionButton) {
subscriptionButton.classList.add('visible-option')
let bodySub = subscriptionButton.parentNode.parentNode;
if (bodySub) bodySub.classList.remove('selected')
}
}
break
}
}
getCookieData() {
if (self.getCookie('cart_data')) {
return JSON.parse(self.getCookie('cart_data'));
} else {
return [];
}
}
finalize(m) {
//alert('test');
//const form = document.createElement('form');
//form.method = 'POST';
if(m) {
window.location.href = `/${this.locale}/user/send-order/?webview_mode=true`
} else {
window.location.href = `/${this.locale}/user/send-order/`
}
//const input = document.createElement('input');
//input.name = 'cart'
//form.submit();
/*
self.request({url: `/${this.locale}/user/send-order/`, data: {cart: 'send-order'}}, res => {
if (res.success) {
if (res.paymentCheckout) {
window.location.href = res.paymentCheckout;
}
}
})*/
}
}
class InvoiceData extends CartBase {
getInvoiceData() {
if (self.getCookie('invoice_data')) {
let invoiceData = JSON.parse(self.getCookie('invoice_data'));
console.log(invoiceData);
Object.keys(invoiceData).forEach(key => {
if (key === 'invoice_data_type') {
let radio = self.get(`[name="invoice_data_type"][value="${invoiceData[key]}"]`);
self.get('.general-invoice').classList.add('added');
let submit;
switch (invoiceData[key]) {
case '1':
submit = self.get('[data-form="form-fizichesko-lice"]');
submit.innerHTML = '<i class="la la-save"></i> ' + submit.dataset.record;
break;
case '2':
submit = self.get('[data-form="form-iuridichesko-lice"]');
submit.innerHTML = '<i class="la la-save"></i> ' + submit.dataset.record;
break;
}
radio.click();
} else {
let input = self.get(`[name="${key}"]`);
if (input.type === 'checkbox') {
input.checked = invoiceData[key];
} else {
input.value = invoiceData[key];
}
}
})
return invoiceData;
}
return [];
}
setInvoiceData(lg) {
self.getAll('[name="invoice_data_type"]', e => {
e.addEventListener('click', () => {
let btn = document.querySelector(`#${e.dataset.content}`);
btn.classList.remove('disabled')
if (e.dataset.content !== 'id1') {
document.querySelector('#id1').classList.add('disabled')
}
if (e.dataset.content !== 'id2') {
document.querySelector('#id2').classList.add('disabled')
}
if (!self.getCookie('invoice_data')) {
if (e.dataset.content !== 'id1') {
self.getAll('#id1 input', input => {
input.value = '';
})
}
if (e.dataset.content !== 'id2') {
self.getAll('#id2 input', input => {
input.value = '';
})
}
}
});
})
self.getAll('.invoice-data .profile-submit', btn => {
let data = {};
btn.addEventListener('click', () => {
self.getAll(`.${btn.dataset.form} [name]`, el => {
if (el.type === 'checkbox') {
data[el.name] = el.checked;
} else {
data[el.name] = el.value;
}
});
self.request({
url: `/${lg}/user/add-invoice-data/`,
data: data
}, res => {
if (res.error) {
self.setError(res.error.key, res.error.message);
} else {
this.getInvoiceData();
purchase.checkActivity()
}
})
})
})
this.getInvoiceData();
}
changeData() {
let generalInvoice = self.get('.general-invoice')
generalInvoice.classList.remove('added');
}
}
class PaymentMethods extends CartBase {
setContainer() {
let paymentMethod = self.getCookie('payment_method')
if (paymentMethod) {
let radioBtn = self.get(`[name="payment_method"][value="${paymentMethod}"]`);
radioBtn.checked = true;
}
}
setMethod(e) {
self.setCookie('payment_method', e.value, 30)
purchase.checkActivity()
}
}
class Purchase extends CartBase {
checkActivity() {
let paymentMethod = self.getCookie('payment_method')
let invoiceData = self.getCookie('invoice_data');
let cartData = self.getCookie('cart_data');
console.log(cartData)
if (paymentMethod && invoiceData && cartData) {
document.querySelector('#purchase_info_continue').classList.remove('disabled')
}
}
allowSendOrder(e) {
let btn = self.get('#send_order');
if (e.checked) {
btn.classList.remove('disabled')
} else {
btn.classList.add('disabled')
}
}
}
@@ -0,0 +1,747 @@
/** @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);
};
function contentRequest(url, content, pagination, callback) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url)
xhr.responseType = 'json';
xhr.onload = () => {
const
contentContainer = document.querySelector(content),
paginationContainer = document.querySelector(pagination)
if (xhr.response) {
if (contentContainer)
contentContainer.innerHTML = xhr.response.html
if (paginationContainer)
paginationContainer.setPagination('button', xhr.response.pages_count, xhr.response.current_page, page => {
callback(page);
})
}
}
xhr.send()
}
function simpleContentRequest(url, callback) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url)
xhr.onload = () => {
callback(xhr.responseText);
}
xhr.send();
}
Element.prototype.setPagination = function (tagName, pagesCount, currentPage, callback) {
this.innerHTML = '';
if (pagesCount > 1) {
let createAppend = (tagName, parent, content) => {
let button = document.createElement(tagName)
parent.appendChild(button)
button.innerHTML = content;
if (Number.isInteger(content)) {
button.setAttribute('data-page', content)
button.addEventListener('click', () => {
this.querySelector('.active').classList.remove('active')
button.classList.add('active')
callback(content)
setTimeout(() => {
window.scrollTo({top: 0, behavior: 'smooth'});
});
})
} else {
if (content !== '...') {
let prev = button.querySelector('.prev')
if (prev) {
prev.addEventListener('click', () => {
this.querySelector('.active').classList.remove('active')
this.querySelector(`[data-page="${currentPage - 1}"]`).classList.add('active')
callback(currentPage - 1)
})
}
let next = button.querySelector('.next')
if (next) {
next.addEventListener('click', () => {
this.querySelector('.active').classList.remove('active')
this.querySelector(`[data-page="${currentPage + 1}"]`).classList.add('active')
callback(currentPage + 1)
})
}
} else {
button.style.pointerEvents = 'none'
}
}
return button;
}
if (currentPage > 1) createAppend('button', this, '<i class="la la-angle-left prev"><i>')
let start = 1, end = pagesCount, step = 3, visible = step * 2;
if (pagesCount > step * 2) {
if (currentPage > step * 2) {
createAppend('button', this, 1)
createAppend('button', this, '...')
start = currentPage - step;
}
}
if (pagesCount - currentPage > step) end = currentPage + step
for (let p = start; p <= end; p++) {
let button = createAppend('button', this, p)
if (p === currentPage)
button.classList.add('active')
}
if (pagesCount - currentPage > step) {
createAppend('button', this, '...')
createAppend('button', this, pagesCount)
}
if (currentPage < pagesCount) {
createAppend('button', this, '<i class="la la-angle-right next"><i>')
}
}
}
Element.prototype.switchClass = function (class1, class2) {
if (this.classList.contains(class1) && !this.classList.contains(class2)) {
this.classList.remove(class1)
this.classList.add(class2)
} else {
this.classList.remove(class2)
this.classList.add(class1)
}
}
Element.prototype.find = function (selector) {
return this.querySelector(selector)
}
Element.prototype.findAll = function (selector, loop) {
let e = this.querySelectorAll(selector)
if (loop) {
e.forEach((e, i) => {
loop(e, i)
})
}
return e;
}
Element.prototype.createIn = function (htmlTag, attributes, events) {
const element = document.createElement(htmlTag);
if (attributes) {
Object.keys(attributes).forEach(attr => {
element.setAttribute(attr, attributes[attr])
})
}
if (attributes) {
Object.keys(attributes).forEach(attr => {
if (attr !== 'content') {
element.setAttribute(attr, attributes[attr])
} else {
element.innerHTML = attributes[attr]
}
})
}
if (events) {
Object.keys(events).forEach(event => {
element.addEventListener(event, events[event])
})
}
this.appendChild(element);
return element;
}
Element.prototype.addEvents = function (events) {
const $this = this;
Object.keys(events).forEach(event => {
$this.addEventListener(event, events[event])
})
return this
}
Element.prototype.addAttributes = function (attributes) {
Object.keys(attributes).forEach(attr => {
if (attr !== 'content') {
this.setAttribute(attr, attributes[attr])
} else {
this.innerHTML = attributes[attr]
}
})
return this
}
document.addEventListener('DOMContentLoaded', () => {
document.body.findAll('[data-hover-title]', (e) => {
const box = e.getBoundingClientRect()
const hoverTitle = e.createIn('div', {
content: e.dataset.hoverTitle,
class: 'dht'
})
const boxTitle = hoverTitle.getBoundingClientRect()
let mv = '0'
if (boxTitle.width > box.width) {
mv = ((boxTitle.width - box.width) * -0.5) + 'px'
} else {
mv = (box.width - boxTitle * 0.5) + 'px'
}
hoverTitle.setAttribute('style', `bottom: ${box.height + 3}px; transform: translateX(${mv})`)
e.addEvents({
mouseenter: () => {
hoverTitle.classList.add('hover')
},
mouseleave: () => {
hoverTitle.classList.remove('hover')
}
})
})
document.querySelectorAll('.drop-btn').forEach(e => {
e.addEventListener('click', () => {
if (e.classList.contains('open')) {
e.classList.remove('open')
} else {
e.classList.add('open')
}
})
})
let hiddenNavBtn = document.querySelector('.hidden-nav-button');
let navHidden = document.querySelector('.hidden-nav');
let mobileSearch = document.querySelector('.main-mobile-nav .search input')
let mobileSearchBtn = document.querySelector('.main-mobile-nav .search .la')
if (hiddenNavBtn) {
hiddenNavBtn.addEventListener('click', () => {
if (navHidden.classList.contains('open')) {
navHidden.classList.remove('open')
let padFilter = document.querySelector('.pad-filter');
if (padFilter)
padFilter.remove()
} else {
navHidden.classList.add('open')
let padFilter = document.createElement('div');
padFilter.classList.add('pad-filter')
document.body.appendChild(padFilter)
}
})
}
document.body.addEventListener('click', () => {
let t = event.target;
if (t !== hiddenNavBtn && t !== navHidden && t !== mobileSearch) {
if (navHidden)
navHidden.classList.remove('open')
}
})
document.querySelectorAll('[data-href]').forEach(e => {
e.addEventListener('click', () => {
window.location.href = e.dataset.href;
})
})
document.querySelectorAll('[data-max-str]').forEach(e => {
if (e.textContent.length > e.dataset.maxStr) {
e.innerHTML = e.textContent.substring(0, e.dataset.maxStr) + '...';
}
})
document.querySelectorAll('[data-pdf]').forEach(pdf => {
pdf.classList.add('pointer');
pdf.addEventListener('click', () => {
//modal.modalPDFFrame(pdf.dataset.pdf);
window.open('https://portal.nasledstvo.bg/publication/?id=' + pdf.dataset.pdf, '')
})
})
})
// Function to load the PDF document
function loadPDF(url, pdfViewer) {
// Check if the browser supports PDF viewing
if (typeof window.navigator.msSaveOrOpenBlob !== 'undefined') {
// For desktop browsers, use the Microsoft Edge browser
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (xhr.status === 200) {
var blob = new Blob([xhr.response], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(blob, 'document.pdf');
}
};
xhr.send();
} else {
// For mobile browsers or other desktop browsers, use a PDF.js viewer
var pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function (pdf) {
pdf.getPage(1).then(function (page) {
var scale = 1.5;
var viewport = page.getViewport({scale: scale});
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
pdfViewer.appendChild(canvas);
page.render({canvasContext: context, viewport: viewport});
});
});
}
}
// Call the loadPDF function with the URL of the PDF document
function openPublication(p) {
modal.modalFrame(p.dataset.publication);
}
function load3dModel(e) {
modal.modalFrame(e.getAttribute('data-model-3d'));
}
const modal = {};
modal.sessionLeft = (msg, time, resetLabel, ev, leftEv) => {
const modalBackground = one('modal-background', document.body);
const modal = one('modal', modalBackground);
setTimeout(() => {
modal.classList.add('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.classList.remove('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 = '<i class="la la-redo-alt"></i> ' + resetLabel;
refresh.addEventListener('click', () => {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
setTimeout(() => {
modal.remove();
}, 1000);
if (ev) {
event.preventDefault();
clearTimeout(timeOut)
ev();
}
})
}
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 = '<i class="la la-times"></i>';
setTimeout(function () {
modal.classList.add('modal-open');
}, 100)
closeButton.addEventListener('click', () => {
modal.classList.remove('modal-open');
setTimeout(function () {
modalBackground.remove();
}, 350)
})
var video = document.createElement('video');
video.setAttribute('controls', true)
video.volume = 0.5
//
// First check for native browser HLS support
//
if (video.canPlayType('application/vnd.apple.mpegurl')) {
//alert('Test 1')
video.src = videoSrc;
//
// If no native HLS support, check if HLS.js is supported
//
modal.appendChild(video);
video.play();
} else if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoSrc);
hls.attachMedia(video);
modal.appendChild(video);
video.play();
} else {
alert('hls is not supported on your browser')
}
}
modal.alert = (msg, link, callback) => {
const modalBackground = one('modal-background', document.body);
const modal = one('modal', modalBackground);
setTimeout(() => {
modal.classList.add('modal-open');
}, 30)
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 confirm = one('modal-button-confirm btn-ib btn-default pointer', modalButtons);
confirm.innerHTML = '<i class="la la-check"></i> OK';
if (link) {
const linkButton = one('modal-button-confirm btn-ib btn-default pointer', modalButtons);
linkButton.innerHTML = link.content;
linkButton.addEventListener('click', () => {
window.location.href = link.href;
})
}
addEventListener('keydown', e => {
if (e.keyCode === 27) {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
}
})
confirm.onclick = () => {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
setTimeout(() => {
modal.remove();
if (callback) {
callback();
}
}, 1000);
}
};
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.classList.add('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 = '<i class="la la-ban"></i> Отказ';
confirm.innerHTML = '<i class="la la-check"></i> OK';
if (typeof onload !== 'undefined') {
onload();
}
addEventListener('keydown', e => {
if (e.keyCode === 27) {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
if (no) {
no();
}
}
})
cancel.onclick = () => {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
if (no) {
no();
}
};
confirm.onclick = () => {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
setTimeout(() => {
modal.remove();
}, 1000);
if (yes) {
yes();
}
}
};
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 = '<i class="la la-times"></i>';
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
//const pdfViewer = document.createElement('div');
//pdfViewer.setAttribute('style', 'border: 0; width: 100%; height: 100%');
//loadPDF(src, pdfViewer)
modal.appendChild(iframe);
}
modal.modalPDFFrame = (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 = '<i class="la la-times"></i>';
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
const pdfViewer = document.createElement('canvas');
pdfViewer.setAttribute('style', 'border: 0; width: 100%; height: 100%');
loadPDF(src, pdfViewer)
modal.appendChild(pdfViewer);
}
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 = '<i class="la la-times"></i>';
setTimeout(function () {
modal.classList.add('modal-open');
}, 100)
closeButton.addEventListener('click', () => {
modal.classList.remove('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.modalSearchBox = (e) => {
event.preventDefault();
const msg = e.dataset.title;
const lg = e.dataset.lang;
const modalBackground = one('modal-background', document.body);
const modal = one('modal modal-search-box', modalBackground);
setTimeout(() => {
modal.classList.add('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 padFilter = one('.pad-filter');
const modalButtons = one('modal-buttons ct', modal)
const cancel = one('modal-button-cancel btn-ib btn-default', modalButtons)
cancel.innerHTML = '<i class="la la-times"></i>';
const input = document.createElement('input');
modal.appendChild(input);
input.innerHTML = 'Търси';
input.className = 'search';
input.focus();
const searchResult = one('search-result', modal);
input.addEventListener('keyup', () => {
if (input.value) {
const xhr = new XMLHttpRequest();
xhr.open('GET', `/${lg}/remote/search/?q=${input.value}`)
xhr.responseType = 'text';
xhr.onload = () => {
searchResult.innerHTML = xhr.responseText;
}
xhr.send()
} else {
searchResult.innerHTML = '';
}
})
//new SearchBoxRemoteInitial(input, {url: '/bg/remote/search', columns: {text: 'Заглавие', type: 'Тип'}})
addEventListener('keydown', e => {
if (e.keyCode === 27) {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
}, 400)
if (no) {
no();
}
}
})
cancel.onclick = () => {
modal.classList.remove('modal-open');
setTimeout(() => {
modalBackground.remove();
if (padFilter)
padFilter.remove();
}, 400)
};
}
const flash = {};
flash.success = (msg, noTopScroll) => {
if (!one('.flash')) {
const flash = one('flash', document.body);
flash.innerHTML = msg;
setTimeout(() => {
flash.classList.add('success');
}, 10)
if (noTopScroll === undefined) {
setTimeout(() => {
window.scroll(0, 0);
}, 100)
}
setTimeout(() => {
document.querySelectorAll('.flash').forEach(f => {
f.classList.remove('success');
setTimeout(() => {
f.remove();
}, 500);
})
}, 4000)
}
}
flash.warning = msg => {
if (!one('.flash')) {
const flash = one('flash', document.body);
flash.innerHTML = msg;
setTimeout(() => {
flash.classList.add('warning');
}, 10)
setTimeout(() => {
document.querySelectorAll('.flash').forEach(f => {
f.classList.remove('warning');
setTimeout(() => {
f.remove();
}, 500);
})
}, 10000)
}
}
flash.error = msg => {
if (!one('.flash')) {
const flash = one('flash', document.body);
flash.innerHTML = msg;
setTimeout(() => {
flash.classList.add('error');
}, 10)
setTimeout(() => {
document.querySelectorAll('.flash').forEach(f => {
f.classList.remove('warning');
setTimeout(() => {
f.remove();
}, 500);
})
}, 15000)
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,296 @@
// keymaster.js
// (c) 2011-2013 Thomas Fuchs
// keymaster.js may be freely distributed under the MIT license.
;(function(global){
var k,
_handlers = {},
_mods = { 16: false, 18: false, 17: false, 91: false },
_scope = 'all',
// modifier keys
_MODIFIERS = {
'⇧': 16, shift: 16,
'⌥': 18, alt: 18, option: 18,
'⌃': 17, ctrl: 17, control: 17,
'⌘': 91, command: 91
},
// special keys
_MAP = {
backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32,
left: 37, up: 38,
right: 39, down: 40,
del: 46, 'delete': 46,
home: 36, end: 35,
pageup: 33, pagedown: 34,
',': 188, '.': 190, '/': 191,
'`': 192, '-': 189, '=': 187,
';': 186, '\'': 222,
'[': 219, ']': 221, '\\': 220
},
code = function(x){
return _MAP[x] || x.toUpperCase().charCodeAt(0);
},
_downKeys = [];
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
// IE doesn't support Array#indexOf, so have a simple replacement
function index(array, item){
var i = array.length;
while(i--) if(array[i]===item) return i;
return -1;
}
// for comparing mods before unassignment
function compareArray(a1, a2) {
if (a1.length != a2.length) return false;
for (var i = 0; i < a1.length; i++) {
if (a1[i] !== a2[i]) return false;
}
return true;
}
var modifierMap = {
16:'shiftKey',
18:'altKey',
17:'ctrlKey',
91:'metaKey'
};
function updateModifierKey(event) {
for(k in _mods) _mods[k] = event[modifierMap[k]];
};
// handle keydown event
function dispatch(event) {
var key, handler, k, i, modifiersMatch, scope;
key = event.keyCode;
if (index(_downKeys, key) == -1) {
_downKeys.push(key);
}
// if a modifier key, set the key.<modifierkeyname> property to true and return
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
if(key in _mods) {
_mods[key] = true;
// 'assignKey' from inside this closure is exported to window.key
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
return;
}
updateModifierKey(event);
// see if we need to ignore the keypress (filter() can can be overridden)
// by default ignore key presses if a select, textarea, or input is focused
if(!assignKey.filter.call(this, event)) return;
// abort if no potentially matching shortcuts found
if (!(key in _handlers)) return;
scope = getScope();
// for each potential shortcut
for (i = 0; i < _handlers[key].length; i++) {
handler = _handlers[key][i];
// see if it's in the current scope
if(handler.scope == scope || handler.scope == 'all'){
// check if modifiers match if any
modifiersMatch = handler.mods.length > 0;
for(k in _mods)
if((!_mods[k] && index(handler.mods, +k) > -1) ||
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
// call the handler and stop the event if neccessary
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
if(handler.method(event, handler)===false){
if(event.preventDefault) event.preventDefault();
else event.returnValue = false;
if(event.stopPropagation) event.stopPropagation();
if(event.cancelBubble) event.cancelBubble = true;
}
}
}
}
};
// unset modifier keys on keyup
function clearModifier(event){
var key = event.keyCode, k,
i = index(_downKeys, key);
// remove key from _downKeys
if (i >= 0) {
_downKeys.splice(i, 1);
}
if(key == 93 || key == 224) key = 91;
if(key in _mods) {
_mods[key] = false;
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
}
};
function resetModifiers() {
for(k in _mods) _mods[k] = false;
for(k in _MODIFIERS) assignKey[k] = false;
};
// parse and assign shortcut
function assignKey(key, scope, method){
var keys, mods;
keys = getKeys(key);
if (method === undefined) {
method = scope;
scope = 'all';
}
// for each shortcut
for (var i = 0; i < keys.length; i++) {
// set modifier keys if any
mods = [];
key = keys[i].split('+');
if (key.length > 1){
mods = getMods(key);
key = [key[key.length-1]];
}
// convert to keycode and...
key = key[0]
key = code(key);
// ...store handler
if (!(key in _handlers)) _handlers[key] = [];
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
}
};
// unbind all handlers for given key in current scope
function unbindKey(key, scope) {
var multipleKeys, keys,
mods = [],
i, j, obj;
multipleKeys = getKeys(key);
for (j = 0; j < multipleKeys.length; j++) {
keys = multipleKeys[j].split('+');
if (keys.length > 1) {
mods = getMods(keys);
}
key = keys[keys.length - 1];
key = code(key);
if (scope === undefined) {
scope = getScope();
}
if (!_handlers[key]) {
return;
}
for (i = 0; i < _handlers[key].length; i++) {
obj = _handlers[key][i];
// only clear handlers if correct scope and mods match
if (obj.scope === scope && compareArray(obj.mods, mods)) {
_handlers[key][i] = {};
}
}
}
};
// Returns true if the key with code 'keyCode' is currently down
// Converts strings into key codes.
function isPressed(keyCode) {
if (typeof(keyCode)=='string') {
keyCode = code(keyCode);
}
return index(_downKeys, keyCode) != -1;
}
function getPressedKeyCodes() {
return _downKeys.slice(0);
}
function filter(event){
var tagName = (event.target || event.srcElement).tagName;
// ignore keypressed in any elements that support keyboard data input
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
}
// initialize key.<modifier> to false
for(k in _MODIFIERS) assignKey[k] = false;
// set current scope (default 'all')
function setScope(scope){ _scope = scope || 'all' };
function getScope(){ return _scope || 'all' };
// delete all handlers for a given scope
function deleteScope(scope){
var key, handlers, i;
for (key in _handlers) {
handlers = _handlers[key];
for (i = 0; i < handlers.length; ) {
if (handlers[i].scope === scope) handlers.splice(i, 1);
else i++;
}
}
};
// abstract key logic for assign and unassign
function getKeys(key) {
var keys;
key = key.replace(/\s/g, '');
keys = key.split(',');
if ((keys[keys.length - 1]) == '') {
keys[keys.length - 2] += ',';
}
return keys;
}
// abstract mods logic for assign and unassign
function getMods(key) {
var mods = key.slice(0, key.length - 1);
for (var mi = 0; mi < mods.length; mi++)
mods[mi] = _MODIFIERS[mods[mi]];
return mods;
}
// cross-browser events
function addEvent(object, event, method) {
if (object.addEventListener)
object.addEventListener(event, method, false);
else if(object.attachEvent)
object.attachEvent('on'+event, function(){ method(window.event) });
};
// set the handlers globally on document
addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
addEvent(document, 'keyup', clearModifier);
// reset modifiers to false whenever the window is (re)focused.
addEvent(window, 'focus', resetModifiers);
// store previously defined key
var previousKey = global.key;
// restore previously defined key and return reference to our key object
function noConflict() {
var k = global.key;
global.key = previousKey;
return k;
}
// set window.key and window.key.set/get/deleteScope, and the default filter
global.key = assignKey;
global.key.setScope = setScope;
global.key.getScope = getScope;
global.key.deleteScope = deleteScope;
global.key.filter = filter;
global.key.isPressed = isPressed;
global.key.getPressedKeyCodes = getPressedKeyCodes;
global.key.noConflict = noConflict;
global.key.unbind = unbindKey;
if(typeof module !== 'undefined') module.exports = assignKey;
})(this);
@@ -0,0 +1,320 @@
class SearchBox {
container
box = document.createElement('div')
list = document.createElement('div')
listItems = document.createElement('div')
selected = document.createElement('div')
searchField = document.createElement('input')
cloneListItems = this.listItems
callback
dynamic = {}
selectedList = {};
constructor(selector) {
if (typeof selector === "string") {
this.container = document.querySelector(selector)
} else {
this.container = selector;
}
if (this.container) {
if (this.container.nodeName === 'SELECT') {
this.dataRetrieve()
} else {
alert('Html element SELECT is required')
}
addEventListener('keydown', ({keyCode}) => {
if (keyCode === 27) {
this.clear()
}
})
}
}
clear() {
this.box.classList.remove('open')
this.searchField.value = ''
this.listItems.querySelectorAll('.list-item').forEach(e => {
e.classList.add('visible')
e.classList.remove('hover')
e.style.display = 'block'
})
}
clearBoxSelected() {
this.clear();
let placeholder = this.container.querySelector('option:first-child');
this.selected.innerHTML = placeholder.innerHTML
this.listItems.querySelectorAll('.list-item').forEach(e => {
e.classList.remove('selected')
})
}
getNextSibling(elem, selector) {
var sibling = elem.nextElementSibling;
while (sibling) {
if (sibling.matches(selector)) return sibling;
sibling = sibling.nextElementSibling
}
}
getPreviousSibling(elem, selector) {
var sibling = elem.previousElementSibling;
if (!selector) return sibling;
while (sibling) {
if (sibling.matches(selector)) return sibling;
sibling = sibling.previousElementSibling;
}
}
keyDown() {
this.searchField.addEventListener('keydown', ({keyCode}) => {
if (keyCode === 38 || keyCode === 40) {
event.preventDefault()
const visibleList = this.listItems.querySelectorAll('.visible:not(.hover)');
const firstItem = visibleList[0];
const lastItem = this.listItems.querySelectorAll('.visible:not(.hover)')[visibleList.length - 1];
if (this.listItems.querySelectorAll('.visible.hover').length === 0) {
if (keyCode === 38 && lastItem)
lastItem.classList.add('hover')
if (keyCode === 40 && firstItem)
firstItem.classList.add('hover')
} else {
const hoverElement = this.listItems.querySelector('.visible.hover')
hoverElement.classList.remove('hover')
//up
if (keyCode === 38) {
const prev = this.getPreviousSibling(hoverElement, '.visible')
if (prev && prev.classList.contains('visible')) {
prev.classList.add('hover')
console.log(prev.offsetTop)
this.listItems.scrollTo({
top: prev.offsetTop - 160,
})
} else {
lastItem.classList.add('hover')
this.listItems.scrollTo({
top: lastItem.offsetTop - 160,
})
}
}
//down
if (keyCode === 40) {
const next = this.getNextSibling(hoverElement, '.visible')
if (next && next.classList.contains('visible')) {
next.classList.add('hover')
this.listItems.scrollTo({
top: next.offsetTop - 160
})
} else {
firstItem.classList.add('hover')
this.listItems.scrollTo({
top: firstItem.offsetTop - 160,
})
}
}
}
}
if (keyCode === 13) {
event.preventDefault()
const currentSelected = this.listItems.querySelector('.hover');
if (currentSelected) {
const selected = this.listItems.querySelector('.selected');
if (!this.container.hasAttribute('multiple')) {
if (selected) {
selected.classList.remove('selected')
}
currentSelected.classList.add('selected')
this.selected.innerText = currentSelected.innerHTML
this.container.value = currentSelected.dataset.select
if (this.dynamic.change) {
this.dynamic.change(this.container.value)
}
} else {
this.multipleSelected(currentSelected, this.container.querySelector(`option[value="${currentSelected.dataset.select}"]`))
}
this.container.parentNode.classList.remove('form-error')
this.clear()
}
}
})
}
multipleSelected(listItem, e) {
if (!this.selected.querySelector(`.selected-box[data-id="${e.value}"]`)) {
const sb = document.createElement('div')
const close = document.createElement('div')
sb.className = 'selected-box'
close.className = 'close'
sb.innerText = e.innerText
sb.setAttribute('data-id', e.value)
const sbExists = this.selected.querySelector('.selected-box')
if (!sbExists) {
this.selected.innerHTML = '';
}
sb.appendChild(close)
this.selected.appendChild(sb)
listItem.classList.add('selected')
e.setAttribute('selected', true)
this.retrieveSelectedData();
sb.addEventListener('click', () => {
event.preventDefault()
e.removeAttribute('selected')
const listItemSelected = this.listItems.querySelector(`.list-item[data-select="${e.value}"]`)
listItemSelected.classList.remove('selected')
sb.remove()
const sbExists = this.selected.querySelector('.selected-box')
if (!sbExists) {
var s = this.container.querySelector('option:first-child')
if (s)
this.selected.innerHTML = s.innerText;
}
this.retrieveSelectedData();
})
}
}
retrieveSelectedData() {
let options = this.container.querySelectorAll('option[selected="true"]');
let data = [];
let ids = [];
options.forEach(e => {
data.push({id: e.getAttribute('value'), text: e.innerHTML})
ids.push(e.getAttribute('value'));
})
if (this.callback) {
this.callback(data, ids.join(','));
}
}
dataRetrieve() {
this.box.classList.add('search-box')
this.list.classList.add('list')
this.selected.classList.add('selected')
this.listItems.classList.add('list-items')
this.list.appendChild(this.searchField)
this.list.appendChild(this.listItems)
this.box.appendChild(this.selected)
this.box.appendChild(this.list)
if (this.container.classList.contains('disabled')) {
this.box.classList.add('disabled')
}
this.box.addEventListener('click', e => {
if (
!event.target.classList.contains('selected-box') &&
!event.target.classList.contains('close')
) {
if (this.box.classList.contains('open')) {
this.clear()
} else {
document.querySelectorAll('.search-box').forEach(b => {
b.classList.remove('open')
})
this.box.classList.add('open')
this.searchField.focus()
}
}
})
this.keyDown()
this.updateFromOptionList()
this.searchField.addEventListener('keyup', e => {
this.listItems.querySelectorAll('.list-item').forEach((e, i) => {
if (e.innerText.toLowerCase().indexOf(this.searchField.value.toLowerCase()) !== -1 || this.searchField.value === '') {
e.style.display = 'block'
e.classList.add('visible')
} else {
e.style.display = 'none'
e.classList.remove('visible')
e.classList.remove('hover')
}
})
})
this.container.parentNode.appendChild(this.box);
}
updateFromOptionList() {
this.listItems.innerHTML = '';
this.container.querySelectorAll('option').forEach((e, i) => {
if (i === 0) {
//if (this.selected.innerText !== '')
this.selected.innerText = e.innerText
}
if (e.value) {
const listItem = document.createElement('div');
listItem.className = 'list-item visible'
listItem.setAttribute('data-select', e.value)
listItem.innerText = e.innerText;
this.listItems.appendChild(listItem)
if (e.hasAttribute('selected') && !this.container.hasAttribute('multiple')) {
this.selected.innerText = e.innerText
listItem.classList.add('selected')
this.listItems.scrollTo({
top: listItem.offsetTop - 160,
})
}
if (e.hasAttribute('selected') && this.container.hasAttribute('multiple')) {
this.multipleSelected(listItem, e)
}
listItem.addEventListener('click', l => {
if (!this.container.hasAttribute('multiple')) {
this.container.value = e.value
this.selected.innerText = e.innerText
if (this.dynamic.change) {
this.dynamic.change(this.container.value)
}
} else {
this.multipleSelected(listItem, e)
}
this.container.parentNode.classList.remove('form-error')
})
}
})
}
updateFromObject(object) {
const $this = this;
object.searchBox.dynamic.change = function (value) {
$this.request(object.url, `${object.queryId}=${value}`, data => {
//console.log(data);
$this.container.innerHTML = $this.container.querySelector('option:first-child').outerHTML
data.forEach(o => {
if (o[object.data.id] && o[object.data.name]) {
const option = document.createElement('option')
option.value = o[object.data.id];
option.innerText = o[object.data.name]
$this.container.appendChild(option)
}
})
if (data.length > 0) {
$this.updateFromOptionList()
$this.container.classList.remove('disabled')
$this.box.classList.remove('disabled')
}
})
}
}
onChange(callback) {
this.callback = callback;
/*this.container.addEventListener('change', ()=> {
let tags = this.container.querySelector('option[selected="true"]')
let selected = [];
tags.forEach(t => {
selected.push({id: t.getAttribute('value'), tag: t.innerHTML})
})
callback(selected);
})*/
}
request(url, query, callback) {
const xhr = new XMLHttpRequest()
xhr.responseType = 'json'
xhr.open('get', `${url}?${query}`)
xhr.onload = () => {
callback(xhr.response)
}
xhr.send()
}
}
@@ -0,0 +1,354 @@
let self = null;
class UserBase {
set(mobile) {
self = this;
self.form(mobile);
}
setAttrEvents(e, attributes, events) {
attributes = attributes || {}
events = events || {}
Object.keys(attributes).forEach(key => {
switch (key) {
case 'tag':
break;
case 'content':
e.innerHTML = attributes[key]
break;
case 'parent':
attributes[key].appendChild(e)
break;
default:
e.setAttribute(key, attributes[key]);
}
})
if (Object.keys(events).length > 0 && e) {
Object.keys(events).forEach(key => {
e.addEventListener(key, events[key])
})
}
return e;
}
element(attributes, events) {
let e = document.createElement(attributes.tag || 'div')
return self.setAttrEvents(e, attributes, events)
}
get(s, events, attributes) {
events = events || {}
attributes = attributes || {}
let e = document.querySelector(s);
self.setAttrEvents(e, attributes, events)
return e;
}
getAll(s, loop) {
let elements = document.querySelectorAll(s);
elements.forEach((e, i) => {
loop(e, i);
})
return elements;
}
collectData(s, data) {
let objectData = {};
this.getAll(s + ' [name]', e => {
if (e.getAttribute('type') === 'checkbox') {
objectData[e.getAttribute('name')] = e.checked
} else {
objectData[e.getAttribute('name')] = e.value;
}
})
if (data) data(objectData)
return objectData
}
toggleClass(element, addClass, removeClass) {
element.classList.remove(removeClass);
element.classList.add(addClass);
}
request(data, done) {
data = data || {};
data.url = data.url || window.location.href
data.method = data.method || 'post'
data.data = data.data || {};
let xhr = new XMLHttpRequest()
xhr.responseType = data.contentType || 'json'
xhr.open(data.method, data.url)
xhr.onload = function () {
if (done) done(xhr.response);
}
xhr.send(JSON.stringify(data.data))
}
getOffset(el) {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
setError(dataKey, message, findBySelector) {
let rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove()
let selector = findBySelector === true ? `iframe[title=${dataKey}]` : `[name="${dataKey}"]`
let input = this.get(selector, {
keypress: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
change: () => {
input.classList.remove('error-input')
rb = self.get(`#bubble-${dataKey}`)
if (rb) rb.remove();
},
}),
rec = this.getOffset(input),
element = self.element({
class: 'error-bubble',
content: message,
id: `bubble-${dataKey}`,
style: `top:${rec.top}px; left:${rec.left}px`,
parent: document.body
})
//if(dataKey !== 'g-recaptcha')
input.classList.add('error-input')
input.focus()
window.addEventListener('resize', () => {
if (element) {
rec = this.getOffset(input)
element.setAttribute('style', `top:${rec.top}px; left:${rec.left}px`)
}
})
setTimeout(() => {
element.remove()
}, 4000)
}
passwordReliable() {
let passwordInput = document.querySelector('[name="password"]');
let passwordWeak = document.querySelector('.password-strength .weak');
let passwordMiddle = document.querySelector('.password-strength .middle');
let passwordStrong = document.querySelector('.password-strength .strong');
passwordInput.addEventListener('keyup', function () {
let str = passwordInput.value;
if (str.length >= 6) {
passwordWeak.classList.remove('unused');
if (str.search(/\d/) > -1 && str.search(/[a-zA-Z]/) > -1) {
passwordMiddle.classList.remove('unused')
if (str.search(/[!@#$%^&*]/) > -1) {
passwordStrong.classList.remove('unused');
} else {
passwordStrong.classList.add('unused')
}
} else {
passwordMiddle.classList.add('unused')
passwordStrong.classList.add('unused')
}
} else {
passwordWeak.classList.add('unused')
passwordMiddle.classList.add('unused')
passwordStrong.classList.add('unused')
}
//console.log(str)
})
}
}
class UserSignUp extends UserBase {
mobileTrue
constructor(mobileTrue) {
super();
this.mobileTrue = mobileTrue
}
form() {
this.passwordReliable();
let submit = self.get('.sign-up-box .submit-panel', {
click: () => {
submit.classList.add('disabled')
self.collectData('.sign-up-box', data => {
self.request({data}, res => {
submit.classList.remove('disabled')
console.log(res)
if (res.error) {
if (res.error.key === 'g-recaptcha-response') {
self.setError('reCAPTCHA', res.error.message, true)
} else {
self.setError(res.error.key, res.error.message)
if (this.mobileTrue === true) {
modal.alert(res.error.message)
}
}
} else {
if (this.mobileTrue === true) {
window.location.href = '/bg/mobile-api/browser-register-close/'
} else {
document.querySelector('.sign-up-box').innerHTML = loginScreen;
}
}
})
})
}
})
}
}
class UserContact extends UserBase {
form() {
self = this;
let submit = self.get('.contact-box .submit-panel', {
click: () => {
submit.classList.add('disabled')
self.collectData('.contact-box', data => {
self.request({data}, res => {
submit.classList.remove('disabled')
if (res.error) {
if (res.error.key === 'g-recaptcha-response') {
self.setError('reCAPTCHA', res.error.message, true)
} else {
self.setError(res.error.key, res.error.message)
}
} else {
document.querySelectorAll('.contact-box [name]').forEach(e => {
e.value = ''
})
flash.success(successMessage, true)
}
})
})
}
})
}
}
class UI extends UserBase {
actions(lg) {
self = this;
let headerToggle = this.get('.header-toggle-panel', {
click: () => {
console.log(this);
//alert('test');
let panel = headerToggle.parentNode;
if (panel.classList.contains('open')) {
panel.classList.remove('open')
} else {
panel.classList.add('open')
}
}
})
let profileSubmit = this.get('.profile-data-submit', {
click: () => {
profileSubmit.classList.add('disabled')
let data = {}
self.getAll('.main-profile-panel input.unlock', input => {
if (input.value === '') {
self.setError(input.name, 'Моля, попълнете име и фамилия')
}
data[input.name] = input.value;
})
self.request({data}, res => {
profileSubmit.classList.remove('disabled')
console.log(res)
if (res.error) {
self.setError(res.error.key, res.error.message)
} else {
self.getAll('.main-profile-panel input.unlock', (input) => {
let inputRow = input.parentNode;
input.classList.remove('unlock')
inputRow.classList.add('ready');
let editBtn = inputRow.querySelector('.edit-profile')
console.log(editBtn)
self.toggleClass(editBtn, 'la-check', 'la-pencil')
profileSubmit.classList.add('inactive')
setTimeout(() => {
inputRow.classList.remove('ready')
self.toggleClass(editBtn, 'la-pencil', 'la-check')
}, 1500)
})
}
})
}
});
let edit = this.getAll('.edit-profile', e => {
e.addEventListener('click', function () {
let input = e.parentNode.querySelector('input');
input.classList.add('unlock');
input.focus()
profileSubmit.classList.remove('inactive')
})
})
self.getAll('.tab-button', btn => {
if (!btn.classList.contains('active')) {
btn.addEventListener('click', () => {
let active = self.get('.tab-button.active')
if (active) {
active.classList.remove('active');
}
const tabContentPanel = self.get('.tab-content-panel');
self.request({
contentType: 'html',
method: 'get',
url: `/${lg}/user/profile-tabs/?tab=${btn.dataset.tab}`
}, content => {
tabContentPanel.innerHTML = content;
})
btn.classList.add('active')
})
}
})
const passwordChangeSubmit = document.querySelector('.change-password-submit');
const passwordChangeForm = document.querySelector('.password-change-form');
passwordChangeSubmit.addEventListener('click', () => {
self.collectData('.password-change-form', data => {
console.log(data);
self.request({
url: `/${lg}/user/change-password/`,
data
}, res => {
if (res.error) {
self.setError(res.error.key, res.error.message)
} else {
passwordChangeForm.classList.remove('open')
passwordChangeForm.querySelectorAll('[name]').forEach(i => {
i.value = ''
})
flash.success(res.success.message)
}
})
})
}
);
this.passwordReliable();
}
openPasswordChangeForm() {
const passwordChangeForm = document.querySelector('.password-change-form')
passwordChangeForm.classList.add('open')
}
closePasswordChangeForm() {
const passwordChangeForm = document.querySelector('.password-change-form')
passwordChangeForm.classList.remove('open')
}
}
@@ -0,0 +1,54 @@
function idleLogout() {
var t;
var sleep = false;
window.onload = resetTimer;
window.onmousemove = resetTimer;
window.onmousedown = resetTimer; // catches touchscreen presses as well
window.ontouchstart = resetTimer; // catches touchscreen swipes as well
window.ontouchmove = resetTimer; // required by some devices
window.onclick = resetTimer; // catches touchpad clicks as well
window.onkeydown = resetTimer;
window.addEventListener('scroll', resetTimer, true); // improved; see comments
function yourFunction() {
clearTimeout(t);
sleep = true;
modal.sessionLeft('Вашата сесия ще изтече след ', 60, null, () => {
sleep = false;
resetTimer();
}, () => {
window.location.href = `/bg/user/logout-all/`
});
}
function resetTimer() {
if(!sleep) {
clearTimeout(t);
t = setTimeout(yourFunction, 9*60*1000); // time is in milliseconds
}
}
}
function checkActivity() {
const xhr = new XMLHttpRequest();
xhr.open('get', '/remote/check-activity/')
xhr.responseType = 'json';
xhr.onload = () => {
if (xhr.response && xhr.response.status) {
if (xhr.response.status === 'inactive') {
window.location.href = xhr.response.redirect;
//console.log(xhr.response)
} else {
console.log(xhr.response)
setTimeout(function () {
checkActivity()
}, 4000)
}
}
}
xhr.send();
}
checkActivity();