summaryrefslogtreecommitdiff
path: root/resources/js/webtrees.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/js/webtrees.js')
-rw-r--r--resources/js/webtrees.js80
1 files changed, 43 insertions, 37 deletions
diff --git a/resources/js/webtrees.js b/resources/js/webtrees.js
index 5af75a5eca..f81733ae44 100644
--- a/resources/js/webtrees.js
+++ b/resources/js/webtrees.js
@@ -56,53 +56,59 @@
}
/**
- * Simple replacement for jQuery().load() - fetch HTML, insert into an element, and execute and scripts.
+ * Simple replacement for jQuery().load() - fetch HTML, insert into an element, and execute any scripts.
*
- * @param {element} element
+ * @param {Element} element
* @param {string} url
- * @param {object|null} data
+ * @param {FormData|null} data
*/
- webtrees.load = function (element, url, data = null) {
- const csrfToken = document.head.querySelector('meta[name=csrf]').getAttribute('content');
+ webtrees.load = async function (element, url, data = null) {
+ const headers = {
+ 'accept': 'text/html',
+ 'x-requested-with': 'XMLHttpRequest',
+ };
- const options = {
+ if (data !== null) {
+ headers['x-csrf-token'] = document.head.querySelector('meta[name=csrf]').getAttribute('content');
+ }
+
+ const response = await fetch(url, {
body: data,
method: data === null ? 'GET' : 'POST',
- headers: new Headers({
- 'accept': 'text/html',
- 'x-requested-with': 'XMLHttpRequest',
- 'x-csrf-token': csrfToken,
- }),
- };
+ headers: new Headers(headers),
+ });
- fetch(url, options)
- .then(response => {
- return response.text();
- })
- .then(html => {
- element.innerHTML = html;
+ const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
+ const scripts = Array.from(doc.querySelectorAll('script'));
- // Parse into a document fragment
- const parser = new DOMParser();
- const doc = parser.parseFromString(html, "text/html");
+ // Don't insert scripts into the document. We will execute them directly.
+ scripts.forEach(script => script.remove());
- // Append script elements to the end of the body.
- Array.from(doc.body.childNodes).forEach(node => {
- if (node.tagName === "SCRIPT") {
- let script = document.createElement('script');// Copy attributes (src, type, etc.)
- Array.from(node.attributes).forEach(attr => {
- script.setAttribute(attr.name, attr.value);
- });
- if (node.src) {
- script.src = node.src;
- } else {
- script.textContent = node.textContent;
- }
- node.remove();
- document.body.appendChild(script);
- }
+ // Replace innerHTML with the loaded HTML.
+ element.replaceChildren(...doc.body.childNodes);
+
+ // Execute scripts sequentially
+ for (const node of scripts) {
+ const script = document.createElement('script');
+
+ for (const attr of node.attributes) {
+ script.setAttribute(attr.name, attr.value);
+ }
+
+ if (node.src) {
+ await new Promise(resolve => {
+ script.onload = resolve;
+ script.onerror = resolve;
+ document.body.appendChild(script);
});
- });
+ } else {
+ script.textContent = node.textContent;
+ document.body.appendChild(script);
+ }
+
+ // Remove the script we just executed to reduce clutter.
+ script.remove();
+ }
}
/**