876 lines
27 KiB
JavaScript
876 lines
27 KiB
JavaScript
/**
|
|
* Vvveb
|
|
*
|
|
* Copyright (C) 2021 Ziadin Givan
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* https://github.com/givanz/Vvveb
|
|
*/
|
|
|
|
window.VvvebTheme = window.VvvebTheme || {ajax:{}};
|
|
window.VvvebApp = window.VvvebApp || {};
|
|
window.VvvebApp.path = document.currentScript.src.replace(/\/public.+$|assets-cache.+$|\/js.+$/, '');
|
|
|
|
VvvebTheme.Ajax = {
|
|
call: function(url, parameters, element, selector, callback, requestType = "POST") {
|
|
if (!url) {
|
|
let action = element.closest("[data-v-vvveb-action]") ?? element;
|
|
url = action.href ?? action.action ?? window.VvvebApp.path + '/index.php?module=' + parameters["module"] + '&action=' + parameters["action"];
|
|
}
|
|
|
|
if (!selector) {
|
|
url += '&_component_ajax=' + parameters["component"] + '&_component_id=' + parameters["component_id"];
|
|
}
|
|
|
|
let loading = element?.querySelector('.loading');
|
|
let btn = element?.querySelector('.button-text');
|
|
|
|
if (loading && loading.classList.contains("d-none")) {
|
|
loading.classList.remove('d-none');
|
|
btn.classList.add('d-none');
|
|
}
|
|
|
|
if (element?.hasAttribute("button")) {
|
|
element.setAttribute("disabled", "true");
|
|
}
|
|
|
|
const controller = new AbortController();
|
|
const signal = controller.signal;
|
|
|
|
fetch(url, {
|
|
withCredentials: true,
|
|
credentials: 'include',
|
|
method: requestType,
|
|
headers: {
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
},
|
|
signal: signal,
|
|
body: new URLSearchParams(parameters)})
|
|
.then(response => {
|
|
if (!response.ok) { throw new Error(response) }
|
|
if (response.redirected) {
|
|
controller.abort();
|
|
window.location.href = response.url;
|
|
}
|
|
|
|
return response.text()
|
|
})
|
|
.then(data => {
|
|
if (selector) {
|
|
let response = new DOMParser().parseFromString(data, "text/html");
|
|
if (!Array.isArray (selector) ) {
|
|
selector = [selector];
|
|
}
|
|
|
|
for (const k in selector) {
|
|
let elementSelector = selector[k];
|
|
let currentElements = document.querySelectorAll(elementSelector);
|
|
let newElements = response.querySelectorAll(elementSelector);
|
|
|
|
if (currentElements && newElements) {
|
|
currentElements.forEach( (e, i) => {
|
|
let newElement = newElements[i] ?? document.createElement("null");
|
|
e.replaceWith(newElement);
|
|
newElement.querySelectorAll('script').forEach(oldScriptEl => {
|
|
const newScriptEl = document.createElement("script");
|
|
|
|
Array.from(oldScriptEl.attributes).forEach( attr => {
|
|
newScriptEl.setAttribute(attr.name, attr.value)
|
|
});
|
|
|
|
const scriptText = document.createTextNode(oldScriptEl.innerHTML);
|
|
newScriptEl.appendChild(scriptText);
|
|
|
|
oldScriptEl.replaceChildren();
|
|
oldScriptEl.parentNode.replaceChild(newScriptEl, oldScriptEl);
|
|
oldScriptEl.remove();
|
|
|
|
});
|
|
});
|
|
} /*if (currentElements) {
|
|
currentElements.forEach(e => e.remove());
|
|
} else if (newElements) {
|
|
//new elements don't have corresponding elements on the page, reload hole page
|
|
response = new DOMParser().parseFromString(data, "text/html")
|
|
document.querySelector("body").replaceWith(response.querySelector("body"));
|
|
break;
|
|
}*/
|
|
}
|
|
}
|
|
|
|
if (callback) callback(data);
|
|
|
|
let loading = element?.querySelector('.loading');
|
|
let btn = element?.querySelector('.button-text');
|
|
|
|
if (loading && btn.classList.contains("d-none")) {
|
|
loading.classList.add('d-none');
|
|
btn.classList.remove('d-none');
|
|
}
|
|
|
|
if (element.hasAttribute("button")) {
|
|
element.removeAttribute("disabled");
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.log(error);
|
|
//displayToast("bg-danger", "Revision", "Error!");
|
|
});
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Cart = {
|
|
|
|
module: 'cart/cart',
|
|
component: 'cart',
|
|
component_id: '0',
|
|
|
|
ajax: function(action, parameters, element, selector, callback) {
|
|
parameters['module'] = parameters['module'] ?? this.module;
|
|
parameters['action'] = parameters['action']?? action;
|
|
parameters['component'] = parameters['component'] ?? this.component;
|
|
parameters['component_id'] = parameters['component_id'] ?? this.component_id;
|
|
VvvebTheme.Ajax.call("", parameters, element, selector, callback);
|
|
},
|
|
|
|
callback: function(data) {
|
|
/*
|
|
let miniCart = document.querySelectorAll("[data-v-component-cart]");
|
|
if (miniCart) {
|
|
miniCart[0].outerHTML = data;
|
|
}*/
|
|
},
|
|
|
|
add: function(productId, options, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
if (options) {
|
|
options['product_id'] = productId;
|
|
} else {
|
|
options = {'product_id':productId};
|
|
}
|
|
return this.ajax('add',options, element, selector, callback);
|
|
},
|
|
|
|
update: function(key, options, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
if (options) {
|
|
options['key'] = key;
|
|
} else {
|
|
options = {'key':key};
|
|
}
|
|
return this.ajax('update',options, element, selector, callback);
|
|
},
|
|
|
|
remove: function(key, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('remove', {'key':key}, element, selector, callback);
|
|
},
|
|
|
|
coupon: function(options, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('coupon', options, element, selector, callback);
|
|
},
|
|
|
|
removeCoupon: function(options, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('removeCoupon', options, element, selector, callback);
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Wishlist = {
|
|
|
|
module: 'user/wishlist',
|
|
component: 'wishlist',
|
|
component_id: '0',
|
|
|
|
ajax: function(action, parameters, element, selector, callback) {
|
|
parameters['module'] = this.module;
|
|
parameters['action'] = action;
|
|
parameters['component'] = this.component;
|
|
parameters['component_id'] = this.component_id;
|
|
VvvebTheme.Ajax.call("", parameters, element, selector, callback);
|
|
},
|
|
|
|
callback: function(data) {
|
|
},
|
|
|
|
add: function(productId, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('add',{'product_id':productId}, element, selector, callback);
|
|
},
|
|
|
|
update: function(productId, quantity, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('update',{'product_id':productId}, element, selector, callback);
|
|
},
|
|
|
|
remove: function(productId, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('remove', {'product_id':productId}, element, selector, callback);
|
|
}
|
|
|
|
}
|
|
|
|
VvvebTheme.Compare = {
|
|
|
|
module: 'cart/compare',
|
|
component: 'compare',
|
|
component_id: '0',
|
|
|
|
ajax: function(action, parameters, element, selector, callback) {
|
|
parameters['module'] = this.module;
|
|
parameters['action'] = action;
|
|
parameters['component'] = this.component;
|
|
parameters['component_id'] = this.component_id;
|
|
VvvebTheme.Ajax.call("", parameters, element, selector, callback);
|
|
},
|
|
|
|
callback: function(data) {
|
|
},
|
|
|
|
add: function(productId, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('add',{'product_id':productId}, element, selector, callback);
|
|
},
|
|
|
|
update: function(productId, quantity, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('update',{'product_id':productId}, element, selector, callback);
|
|
},
|
|
|
|
remove: function(productId, element, selector, callback = false) {
|
|
if (!callback) callback = this.callback;
|
|
return this.ajax('remove', {'product_id':productId}, element, selector, callback);
|
|
}
|
|
|
|
}
|
|
|
|
VvvebTheme.Comments = {
|
|
|
|
module: 'content/post',
|
|
|
|
ajax: function(action, parameters, element, selector, callback = false) {
|
|
parameters['module'] = parameters['module'] ?? this.module;
|
|
parameters['action'] = parameters['action'] ?? action;
|
|
VvvebTheme.Ajax.call("", parameters, element, selector, callback);
|
|
},
|
|
|
|
add: function(parameters, element, selector, callback = false) {
|
|
return this.ajax('addComment',parameters, element, selector, callback);
|
|
},
|
|
|
|
update: function(productId, quantity, element, selector, callback = false) {
|
|
return this.ajax('update',{'product_id':productId, 'quantity':quantity}, selector);
|
|
},
|
|
|
|
remove: function(productId) {
|
|
return this.ajax('remove', {'product_id':productId}, selector);
|
|
}
|
|
}
|
|
|
|
VvvebTheme.User = {
|
|
|
|
module: 'user/login',
|
|
component: 'user',
|
|
component_id: '0',
|
|
|
|
ajax: function(action, parameters, element, selector, callback = false) {
|
|
parameters['module'] = parameters['module'] ?? this.module;
|
|
parameters['action'] = parameters['action'] ?? action;
|
|
parameters['component'] = parameters['component'] ?? this.component;
|
|
parameters['component_id'] = parameters['component_id'] ?? this.component_id;
|
|
|
|
VvvebTheme.Ajax.call("", parameters, element, selector, callback);
|
|
},
|
|
|
|
login: function(parameters, element, selector, callback = false) {
|
|
return this.ajax('index' ,parameters, element, selector, callback);
|
|
},
|
|
}
|
|
|
|
VvvebTheme.Search = {
|
|
|
|
module: 'search',
|
|
component: 'search',
|
|
component_id: '0',
|
|
|
|
ajax: function(action, parameters, element, selector, callback = false) {
|
|
parameters['module'] = parameters['module'] ?? this.module;
|
|
parameters['action'] = parameters['action'] ?? action;
|
|
parameters['component'] = parameters['component'] ?? this.component;
|
|
parameters['component_id'] = parameters['component_id'] ?? this.component_id;
|
|
|
|
VvvebTheme.Ajax.call("/search", parameters, element, selector, callback);
|
|
},
|
|
|
|
query: function(parameters, element, selector, callback) {
|
|
return this.ajax('index' ,parameters, element, selector, callback);
|
|
},
|
|
}
|
|
|
|
VvvebTheme.Alert = {
|
|
|
|
show: function(message) {
|
|
let alertTop = document.querySelector('.alert-top');
|
|
alertTop.querySelector(".message").innerHTML = message;
|
|
alertTop.classList.add("show");
|
|
alertTop.style.display = "block";
|
|
|
|
setTimeout(function () {
|
|
alertTop.style.display = "none";
|
|
}, 4000);
|
|
}
|
|
}
|
|
|
|
document.querySelector('.alert-top .btn-close')?.addEventListener('click', function (e) {
|
|
let alert = this.closest(".alert");
|
|
alert.classList.remove('show')
|
|
alert.style.display = "";
|
|
e.preventDefault();
|
|
});
|
|
|
|
function objectSerialize(serializeArray) {
|
|
let returnObject = {};
|
|
for (let i = 0; i < serializeArray.length; i++){
|
|
returnObject[serializeArray[i]['name']] = serializeArray[i]['value'];
|
|
}
|
|
return returnObject;
|
|
}
|
|
|
|
|
|
function elementProduct(element) {
|
|
let product = element.closest("[data-v-product]");
|
|
if (!product) {
|
|
product = element.closest("[data-v-component-product]");
|
|
}
|
|
if (!product) {
|
|
product = element.closest("[data-v-cart-product]");
|
|
}
|
|
|
|
return product;
|
|
}
|
|
|
|
VvvebTheme.Gui = {
|
|
|
|
init: function() {
|
|
let events = [];
|
|
|
|
document.querySelectorAll("[data-v-vvveb-action]").forEach(function (el) {
|
|
|
|
let on = "click";
|
|
if (el.dataset.vVvvebOn) on = el.dataset.vVvvebOn;
|
|
|
|
if (events.indexOf(on) > -1) return;
|
|
events.push(on);
|
|
|
|
document.addEventListener(on, function (e) {
|
|
let element = e.target.closest("[data-v-vvveb-action]");
|
|
if (element) {
|
|
let action = element.dataset.vVvvebAction;
|
|
let elOn = element.dataset.vVvvebOn ?? "click";
|
|
|
|
if (elOn == on && VvvebTheme.Gui.hasOwnProperty(action)) {
|
|
VvvebTheme.Gui[action].call(e.target, e);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
/*
|
|
document.querySelectorAll("[data-v-vvveb-action]").forEach(function (el) {
|
|
|
|
let on = "click";
|
|
if (el.dataset.vVvvebOn) on = el.dataset.vVvvebOn;
|
|
let event = '[data-v-vvveb-action="' + el.dataset.vVvvebAction + '"]';
|
|
|
|
if (events.indexOf(event + on) > -1) return;
|
|
events.push(event + on);
|
|
|
|
if (VvvebTheme.Gui.hasOwnProperty(el.dataset.vVvvebAction)) {
|
|
document.addEventListener(on, function (e) {
|
|
let element = e.target.closest("[data-v-vvveb-action]");
|
|
if (element) {
|
|
VvvebTheme.Gui[el.dataset.vVvvebAction].call(e.target, e);
|
|
}
|
|
});
|
|
//document).addEventListener(on, VvvebTheme.Gui[this.dataset.vVvvebAction]);
|
|
}
|
|
});
|
|
*/
|
|
},
|
|
|
|
addToCart: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let product = elementProduct(this);
|
|
|
|
let img = product.querySelector("img[data-v-product-image], img[data-v-product-image-src], img[data-v-product-image], img[data-v-product-main-image]");
|
|
let name = product.querySelector("[data-v-product-name]").textContent ?? "";
|
|
let quantity = product.querySelector('[name="quantity"]')?.value ?? 1;
|
|
let id = this.dataset.product_id ?? product.dataset.product_id;
|
|
let options = {quantity};
|
|
|
|
if (!id) {
|
|
id = product.dataset.product_id;
|
|
if (!id) {
|
|
id = product.querySelector('input[name="product_id"]').value;
|
|
}
|
|
}
|
|
|
|
let cart_add_text = 'was added to cart';
|
|
let target = e.target.closest("button, input");
|
|
|
|
if (target?.form) {
|
|
options = Object.fromEntries(new URLSearchParams(new FormData(target.form)));
|
|
if (!target.form.checkValidity()) {
|
|
target.form.requestSubmit();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Cart.add(id, options, element, ['.mini-cart', '[data-v-notifications]'], function() {
|
|
let src = img.getAttribute("src");
|
|
VvvebTheme.Alert.show(`
|
|
<div class="clearfix">
|
|
<img class="float-start me-2" height="80" src="${src}">  
|
|
<div class="float-start"><a href="#">${name}<a><br> <span class="text-muted">${cart_add_text}<span></span></div>
|
|
</div>
|
|
<div class="row mt-2 g-2 " data-v-if="cart.total_items">
|
|
<div class="col-6">
|
|
<a href="${window.VvvebApp.path}/cart" class="btn btn-light btn-sm border w-100" data-v-url="cart/cart/index">
|
|
<i class="la la-shopping-cart la-lg"></i>
|
|
<span>View cart</span>
|
|
</a>
|
|
</div>
|
|
<div class="col-6">
|
|
<a href="${window.VvvebApp.path}/checkout" class="btn btn-primary btn-sm w-100 px-2" data-v-url="checkout/checkout/index">
|
|
<span>Checkout</span>
|
|
<i class="la la-arrow-right la-lg"></i>
|
|
</a>
|
|
</div>
|
|
</div>`);
|
|
});
|
|
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
removeFromCart: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
|
|
let product = this.closest("[data-v-product]");
|
|
if (!product) {
|
|
product = this.closest("[data-v-component-product]");
|
|
}
|
|
if (!product) {
|
|
product = this.closest("[data-v-cart-product]");
|
|
}
|
|
let img = product.querySelector("[data-v-product-image],[data-v-product-image], [data-v-cart-product-image]")?.getAttribute("src") ?? "";
|
|
let name = product.querySelector("[data-v-product-name]")?.textContent ?? "";
|
|
let key = this.dataset.key;
|
|
let selector = this.dataset.selector ?? '.cart-box';
|
|
|
|
if (!key) {
|
|
key = product.dataset.key;
|
|
if (!key) {
|
|
key = product.querySelector('input[name="key"]').value;
|
|
}
|
|
}
|
|
|
|
let updatElements = ['.mini-cart', '[data-v-notifications]'];
|
|
//if on cart page update also cart page elements
|
|
for (selector of ['[data-v-cart]', '.cart-right-column']) {
|
|
if (document.querySelector(selector)) {
|
|
updatElements.push(selector);
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Cart.remove(key, element, updatElements, function() {
|
|
product.remove();
|
|
|
|
//if on cart page and cart empty refresh page
|
|
let cartContainer = document.getElementById("cart-container");
|
|
if (cartContainer &&
|
|
cartContainer.querySelectorAll("[data-v-cart-product]").length == 0 ) {
|
|
cartContainer.remove();
|
|
location.reload();
|
|
}
|
|
|
|
VvvebTheme.Alert.show('<img height=50 src="' + img + '">   <strong>' + name +'</strong> was removed from cart');
|
|
});
|
|
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
addToWishlist: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let product = elementProduct(this);
|
|
let id = this.dataset.product_id ?? product.dataset.product_id;
|
|
let img = product.querySelector("img[data-v-product-image], img[data-v-product-image], img[data-v-cart-product-image], img[data-v-product-main-image]")?.getAttribute("src") ?? "";
|
|
|
|
if (!id) {
|
|
id = product.dataset.product_id;
|
|
if (!id) {
|
|
id = product.querySelector('input[name="product_id"]').value;
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Wishlist.add(id, element, false, function(data) {
|
|
VvvebTheme.Alert.show('<img height=50 src="' + img + '">   <strong>' + name +'</strong> was added to wishlist');
|
|
});
|
|
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
addToCompare: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let product = elementProduct(this);
|
|
let id = this.dataset.product_id ?? product.dataset.product_id;
|
|
let img = product.querySelector("img[data-v-product-image], img[data-v-product-image], img[data-v-cart-product-image], img[data-v-product-main-image]")?.getAttribute("src") ?? "";
|
|
|
|
if (!id) {
|
|
id = product.dataset.product_id;
|
|
let input = product.querySelector('input[name="product_id"]');
|
|
if (!id && input) {
|
|
id = input.value;
|
|
}
|
|
}
|
|
|
|
VvvebTheme.Compare.add(id, element, false, function(data) {
|
|
VvvebTheme.Alert.show('<img height=50 src="' + img + '">   <strong>' + name +'</strong> was added to compare');
|
|
});
|
|
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
|
|
replyTo: function(e) {
|
|
let commentId = this.dataset.comment_id;
|
|
let commentAuthor = this.dataset.comment_author;
|
|
let commentForm = document.getElementById("comment-form");
|
|
//location.hash = "#comment-form";
|
|
/*
|
|
window.scrollTo({
|
|
top: commentForm.offsetTop + commentForm.clientHeight,
|
|
left: 0,
|
|
behavior: "smooth",
|
|
});*/
|
|
|
|
commentForm.querySelector("input[name=parent_id]").value = commentId;
|
|
|
|
if (commentId > 0) {
|
|
document.querySelector(".replyto").style.display = "";
|
|
document.querySelector(".replyto [data-comment-author]").innerHTML = commentAuthor;
|
|
} else {
|
|
document.querySelector(".replyto").style.display = "none";
|
|
}
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
addComment: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let selector = this.dataset.selector ?? ".post-comments";
|
|
let form = this;
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
|
|
|
|
VvvebTheme.Comments.add(parameters, element, selector, function () {
|
|
form.reset();
|
|
});
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
addReview: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let selector = this.dataset.selector ?? ".product-reviews";
|
|
let form = this;
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
|
|
parameters['module'] = 'product/product';
|
|
parameters['action'] = 'addReview';
|
|
|
|
VvvebTheme.Comments.add(parameters, element, selector, function () {
|
|
form.reset();
|
|
});
|
|
|
|
e.preventDefault();
|
|
|
|
},
|
|
|
|
addQuestion: function(e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let selector = this.dataset.selector ?? ".product-questions";
|
|
let form = this;
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
|
|
parameters['module'] = 'product/product';
|
|
parameters['action'] = 'addQuestion';
|
|
|
|
VvvebTheme.Comments.add(parameters, element, selector, function () {
|
|
form.reset();
|
|
});
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
search: function (e) {
|
|
clearTimeout(window.searchDebounce);
|
|
let form = this;
|
|
if (this.form) {
|
|
form = this.form;
|
|
}
|
|
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
|
|
let element = this;
|
|
let selector = this.dataset.selector;
|
|
let loading = form.querySelector(".loading");
|
|
if (loading) {
|
|
loading.classList.remove('d-none');
|
|
}
|
|
|
|
document.querySelector(selector).replaceChildren();
|
|
window.searchDebounce = setTimeout(function () {
|
|
VvvebTheme.Search.query(parameters, element, selector, function(data) {
|
|
if (loading) {
|
|
loading.classList.add('d-none');
|
|
}
|
|
});
|
|
e.preventDefault();
|
|
|
|
}, 1000);
|
|
},
|
|
|
|
login: function (e) {
|
|
let element = this.closest("[data-v-vvveb-action]") ?? this;
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(this)));
|
|
let componentUser;
|
|
let url = this.dataset.vUrl ?? false;
|
|
let selector = this.dataset.selector ?? '.user-box';
|
|
/*
|
|
if (url) {
|
|
VvvebTheme.User.module = url;
|
|
}
|
|
*/
|
|
componentUser = this.closest('[data-v-component-user]');
|
|
//parameters['component_id'] = document.querySelectorAll('[data-v-component-user]').index(componentUser);
|
|
|
|
VvvebTheme.User.login(parameters, element, selector/*, function(data) {
|
|
|
|
//document.querySelectorAll("[data-v-component-user]")[0].outerHTML = data;
|
|
componentUser.html(data);
|
|
// alert("Login");
|
|
}*/);
|
|
e.preventDefault();
|
|
},
|
|
|
|
//used to submit any form without refreshing page, used for contact forms
|
|
submit: function (e) {
|
|
let form = this;
|
|
let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
|
|
let componentUser;
|
|
let url = this.dataset.vUrl ?? false;
|
|
let selector = this.dataset.selector;
|
|
let loading = this.querySelector("button .loading, .btn .loading");
|
|
|
|
if (loading) {
|
|
loading.classList.remove("d-none");
|
|
loading.parentNode.querySelector(".button-text")?.classList.add("d-none");
|
|
}
|
|
|
|
loadAjax(url, selector, () => {
|
|
if (loading) {
|
|
loading.classList.add("d-none");
|
|
loading.parentNode.querySelector(".button-text")?.classList.remove("d-none");
|
|
form.reset();
|
|
}
|
|
}, parameters, "post");
|
|
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
let delay = (function(){
|
|
let timer = 0;
|
|
return function(callback, ms){
|
|
clearTimeout (timer);
|
|
timer = setTimeout(callback, ms);
|
|
};
|
|
})();
|
|
|
|
function isEditor () {
|
|
return document.getElementById("vvvebjs-styles") || window.location.href.includes('r=');
|
|
}
|
|
|
|
let urlCache = {};
|
|
|
|
function preloadUrl(e) {
|
|
delay(() => loadUrl(e, true), 200);
|
|
}
|
|
|
|
//ajax url
|
|
function loadAjax(url, selector, callback = null, params = {}, method = "get") {
|
|
let options = {
|
|
method,
|
|
withCredentials: true,
|
|
credentials: 'include'
|
|
};
|
|
|
|
if (method == "post" && params) {
|
|
options.body = new URLSearchParams(params);
|
|
}
|
|
|
|
if (!url) url = window.location.href;
|
|
let progressPercent = 10;
|
|
let progressTimer;
|
|
|
|
if (VvvebTheme.ajax.progressStatus) {
|
|
let progressTimer = () => {
|
|
if (progressPercent >= 95 || progressPercent == 0) {
|
|
clearTimeout(progressTimer);
|
|
} else {
|
|
progressPercent += 5;
|
|
setTimeout(progressTimer, 100);
|
|
}
|
|
VvvebTheme.ajax.progressStatus(progressPercent);
|
|
}
|
|
//show progress bar only if takes longer than 1 sec
|
|
setTimeout(progressTimer, 1000);
|
|
}
|
|
|
|
fetch(url, options).
|
|
then((response) => {
|
|
//if (!response.ok) { throw new Error(response) }
|
|
if (VvvebTheme.ajax.progressStatus && progressPercent > 10) {
|
|
progressPercent = 100;
|
|
VvvebTheme.ajax.progressStatus(progressPercent);
|
|
}
|
|
return response.text();
|
|
}).
|
|
then(function (data) {
|
|
if (selector) {
|
|
let response = new DOMParser().parseFromString(data, "text/html");
|
|
|
|
if (!Array.isArray (selector) ) {
|
|
selector = [selector];
|
|
}
|
|
|
|
for (const k in selector) {
|
|
let elementSelector = selector[k];
|
|
let currentElements = document.querySelectorAll(elementSelector);
|
|
let newElements = response.querySelectorAll(elementSelector);
|
|
|
|
if (currentElements && newElements) {
|
|
if (currentElements.length != newElements.length) {
|
|
//new elements does not match corresponding elements on the page, reload hole page
|
|
response = new DOMParser().parseFromString(data, "text/html")
|
|
document.querySelector("body").replaceWith(response.querySelector("body"));
|
|
break;
|
|
}
|
|
|
|
currentElements.forEach( (e, i) => {
|
|
let newElement = newElements[i] ?? document.createElement("null");
|
|
e.replaceWith(newElement);
|
|
newElement.querySelectorAll('script').forEach(oldScriptEl => {
|
|
const newScriptEl = document.createElement("script");
|
|
|
|
Array.from(oldScriptEl.attributes).forEach( attr => {
|
|
newScriptEl.setAttribute(attr.name, attr.value)
|
|
});
|
|
|
|
const scriptText = document.createTextNode(oldScriptEl.innerHTML);
|
|
newScriptEl.appendChild(scriptText);
|
|
|
|
oldScriptEl.replaceChildren();
|
|
oldScriptEl.parentNode.replaceChild(newScriptEl, oldScriptEl);
|
|
oldScriptEl.remove();
|
|
|
|
});
|
|
});
|
|
} if (currentElements) {
|
|
currentElements.forEach(e => e.remove());
|
|
} else if (newElements) {
|
|
//new elements don't have corresponding elements on the page, reload hole page
|
|
response = new DOMParser().parseFromString(data, "text/html")
|
|
document.querySelector("body").replaceWith(response.querySelector("body"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (callback) callback();
|
|
}
|
|
|
|
if (VvvebTheme.ajax.progressStatus) {
|
|
progressPercent = 0;
|
|
VvvebTheme.ajax.progressStatus(0);
|
|
}
|
|
|
|
if (VvvebTheme.ajax.afterLoad) {
|
|
VvvebTheme.ajax.afterLoad();
|
|
}
|
|
|
|
window.dispatchEvent(new CustomEvent("vvveb.loadUrl", {detail: {url, selector}}));
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
}
|
|
|
|
|
|
VvvebTheme.ajax.selector = VvvebTheme.ajax.selector || "a[data-url], a[data-page-url], a[data-v-url], a[data-v-menu-item-url], a[data-v-post-url], a[data-v-product-url], a[data-v-cat-url], a[data-v-archive-url], a[data-v-admin-url], a[data-v-post-author-url], a[data-v-breadcrumb-item-url], a[data-v-categories-cat-url], a[data-v-cart-product-url]";
|
|
VvvebTheme.ajax.siteContainer = VvvebTheme.ajax.siteContainer || ["#site-content", "body > section"];
|
|
VvvebTheme.ajax.scrollContainer = VvvebTheme.ajax.scrollContainer || "body";
|
|
VvvebTheme.ajax.skipUrl = VvvebTheme.ajax.skipUrl || [];
|
|
|
|
|
|
if (!isEditor()) {
|
|
document.addEventListener("click", function (e) {
|
|
let element = e.target.closest(VvvebTheme.ajax.selector);
|
|
if (element) {
|
|
let url = element.getAttribute("href") ?? "";
|
|
let regex = new RegExp("^.*//" + window.location.host);
|
|
url = url.replace(regex, "");
|
|
if (!url || (url.indexOf("//") != -1) || element.target //external url
|
|
|| (VvvebTheme.ajax.skipUrl.length && (VvvebTheme.ajax.skipUrl.includes(url) || VvvebTheme.ajax.skipUrl.includes(window.location.pathname)))
|
|
) return;
|
|
|
|
let selector = element.dataset.selector || VvvebTheme.ajax.siteContainer;
|
|
|
|
loadAjax(url, selector, () => {
|
|
//if (element.dataset.scroll) {
|
|
let target = document.querySelector(VvvebTheme.ajax.scrollContainer);
|
|
let scrollTo = element.dataset.scroll || (selector == VvvebTheme.ajax.siteContainer ? "start" : "start");
|
|
target.scrollIntoView({behavior: "smooth", block: scrollTo, inline: scrollTo});
|
|
//}
|
|
window.history.pushState({url, selector}, null, url);
|
|
});
|
|
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
|
|
addEventListener("popstate", checkState);
|
|
|
|
function checkState(e) {
|
|
if (e.state && e.state.url) {
|
|
loadAjax(e.state.url, e.state.selector);
|
|
}
|
|
}
|
|
|
|
window.history.pushState({url:window.location.pathname, selector:".content-body"}, null, window.location.href);
|
|
|
|
|
|
VvvebTheme.Gui.init();
|