Paul: horizontales Balkendiagramm erstellen

Hallo zusammen,

ich bin auf der Suche nach einer Möglichkeit ein horizontales Balkendiagramm (die 0 soll dabei in der Mitte sein) zu erstellen. Die Werte sollen aus der Datenbank ausgelesen werden. Das Ganze soll auf meiner Homepage dann laufen.
Ich benötige das, um eine Formularauswertung zu machen. Dabei soll pro Frage die max. erreichbare Punktezahl angezeigt werden und die erreichte Punktzahl.

Ich hoffe, ich konnte es einigermaßen verständlich beschreiben.
Jedenfalls wäre ich echt froh, wenn mir da jemand weiterhelfen könnte.

  1. Tach!

    ich bin auf der Suche nach einer Möglichkeit ein horizontales Balkendiagramm (die 0 soll dabei in der Mitte sein) zu erstellen.

    Mach einfach schicken DIV, bestimme dessen Breite und ggf. die Position über "Inline-CSS":

    <div class="balken_<?php echo eineTolleBerechnung($n); ?>" style="width:<?php echo andereTolleBerechnung($n); ?>px">Beschriftung oder &nbsp;</div>

    Den Rest, der nicht für den Balken individuell ist (Hintergrundbild, Farbe), kannst im normalen CSS bestimmen, mach dafür aber Klassen.

    Jörg Reinholz

    1. also ich hab das mit dem Balkendiagramm schonmal hinbekommen. Jetzt hab ich nur noch das Problem, dass die Balken derzeit untereinander sind und nicht vom gleichen 0-Punkt aus der negative nach links und der positive nach rechts geht. Kann mir da jemand weiterhelfen wie das geht? Die Balken positionieren geht ja mit top: und left: Aber wie bekomm ich es hin, dass der eine sich nach links und der andere sich nach rechts entwickelt?

      Ich hab euch hier mal meinen bisherigen Quellcode. Vlt könnt ihr mir da ja weiterhelfen. Eine weitere Frage ist, wie kann ich diesen Code mehrfach auf meiner Seite einbinden ohne dass sich die Grafen überlagern.

      Hier mein Quellcode und ich danke euch jetzt schon für eure Hilfe.

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
         "http://www.w3.org/TR/html4/strict.dtd">
      <html>
         <head>
            <title>Unser Balkendiagramm</title>
      <style type="text/css">
      #bardemo {
         position:relative;
         padding:0;
         border: 1px solid #000;
         font-family:verdana;
         width:600px;
         height:180px;
         background: #fff;
         margin:auto
      }
      #bardemo div.title {
         padding:0;
         position:relative;
         font:12px;
         font-weight:bold;
         top:5px;
         text-align:center;
         line-height:15px;
      }
      #bardemo div.axis {
         padding:0;
         position:absolute;
         top:30px;
         left:100px;
         width:470px;
         height:105px;
         border-bottom:1px solid black;
         border-left:1px solid black;
      }
      #bardemo div.bar {
         position:absolute;
         left:0;
         height:20px;
         padding:10px 0px 0 0;
         text-align:right;
         font-size:10px;
         color: #000;
         font-weight:bold;
      }
      #bardemo div.bar_1 {
         top:15px;
         width:0px;
         background:#c00;
      }
      #bardemo div.bar_2 {
         top:60px;
         width:0px;
         background:#0c0;
         background-position:0;
      }
      #bardemo div.bar_3 {
         top:15px;
         width:0px;
         background:#0c0;
         background-position:0;
      }
      #bardemo div.labels {
         padding:0;
         position:absolute;
         top:30px;
         left:10px;
         width:100px;
         height:150px;
         line-height:30px;
      }
      #bardemo div.label {
         position:absolute;
         left:0;
         height:30px;
         padding:0;
         font-size:8px;
      }
      #bardemo div.label_1 {
         top:15px;
         color:#c00;
      }
      #bardemo div.label_2 {
         top:60px;
         color:#0c0;
      }
      #bardemo div.label_3 {
         top:15px;
         color:#0c0;
      }
      #bardemo div.label_4 {
         top:60px;
         color:#00c;
      }
      #bardemo div.unit {
         padding:0;
         position:absolute;
         top:150px;
         left:50px;
         width:400px;
         font-size:8px;
         text-align:center;
      }
      </style>
         </head>
         <body onload="javascript:show_bars();">
            <div id="bardemo">
               <div class="title"><?php echo $bewertung; ?></div>
               <div class="axis">
                  <div id="bardemo_bar1" class="bar bar_1"></div>
                  <div id="bardemo_bar2" class="bar bar_2"></div>
                  <div id="bardemo_bar2" class="bar bar_3"></div>
                  <div id="bardemo_bar2" class="bar bar_4"></div>
               </div>
               <div class="labels">
                  <div class="label label_1">positiv (<?php echo "$positiv von $maxp "; ?>)</div>
                  <div class="label label_2">negativ (<?php echo "$negativ von $maxn "; ?>)</div>
               </div>
               <div class="unit">%</div>
            </div>

      <script type="text/javascript">
      /* Balkenobjekte */
      var bardemo_bars = new Array(
      document.getElementById('bardemo_bar1'),
      document.getElementById('bardemo_bar2')
      );
      /* Startwerte der Balken */
      var bardemo_current = new Array(0,0);
      /* Zielwerte der Balken */
      var bardemo_target  = new Array(<?php echo $positiv; ?>, <?php echo $negativ; ?> );
      /* Schrittweite */
      var bardemo_step = 0.25;
      /* Verzoegerung zwischen Schritten in ms */
      var bardemo_time = 20;

      function show\_bars() {  
      	/\* Schalter: Sind wir fertig? \*/  
      	var done = true;  
      	/\* Balken durchlaufen \*/  
      	for (var i = 0; i < bardemo\_bars.length; i++) {  
      		if (bardemo\_current[i] < bardemo\_target[i]) {  
      		/\* Max. Laenge nicht erreicht \*/  
      			/\* Balken ist noch nicht fertig \*/  
      			done = false;  
      			/\* Um Schrittweite erhoehen \*/  
      			bardemo\_current[i] += bardemo\_step;  
      			/\* DIV auf entsprechende Laenge setzen  
      			   1 Step = 1 Pixel \*/  
      			bardemo\_bars[i].style.width = (bardemo\_current[i] / bardemo\_step) + 'px';  
      		} else {  
      		/\* Max. Laenge erreicht \*/  
      			/\* Label in Balken schreiben \*/  
      			bardemo\_bars[i].innerHTML = bardemo\_target[i] + ' &nbsp;';  
      		}  
      	}  
      	/\* Wenn nicht fertig, dann show\_bars() in bardemo\_time ms  
      	   erneut ausfuehren \*/  
      	if (!done) window.setTimeout("show\_bars()",bardemo\_time);  
      }  
      

      </script>

      </body>
      </html>

      1. Eine weitere Frage ist, wie kann ich diesen Code mehrfach auf meiner Seite einbinden ohne dass sich die Grafen überlagern.

        Das ist einfach: Packe jeden Balken in einen div mit der Breite 100% (des umgebenden Elements) In dem div bringe auch alles übrige unter (Abstände, Informationen...)

        Aber wie bekomm ich es hin, dass der eine sich nach links und der andere sich nach rechts entwickelt?

        Balken mit positiven Werten bekommen eine Position left:50%.
        Balken mit negativen Werten bekommen eine Position left:50% und ein negatives margin-left in der kalkulierten Breite des Balkens (N px).

        Du kannst natürlich auch css3 und calc benutzen:

        Balken mit negativen Werten bekommen dann eine Position left:calc(50% - N px) die kalkulierte Breite mit with: N px

        Jörg Reinholz

        1. Om nah hoo pez nyeetz, Jörg Reinholz!

          Du kannst natürlich auch css3 und calc benutzen:

          Das kommt auf die erwarteten Besucher an.

          Matthias

          --
          1/z ist kein Blatt Papier.

          1. ich hab das jetzt alles soweit hinbekommen.
            Jetzt hab ich nur noch ein Problem. Wenn ich das Diagramm mehrfach mit unterschiedlichen Werten einbinden möchte, dann rutschen alle Grafen auf die aller erste Zeichenebene und bei den anderen ist nur noch der leere Zeichenplatz zu sehen. Könnt ihr mir da vielleicht noch einen Tipp geben wie ich das ändern kann. Hab das in meinem Quellcode immer mit <div> eingebunden.

            Hier mal der Quellcode von meiner Grafik. Wenn ihr den von der Seite wo ich die Grafen einbinde auch noch braucht, einfach bescheid geben.

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
               "http://www.w3.org/TR/html4/strict.dtd">
            <html>
               <head>
                  <title>Unser Balkendiagramm</title>
            <style type="text/css">
            #bardemo {
               position:relative;
               padding:0;
               border: 1px solid #000;
               font-family:verdana;
               width:900px;
               height:150px;
               background: #fff;
               margin:auto
            }
            #bardemo div.title {
               padding:0;
               position:relative;
               font:14px;
               font-weight:bold;
               top:5px;
               text-align:center;
               line-height:15px;
            }
            #bardemo div.axis {
               padding:0;
               position:absolute;
               top:30px;
               left:400px;
               width:470px;
               height:80px;
               border-bottom:1px solid black;
               border-left:1px solid black;
            }
            #bardemo div.axis2 {
               padding:0;
               position:absolute;
               top:30px;
               left:135px;
               width:470px;
               height:80px;
               border-bottom:1px solid black;
            }

            #bardemo div.bar {
               position:absolute;
               left:0;
               height:40px;
               padding:10px 0px 0 0;
               text-align:right;
               font-size:11px;
               color: #000;
               font-weight:bold;
            }
            #bardemo div.bar_1 {
               top:15px;
               width:0px;
               background:#999;
               vertical-align:central;
            }
            #bardemo div.bar_2 {
               top:15px;
               width:0px;
               left: <?php echo  $abc= 4* $maxn;; ?>px;
               background:#F60;
               background-position:0;
               color:#000;
               vertical-align:central;
            }
            #bardemo div.bar_3 {
               top:15px;
               width:0px;
               background:#060;
               background-position:0;
               color:#000;
               vertical-align:central;
            }
            #bardemo div.bar_4 {
               top:15px;
               width:0px;
               left:<?php echo  $abc= 4* $maxn;; ?>px;
               background:#999;
               background-position:0;
               text-align:left;
               vertical-align:central;
            }
            #bardemo div.labels {
               padding:0;
               position:absolute;
               top:30px;
               left:10px;
               width:100px;
               height:150px;
               line-height:30px;
            }
            #bardemo div.label {
               position:absolute;
               left:-8px;
               height:30px;
               padding:0;
               font-size:9px;
            }
            #bardemo div.label_1 {
               top:15px;
               color:#060;
            }
            #bardemo div.label_2 {
               top:60px;
               color:#F60;
            }
            #bardemo div.label_3 {
               top:15px;
               color:#0c0;
            }
            #bardemo div.label_4 {
               top:60px;
               color:#00c;
            }
            #bardemo div.unit {
               padding:0;
               position:absolute;
               top:120px;
               left:250px;
               width:400px;
               font-size:10px;
               text-align:center;
               font-weight:bold;

            }
            </style>
               </head>
               <body onload="javascript:show_bars();">
                  <div id="bardemo">
                     <div class="title"><?php echo $bewertung; ?></div>
                     <div class="axis">
                        <div id="bardemo_bar1" class="bar bar_1"></div>
                        <div id="bardemo_bar2" class="bar bar_2"></div>
                        <div id="bardemo_bar3" class="bar bar_3"></div>
                        <div id="bardemo_bar4" class="bar bar_4"></div>
                     </div>
                     <div class="axis2">
                        <div id="bardemo_bar1" class="bar bar_1"></div>
                        <div id="bardemo_bar2" class="bar bar_2"></div>
                        <div id="bardemo_bar3" class="bar bar_3"></div>
                        <div id="bardemo_bar4" class="bar bar_4"></div>
                     </div>
                     <div class="labels">
                        <div class="label label_1">positiv (<?php echo "$positiv von $maxp "; ?>)</div>
                        <div class="label label_2">negativ (<?php echo "$negativ von $maxn "; ?>)</div>
                     </div>
                     <div class="unit">erreichte Punkte</div>
                  </div>

            <script type="text/javascript">
            /* Balkenobjekte */
            var bardemo_bars = new Array(
            document.getElementById('bardemo_bar1'),
            document.getElementById('bardemo_bar2'),
            document.getElementById('bardemo_bar3'),
            document.getElementById('bardemo_bar4')
            );
            /* Startwerte der Balken */
            var bardemo_current = new Array(0,0,0,0);
            /* Zielwerte der Balken */
            var bardemo_target  = new Array(<?php echo $maxp; ?>, <?php echo $asd = -1 * $maxn; ?>, <?php echo $positiv; ?>, <?php echo $qwe = -1 * ($maxn - $negativ); ?> );
            /* Schrittweite */
            var bardemo_step = 0.25;
            /* Verzoegerung zwischen Schritten in ms */
            var bardemo_time = 20;

            function show\_bars() {  
            	/\* Schalter: Sind wir fertig? \*/  
            	var done = true;  
            	/\* Balken durchlaufen \*/  
            	  
            	  
            	for (var i = 0; i < bardemo\_bars.length; i++) {  
            				if(bardemo\_target[i] > -1){  
            				  
            					if (bardemo\_current[i] < bardemo\_target[i]) {  
            					/\* Max. Laenge nicht erreicht \*/  
            						/\* Balken ist noch nicht fertig \*/  
            						done = false;  
            						/\* Um Schrittweite erhoehen \*/  
            						bardemo\_current[i] += bardemo\_step;  
            						/\* DIV auf entsprechende Laenge setzen  
            						   1 Step = 1 Pixel \*/  
            						bardemo\_bars[i].style.width = (bardemo\_current[i] / bardemo\_step) + 'px';  
            						}  
            					else {  
            					/\* Max. Laenge erreicht \*/  
            						/\* Label in Balken schreiben \*/	  
            							if(bardemo\_target[i] == <?php echo $asd; ?>){  
            								bardemo\_bars[i].innerHTML = <?php echo $negativ; ?> + ' &nbsp;';  
            							}  
            							  
            							else if(bardemo\_target[i] == <?php echo $qwe; ?>){  
            								bardemo\_bars[i].innerHTML = ' &nbsp;' + <?php echo $maxn; ?>;  
            							}  
            							  
            							else{  
            								bardemo\_bars[i].innerHTML = bardemo\_target[i] + ' &nbsp;';							  
            							}  
            					}  
            				}  
            				  
            	}  
            			  
            	/\* Wenn nicht fertig, dann show\_bars() in bardemo\_time ms  
            	   erneut ausfuehren \*/  
            	if (!done) window.setTimeout("show\_bars()",bardemo\_time);  
            }  
            

            </script>

            </body>
            </html>

            1. Wenn ich das Diagramm mehrfach mit unterschiedlichen Werten einbinden möchte, dann rutschen alle Grafen auf die aller erste Zeichenebene und bei den anderen ist nur noch der leere Zeichenplatz zu sehen. Könnt ihr mir da vielleicht noch einen Tipp geben wie ich das ändern kann. Hab das in meinem Quellcode immer mit <div> eingebunden.

              Kannst Du uns den resultierenden HTML-Quelltext ohne PHP geben? Zur Not auf pastebin und dann hier verlinken.

              Jörg Reinholz

              1. Hallo Jörg,

                ich hab nun einmal den Seitenquelltext meiner Ausgabe hochgeladen und hier ist der Link dazu. Ich hoffe, dass dies auch das ist was du gewollt hast.

                Paul

                Seitenquelltext zum Problem

                1. Hallo Paul alias Benedikt,

                  ich hab nun einmal den Seitenquelltext meiner Ausgabe hochgeladen und hier ist der Link dazu. Ich hoffe, dass dies auch das ist was du gewollt hast.
                  Seitenquelltext zum Problem

                  Teile davon kommen mir ausgesprochen bekannt vor. Nur was ist das für eine üble Verschachtelung? Ich zähle nicht weniger als zehn willkürlich ineinander geschachtelte HTML-Dokumente mit DOCTYPE, head- und body-Element. Dass da nichts Sinnvolles dabei rauskommt, ist klar. Verwunderlich ist, dass einige Browser überhaupt noch etwas daraus machen können.

                  Ein HTML-Dokument besteht aus genau EINER DOCTYPE-Deklaration, EINEM head-Element und EINEM body-Element. Bevor wir weiter nach irgendwelchen Detailfehlern suchen, solltest du erstmal die Grobstruktur in Ordnung bringen, sonst ist das zwecklos.

                  Und beschränke dich bitte auf EINEN Namen.

                  Ciao,
                   Martin

                  --
                  In Ägypten haben früher 150000 Leute 35 Jahre lang an einer Pyramide gearbeitet. Aber bei uns arbeiten doppelt so viele Leute doppelt so lange allein an der Baugenehmigung.
                    (Dieter Nuhr, deutscher Kabarettist)
                  Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                  1. Danke für den Tipp, und den Beitrag den du gemeint hast, Martin, das ist der von meinem Bruder, weil wir das zusammen machen. Ich habe den Code nun von sämtlichen überflüssigen <head> Elementen gesäubert. Die <body> Elemente habe ich auch entsprechend gelöscht. Ich hoffe, das erleichtert nun ein wenig eure Fehlersuche, weil ich bin bisher noch nicht weitergekommen. :(

                    Hier der Link zum neuen Quellcode

                    1. Hallo,

                      Danke für den Tipp, und den Beitrag den du gemeint hast, Martin, das ist der von meinem Bruder, weil wir das zusammen machen.

                      dann bitte ich um Verzeihung für den Vorwurf; nur ist das leider keine Seltenheit, dass hier Leute unter verschiedenen Namen ("Sockenpuppen") mehrmals das gleiche Thema diskutieren, eventuell mit geringfügig anderen Fragestellungen, und so auf mehr Aufmerksamkeit hoffen. Das ist aber unfair gegenüber anderen, die das nicht tun (ebenso wie offensichtliche Doppelpostings), und deshalb unerwünscht.

                      Ich habe den Code nun von sämtlichen überflüssigen <head> Elementen gesäubert. Die <body> Elemente habe ich auch entsprechend gelöscht.

                      Naja, aber das Grundproblem bleibt. Ihr habt offensichtlich mehrere eigenständige Dokumente einfach ineinander gesteckt. Die HTML-Struktur ist dadurch immer noch grob fehlerhaft; ich sehe beispielsweise immer noch mehrere body-Starttags, style-Blöcke innerhalb von body (anstatt im head), und mehrere div-Elemente mit derselben ID. Das darf auch ebensowenig sein, wie zwei Personalausweise mit derselben Nummer, oder zwei Autos mit demselben Kennzeichen auf offener Straße.
                      Bei genauerem Hinsehen fällt auch auf, dass die style- und script-Blöcke immer die gleichen sind, offenbar durch simples mehrfaches Einkopieren desselben Dokuments.

                      Ich sehe wirklich nur einen vernünftigen Weg, aus diesem Schlamassel wieder rauszukommen: Die Baustelle aufgeben und nochmal frisch anfangen. Und zwar wohlüberlegt, nicht einfach planlos Dinge mehrfach zusammenkopieren.
                      Das Script, das du für die Balkendiagramme verwenden willst, ist offensichtlich nicht dafür gedacht, mehrmals im Dokument eingesetzt zu werden bzw. mehrere Diagramme in einem Dokument zu verwalten. Das müsste man also erstmal so aufbohren, dass das überhaupt möglich ist.

                      Ich weiß allerdings nicht, ob ich beim Neuaufbau der optimale Begleiter bin, denn ich würde den bisherigen Diagramm-Ansatz komplett über Bord werfen und das Projekt "Balkendiagramm" (oder "Bargraph") dann von Grund auf neu aufsetzen - als frei konfigurierbares, wiederverwendbares Javascript-Modul. Wenn du den Weg mitgehen willst, bist du herzlich eingeladen.

                      So long,
                       Martin

                      --
                      Ist die Katze gesund,
                      freut sich der Hund.
                      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                      1. also ich bin prinzipiell für jeden Weg der zum Ziel führt offen. Was das ziellose zusammenkopieren angeht, so kann ich das aus meiner Sicht nur verneinen. Wir haben eine eigenständige Datei gemacht in der das Balkendiagramm erstellt wird und die dann an den Stellen an denen das Diagramm erscheinen soll in die entsprechenden <div> Blöcke geschrieben. So wurde es auch an anderer Stelle empfohlen. Aber anscheinend ist der Code für die Grafik echt nicht dazu gedacht. Was du bei deinem Angebot nicht vergessen darfst ist, dass wir relativ neu sind in dem Gebiet und uns gerade einarbeiten. Wenn dich das also nicht abschreckt, so gehen wir den Weg den du vorschlägst gerne mit.

                        1. Om nah hoo pez nyeetz, Paul!

                          Wenn dich das also nicht abschreckt, so gehen wir den Weg den du vorschlägst gerne mit.

                          Ganz wichtig dabei ist, aber bei _einem_ Weg zu bleiben. Vor allem weil es ggf. unterschiedliche Sicht- und Herangehensweisen geben könnte. Da wäre dann ein Hin- und Herspringen von HelferA zu HelferB kontraproduktiv und würde imho für die Helfer Frustrationspotential liefern.

                          Matthias

                          --
                          1/z ist kein Blatt Papier.

                          1. Das versteht sich von selbst. Deshalb würde ich Martins Angebot, wenn er mag, gerne annehmen :)

                            1. Schönen Abend auch,

                              Das versteht sich von selbst. Deshalb würde ich Martins Angebot, wenn er mag, gerne annehmen :)

                              na prima, also krempel ich mal symbolisch die Ärmel hoch. Allerdings habe ich auch hier und da noch andere Dinge zu tun, deshalb muss ich dich leider bis morgen abend vertrösten.

                              So long,
                               Martin

                              --
                              Die letzten Worte des Hardware-Bastlers:
                              Das Netzkabel lass ich wegen der Erdung lieber dran.
                              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                              1. sehr gut, ich krempel dann genauso meine Arme hoch :) dann kann das ja nur gut werden. Ich bin allerdings heute den ganzen Tag auf der Bauma in München gewesen und morgen beim DFB-Pokal-Halbfinale. Am Donnerstag kann es dann bei mir auch los gehn. Wenn du bis dahin schon Tipps hast was ich machen kann, einfach schreiben, ich werde mir das dann entsprechend durchlesen und versuchen umzusetzen.

                                1. Schönen Abend auch,

                                  wer gackert, muss auch legen, sagt man. Also wenn ich schon Versprechungen mache, sollte ich auch dazu stehen.

                                  sehr gut, ich krempel dann genauso meine Arme hoch :) dann kann das ja nur gut werden. Ich bin allerdings heute den ganzen Tag auf der Bauma in München gewesen und morgen beim DFB-Pokal-Halbfinale.

                                  geht's da nicht um dieses seltsame Spiel, bei dem ungefähr zwanzig Männer hinter nur einem Ball herrennen?

                                  Also, Balkendiagramme.

                                  Mein Ansatz sieht zunächst vor, möglichst viel mit HTML/CSS zu machen und Javascript wirklich nur für die Dynamik zu verwenden. Ich würde also die Diagramme komplett im HTML definieren, und ihre visuellen Grundeigenschaften in CSS.

                                  <div class="chart" id="activity">  
                                  <p>Besucherzahlen im Vergleich zum Vormonat</p>  
                                  <div class="bar"></div>  
                                  <p>Zahl der Beiträge im Vergleich zum Vormonat</p>  
                                  <div class="bar"></div>  
                                  </div>  
                                    
                                  <p>Betrachten wir dazu die Kostenentwicklung:</p>  
                                    
                                  <div class="chart" id="cost">  
                                  <p>Kostenentwicklung insgesamt</p>  
                                  <div class="bar"></div>  
                                  <p>Kostenentwicklung je Beitrag</p>  
                                  <div class="bar"></div>  
                                  </div>
                                  

                                  Dieses inhaltlich sinnfreie Codefragment definiert zwei Bargraph-Felder mit jeweils zwei Balken. Ich verzichte jetzt auf ein Styling für die Containerelemente div.chart sowie für die p-Elemente, und konzentriere mich stattdessen auf die eigentlichen Balken, die als div.bar selektierbar sind. Ich lege hier Position und Größe der Balken für den Wert 0 fest.

                                  div.bar  
                                   { height: 8px;  
                                     border: 1px solid #000;  
                                     margin-left: 50%;  
                                     width: 0;  
                                   }
                                  

                                  Dazu kommt nun ein Javascript, das in einer komplexen Struktur definiert, welche Elemente als Bargraph agieren sollen, und welchen Wertebereich sie abdecken sollen.

                                  var bargraph =  
                                   [ { range: 5000, elem: document.getElementById("activity").getElementByClassName("bar")[0] },  
                                     { range:  100, elem: document.getElementById("activity").getElementByClassName("bar")[1] },  
                                     { range: 2000, elem: document.getElementById("cost").getElementByClassName("bar")[0] },  
                                     { range:  200, elem: document.getElementById("cost").getElementByClassName("bar")[1] }  
                                   ];
                                  

                                  Das ist ein Array mit vier Elementen, jedes davon ein Object mit den zwei Feldern range und elem. An dieser Stelle ist es mir völlig egal, wo die zugehörigen Balken im Dokument stehen und wie sie gruppiert sind, da sie durch die Referenz elem eindeutig adressiert werden. Allerdings muss man darauf achten, dass dieser Script-Abschnitt erst ausgeführt wird, nachdem die Elemente, auf die er sich bezieht, auch bekannt sind - er muss also entweder am Ende des Dokuments oder in einem onload-Handler stehen.

                                  Jetzt fehlt nur noch ein Stückchen Script, das die Balken anhand aktueller Werte breiter oder schmaler macht bzw. richtig positioniert. Dafür definiere ich eine Funktion, die den Index des Balkens und den aktuellen Wert bekommt, aus dem range-Feld der Definitionen die richtige Breite und Position errechnet, und dann das in der Definition benannte Element mit den entsprechenden CSS-Eigenschaften versorgt.

                                  function UpdateBar(n, val)  
                                   { if (n<0 || n>bargraph.length) // bezeichnet n eine gültige Balken-Definition?  
                                        return;                    // nein, dann ignorieren  
                                    
                                     val *= 50/bargraph[n].range;  // Normierung: range wird auf 50 (Prozent) abgebildet  
                                     var el = bargraph[n].elem;    // Referenz auf das zugehörige Element aus der Definition  
                                    
                                     if (val>0)                               // Wert positiv und nicht 0  
                                      { el.style.marginLeft = "50%";          // Balken beginnt bei 50%  
                                        el.style.width      = val + "%";      // und hat die vorher berechnete Länge  
                                      }  
                                     else  
                                     if (val<0)                               // Wert negativ  
                                      { val = -val;                           // dann mach ihn positiv  
                                        el.style.marginLeft = (50-val)+"%";   // Balken beginnt zwischen linkem Rand und 50%  
                                        el.style.width      = val + "%";      // und hat die vorher berechnete Länge  
                                      }  
                                     else                                     // Wert genau 0  
                                      { el.style.marginLeft = "50%";          // Balken sitzt in der Mitte  
                                        el.style.width      = "0";            // und hat Länge 0  
                                      }  
                                   }
                                  

                                  Das ist mal nur ein erster Entwurf, den man natürlich noch beliebig verfeinern kann. Vor allem habe ich bisher auf die Berücksichtigung von Fehlern wie etwa Bereichsüberschreitungen verzichtet. Wenn man mit UpdateBar() also Werte setzt, die über den mit range definierten Bereich hinausgehen, wird das möglicherweise die Darstellung sprengen. Aber das soll auch zunächst nur ein Anfang sein, von dem aus man weiter vorgehen kann. Dass man diesen Ansatz beliebig ausbauen kann, dürfte auch klar sein.

                                  So long,
                                   Martin

                                  --
                                  F: Wer waren die ersten modernen Politiker?
                                  A: Die Heiligen drei Könige. Sie legten die Arbeit nieder, zogen teure Klamotten an und gingen auf Reisen.
                                  Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                  1. [latex]Mae  govannen![/latex]

                                    var bargraph =

                                    [ { range: 5000, elem: document.getElementById("activity").getElementByClassName("bar")[0] },
                                       { range:  100, elem: document.getElementById("activity").getElementByClassName("bar")[1] },
                                       { range: 2000, elem: document.getElementById("cost").getElementByClassName("bar")[0] },
                                       { range:  200, elem: document.getElementById("cost").getElementByClassName("bar")[1] }
                                    ];

                                    
                                    >  
                                      
                                    Warum wiederholt die Referenzen und deren Kinder ermitteln?  
                                      
                                    Außerdem wurde leider document.[getElementsByClassName()](http://caniuse.com/#search=getElementsByClassName) erst so spät browserübergreifend implementiert, daß man oft mit [querySelectorAll](http://caniuse.com/#search=querySelectorAll) genauso oder einfacher arbeiten kann. Im Falle von IE8 ist QSA sogar (für CSS2.1 Selektoren) die bessere Wahl, da gEBCN erst ab IE9 implementiert ist (zumindest laut caniuse; da ich gerade erst XP neu installiere(n muß), habe ich zur Zeit leider noch IE6 und kann es nicht selber testen)  
                                      
                                    ~~~javascript
                                    var el_acti = document.querySelectorAll("#activity .bar"),  
                                        el_cost = document.querySelectorAll("#cost .bar"),  
                                        bargraph = [  
                                            { range: 5000, elem: el_acti[0]},  
                                            { range:  100, elem: el_acti[1]},  
                                            { range: 2000, elem: el_cost[0]},  
                                            { range:  200, elem: el_cost[1]}  
                                        ];
                                    

                                    function UpdateBar(n, val)

                                    { if (n<0 || n>bargraph.length) // bezeichnet n eine gültige Balken-Definition?
                                          return;                    // nein, dann ignorieren

                                      
                                    Ach, du machst das auch so? Ich finde in Funktionen eine einfache "negative" Abfrage mit return auch schöner als tief verschachtelet "positive" Abfragen.  
                                      
                                      
                                    ♫ FIIIIISCH!! ♪  
                                      
                                    Ric... äh Kai  
                                    
                                    -- 
                                    `var jQuery = $(hit);`{:.language-javascript}  
                                    „Die Borg würden nicht mal Spaß verstehen, wenn sie einen Vergnügungspark assimiliert hätten!” (B'Elanna Torres)  
                                      
                                    [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)  
                                    
                                    
                                  2. Om nah hoo pez nyeetz, Der Martin!

                                      
                                    
                                    > function UpdateBar(n, val)  
                                    >  { if (n<0 || n>bargraph.length) // bezeichnet n eine gültige Balken-Definition?  
                                    >       return;                    // nein, dann ignorieren
                                    
                                    

                                    Warum machst du das so? Was spricht gegen

                                    function UpdateBar(n, val) {  
                                      if (n >= 0 && n <= bargraph.length) {  
                                        tu was  
                                      }  
                                    }
                                    

                                    Diese Frage ist keine "Ätsch ich weiß was", sondern mich interessiert, ob es technische Gründe gibt.

                                      
                                    
                                    >    else                                     // Wert genau 0  
                                    >     { el.style.marginLeft = "50%";          // Balken sitzt in der Mitte  
                                    >       el.style.width      = "0";            // und hat Länge 0  
                                    >     }  
                                    >  }
                                    
                                    

                                    Das kann wohl in den then-Zweig mit rein oder stört dich das resultierende width: 0%;?

                                    Matthias

                                    --
                                    1/z ist kein Blatt Papier.

                                    1. Hallo,

                                      function UpdateBar(n, val)
                                      { if (n<0 || n>bargraph.length) // bezeichnet n eine gültige Balken-Definition?
                                            return;                    // nein, dann ignorieren

                                      
                                      >   
                                      > Warum machst du das so? Was spricht gegen  
                                      > ~~~javascript
                                      
                                      function UpdateBar(n, val) {  
                                      
                                      >   if (n >= 0 && n <= bargraph.length) {  
                                      >     tu was  
                                      >   }  
                                      > }
                                      
                                      

                                      Kai fand's auch gut. ;-)
                                      Im Ernst: Ich finde es einfach übersichtlicher, weil es eine Verschachtelungs-Ebene einspart und der "Fehlerfall" sofort abgefrühstückt ist, ohne dass man die schließende Klammer dieses Blocks bis ganz unten vor sich herschiebt.

                                      else                                     // Wert genau 0
                                          { el.style.marginLeft = "50%";          // Balken sitzt in der Mitte
                                            el.style.width      = "0";            // und hat Länge 0
                                          }
                                      }

                                      
                                      > Das kann wohl in den then-Zweig mit rein oder stört dich das resultierende `width: 0%;`{:.language-css}?  
                                        
                                      Ich hatte einfach noch nicht den "brains based optimizer" drüberlaufen lassen. Das auch an Kai, dessen Einwand gegen die mehrmalige Ermittlung desselben Elements im DOM natürlich vollkommen berechtigt ist.  
                                        
                                      Ciao,  
                                       Martin  
                                      
                                      -- 
                                      Treffen sich zwei Freundinnen nach langer Zeit wieder. "Gut siehste aus. Hast du abgenommen?" - "Nö." - "Hmm, dann haste zugenommen. Steht dir aber gut."  
                                      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                      
                                  3. Hallo Martin,

                                    zunächst mal tausend dank, dass du dir die Mühe gemacht hast etwas zu entwerfen. Ich hab jetzt nur ein kleines Problem ;) und weiß nicht weiter.

                                    Ich hab deinen Code einmal bei mir eingebunden und nix abgeändert, wollte also nur mal das Ergebnis sehn. Das Problem ist jetzt, dass bei der Grafik keine Balken angezeigt werden. Ich hab hier mal den Code von meiner Ausgabeseite. Vielleicht kannst du mir ja weiterhelfen und sagen an was es liegt. Ich kenn mich wie gesagt bei Javascript absolut gar nicht aus.

                                    Hier mal mein Code:

                                    Hier der Link zum Code

                                    1. Hallo,

                                      Ich hab deinen Code einmal bei mir eingebunden und nix abgeändert, ...

                                      ... bis auf die kleinen Optimierungen, die Kai empfohlen hat - und das ist okay so.

                                      Das Problem ist jetzt, dass bei der Grafik keine Balken angezeigt werden.

                                      *g*
                                      Sorry, mir war nicht klar, dass du in Javascript völlig unerfahren bist; ich hatte angenommen, du würdest dich "ein bisschen" auskennen und wärest in der Lage, den Code zumindest nachzuvollziehen und zu verstehen.

                                      Dann hättest du nämlich bemerkt, dass ich nirgends einen Aufruf der Funktion UpdateBar() notiert habe. Das war mir so selbstverständlich, dass ich völlig vergessen habe, das zu erwähnen.

                                      Ja, also ... UpdateBar() ist natürlich dafür gedacht, bei jedem Aufruf einen der Balken mit einem neuen Wert zu versorgen und ihn entsprechend diesem Wert im Verhältnis zu seinem range (Wertebereich) zu skalieren. Das kann quasi-statisch passieren; es kann auch dynamisch wieder und wieder erfolgen, um Werte "in Echtzeit" darzustellen, die sich permanent ändern können.

                                      Pack mal zur Demonstration irgendwo in dein Testdokument noch ein Eingabefeld mit einem JS-Eventhandler, etwa so:

                                      <input type="text" onchange="UpdateBar(0,this.value);">

                                      Das heißt: Jedesmal, wenn sich der Inhalt des Eingabefelds ändert (onchange), wird die Funktion UpdateBar() aufgerufen und bekommt als ersten Parameter den Wert 0 (damit wird der erste definierte Balken angesprochen), und als zweiten Parameter den aktuellen Inhalt des Eingabefelds (this.value). Und nun gib mal testweise Zahlenwerte zwischen -5000 und +5000 ein. Teste auch mal Zahlen, die diesen Wertebereich überschreiten, und schau dir an, was in diesem nicht abgesicherten Fehlerfall passiert.
                                      Beachte, dass onchange erst anspricht, wenn das Eingabefeld den Focus verliert, der Cursor also nicht mehr im Feld steht.

                                      Prinzip verstanden?

                                      Auf diese Weise kannst du nun jederzeit und an jeder Stelle, wo es dir sinnvoll erscheint, einen der Balken (oder auch mehrere) aktualisieren. Mindestens einmal muss das allerdings passieren, denn die statischen Voreinstellungen zeigen ja alle Balken mit der Breite 0, also für den Wert 0 an.

                                      So long,
                                       Martin

                                      --
                                      Noch Fragen? - Ich weiß es auch nicht.
                                      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                      1. Hallo Martin,

                                        dass du die Funktion nirgends aufgerufen hast, hab ich gesehn und mich auch gewundert. Das Problem was ich habe ist nur, dass ich meine Auswertung ja in ner anderen Datei gespeichert hab und die Werte dazu nach der Formulareingabe erst aus der Datenbank auslese.
                                        Jetzt ist meine Idee, dass ich ein verstecktes Feld anlege wo ich diese Werte dann einfülle und dann damit die Funktion aufrufe. Geht das oder wie kann ich das sonst realisieren. Sorry, dass ich vlt total dämliche Fragen stell aber ich kenn mich da echt nicht aus.

                                        1. Hi,

                                          Das Problem was ich habe ist nur, dass ich meine Auswertung ja in ner anderen Datei gespeichert hab und die Werte dazu nach der Formulareingabe erst aus der Datenbank auslese.

                                          das heißt, du generierst das Dokument mit den Balkendiagrammen sowieso serverseitig? - Dann kann man die Aufrufe von UpdateBar(), einen für jeden Balken, natürlich auch durch das serverseitige Script ausgeben lassen, beispielsweise am Ende des Dokuments, und den aktuell gewünschten Wert jedes Balkens dort hineinschreiben.

                                          Die nächste Überlegung wäre schließlich, die Balkendiagramme gleich serverseitig (ich vermute PHP) statisch mit den entsprechenden CSS-Werten zu generieren. Javascript wäre dann überhaupt nicht mehr nötig. Ich bin bei meiner Überlegung davon ausgegangen, dass du die Dynamik der Balkendiagramme brauchst, zumal du von Anfang an eine Javascript-Lösung hattest (auch wenn die nicht ganz das geleistet hat, was du wolltest).

                                          Jetzt ist meine Idee, dass ich ein verstecktes Feld anlege wo ich diese Werte dann einfülle und dann damit die Funktion aufrufe.

                                          Auch eine Möglichkeit, aber umständlich.

                                          So long,
                                           Martin

                                          --
                                          Moskito, ergo summ.
                                          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                          1. Hallo Martin,

                                            dann haben wir aneinander vorbeigeredet/ -geschrieben ;)
                                            Also mein Vorgehen ist folgendermaßen:

                                            1. Benutzer füllt einen Fragebogen online aus
                                            2. Die Eingabe des Fragebogens wird in eine Datenbank gespeichert
                                            3. Das Ausgabeformular liest die Datenbank aus und übergibt die Punktzahl für den entsprechenden Balken an eine Variable

                                            4. Die Punktzahl soll in einem Balkendiagramm grafisch dargestellt werden. Hier fände wäre es natürlich deluxe, wenn die maximal erreichbare Punktzahl als Balken im Hintergrund liegt. Der Balken sollte nach Möglichkeit so dargestellt werden, dass die aufsummierten Negativ-Werte den gleichen 0-Punkt haben wie die Positiv-Werte.

                                            Ich hoffe, du verstehst was ich meine :)
                                            Die Javascript Variante habe ich nur gewählt gehabt, weil ich im Netz sonst nix gefunden hab wie man das machen kann. Nur mit CSS bin ich da nicht weitergekommen, aber du kennst dich da ja deutlich besser aus als ich deshalb hast du da sicherlich schon eine Idee, oder?

                                            Nochmals tausend Dank für deine Hilfe!

                                            Viele Grüße
                                            Paul