[FRAGE] DIV-Inhalt mittels XML und Ajax ändern

Wenn du ganz sicher gehen willst, kannst du im JSON auch die Unicode-Maskierung verwenden: "\uXXXX" z.B. "\u00E4" für "ä"
Das hört sich gut an! Ja denke da auf Nummer sicher zu gehen ist schon besser. Hab jetzt ewig gesucht nach einer Liste mit allen JSON Unicode-Maskierungen, habe aber keine komplette Liste gefunden. Viele Seiten schreiben viel darüber und führen auch ein paar kleine Beispiele, aber komplett für die ganzen Sprachen finde ich leider nichts. Kennst Du eine Quelle?

- - - Aktualisiert - - -

@tsseh:
Danke für Dein Skript in pur JS. In meiner Seite habe ich das mit Deinem Code noch nicht zum laufen gebracht, aber da mache ich morgen weiter. Dein Codefunktioniert bei mir in Firefox super. In Chrome und Opera erscheint gar nichts. In der Fehlerkonsole erscheint diese Fehlermeldung:Fehlermeldung.JPG. Kannst Du damit was anfangen? Das ist rein Dein Code ohne irgendwelche Änderung. Wie gesagt in Chrome/Opera kommt nur eine komplett weiße Seite.

Problem Nr.2:
In meiner Seite habe ich derzeit ja noch das JSON-Auslesen mit JQUERY drin.... jetzt ist mir aber aufgefallen, dass viele andere Skripte, die unten im body-tag sind, nicht mehr funktionieren. Ich habe auch getestet wie es ist wenn diese anderen Skripte nicht mehr unten im body stehen sondern in einer externen JS-Datei.... aber alles gleich. Wenn ich den Inhalt umschließenden script-tag <script id="personTpl" type="text/template"> <!-- Start JSON artaTpl--> entferne, dann funktionieren alle meine alten Skripte wieder. Kann das etwas damit zu tun haben, dass ich so hier JQUERY und pur JS gemixt ist, sodass die sich gegenseitig ausschließen und man sich für eine Variante entscheiden muss??? Etwas anderes fällt mir gerade nicht ein.....
 
Das hört sich gut an! Ja denke da auf Nummer sicher zu gehen ist schon besser.
nein, das ist unnötig.

Dein Codefunktioniert bei mir in Firefox super. In Chrome und Opera erscheint gar nichts.
ja im chrome gehen keine lokalen xmlhttp-requests https://bugs.chromium.org/p/chromium/issues/detail?id=47416 wenn man chrome nicht mit "--allow-file-access-from-files" aufruft

Wenn ich den Inhalt umschließenden script-tag <script id="personTpl" type="text/template"> <!-- Start JSON artaTpl--> entferne, dann funktionieren alle meine alten Skripte wieder.
scripte die mit innerHTML="..." eingefügt werden, werden nocht geparst. und selbst wenn, kann es sein, dass du diese noch anpassen musst, weil sie z.b. auf ein event warten, was schon durch ist (z.b. DOMContentLoaded)
pach also keine scripte in ein template sondern ans ende des body.
oder meinst du sie stehen schon da und machen jetzt nicht mehr das was sie vorher gemacht haben? die dom-elemente aus dem template sind ja jetzt erst später verfügbar.

Kann das etwas damit zu tun haben, dass ich so hier JQUERY und pur JS gemixt ist, sodass die sich gegenseitig ausschließen und man sich für eine Variante entscheiden muss???
jquery ist auch pures JS und stellt dir nur weitere pure js-funktionen zur verfügung.

- - - Aktualisiert - - -

oder meinst du sie stehen schon da und machen jetzt nicht mehr das was sie vorher gemacht haben? die dom-elemente aus dem template sind ja jetzt erst später verfügbar.
mal als beispiel das registrieren der click-event-handler in meinem script. wenn das bei dir am ende vom body steht geht das mit dem template nicht mehr, da das element noch nicht im dom ist. deswegen passier das bei mir in der funktion changeLang nach dem einfügen des templates
 
Hallo meine netten Helfer :)

Wieder ist eine ganze Zeit lang verstrichen, aber nach viel probieren und testen funktioniert jetzt endlich das JSON/Mustache-Skript auf meiner Seite und übersetzt alle Inhalte zuverlässig. Das war ein langer Weg und ohne Eure Hilfe @kkapsner und @tsseh hätte ich das mit Sicherheit noch nicht geschafft. Danke nochmal!!

Jetzt ist nur noch ein Problem, das ich schon vor zwei Wochen hatte und mir das nicht ganz erklären kann.

Einiger meiner anderen JS-Skripte funktionieren nicht mehr.
tsseh schrieb:
scripte die mit innerHTML="..." eingefügt werden, werden nocht geparst. und selbst wenn, kann es sein, dass du diese noch anpassen musst, weil sie z.b. auf ein event warten, was schon durch ist (z.b. DOMContentLoaded)
pach also keine scripte in ein template sondern ans ende des body.
oder meinst du sie stehen schon da und machen jetzt nicht mehr das was sie vorher gemacht haben? die dom-elemente aus dem template sind ja jetzt erst später verfügbar.
Meine Skripte stehen unten ganz am Ende im body. Die haben genau so vorher funktioniert, jetzt gehen die meisten davon aber nicht mehr.

HTML:
	<head>
		<meta charset="UTF-8" />

		<link rel="stylesheet" type="text/css" href="assets/css/xxx.css" />
		<link rel="stylesheet" type="text/css" href="assets/offcanvas/classie.css" />
		<link rel="stylesheet" type="text/css" href="assets/offcanvas/normalize.css" />
		<link rel="stylesheet" type="text/css" href="assets/offcanvas/demo.css" />
		<link rel="stylesheet" type="text/css" href="assets/offcanvas/oc.css" />
		<link rel="stylesheet" type="text/css" href="assets/css/style.css" />
		<link rel="stylesheet" type="text/css" href="assets/css/icons.css" />
		<link rel="stylesheet" type="text/css" href="assets/css/hamburgers.css" />
		<link rel="stylesheet" type="text/css" href="assets/css/simptip.css" media="screen,projection" />
		<script src="assets/js/mustache.js"></script>
		<script src="assets/js/modernizr.custom.js"></script>
	</head>
	<body>
		<div id="output"></div>
		<script id="template" type="x-tmpl-mustache">
			/*{{Texte}}*/
		</script>


		<script>												//Sprachumschaltung funktioniert
    (function()
    {
      function changeLang(lang)
      {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", lang + '.json');
        xhr.onreadystatechange = function ()
        {
          if (this.readyState == 4 && (this.status == 200 || this.status == 0))
          {
            var data = JSON.parse(this.responseText);
            var template = document.getElementById('template').innerHTML;
            var rendered = Mustache.render(template, data);
            var content = document.getElementById('content');
            content.innerHTML = rendered;
            [].forEach.call(content.getElementsByClassName('flag'), function(elem)
            {
              elem.addEventListener("click", function(e)
              {
                changeLang(e.target.dataset.lang);
              });
            });
          };
        };
        xhr.send(null);
      }
      changeLang('en');
    })();
		</script>


		<script>
		var forEach=function(t,o,r){if("[object Object]"===Object.prototype.toString.call(t))for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&o.call(r,t[c],c,t);else for(var e=0,l=t.length;l>e;e++)o.call(r,t[e],e,t)};

		Array.prototype.forEach.call(										//funktioniert nicht
			document.querySelectorAll(".hamburger"),
			function(hamburger){
				var side = document.querySelector(".hoverside");
				side.addEventListener("mouseover", function(){
					hamburger.classList.add("is-active");
				}, false);
				side.addEventListener("mouseout", function(){
					hamburger.classList.remove("is-active");
				}, false);
			}
		);

		Array.prototype.forEach.call(										//funktioniert nicht
			document.querySelectorAll(".hamburger"),
			function(hamburger){
				var box = document.querySelector(".hamburger");
				box.addEventListener("mouseover", function(){
					hamburger.classList.add("is-hovered");
				}, false);
				box.addEventListener("mouseout", function(){
					hamburger.classList.remove("is-hovered");
				}, false);
			}
		);

		document.body.addEventListener("mousemove",function(event) {						//funktioniert
				if (event.pageX < 5) {
						document.body.classList.add("show-menu");
				}
		});

		var mainwrap = document.querySelector("#main-wrap");							//funktioniert nicht
		mainwrap.addEventListener("click",function() {
						document.body.classList.remove("show-menu");
		});



		var navstart = document.getElementById('start');							//funktioniert nicht
		navstart.onclick = function() {
				var content = document.getElementById('content-wrap');
				content.style.display = 'block';
		};


		var contentclose = document.getElementById('contentclose');						//funktioniert nicht
		contentclose.onclick = function(event) {
				var content = document.getElementById('content-wrap');
				content.style.display = 'none';
				event.stopPropagation();
		};



		</script>

		<script src="assets/offcanvas/classie.js"></script>
		<script src="assets/offcanvas/main.js"></script>

	</body>


Ist das eigentlich ok wenn so viele Skripte unten im body stehen? Ist es nicht besser diese auch in eine js-Datei auszulagern? Wie sollte ich das dann am besten auslagern? Alles in eine Datei und dann auch unten hin bei den anderen beiden oder oben in den header?

- - - Aktualisiert - - -

Ah und doch noch eine weitere Frage :)

So jetzt bei dem Skript werden die json-Sprachdateien ja aus dem gleichen Ordner geöffnet. Wie bzw. wo kann ich einen tieferen Pfad zur Datei eintragen?
Die Datei soll später liegen in assets/lang/eng.json

- - - Aktualisiert - - -

Uuund noch eine kleine Kleinigkeit ;) fällt mir gerade auf. Kann man in Abhängigkeit zur gewählten Sprache bestimmte css-Klassen ändern? Es geht eigentlich nur um Kleinigkeiten die angepasst werden müssten, also nicht wirklich viel. Wäre es da vielleicht besser für jede Sprache, bei der etwas geändert werden muss eine eigene css-Datei mit den jeweiligen Klassen zu erstellen und diese bei Klick zu laden? Wie genau müsste das dann gehen?

Beispiel: Das Wort "Anbieterkennzeichnung", habe ich auf englisch übersetzt mit "Provider Information".
Die id lautet #impressum. Bei Deutsch ist letter-spacing: 0.09em. Bei Englisch müsste das 0.16em werden.
 
Zuletzt bearbeitet:
Meine Skripte stehen unten ganz am Ende im body. Die haben genau so vorher funktioniert, jetzt gehen die meisten davon aber nicht mehr.

das ist dein html zur laufzeit deiner scripte

HTML:
<div id="output"></div>

dort existiert kein element mit klasse .hamburger, document.querySelectorAll(".hamburger") liefert eine leere collection und die schleife wird nicht durchlaufen

Code:
Array.prototype.forEach.call(										//funktioniert nicht
			document.querySelectorAll(".hamburger"),
			function(hamburger){
				var side = document.querySelector(".hoverside");
				side.addEventListener("mouseover", function(){
					hamburger.classList.add("is-active");
				}, false);
				side.addEventListener("mouseout", function(){
					hamburger.classList.remove("is-active");
				}, false);
			}
		);

das gleiche mit dem element mit id main-wrap, start und contentclose

hier wird das template erst ins dom eingefügt, dort müssen auch die scripte hin
Code:
    (function()
    {
      function changeLang(lang)
      {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", lang + '.json');
        xhr.onreadystatechange = function ()
        {
          if (this.readyState == 4 && (this.status == 200 || this.status == 0))
          {
            var data = JSON.parse(this.responseText);
            var template = document.getElementById('template').innerHTML;
            var rendered = Mustache.render(template, data);
            var content = document.getElementById('content');
            content.innerHTML = rendered;
            [].forEach.call(content.getElementsByClassName('flag'), function(elem)
            {
              elem.addEventListener("click", function(e)
              {
                changeLang(e.target.dataset.lang);
              });
            });
            // HIER DEINE SCRIPTE EINFÜGEN
            
          };
        };
        xhr.send(null);
      }
      changeLang('en');
    })();

das kann da stehenbleiben, es funktioniert ja auch, weil document.body von anfang an existiert

Code:
document.body.addEventListener("mousemove",function(event) {						//funktioniert
				if (event.pageX < 5) {
						document.body.classList.add("show-menu");
				}
		});

Ist das eigentlich ok wenn so viele Skripte unten im body stehen? Ist es nicht besser diese auch in eine js-Datei auszulagern? Wie sollte ich das dann am besten auslagern? Alles in eine Datei und dann auch unten hin bei den anderen beiden oder oben in den header?
ich würd alles in eins machen und dann ans ende des body

So jetzt bei dem Skript werden die json-Sprachdateien ja aus dem gleichen Ordner geöffnet. Wie bzw. wo kann ich einen tieferen Pfad zur Datei eintragen?
Die Datei soll später liegen in assets/lang/eng.json
jetzt werden sie ja von diesem pfad geladen
xhr.open("GET", lang + '.json');
den kannst du ja ändern

Uuund noch eine kleine Kleinigkeit ;) fällt mir gerade auf. Kann man in Abhängigkeit zur gewählten Sprache bestimmte css-Klassen ändern? Es geht eigentlich nur um Kleinigkeiten die angepasst werden müssten, also nicht wirklich viel. Wäre es da vielleicht besser für jede Sprache, bei der etwas geändert werden muss eine eigene css-Datei mit den jeweiligen Klassen zu erstellen und diese bei Klick zu laden? Wie genau müsste das dann gehen?
das geht schon, aber einfacher würde ich finden du machst dann klassen ala class-de, class-en, ... und packst alles in eine css datei solange das bei wenigen ausnahmen bleibt
 
Mufasa schrieb:
Meine Skripte stehen unten ganz am Ende im body. Die haben genau so vorher funktioniert, jetzt gehen die meisten davon aber nicht mehr.
tsseh schrieb:
hier wird das template erst ins dom eingefügt, dort müssen auch die scripte hin
HELL YEAH!!! You're the best :eagerness::eagerness:
____________________________________________________________________________________________

Mufasa schrieb:
Ist das eigentlich ok wenn so viele Skripte unten im body stehen?
tsseh schrieb:
ich würd alles in eins machen und dann ans ende des body
Die paar, die ich jetzt nach dem Template eingefügt hab, die sollen da bleiben, oder?!? Kann ich die dann auch in eine externe Datei packen und dort einfügen? Etwa so...
Code:
                changeLang(e.target.dataset.lang);
              });
            });
            // HIER DEINE SCRIPTE EINFÜGEN
            script.src = url;  //???
            
          };
        };
        xhr.send(null);
____________________________________________________________________________________________

Mufasa schrieb:
Wie bzw. wo kann ich einen tieferen Pfad zur Datei eintragen?
tsseh schrieb:
jetzt werden sie ja von diesem pfad geladen
xhr.open("GET", lang + '.json');
den kannst du ja ändern
Aber ich kann doch nicht einfach '.json' ersetzen mit 'assets/lang'. Deswegen hab ich gefragt, weil mir nicht klar ist wo ich den Pfad definieren kann.
Ich könnte ja eine Pfadvariable anlegen wie var langurl = "/assets/lang";
Nur wo füge ich dann langurl ein??
____________________________________________________________________________________________

Mufasa schrieb:
Kann man in Abhängigkeit zur gewählten Sprache bestimmte css-Klassen ändern?
tsseh schrieb:
das geht schon, aber einfacher würde ich finden du machst dann klassen ala class-de, class-en, ... und packst alles in eine css datei solange das bei wenigen ausnahmen bleibt
OK, ich hab ja meine Haupt-Style-Datei, das ist "style.css". Dann würde ich eine neue css-Datei anlegen (lang-style.css) und alle sprachspezifischen Änderungen da rein packen. Zum Beispiel gäbe es dann ein #impressum-de und ein #impressum-en, ... - Nur wie ersetze ich die dann immer? Meine Standard-Sprache ist ja englisch, das heißt der muss dann #impressum-en laden und bei Klick auf deutsch dann entsprechend #impressum-de.
____________________________________________________________________________________________

Gerade fällt mir noch ein Fehler auf. Wenn ich die Sprache ändere, dann werden scheinbar alle DIVs, die geändert werden neu geladen, richtig?!? Bei den meisten ist das auch kein Problem, nur mein Hauptinhalt #content-wrap ist beim Laden der Seite immer unsichtbar, das heißt display:none; - Erst mit Klick auf einen Menüpunkt (nicht Sprachwahl) wird es mit display:block; sichtbar.

Sooo wenn ich das nun sichtbar habe und die Sprache (mit Klick auf ein flag-icon) wechsle, wird das wieder unsichtbar. Hast Du eine Idee wie man das sichtbar lassen könnte? (Meine Idee weiter unten.)

Eine weitere Schwierigkeit ist dabei, dass wenn #content-wrap unsichtbar ist, dann soll auch eine Sprachumschaltung das nicht ändern. Dann würden eben nur die Menüpunkte und so geändert werden.

Ich hatte gedacht evtl. könnte man bei Klick auf eine Flagge den aktuellen value von display bei #content-wrap zum Zeitpunkt der Sprachumschaltung auslesen und dann als neuen Wert übergeben. Was hälst Du davon? Ist das so machbar? Oder fällt Dir noch eine andere/bessere Variante ein?

Dafür hab ich versucht erstmal den aktuellen Wert als alert auszugeben, aber irgendwie funktioniert das nicht. Also.... es tut sich gar nichts, kein alert. Kannst Du mal checken wo der Fehler steckt?
PHP:
var flags = document.getElementsByClassName('flag');
flags.onclick = function() {
		alert(document.getElementById("content-wrap").style.display);
};
 
Zuletzt bearbeitet:
Die paar, die ich jetzt nach dem Template eingefügt hab, die sollen da bleiben, oder?!? Kann ich die dann auch in eine externe Datei packen und dort einfügen?
du kannst sie in eine extra datei in eine funktion packen und diese funktion dort aufrufen

Aber ich kann doch nicht einfach '.json' ersetzen mit 'assets/lang'. Deswegen hab ich gefragt, weil mir nicht klar ist wo ich den Pfad definieren kann.
der pfad hier ist lang+".json" was zu "de.json" bzw. "en.json" wird. wenn du da was anderes haben willst, schreib es einfach hin.

OK, ich hab ja meine Haupt-Style-Datei, das ist "style.css". Dann würde ich eine neue css-Datei anlegen (lang-style.css) und alle sprachspezifischen Änderungen da rein packen.
kannst du machen, laden kannst du das z.b. so

Code:
if ($("#"+lang+"css").length == 0)// um nicht mehrfach zu laden bei wechsel de -> en -> de -> ...
{
  var link = document.createElement('link');
  link.id = lang+"css";
  link.rel = "stylesheet";
  link.type = "text/css";
  link.href = lang+".css"; // kannst du wieder belibig anpassen
  $('head').append(link);
}

Nur wie ersetze ich die dann immer? Meine Standard-Sprache ist ja englisch, das heißt der muss dann #impressum-en laden und bei Klick auf deutsch dann entsprechend #impressum-de.
laden muss er "de.css" und "en.css" (oder ähnlich) dort ist dann der style für #impressum-de bzw. #impressum-en definiert

Wenn ich die Sprache ändere, dann werden scheinbar alle DIVs, die geändert werden neu geladen, richtig?!?
ja

Sooo wenn ich das nun sichtbar habe und die Sprache (mit Klick auf ein flag-icon) wechsle, wird das wieder unsichtbar. Hast Du eine Idee wie man das sichtbar lassen könnte?
du musst dir die aktuelle seite ja merken, das macht man idR. über die history und manipulation des hash. hier mal ein beispiel mit jquery mobile um mir die arbeit zu spaaren, wie das mit dem hash geht sollte ersichtlich sein.
Anhang anzeigen test.zip
die abhängigkeiten
HTML:
    <link rel="stylesheet" type="text/css" href="jquery.mobile-1.4.5.css" />
    <script src="jquery.js"></script>
    <script src="jquery.mobile-1.4.5.js"></script>
    <script src="mustache.js"></script>
musst du dir mal selbst runterladen.

Eine weitere Schwierigkeit ist dabei, dass wenn #content-wrap unsichtbar ist, dann soll auch eine Sprachumschaltung das nicht ändern. Dann würden eben nur die Menüpunkte und so geändert werden.
warum?

Ich hatte gedacht evtl. könnte man den aktuellen value von display bei #content-wrap auslesen und dann bei Klick auf eine Flagge als neuen Wert übergeben. Was hälst Du davon? Ist das so machbar?
dann würde der back-button nicht funktionieren

- - - Aktualisiert - - -

hier mal ein beispiel mit jquery mobile um mir die arbeit zu spaaren, wie das mit dem hash geht sollte ersichtlich sein.
wenn du jquery-mobile nicht nehmen möchtest hier mal ein einfacher router
http://krasimirtsonev.com/blog/article/A-modern-JavaScript-router-in-100-lines-history-api-pushState-hash-url
keine ahnung ob der was taugt

- - - Aktualisiert - - -

oder nochmal zurück auf null, meine aussage aus #12
http://forum.jswelt.de/ajax/62508-div-inhalt-mittels-xml-ajax-ndern.html#post400660
stimmt vermutlich nicht. du willst nicht nur mal auf die schnelle auf einer seite ein paar texte sprachabhängig machen, sondern willst eine spa erstellen, mit sprachunterstützung.
dann müsstest du alles, vom laden der sprachen über das routing bis zum template selbst bauen bzw. dir eine jeweils passende lib suchen, oder du nimmst ein aufeinander abgestimmtes gesammtpacket.
angular wäre so eins. dafür sollte man aber fit sein in js.
 
Danke schön, das schaue ich mir auf jeden Fall an und werde mir auch die Webseite und Beispiele dort genau angucken und probieren. Aber das ganze so umzubauen dauert denke ich doch ein ganzes Weilchen. Auch wenn das ohne Routing wirklich Murks ist, da ja dann -wie Du schon sagtest- auch der Back-Button nicht funktioniert, muss ich das jetzt so schnell wie möglich online bringen und dann später umbauen auf sammy.

Gibt es eine "schnelle Lösung" für das display-Problem? Vielleicht so wie ich das angedacht hatte irgendwie zum Zeitpunkt der Sprachumschaltung den aktuellen value von display von #content-wrap auslesen und dann wieder als neuen value übergeben. Wäre das so überhaupt machbar? Das ist so die leichteste quick-and-dirty-Lösung die mir einfällt. Oder fällt Dir da vielleicht noch eine andere Möglichkeit ein?

Klar ist, dass das Ganze später auf jeden Fall mit einem Router ausgestattet werden muss. Nur blicke ich da ehrlich gesagt noch nicht wirklich durch..... :(
 
Gibt es eine "schnelle Lösung" für das display-Problem? Vielleicht so wie ich das angedacht hatte irgendwie zum Zeitpunkt der Sprachumschaltung den aktuellen value von display von #content-wrap auslesen und dann wieder als neuen value übergeben. Wäre das so überhaupt machbar? Das ist so die leichteste quick-and-dirty-Lösung die mir einfällt. Oder fällt Dir da vielleicht noch eine andere Möglichkeit ein?
soweit ich das verstanden habe, zeigst du in #content-wrap deine seiten an, die du über ein menü wählst.
du musst dir also merken
* welche sprache ist aktuell eingestellt
* welche seite wird gerade angezeigt
damit kannst du
* beim umschalten der sprache die gerade angezeigte seite in der neuen sprache laden
* beim wählen einer neuen seite diese neue seite in der gerade eingestellten sprache laden
die gerade angezeigte seite kannst du dir merken wie du willst. wenn du einen menüpunkt wählst musst du dir irgendwie die damit gewählte seite merken.
ein router macht das über den hash und deckt über die history gleich den back.button ab und sorgt dafür, daß man links auf seiten (und nicht nur auf die startseite) speichern kann.
in meinem beispiel ist die aktuelle seite im parameter id von function load(lang, id) gespeichert.
rufst du load mit gemerkter sprache und neuer seite als id direkt aus deinem menü auf kannst du den router auch weglassen, das funktioniert immer noch.

- - - Aktualisiert - - -

Anhang anzeigen test.zip
 
Zurück
Oben