String per JS effizient splitten
heinetz
- javascript
Hallo Forum,
ich will diese Methode als Äquivalent zu jQuery $.load() umbauen.
getModalContent() {
return new Promise((resolve, reject) => {
if (this.modalContentUrl) {
addClass(this.elements.self, this.modalContentLoadingClass);
const ajax = new XMLHttpRequest();
ajax.open('GET', this.modalContentUrl, true);
ajax.send();
ajax.onload = () => {
if (ajax.status === 200) {
this.elements.body.innerHTML = ajax.responseText;
resolve(ajax.status);
} else {
reject(ajax.status);
}
};
ajax.ontimeout = () => {
reject(ajax.timeout);
};
} else {
resolve(true);
}
});
}
Die bestehende Methode erwartet in dem Parameter this.modalContentUrl eine Url. Bspw. /folder/file.html. Im Gegensatz dazu kann man der jQuery-Methode load als Parameter folgendes mitgeben:
/folder/file.html .class
Das versuche ich gerade umzusetzen. Im Moment scheitere ich daran, dass ich zwar ajax.responseText aber nicht ajax.responseXML zur Verfügung habe.
Kann man da auf den ersten Blick sehen, warum das nicht geht?
danke für Tipps und
beste gruesse, heinetz
hallo
Ohne dir helfen zu können, ist mir aufgefallen dass du mit
if (ajax.status === 200) { this.elements.body.innerHTML = ajax.responseText; resolve(ajax.status); } else { reject(ajax.status); }
Eigentlich die Möglichkeit des Caches (status 304) verwirfst. Das sollte man ohne guten Grund für
ajax.open('GET', ....
nicht tun.
Was verstehst Du unter String splitten? Splitten zu was? MfG
@@heinetz
Du verwendest Promise
(modern), aber XMLHttpRequest
(alt) – das passt nicht zusammen. Warum nicht das Fetch API?
LLAP 🖖
Ich hab's nicht geschrieben aber es funktioniert. Ich würde es nur gerne auf meine Bedürfnisse anpassen.
gruss, heinetz
Hallo heinetz,
die jQuery-Methode lädt ein HTML Fragment und extrahiert dann daraus einen Container. Wie sie das macht, steht auf api.jquery.com:
jQuery uses the browser's .innerHTML property to parse the retrieved document and insert it into the current document. During this process, browsers often filter elements from the document such as <html>, <title>, or <head> elements. As a result, the elements retrieved by .load() may not be exactly the same as if the document were retrieved directly by the browser.
Man müsste sich den jquery sourcecode anschauen um zu sehen wie sie es genau machen, aber ICH würde so vorgehen:
Damit nutzt Du soweit es möglich ist nativen Browsercode. Wie jQuery das macht, weiß ich nicht, die wollen ja auch alte Browser supporten die kein DocumentFragment kennen; ich mutmaße mal, dass jQuery dafür ein verstecktes Dummy-div ins DOM legt und das geladene HTML temporär darin unterbringt.
Rolf
hallo
Hallo heinetz,
die jQuery-Methode lädt ein HTML Fragment und extrahiert dann daraus einen Container. Wie sie das macht, steht auf api.jquery.com:
jQuery uses the browser's .innerHTML property to parse the retrieved document and insert it into the current document. During this process, browsers often filter elements from the document such as <html>, <title>, or <head> elements. As a result, the elements retrieved by .load() may not be exactly the same as if the document were retrieved directly by the browser.
Man müsste sich den jquery sourcecode anschauen um zu sehen wie sie es genau machen, aber ICH würde so vorgehen:
- html als text vom server holen
warum nicht als html
- mit createDocumentFragment ein DocumentFragment erzeugen
unntötig wenn als html
- darin ein div anlegen (weil das DocumentFragment kein innerHTML hat)
unnötg, wenn als html
- dem innerHTML des div das geladene html zuweisen
- in dem div mit querySelector den gewünschten Container lokalisieren
- den clonen und den Klon im eigenen DOM einsetzen
So ähnlich mach' ich es:
_.xhr = new XMLHttpRequest();
_.xhr.open("GET",_.sitemapUri);
_.xhr.responseType = 'document';
_.xhr.addEventListener('load', function(event) {
if( _.xhr.status == 200 || _.xhr.status == 304 ){
_.searchitems = _.xhr.responseXML.querySelectorAll('[data-for~="searchform"] a[href]');
_.sitemap = _.xhr.responseXML.querySelector('[data-for~="navigation"]');
if( _.sitemap ){
document.querySelector(".addSitemapContent").appendChild( _.sitemap );
if(_.searchitems) searchform(_.searchitems);
}
setAriaCurrentPage();
// initialise functions
_.functions = document.querySelectorAll("script[data-initfunction]");
for(var i=0; i<_.functions.length;i++){
_.funcname = _.functions[i].getAttribute("data-initfunction");
window[_.funcname]();
}
} else {
console.warn(_.xhr.statusText);
}
});
_.xhr.send();
Hallo beatovich,
autsch. Einfacher geht's nicht…
Rolf
Hallo Rolf,
https://developer.mozilla.org/de/docs/Web/API/DOMParser wäre auch noch eine Option. Den verwende ich bei einer xml-Datei, da ich mich auf responseXML nicht verlassen kann.
Gruß
Jürgen
Ja, damit hatte ich's dann auch gelöst:
getModalContent() {
return new Promise((resolve, reject) => {
if (this.modalContentUrl) {
const [contentUrl, contentSelector] = this.modalContentUrl.split(/\s/);
addClass(this.elements.self, this.modalContentLoadingClass);
const ajax = new XMLHttpRequest();
ajax.open('GET', contentUrl, true);
ajax.send();
ajax.onload = () => {
if (ajax.status === 200) {
if (contentSelector) {
const contentElement = new DOMParser()
.parseFromString(ajax.responseText, 'text/html')
.querySelector(contentSelector);
this.elements.body.innerHTML = '';
this.elements.body.appendChild(contentElement);
this.contentElement = contentElement;
} else {
this.elements.section.innerHTML = ajax.responseText;
}
// history.pushState({ url: contentUrl }, null, contentUrl);
resolve(ajax.status);
} else {
reject(ajax.status);
}
};
ajax.ontimeout = () => {
reject(ajax.timeout);
};
} else {
resolve(true);
}
});
}
Hallo Forum,
in meiner Lösung steht (auskommentiert) mein erster Anlauf mit der history-API. Ich habe damit ein wenig herum experimentiert, würde das Verhalten nun aber gerne vorher mal planen. Helft Ihr mir dabei?
Wie man an dem Code erkennen kann, lade ich per Ajax Content in ein Modal-Popup. Was ich erreichen möchte ist grundsätzlich, dass in der Adresszeile, die "richtige" URL steht wenn man ... navigiert. D.h.
Beim Aufruf der Seite "home.html" ist das Modal initial nicht sichtbar ... in der Adresszeile steht also "home.html".
Per Click auf der Seite wird das Modal sichtbar und der Inhalt von "page1.html" per Ajax nachgeladen ... in der Adresszeile soll also "page1.html".
Wird das Modal geschlossen soll in der Adresszeile wieder "home.html" stehen.
Bis dahin habe ich's relativ einfach hinbekommen. Interessant wird's hier:
Beim initialen Aufruf der Seite und bei der Benutzung der Back/Forward-Buttons des Browsers soll sich nicht nur die Adresszeile ändern, sondern der entsprechende Zustand abgebildet werden.
Dafür würde ich gerne einen Ansatz entwickeln.
gruss, heinetz