diff --git a/xo.js b/xo.js
index 594e6a3..a22f1a2 100644
--- a/xo.js
+++ b/xo.js
@@ -597,7 +597,7 @@ xover.init.Observer = function (target_node = window.document) {
threshold: 0, // Percentage of the element's visibility to trigger the callback
});
- const elementsToObserve = target_node.querySelectorAll('[xo-suspense*="Intersection"]');
+ const elementsToObserve = target_node.querySelectorAll('[xo-suspense*="Intersect"]');
elementsToObserve.forEach(element => {
intersection_observer.observe(element);
});
@@ -665,7 +665,7 @@ xover.init.Observer = function (target_node = window.document) {
let append_event = new xover.listener.Event('append', { target }, node);
window.top.dispatchEvent(append_event);
if (!target.contains(node)) continue;
- const elementsToObserve = typeof (node.querySelectorAll) == 'function' && node.querySelectorAll('[xo-suspense*="Intersection"]') || [];
+ const elementsToObserve = typeof (node.querySelectorAll) == 'function' && node.querySelectorAll('[xo-suspense*="Intersect"]') || [];
elementsToObserve.forEach(element => {
intersection_observer.observe(element);
});
@@ -742,7 +742,7 @@ xover.init.Observer = function (target_node = window.document) {
}
for (let node of [...mutation.addedNodes].filter(node => node instanceof Element && ![HTMLStyleElement, HTMLScriptElement].includes(node.constructor))) {
window.top.dispatchEvent(new xover.listener.Event('append', { target }, node));
- const elementsToObserve = node.querySelectorAll('[xo-suspense*="Intersection"]');
+ const elementsToObserve = node.querySelectorAll('[xo-suspense*="Intersect"]');
elementsToObserve.forEach(element => {
intersection_observer.observe(element);
});
@@ -1263,7 +1263,22 @@ Object.defineProperty(xover.listener, 'dispatcher', {
if (xover.listener.debug.matches.call(context, handler, xover.listener.debugger) && !xover.listener.debug.matches.call(context, handler, xover.listener.debuggerExceptions)) {
debugger;
}
- returnValue = /*await */handler.apply(context, event instanceof CustomEvent && (event.detail instanceof Array && [...event.detail, event] || event.detail && handler.toString().replace(/^[^\{\)]+/g, '')[0] == '{' && [{ event: event.srcEvent || event, ...event.detail }, event] || (handler.toString().split(/\(|\)/).splice(1, 1)[0] || '') == 'event' && [event.srcEvent || event] || []) || arguments); /*Events shouldn't be called with await, but can return a promise*/
+ let args
+ if ((event.detail || {}).constructor === {}.constructor && handler.toString().replace(/^[^\{\)]+/g, '')[0] == '{') {
+ args = (((event.detail || {}).args || [])[0] || []).constructor === {}.constructor && (event.detail || {}).args || [{ event: event.srcEvent || event, ...event.detail }];
+ } else if ((handler.toString().split(/\(|\)/).splice(1, 1)[0] || '') == 'event') {
+ args = [event.srcEvent || event] || event.detail.args || []
+ } else {
+ args = (event.detail || {}).args || arguments;
+ }
+ //args = (event instanceof CustomEvent && (
+ // event.detail instanceof Array && [...event.detail, event]
+ // || event.detail && handler.toString().replace(/^[^\{\)]+/g, '')[0] == '{'
+ // && [{ event: event.srcEvent || event, ...event.detail }, event]
+ // || (handler.toString().split(/\(|\)/).splice(1, 1)[0] || '') == 'event'
+ // && [event.srcEvent || event] || event.detail.args || [])
+ // || arguments) //former method
+ returnValue = /*await */handler.apply(context, args); /*Events shouldn't be called with await, but can return a promise*/
if (returnValue !== undefined) {
//event.returnValue = returnValue; //deprecated
if (event.detail) {
@@ -1369,7 +1384,7 @@ Object.defineProperty(xover.listener, 'on', {
let params;
if ('!'.includes(condition[0])) {
params = new URLSearchParams("?")
- params.set(condition,"")
+ params.set(condition, "")
} else {
params = new URLSearchParams("?" + condition)
}
@@ -3752,12 +3767,12 @@ xover.dom.createDialog = function (message) {
if (!dialog) {
let frag = window.document.createDocumentFragment();
let p = window.document.createElement('p');
- p.innerHTML = ``;
+ p.innerHTML = ``;
frag.append(...p.childNodes);
window.document.body.appendChild(frag);
dialog = document.querySelector(`#${dialog_id}`);
}
- dialog.querySelector("section").innerHTML = '';
+ [...dialog.querySelectorAll("form > :not(menu)")].removeAll();
if (message.documentElement instanceof HTMLHtmlElement) {
const blob = new Blob([message], { type: 'text/html' });
const blobUrl = URL.createObjectURL(blob);
@@ -3782,7 +3797,7 @@ xover.dom.createDialog = function (message) {
message = message.statusText;
}
- dialog.querySelector("section").append(message);
+ dialog.querySelector("form").prepend(message);
document.querySelector(`#${dialog_id}`);
typeof (dialog.showModal) == 'function' && dialog.showModal();
xover.messages.set(original_message, dialog);
@@ -4355,6 +4370,12 @@ xover.modernize = async function (targetWindow) {
if (typeof (Delay) == 'undefined') Delay = async function (time = 1000, then_clause) { return xover.delay(time).then(result => then_clause ? xover.eval.call(this, then_clause) : result) }
+ if (typeof (Intersect) == 'undefined') Intersect = function () { return this.isIntersecting || null };
+
+ if (typeof (XML) == 'undefined') XML = xover.xml.fromString;
+
+ if (typeof (HTML) == 'undefined') HTML = xover.string.toHTML;
+
if (typeof (CurrentYear) == 'undefined') CurrentYear = () => new Date().getFullYear();
if (typeof (Entries) == 'undefined') Entries = (node) => [node.name, +node.value];
@@ -4369,8 +4390,6 @@ xover.modernize = async function (targetWindow) {
if (typeof (Find) == 'undefined') Find = function (selector, target = document) { return selector ? target.querySelector(selector) : target.contains(this) && this }
- if (typeof (Intersection) == 'undefined') Intersection = function () { return this.isIntersecting || null };
-
if (typeof (Avg) == 'undefined') Avg = (result, value, ix, array) => (+result + +value) / (ix == array.length - 1 ? array.length : 1);
if (typeof (Money) == 'undefined') Money = function (x, format = xover.site.locale) {
@@ -4904,10 +4923,11 @@ xover.modernize = async function (targetWindow) {
for (let [namespace, attributes] of Object.entries(mutation.attributes || {})) {
for (let [attribute_name, [attribute, old_value]] of Object.entries(attributes)) {
- if (String(attribute.value) === String(old_value)) continue;
- let node_event = new xover.listener.Event('change', { srcElement: active_element, element: target, attribute, value: attribute.value, old: old_value, removedNodes: mutation.removedNodes, addedNodes: mutation.addedNodes, attributes: mutation.attributes }, attribute);
+ let current_value = attribute.value;
+ if (String(current_value) === String(old_value)) continue;
+ let node_event = new xover.listener.Event('change', { srcElement: active_element, element: target, attribute, value: current_value, old: old_value, removedNodes: mutation.removedNodes, addedNodes: mutation.addedNodes, attributes: mutation.attributes }, attribute);
window.top.dispatchEvent(node_event);
- if (node_event.defaultPrevented) delete (mutation.attributes[attribute.namespaceURI] || {})[attribute.localName];
+ if (node_event.defaultPrevented || current_value == null && target.hasAttributeNS(attribute.namespaceURI, attribute.localName)) delete (mutation.attributes[attribute.namespaceURI] || {})[attribute.localName];
if (!Object.keys(mutation.attributes[attribute.namespaceURI] || {}).length) delete mutation.attributes[attribute.namespaceURI];
}
}
@@ -5393,17 +5413,7 @@ xover.modernize = async function (targetWindow) {
Object.defineProperty(Node.prototype, 'dispatch', {
value: function (event_name, ...args) {
let detail = { target: this, element: this.closest("*"), attribute: this instanceof Attr ? this : null };
- for (let arg of args) {
- if (arg instanceof Array) {
- detail.args = detail.args || []
- detail.args.concat(arg)
- } else if (arg && arg.constructor === {}.constructor) {
- detail = { ...detail, ...arg }
- } else {
- detail.args = detail.args || []
- detail.args.push(arg)
- }
- }
+ if (args.length) detail.args = args;
let event = new xover.listener.Event(event_name, detail, this);
window.top.dispatchEvent(event);
return event.detail.returnValue;
@@ -9250,17 +9260,17 @@ xover.fetch = async function (url, ...args) {
if (!controller.signal.aborted) {
progress();
}
- let document = await response.processBody.apply(this);
+ let body = await response.processBody.apply(this);
- if (document instanceof Document) {
+ if (body instanceof Object) {
let url = request.url;
let href = url.href.replace(new RegExp(`^${location.origin}`), "").replace(new RegExp(`^${location.pathname.replace(/[^/]+$/, "")}`), "").replace(/^\/+/, '');
- Object.defineProperty(document, 'url', {
+ Object.defineProperty(body, 'url', {
get: function () {
return url;
}
});
- Object.defineProperty(document, 'href', {
+ Object.defineProperty(body, 'href', {
get: function () {
return href
}
@@ -9268,7 +9278,7 @@ xover.fetch = async function (url, ...args) {
}
let self = this;
if (this instanceof xover.Source) {
- Object.defineProperty(document, 'source', {
+ Object.defineProperty(body, 'source', {
get: function () {
return self;
}
@@ -9276,7 +9286,7 @@ xover.fetch = async function (url, ...args) {
}
response.tag = ((`${url.pathname || url}`).replace(/^\//, ''));
let manifest_settings = xover.manifest.getSettings(response.tag, "stylesheets");
- document instanceof XMLDocument && manifest_settings.reverse().map(stylesheet => {
+ body instanceof XMLDocument && manifest_settings.reverse().map(stylesheet => {
return_value.addStylesheet(stylesheet);
});
//window.top.dispatchEvent(new xover.listener.Event(`response`, { request }, response));
@@ -9293,7 +9303,7 @@ xover.fetch = async function (url, ...args) {
xover.session.status = "unauthorized";
}
if (response.status == 204) {
- document = xover.xml.createDocument();
+ body = xover.xml.createDocument();
}
if (response.ok) {
@@ -9301,7 +9311,7 @@ xover.fetch = async function (url, ...args) {
(request.headers.get("Accept") || "").indexOf("*/*") != -1 ||
request.headers.get("Accept").split(/\s*,\s*/g).includes(response.headers.get("content-type")) ||
xover.mimeTypes[response.bodyType] == request.headers.get("Accept") ||
- (request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(document.type) != -1 ||
+ (request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(body.type) != -1 ||
(request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(response.bodyType) != -1) {
return Promise.resolve(response);
@@ -9320,11 +9330,11 @@ xover.fetch = async function (url, ...args) {
//} else if (
// (request.headers.get("Accept") || "").indexOf("*/*") != -1 ||
// xover.mimeTypes[response.bodyType] == request.headers.get("Accept") ||
- // (request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(document.type) != -1 ||
+ // (request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(body.type) != -1 ||
// (request.headers.get("Accept") || "").replace("text/plain", "text").indexOf(response.bodyType) != -1) {
// return Promise.resolve(response);
- //} else if (response.bodyType == 'html' && document instanceof DocumentFragment) {
- // xover.dom.createDialog(document);
+ //} else if (response.bodyType == 'html' && body instanceof DocumentFragment) {
+ // xover.dom.createDialog(body);
//}
//return Promise.reject(response);
}
@@ -11931,6 +11941,30 @@ xover.listener.on('dialog::iframe', function () {
}
})
+xover.listener.on('hotreload', function ( file_name ) {
+ let document = this instanceof Document && this || this.ownerDocument || window.document;
+ let file = xover.URL(file_name);
+ let current_url = xover.URL(location);
+ let not_found = true;
+ if (current_url.href == file.href) {
+ location.href = location.href;
+ not_found = false;
+ }
+ let scripts = document.select(`//html:link/@href|//html:script/@src`);
+ for (let src of scripts.filter(script => xover.URL(script.value).pathname == file.pathname)) {
+ let old_script = src.parentNode;
+ let new_script = document.createElement(old_script.tagName); /*script.cloneNode(); won't work properly*/
+ [...old_script.attributes].map(attr => new_script.setAttributeNode(attr.cloneNode(true)));
+ old_script.parentNode.replaceChild(new_script, old_script);
+ not_found = false;
+ }
+ for (let section of [...xover.site.stylesheets, ...xover.site.sections].filter(node => node.source && xover.URL(node.href || (node.source || {}).href).pathname == file.pathname)) {
+ section.source.reload().then(() => section.render())
+ not_found = false;
+ }
+ if (not_found) xo.site.stylesheets.reload()
+})
+
xover.listener.on(['append::dialog[open]'], function () {
// fixes browser's behavior that won't show backdrop unless it is closed and reopened again
this.close()