• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Rahmen um nicht vorhandene Zellen

Der Hans

Mitglied
Gibt es eine Möglichkeit, bei einer Tabelle, die z.B. in der ersten Zeile 100 Zellen und in der zweiten Zeile 50 Zellen hat, die jeweils per border="1" rules="all" optisch von einander getrennt werden, den Rahmen um die leere Fläche nach den 50 Zellen der zweiten Zeile wegzulassen?

Der Code, mit dem die Tabelle generiert wird, sieht so aus:
PHP:
echo '<table border="1" rules="all">
     <tr>';
for($i=1;$i<=count($zahlen)+1;$i++){
      // Markiere alle Primzahlen Rot
      if($zahlen[$i]!=""){
           $color="#FF0000";
      }
      else{
           $color="#FFFFFF";
      }
      echo '<td bgcolor='.$color.' style="width:7px; height:10px"></td>';
      // Zeilenumbruch nach X geprüften Zahlen
      $zeilenumbruch = 100;        
      if($i>0 && $i%$zeilenumbruch==0){
           echo '<tr></tr>';
      }        
}
echo '</table>';
$zahlen ist dabei ein Array frei wählbarer Größe, muss also nicht zwingend ein Vielfaches von $zeilenumbruch sein. Dadurch entsteht leider oben genannter Rahmen um nicht belegten Platz zwischen der letzten Zelle der letzten Zeile und dem rechten Rand aller vorangegangenen Zeilen. Das sieht dann z.B. so aus (100 Zellen pro Zeile, 150 Zahlen abgefragt):

primnq.jpg


Ich hätte es gerne so (ungewünschten Rahmen per Paint entfernt):

primh.jpg
 
Werbung:
Ich würde zuerst das HTML auf Gültigkeit prüfen. Soweit ich das sehe, ist die Tabellenstruktur falsch
 
Werbung:
Du solltest den "border" aus dem <table> Tag entfernen oder auf den Wert ="0" setzen
und dann für das <td> Tag im style zusätzlich einen Border definieren.
z.B.: border:1px solid black;

Dan wird auch nur jedes vorhandene <td> Element mit einem Border ausgegeben.
 
Da keine einzige Zelle einen Inhalt hat (ich gebe sie nur mit unterschiedlichen Hintergrundfarben aus), bringt mich das leider nicht weiter.

Ich würde zuerst das HTML auf Gültigkeit prüfen. Soweit ich das sehe, ist die Tabellenstruktur falsch
Da habe ich doch tatsächlich <tr> und </tr> nach dem Zeilenumbruch vertauscht, danke für den Hinweis.

Du solltest den "border" aus dem <table> Tag entfernen oder auf den Wert ="0" setzen
und dann für das <td> Tag im style zusätzlich einen Border definieren.
z.B.: border:1px solid black;

Dan wird auch nur jedes vorhandene <td> Element mit einem Border ausgegeben.
Danke, du hast mich auf den richtigen Weg gebracht. Ich habe das bis jetzt mit zwei CSS-Klassen gelöst, eine für die ganze Tabelle und eine für die einzelnen Zellen.

Für die Tabelle:
HTML:
.table_collapse{
     border-collapse: collapse;
}

Für die Zellen:
HTML:
.td_border{
     border: 1px solid black;
}

PHP:
echo '<table class="table_collapse">
<tr>';
for($i=1;$i<=count($zahlen)+1;$i++){
     // Markiere alle Primzahlen Rot
     if($zahlen[$i]!=""){
         $color="#FF0000";
     }
     else{
         $color="#FFFFFF";
     }
     echo '<td bgcolor='.$color.' style="width:7px; height:10px" class="td_border"></td>';
     // Zeilenumbruch nach X geprüften Zahlen
     $zeilenumbruch = 100;        
     if($i>0 && $i%$zeilenumbruch==0){
         echo '</tr><tr>';
     }        
}
echo '</table>';

Allerdings ist das auch noch nicht ganz korrekt, ab einer Tabellengröße von 3 Zeilen wird ab und zu bei mindestens der letzten Zeile der abschließende horizontale Balken nicht dargestellt:

primvz.jpg


Auch eine Umstrukturierung dahin, dass ich den HTML-Code nicht mehr in PHP, sondern den PHP-Code in den HTML-Code einbette (z.B. <td bgcolor='<? echo $color; ?>' class="td_border"></td> statt echo '<td bgcolor='.$color.' style="width:7px; height:10px" class="td_border"></td>';), hat mich bisher, bis auf die Tatsache, dass der Seitenquelltext übersichtlicher geworden ist, nicht weiter gebracht.
 
Der HTML Code dürfte nach wie vor nicht Gültig sein.

Ich würde einfach den Zellen Klassen geben. Einmal .zahl für den Rahmen und .primzahl für den Hintergrund. Das ist einfacher als mit inline Styles zu arbeiten, ausserdem kannst du dann einfacher das HTML Tabellengerüst in eine gültige Form bringen.
 
Werbung:
Ich würde einfach den Zellen Klassen geben. Einmal .zahl für den Rahmen und .primzahl für den Hintergrund. Das ist einfacher als mit inline Styles zu arbeiten, ausserdem kannst du dann einfacher das HTML Tabellengerüst in eine gültige Form bringen.
Den Rahmen brauchen alle Zellen, die Einfärbung aber nur ausgewählte. Ich habe es jetzt mal mit 3 Klassen gemacht:
HTML:
.td_border{
    border: 1px solid black;
    width: 7px;
    height: 10px
}
.td_prime_red{
    background-color: red;
}
.td_prime_white{
    background-color: white;
}

Welche der td_prime_red/white-Klassen verwendet wird, frage ich unmittelbar vor der Ausgabe ab:
PHP:
if($zahlen[$i]!=""){
    $color="red";
}
else{
    $color="white";
}
Die Abfrage wird dann so weiterverarbeitet, damit die Primzahlen markiert werden:
HTML:
<td class="td_border td_prime_<? echo $color ?>"></td>

An der Fehldarstellung der Zeilenabschlüsse ändert das aber leider nichts.
Edit: Ich hatte es bisher nur im Firefox 6.0.1 probiert, ein Test im IE6 hat mir gerade fehlerfreie Tabellenrahmen geliefert.

Der HTML Code dürfte nach wie vor nicht Gültig sein.
Hapert es deiner Meinung nach noch an anderen Stellen oder nur bei den Inline-Styles?
 
Die letzte Reihe hat immer zu wenig Zellen, wenn die Maximale Anzahl der Spalten nicht teilbar ist mit der maximalen anzahl der Zellen. Ausserem hasat du am Schluss immer [...]</tr><tr></table> das ist ungültiges HTML. Du brauchst nur ZWEI Klassen.

Leider kann ich nicht gut genug PHP um dir das mal eben zu zeigen, in Perl würde das so aussehen:
Code:
#!/usr/bin/perl -w
use strict; 
use CGI qw(-no_xhtml);
use constant NL => "\n";

my $css =<<EOT;
.zahl {
	border:1px solid black;
}
.prim {
	background-color:red;
}
EOT

print CGI::header(), CGI::start_html(-style => {-code => $css} ), main(), CGI::end_html();

sub main {
	my $max = 95;
	my %prim = map { $_ => prime_number($_) } 0...$max;
	my $ret = '';
	my $zeilenumbruch = 10;
	my @rows;
	my $i;
	for $i(1...$max) {
		my $class = 'zahl';
		if($prim{$i}) { $class .= ' prim';}
		push @rows, '<td class="' . $class . '">'. $i . '&nbsp;</td>';
		if($i % $zeilenumbruch == 0){
			$ret .= '<tr>' . (join '', @rows) . '</tr>' . NL;
			@rows = ();
		}
	}
	if(@rows) {
		while(scalar @rows < $zeilenumbruch) {
			push @rows, '<td>&nbsp;</td>';
		}
		$ret .= '<tr>' . (join '', @rows) . '</tr>' . NL;
	}
	
	return $max . '<table>' . $ret . '</table>';
}
sub prime_number{
	return 0 if (int ($_[0]) != $_[0]);
	
	foreach my $divider (2..sqrt($_[0])) {
		my $quotient = $_[0] % $divider;
		return 0 if ($quotient == 0);
	}
	return 1;
}
 
Die letzte Reihe hat immer zu wenig Zellen, wenn die Maximale Anzahl der Spalten nicht teilbar ist mit der maximalen anzahl der Zellen.
Ich will ja gerade nur soviele Zellen, wie Zahlen überprüft werden. Bei 150 Zahlen soll die zweite Zeile eben nur 50 Zellen haben.

Ausserem hasat du am Schluss immer [...]</tr><tr></table> das ist ungültiges HTML.
Das ist mir gerade auch aufgefallen, das unterdrücke ich jetzt durch if($i<count($zahlen)) vor der Ausgabe des <tr></tr>-Blocks.

Du brauchst nur ZWEI Klassen. Leider kann ich nicht gut genug PHP um dir das mal eben zu zeigen, in Perl würde das so aussehen:
Code:
#!/usr/bin/perl -w
use strict; 
use CGI qw(-no_xhtml);
use constant NL => "\n";

my $css =<<EOT;
.zahl {
    border:1px solid black;
}
.prim {
    background-color:red;
}
EOT

print CGI::header(), CGI::start_html(-style => {-code => $css} ), main(), CGI::end_html();

sub main {
    my $max = 95;
    my %prim = map { $_ => prime_number($_) } 0...$max;
    my $ret = '';
    my $zeilenumbruch = 10;
    my @rows;
    my $i;
    for $i(1...$max) {
        my $class = 'zahl';
        if($prim{$i}) { $class .= ' prim';}
        push @rows, '<td class="' . $class . '">'. $i . '&nbsp;</td>';
        if($i % $zeilenumbruch == 0){
            $ret .= '<tr>' . (join '', @rows) . '</tr>' . NL;
            @rows = ();
        }
    }
    if(@rows) {
        while(scalar @rows < $zeilenumbruch) {
            push @rows, '<td>&nbsp;</td>';
        }
        $ret .= '<tr>' . (join '', @rows) . '</tr>' . NL;
    }
    
    return $max . '<table>' . $ret . '</table>';
}
sub prime_number{
    return 0 if (int ($_[0]) != $_[0]);
    
    foreach my $divider (2..sqrt($_[0])) {
        my $quotient = $_[0] % $divider;
        return 0 if ($quotient == 0);
    }
    return 1;
}
Da blicke ich gerade gar nicht durch. :(
 
Werbung:
Ich will ja gerade nur soviele Zellen, wie Zahlen überprüft werden. Bei 150 Zahlen soll die zweite Zeile eben nur 50 Zellen haben.
Schon klar, aber damit hast du ungültigen HTML Code.

Hier mal das Perl Skript: Untitled Document (ich habe hier table border=1 benutzt, damit du siehst wie die Tabelle aufgefüllt wird, wenn diese Angabe wegfällt, siehst du diese Zellen nicht mehr.)
 
Ich habe den Code jetzt so erweitert, dass die letzte Zeile automatisch mit leeren <td></td>-Blöcken aufgefüllt wird, wenn ich kein Vielfaches der Spaltenanzahl anzeigen will. Wahrscheinlich noch viel zu kompliziert (ich habe jetzt jeweils eine Klasse für rote und weiße Zellen sowie für umrahmte und nicht umrahmte, also 4 wo du 2 hast), aber es geht.
Dein Perl-Script habe ich bisher noch nicht wirklich durchschaut, aber auf den ersten Blick scheint es mehrere CSS-Klassen bei Bedarf zusammenzufassen (if($prim{$i}) { $class .= ' prim';}), richtig?

Bleibt noch das Problem des nicht korrekt angezeigten Rahmens im Firefox, der IE6 scheint mit den Tabellen kein Problem zu haben. Das sind im Moment die einzigen beiden Browser, die ich testen kann.
 
der IE6 als Browser ohne Probleme, kannte ich bisher eher anders herum.:D

füge in deine leeren <td></td> ein &nbsp; ein (nbsp =nonbreaking space = Leerzeichen ohne Umbruch), dann sollten die leeren Zellen auch korrekt mit dem CSS Rahmen angezeigt werden.
 
Werbung:
Ein &nbsp; ändert leider (wie jede andere Ausgabe innerhalb der Zellen), außer dass es die Höhenbegrenzung von 10px ignoriert und jede Zelle 22px hoch ausgibt, nichts am fehlerhaften Rahmen.
 
Zuletzt bearbeitet:
Bleibt noch das Problem des nicht korrekt angezeigten Rahmens im Firefox, der IE6 scheint mit den Tabellen kein Problem zu haben. Das sind im Moment die einzigen beiden Browser, die ich testen kann.
Ich weiß nicht von was für einen Fehlerhaften Rahmen du sprichst?
Ich hab mein Skript nochmal umgebaut, dass die Vorgaben von dir umgesetzt werden und sehe keinen Fehler im Firefox.
 
Ich weiß nicht von was für einen Fehlerhaften Rahmen du sprichst?
Ich hab mein Skript nochmal umgebaut, dass die Vorgaben von dir umgesetzt werden und sehe keinen Fehler im Firefox.

Von dieser Fehldarstellung am rechten Rand rede ich:
Allerdings ist das auch noch nicht ganz korrekt, ab einer Tabellengröße von 3 Zeilen wird ab und zu bei mindestens der letzten Zeile der abschließende horizontale Balken nicht dargestellt:

primvz.jpg

Die gesamte Tabelle bekommt diese Klasse verpasst:
HTML:
.table_collapse{
    border-collapse: collapse;
}
Die einzelnen Zellen jeweils eine td_border_1/0 und eine td_prime_0/1:
HTML:
}
.td_border_1{
    border: 1px solid #000000;
    width: 7px;
    height: 10px;
}
.td_border_0{
    border: 0px;
    width: 7px;
    height: 10px;
}
.td_prime_1{
    background-color: red;
}
.td_prime_0{
    background-color: white;
}

Wenn ich in der Tabellen-Klasse border-collapse:separate einstelle wird zwar im Firefox (der IE zeigt dann gar keine Rahmen mehr) alles formal richtig dargestellt, mir gefallen die Zwischenräume zwischen den einzelnen Zellen allerdings nicht.
 
Werbung:
Hier ist mal mein gesamter Code (inkl. einer weiteren Tabelle, die Primzahlen ausgibt, aber hier nicht Thema ist, da sie so ist, wie sie sein soll), kannst ja mal probieren, ob er bei dir richtig ausgeführt wird oder ob du einen Fehler findest.

Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Primzahltabelle und -verteilung</title>
        <style type="text/css">
            .table_collapse{
                border-collapse: collapse;
            }
            .td_prime_numbers{
                width: 55px;
            }
            .td_border_1{
                border: 1px solid #000000;
                width: 7px;
                height: 10px;
            }
            .td_border_0{
                border: 0px;
                width: 7px;
                height: 10px;
            }
            .td_prime_1{
                background-color: red;
            }
            .td_prime_0{
                background-color: white;
            }
        </style>
    </head>
    <body>
        <form action="sieb_von_eratosthenes.php" method="post">
            <input type="text" name="prim_ende" value="Obergrenze"
                onfocus="if(this.value=='Obergrenze'){this.value=''}" onblur="if(this.value==''){this.value='Obergrenze'}">
            <input type="submit" name="submit" value="anzeigen"><br>
            <input type="checkbox" name="prim_tab" value="Primzahltabelle" checked="checked">Primzahltabelle<br>
            <input type="checkbox" name="prim_ver" value="Primzahlverteilung" checked="checked">Primzahlverteilung<br><br>
        </form>
<?
// Prüfe, ob eine Obergrenze gesetzt wurde
if(isset($_POST['prim_ende'])){
    $ende = $_POST['prim_ende'];
    // Entferne alle Leerzeichen
    $ende = str_replace(" ", "", $ende);
    // Prüfe, ob die eingegebene Obergrenze numerisch ist
    if(is_numeric($ende)){
        // Entferne alle Nullen am Anfang des Strings
        for($i=0;$i<strlen($ende);$i++){
            if($ende[0]=="0"){
                $ende = substr($ende, 1);
            }
        }
        // Prüfe, ob die eingegebene Obergrenze größer gleich 1 ist
        if($ende>=1){
            $zahlen = array();
            for($i=2;$i<=$ende;$i++){
                $zahlen[$i] = $i;
            }
            for($i=2;$i<=$ende;$i++){
                if($zahlen[$i]!=""){
                    $sieb = $i*2;
                    while($sieb<=$ende){
                        $zahlen[$sieb]="";
                        $sieb = $sieb+$i;
                    }
                }
            }
            // Primzahltabelle
            if($_POST['prim_tab']){
                $zeilenumbruch_tab = 20;?>
Primzahlen bis <? echo $ende; ?>:
        <br><br>
        <table>
            <tr>
                 <? for($i=1;$i<=$ende;$i++){
                    if($zahlen[$i]!=""){ ?>
                <td class="td_prime_numbers"><? echo $zahlen[$i]; ?></td>
                        <? $j++;
                        // Zeilenumbruch nach X Primzahlen
                        if($j > 1 && $j%$zeilenumbruch_tab==0){ ?>
            </tr>
            <tr>
                        <?}
                    }
                }
                $rows_tab = floor($j/$zeilenumbruch_tab);
                if($j%$zeilenumbruch_tab!=0){
                    $rows_tab+=1;
                }
                $td_bis_tab = $rows_tab*$zeilenumbruch_tab;
                for($i=$j;$i<$td_bis_tab;$i++){?>
                        <td class="td_prime_numbers"></td>
                <?}    ?>
            </tr>
        </table>
        <br><br>
            <?}
            // Primzahlverteilung
            if($_POST['prim_ver']){
            $zeilenumbruch_ver = 100;
            $rows_ver = floor($ende/$zeilenumbruch_ver);
            if($ende%$zeilenumbruch_ver!=0){
                $rows_ver+=1;
            }
            $td_bis_ver = $rows_ver*$zeilenumbruch_ver;?>    
Primzahlverteilung:
        <br><br>
        <table class="table_collapse">
            <tr>
                <? for($i=1;$i<=$td_bis_ver;$i++){
                    // Umrahme jede Zelle, wenn sie innerhalb der angegebenen Obergrenze liegt
                    if($i<=$ende){
                        $border = "1";
                    }
                    else{
                        $border = "0";
                    }
                    // Markiere alle Primzahlen Rot
                    if($zahlen[$i]!=""){
                        $prime="1";
                    }
                    else{
                        $prime="0";
                    } ?>
                <td class="td_border_<? echo $border; ?> td_prime_<? echo $prime ?>"> </td>
                    <? // Zeilenumbruch nach X geprüften Zahlen
                    if($i>0 && $i<$td_bis_ver && $i%$zeilenumbruch_ver==0){?>
            </tr>
            <tr>
                    <?}        
                    }?>
            </tr>
        </table>
    </body>
            <?}
        }
// Meldung, wenn eingegebener Wert kleiner 1 ist
        else{
            echo "Bitte einen Wert gr&ouml;&szlig;er gleich 1 eingeben";    
        }
    }    
// Meldung, wenn nicht nur Ziffern eingegeben wurden
    else{
        echo "Bitte ausschlie&szlig;lich Ziffern eingeben.";
    }
}
// Meldung, wenn keine Eingabe gemacht wurde
else{
    echo "Bitte zuerst eine Obergrenze zur Darstellung von Primzahlen festlegen.";
}
if(!$_POST['prim_tab'] && !$_POST['prim_ver'] && $_POST['prim_ende']){
    echo "Bitte aktivieren Sie mindestens eine Checkbox zur Anzeige der Primzahltabelle oder -verteilung.";
}?>
</html>
 
also bei mir gibt es kein Problem im Firefox in der Darstellung. Es sieht auch ncith so aus, wie auf deinem Screenshot.
 
Werbung:
Dann wird es wohl ein lokales Code-Problem sein, damit kann ich zumindest etwas besser leben als mit einem nicht zu behebendem Problem im Code. Damit kann der Thread hier dann zu den Akten gelegt werden.
 
Wollte nur kurz bestätigen, bei mir wird auch alles richtig angezeigt. Eventuell mal den Cache löschen....
 
Zurück
Oben