From 9f1a3887db4f91a5f9ac0f7c6aed8fde3f610d9c Mon Sep 17 00:00:00 2001 From: josh-tt Date: Fri, 25 Aug 2023 11:57:57 +0800 Subject: [PATCH 1/5] Added support for children --- xajax/src/index.js | 100 +++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/xajax/src/index.js b/xajax/src/index.js index 4650c0a..83c48c6 100644 --- a/xajax/src/index.js +++ b/xajax/src/index.js @@ -1,38 +1,76 @@ const xParser = new DOMParser(); export default function (Alpine) { - Alpine.directive('ajax', async (el, { expression, modifiers }, { effect, evaluateLater }) => { - const target = evaluateLater(expression); - let query; - - if (modifiers.includes('query')) query = modifiers[modifiers.indexOf(modifiers.includes('class') ? 'class' : 'query') + 1]; - if (modifiers.includes('class')) query = '.' + query; - - effect(() => { - target(async (target) => { - if (!target) return el.dispatchEvent(new CustomEvent('halted', { detail: 'Target is not defined', ...eventDefaults })); - try { - const response = await fetch(target, { mode: 'no-cors' }); - if (!response.ok) throw new Error(response.statusText); - const content = await response.text(); - const doc = xParser.parseFromString(content, 'text/html'); - const selector = query ? (modifiers.includes('all') ? doc.body.querySelectorAll(query) : doc.body.querySelector(query)) : doc.body; - if (!selector) throw new Error('Selected element not found'); - - el.dispatchEvent(new Event('load', eventDefaults)); - if (modifiers.includes('replace')) return el.replaceWith(selector); - if (modifiers.includes('all')) return el.replaceChildren(...selector); - if (selector.tagName == 'BODY') return el.replaceChildren(...selector.children); - return el.replaceChildren(selector); - } catch (e) { - console.error(e); - el.dispatchEvent(new Event('error', { detail: e, ...eventDefaults })); - } - }); - }); - }); + Alpine.directive('ajax', async (el, { expression, modifiers }, { effect, evaluateLater }) => { + + const target = evaluateLater(expression); + let query; + + if (modifiers.includes('query')) query = modifiers[modifiers.indexOf(modifiers.includes('class') ? 'class' : 'query') + 1]; + if (modifiers.includes('class')) query = '.' + query; + + effect(() => { + target(async (target) => { + if (!target) return el.dispatchEvent(new CustomEvent('halted', { detail: 'Target is not defined', ...eventDefaults })); + try { + const response = await fetch(target, { mode: 'no-cors' }); + if (!response.ok) throw new Error(response.statusText); + const content = await response.text(); + const doc = xParser.parseFromString(content, 'text/html'); + + // If both 'all' and 'children' modifiers, append '>*' to the query to select all children of the selected element. + const updatedQuery = modifiers.includes('all') ? + doc.body.querySelectorAll(modifiers.includes('children') ? query + '>*' : query) : + doc.body.querySelector(query); + + const selector = query ? updatedQuery : doc.body; + if (!selector) throw new Error('Selected element not found'); + + el.dispatchEvent(new Event('load', eventDefaults)); + + // Handles edge case where combination of all, replace, and children modifiers are used + if (modifiers.includes('replace') && modifiers.includes('all') && modifiers.includes('children')) { + if (selector instanceof NodeList) { + console.log('xajax: Fetched NodeList:', selector); + let fragment = document.createDocumentFragment(); + selector.forEach(node => { + console.log('xajax: Node children:', node.children); + Array.from(node.children).forEach(child => fragment.appendChild(child.cloneNode(true))); + }); + console.log('xajax: Final fragment:', fragment); + el.replaceWith(fragment); + return; + } + } + + // Added Conditon for 'replace' and 'children' modifiers + if (modifiers.includes('replace') && modifiers.includes('children')) return el.replaceWith(...selector.children); + + // Handle 'replace' modifier for NodeList case - spreads the NodeList and replaces the current element with all nodes from the list + // Corrects behavior for the scenario where fetching all instances of an element and replacing them, but the element is not a direct child of the parent + if (modifiers.includes('replace')) { + if (selector instanceof NodeList) { + el.replaceWith(...selector); + } else { + el.replaceWith(selector); + } + return; + } + + if (modifiers.includes('all')) return el.replaceChildren(...selector); + + // Include a check for 'children' modifier + if (selector.tagName == 'BODY' || modifiers.includes('children')) return el.replaceChildren(...selector.children); + return el.replaceChildren(selector); + } catch (e) { + console.error(e); + el.dispatchEvent(new Event('error', { detail: e, ...eventDefaults })); + } + }); + }); + }); } const eventDefaults = { - bubbles: false + bubbles: false }; From 5fd9197f527b855e4d08ed25316928aa026215b5 Mon Sep 17 00:00:00 2001 From: josh-tt Date: Fri, 25 Aug 2023 12:07:09 +0800 Subject: [PATCH 2/5] Create various-examples-with-children.html Test page for pr that supports child modifiers. --- .../various-examples-with-children.html | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 xajax/sandbox/various-examples-with-children.html diff --git a/xajax/sandbox/various-examples-with-children.html b/xajax/sandbox/various-examples-with-children.html new file mode 100644 index 0000000..79b4b54 --- /dev/null +++ b/xajax/sandbox/various-examples-with-children.html @@ -0,0 +1,54 @@ + + + + + + + X-Ajax + + + + +
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
...loading
+ + +
+
...loading
+
+ +
+ + + From 70deb9672ccfe07766eded0a93b1df538baef6a4 Mon Sep 17 00:00:00 2001 From: josh-tt Date: Fri, 25 Aug 2023 12:15:32 +0800 Subject: [PATCH 3/5] Create test-content-with-children.html Page to use to test using x-ajax with child modifiers --- xajax/sandbox/test-content-with-children.html | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 xajax/sandbox/test-content-with-children.html diff --git a/xajax/sandbox/test-content-with-children.html b/xajax/sandbox/test-content-with-children.html new file mode 100644 index 0000000..e1dcacd --- /dev/null +++ b/xajax/sandbox/test-content-with-children.html @@ -0,0 +1,42 @@ + + + + + + + X-Ajax + + + + + // This is a page of content to test x-ajax with children +
+
+
This is a div with plain text.
+
+
+

Paragraph inside inner div.

+
+
+
+
+ First child div. + Child of first child div. +
+
+ Second child div. + Child of second child div. +
+
+
+ + + From 811c4dbe00a2b780a12fae2e1b3d94609f27c8e3 Mon Sep 17 00:00:00 2001 From: josh-tt Date: Fri, 25 Aug 2023 12:16:24 +0800 Subject: [PATCH 4/5] Rename various-examples-with-children.html to test-x-ajax-with-children.html --- ...examples-with-children.html => test-x-ajax-with-children.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename xajax/sandbox/{various-examples-with-children.html => test-x-ajax-with-children.html} (100%) diff --git a/xajax/sandbox/various-examples-with-children.html b/xajax/sandbox/test-x-ajax-with-children.html similarity index 100% rename from xajax/sandbox/various-examples-with-children.html rename to xajax/sandbox/test-x-ajax-with-children.html From 22e1b06b358dad2f3bd2a8629c44d5cf535bd879 Mon Sep 17 00:00:00 2001 From: josh-tt Date: Fri, 25 Aug 2023 12:33:37 +0800 Subject: [PATCH 5/5] fixed format indents