klawischnigg: DOM und svg

Hi there,

Kennt sich hier jemand mit der Manipulation von svg-Graphiken mit Javascript von ausserhalb der Graphik aus?

Das Problem ist, ich habe ein als svg-Graphik dargestelltes Balkendiagramm, in dem ich mit Javascript etwas ändern müsste. Wenn ich mit document.getElementsByTagName die Elemente in der Graphik selektiere, dann kann ich mir diese Selektion in der Browserkonsole zwar detailliert anzeigen lassen, in Javascript aber sind diese Selektionen leer - auch .length gibt nur 0 zurück.

Konkret, in der Graphik gibt es ein Element <text>, dessen Position ich verändern müsste. Das kann ich in der Browserkonsole auch problemlos, die Beschriftung ändert wie gewünscht die Lage in der Graphik. Nur mit Javascript komm' ich da nicht 'ran.

Ich hab's auch noch mit document.getElementsByTagNameNS probiert, selbes Ergebnis - der Browser kennt das, Javascript nicht. Gibts da irgendeine Lösung, mit Javascript in das DOM des svg "'reinzukommen"? Die Beispiele, die ich ergoogelt habe, beschäftigen sich alle nur mit Javascript innerhalb der Graphik, das scheidet für mich aber aus...

akzeptierte Antworten

  1. Servus!

    Ich hab's auch noch mit document.getElementsByTagNameNS probiert, selbes Ergebnis - der Browser kennt das, Javascript nicht. Gibts da irgendeine Lösung, mit Javascript in das DOM des svg "'reinzukommen"? Die Beispiele, die ich ergoogelt habe, beschäftigen sich alle nur mit Javascript innerhalb der Graphik, das scheidet für mich aber aus...

    Das hier kennst du wohl schon, oder?

    Herzliche Grüße

    Matthias Scharwies

    --
    Einfach mal was von der ToDo-Liste auf die Was-Solls-Liste setzen.“
    1. Hi there,

      Ich hab's auch noch mit document.getElementsByTagNameNS probiert, selbes Ergebnis - der Browser kennt das, Javascript nicht. Gibts da irgendeine Lösung, mit Javascript in das DOM des svg "'reinzukommen"? Die Beispiele, die ich ergoogelt habe, beschäftigen sich alle nur mit Javascript innerhalb der Graphik, das scheidet für mich aber aus...

      Das hier kennst du wohl schon, oder?

      Ja, aber ich muß bekennen, daß ich das nicht wirklich auf mein Problem bezogen habe. Ich hab da nur irgendetwas von "AddEventListener" und von externem SVG gelesen. Vielleicht bin ich ja zu unflexibel, aber ich hab weder einen Event noch ein externes SVG;) - anyway, wenn ich es richtig verstehe, ist Deine Botschaft, es funktioniert, aber anders, als ich mir das vorgestellt habe...

    2. Hi there,

      Ich hab's auch noch mit document.getElementsByTagNameNS probiert, selbes Ergebnis - der Browser kennt das, Javascript nicht. Gibts da irgendeine Lösung, mit Javascript in das DOM des svg "'reinzukommen"? Die Beispiele, die ich ergoogelt habe, beschäftigen sich alle nur mit Javascript innerhalb der Graphik, das scheidet für mich aber aus...

      Das hier kennst du wohl schon, oder?

      Tja, ich fürcht', das wird nix. Ich weiß, jetzt bin ich lästig, aber ich kann die Graphik nicht einmal richtig selektieren, (weil es eben kein externes Objekt ist) - die Graphik steht so in der Seite:

      <div class="CHARTWRAPPER">
      <svg xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="100%" height="100%" class="ct-chart-bar" style="width: 100%; height: 100%;">...</svg>
      </div>
      

      Das umgebende DIV stammt von mir, aber das nützt mir auch nix, ich hab gedacht, daß ich vielleicht über den ersten Kindknoten auf das SVG komme, aber ein .firstChild gibt auch nix zurück. Verd..., wie macht der Browser das...?

  2. Moin,

    Das Problem ist, ich habe ein als svg-Graphik dargestelltes Balkendiagramm, in dem ich mit Javascript etwas ändern müsste. Wenn ich mit document.getElementsByTagName die Elemente in der Graphik selektiere, dann kann ich mir diese Selektion in der Browserkonsole zwar detailliert anzeigen lassen, in Javascript aber sind diese Selektionen leer - auch .length gibt nur 0 zurück.

    Das funktioniert zumindest für „Easter Eggs“ … 😉 Wie sieht denn dein Ansatz bisher aus und wo hakt es genau?

    Viele Grüße
    Robert

    1. Hi there,

      Das funktioniert zumindest für „Easter Eggs“ … 😉 Wie sieht denn dein Ansatz bisher aus und wo hakt es genau?

      so, jetzt hab ich schon einige Osterreier gebastelt, dabei war ja grad erst Murmeltiertag...

      Was ich probiert habe? Gute Frage, alle Maßnahmen halt, die mir bisher bekannt waren, um irgendwelche Elemente auf einer Webseite anzusprechen oder zu selektieren. Mein Problem dürfte sein, daß sich das svg aus der Graphik-Lib mit irgendeinem Namespace einklinkt, und das verhindert offenbar, daß man irgendwie drauf zugreifen kann. Leider hab ich auf die Erzeung der Graphik überhaupt keinen Einfluß (ja, ok, ich könnte die Library umschreiben, aber das zahlt mir keiner und bis Ostern hab ich auhc nicht Zeit, auch wenn ich die Eier jetzt schon habe)

      Ich hab mein Elend hier beschrieben...

      1. Moin,

        also das liefert mir einmal das komplette svg-Element und dann das x-Attribut des Rechtecks:

        <!doctype html>
        <html>
        <head>
        <meta charset="utf-8">
        <script>
        function moin() {
        	let svg = document.getElementsByTagName('svg');
        
        	if (svg.length === 0) {
        		console.warning('No SVG elements found.');
        		return;
        	}
        	
        	console.log(svg[0]);
        	
        	let r = svg[0].getElementsByTagName('rect');
        	
        	console.log(r[0].getAttribute('x'));
        }
        </script>
        </head>
        <body>
        <div class="CHARTWRAPPER">
        <svg xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="100%" height="100%" class="ct-chart-bar" style="width: 100%; height: 100%;">
        	<rect width="200" height="100" x="100" y="100" style="stroke-width:5;stroke:red;fill:black"/>
        </svg>
        </div>
        <button type="button" onclick="moin()">Klick</button>
        </body>
        </html>
        

        <svg class="ct-chart-bar" xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="100%" height="100%" style="width: 100%; height: 100%;"> …

        100

        1. Moin,

          also das liefert mir einmal das komplette svg-Element und dann das x-Attribut des Rechtecks:

          Klassischer Fall von komplett daneben und trotzdem richtig - das svg-Element wird auf der Seite von der js-library dynamisch erzeugt. Dein Beispiel hat mir die Augen geöffnet, weil der einzige Unterschied war, daß Du natürlich die HTML-Abteilung einfach so hingeschrieben hast. Mit anderen Worten - mein Problem war ein Timing-Problem und ich hab's jetzt so formuliert:

          window.setTimeout(function(){
          		let svg = document.getElementsByTagName('svg');
          ...etc.
          

          und siehe da, Javascript findet das svg-Element😉!

          Danke für Dein Bemühen, alleine wäre ich da wahrscheinlich erst übermorgen d'raufgekommen...

          1. Moin,

            Klassischer Fall von komplett daneben und trotzdem richtig - das svg-Element wird auf der Seite von der js-library dynamisch erzeugt. Dein Beispiel hat mir die Augen geöffnet, weil der einzige Unterschied war, daß Du natürlich die HTML-Abteilung einfach so hingeschrieben hast. Mit anderen Worten - mein Problem war ein Timing-Problem und ich hab's jetzt so formuliert:

            window.setTimeout(function(){
            		let svg = document.getElementsByTagName('svg');
            ...etc.
            

            Ist dieser Ansatz nicht etwas ungenau – was, wenn das Laden und Erstellen der Elemente länger dauert? Gibt es kein passendes Event dafür?

            Viele Grüße
            Robert

            1. Hallo Robert,

              man müsste die Lib kennen um zu wissen was sie wie tut.

              Also flugs gedownloaded, erstes Sample probiert, ein bisschen durchgesteppt mit dem Debugger, und aha!

              let chart = new Chartist.Line('.ct-chart', data, options);
              chart.on("created", function() { 
                 document.querySelector(".ct-chart .ct-series-a path").style.fill = "green";
              });
              

              Nicht, dass die Doku das sinnvoll erklären würde. Dass es ein "created" event gibt, habe ich per Debugger herausgefunden. Vielleicht findet man mehr raus wenn man die Examples alle durcharbeitet. Die API Doku verrät nur die .on Methode. Wer schreibt heute schon noch brauchbare Dokus. Ein paar Examples zusammengekloppt, API Referenz aus den Autodocs generiert, fertig. So grundlegende Dinge wie "das Ding agiert asynchron mit setTimeout" und "unser Event-System funktioniert so und so" muss man dann erraten. Aber ist vielleicht auch besser so. Dieser Satz:

              The handler callbacks are synchronous and will run in the main thread rather than the event loop.

              zeigt, dass der Autor nicht wirklich verstanden hat, was Events und Eventloop sind.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. Hi there,

                man müsste die Lib kennen um zu wissen was sie wie tut.

                Allerdings

                Also flugs gedownloaded, erstes Sample probiert, ein bisschen durchgesteppt mit dem Debugger, und aha!

                let chart = new Chartist.Line('.ct-chart', data, options);
                chart.on("created", function() { 
                   document.querySelector(".ct-chart .ct-series-a path").style.fill = "green";
                });
                

                Nicht, dass die Doku das sinnvoll erklären würde.

                Das ganze ist ziemlich schlecht dokumentiert. Immer wenn's halbwegs interessant wird wird auf die examples verwiesen, und dort kann man dann erraten, an welchen Parametern man schrauben kann.

                Was ich damit sagen will - es steht nicht dafür und vor allem, das bezahlt mir keiner, daß ich da an der Chartist-Akademie einen Studienplatz belege und ein Semester studiere...

              2. Lieber Rolf,

                Dass es ein "created" event gibt, habe ich per Debugger herausgefunden.

                welch bewundernswerte Fleißarbeit für eine Frage im Forum! Dafür +1 von mir.

                Liebe Grüße

                Felix Riesterer

                1. Hallo Felix,

                  das waren 15 Minuten, inclusive Download.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
            2. Hi there,

              window.setTimeout(function(){
              		let svg = document.getElementsByTagName('svg');
              ...etc.
              

              Ist dieser Ansatz nicht etwas ungenau – was, wenn das Laden und Erstellen der Elemente länger dauert? Gibt es kein passendes Event dafür?

              Ja, da hast Du recht. Aber nachdem es um so etwas Wichtiges wie die Position von Zahlenwerten in einem Balkendiagramm geht erzähl ich Dir jetzt lieber nicht, wo mir das vorbei....

              Das eigentliche Problem ist, daß ich auf das Javascript in diesen Chartist-Graphiken keinen Einfluß hab. Da wird auch nichts geladen, was man abfragen könnte. Man könnte natürlich zB eine Schleife einbauen, die die Existenz der svg-Graphik abfragt, was in dem Fall legitim wäre, weil ich ja weiß, das sie da sein muß. Aber, wie gesagt, ich steuer' damit keinen Krankenwagen und kein Atomkraftwerk...;)

  3. Hallo,

    im Wiki-Tutorial zu Maus- und Touch-Aktionen habe als Beispiel ein SVG-Zoom erstellt. Vielleicht hilft's dir weiter.

    Gruß
    Jürgen

    1. Hi there,

      im Wiki-Tutorial zu Maus- und Touch-Aktionen habe als Beispiel ein SVG-Zoom erstellt. Vielleicht hilft's dir weiter.

      war's nicht ganz, aber auf alle Fälle Danke für's Mitdenken...!