Initial import
This commit is contained in:
@@ -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();
|
||||
Reference in New Issue
Block a user