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.
+
+
+
+
+
+
diff --git a/xajax/sandbox/test-x-ajax-with-children.html b/xajax/sandbox/test-x-ajax-with-children.html
new file mode 100644
index 0000000..79b4b54
--- /dev/null
+++ b/xajax/sandbox/test-x-ajax-with-children.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+ X-Ajax
+
+
+
+
+
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
...loading
+
+
+
+
+
+
+
+
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
};