Mehrere Objekte behandeln
Markus
- javascript
Ich habe in einer Tabelle mehrere Zeilen. Jede einzelne lässt sich ausblenden.
Nun möchte ich aber über ein klick mehrere Zeilen ausblenden und hänge ein wenig.
Beispiel (noch nicht auf id achten):
Überschrift 1
-> Satz 1 (id: zeile1[0])
-> Satz 2 (id: zeile1[1])
-> Satz 3 (id: zeile1[2])
Überschrift 2
-> Satz 1 (id: zeile2[0])
Überschrift 3
-> Satz 1 (id: zeile3[0])
-> Satz 2 (id: zeile3[1])
Zum Ausblenden der jeweiligen Zeile nutze ich folgendes:
document.getElementById(layerName).style.display = (document.getElementById(layerName).style.display=="block" ? "none" : "block");
Ich dachte jetzt, dass man die ids wie oben gezeigt setzten könnte und dann über eine Schleife die jeweils zutreffenden Zeilen Zeilen ausblendet. Wenn ich auf die Überschrift klicke sollen eben immer die dazugehörigen, sich darunter befindenden, Sätze ausgeblendet werden.
Ich hoffe ihr versteht was ich meine.
Vielen Dank im Voraus.
Hell-O!
Beispiel (noch nicht auf id achten):
Überschrift 1
-> Satz 1 (id: zeile1[0])
-> Satz 2 (id: zeile1[1])
-> Satz 3 (id: zeile1[2])
Überschrift 2
-> Satz 1 (id: zeile2[0])
Überschrift 3
-> Satz 1 (id: zeile3[0])
-> Satz 2 (id: zeile3[1])
Wie wäre es, statt oder zusätzlich zur ID das name-Attribut zu verwenden? Denn im Gegensatz zur ID darf ein Name mehrfach in einem HTML-Dokument vorkommen.
Ich dachte jetzt, dass man die ids wie oben gezeigt setzten könnte und dann über eine Schleife die jeweils zutreffenden Zeilen ausblendet. Wenn ich auf die Überschrift klicke sollen eben immer die dazugehörigen, sich darunter befindenden, Sätze ausgeblendet werden.
Das sollte mit Namen, die eindeutig einer Überschrift zugeordnet sind, kein Problem sein:
Überschrift 1
-> Satz 1 (id: zeile1[0], name: Überschrift1)
-> Satz 2 (id: zeile1[1], name: Überschrift1)
-> Satz 3 (id: zeile1[2], name: Überschrift1)
Überschrift 2
-> Satz 1 (id: zeile2[0], name: Überschrift2)
Überschrift 3
-> Satz 1 (id: zeile3[0], name: Überschrift3)
-> Satz 2 (id: zeile3[1], name: Überschrift3)
Gehe dann mit Hilfe von getElementsByName in einer for-Schleife die Elemente durch und blende sie ein oder aus.
Siechfred
hi,
Wie wäre es, statt oder zusätzlich zur ID das name-Attribut zu verwenden?
In diesem Fall vermutlich ungünstig.
Denn im Gegensatz zur ID darf ein Name mehrfach in einem HTML-Dokument vorkommen.
Im Gegensatz zu ID ist die Menge der Elemente, die ein name-Attribut haben, ziemlich begrenzt.
gruß,
wahsaga
Nungut, ich weiß, dass meine Idee in der Umsetzng möglich ist. Ich hänge nur bei der for-Schleife. Habt ihr keinen Denkanstoß der mich dort weiter bringen könnte?
Nungut, ich weiß, dass meine Idee in der Umsetzng möglich ist. Ich hänge nur bei der for-Schleife. Habt ihr keinen Denkanstoß der mich dort weiter bringen könnte?
document.getElementByTagName()
Struppi.
document.getElementByTagName()
Struppi.
Sieht nicht gerade nach einer for-Schleife aus, hmmm? Ihr scheint mich anscheinend nicht wirklich zu verstehen. Was bringt mir denn bitte der Tag Name? Ich habe unter Unständen rund 1000 tr-Elemente wobei ich nur 2 oder drei aufdecken will.
Jetzt eher verstanden?
Sieht nicht gerade nach einer for-Schleife aus, hmmm? Ihr scheint mich anscheinend nicht wirklich zu verstehen. Was bringt mir denn bitte der Tag Name? Ich habe unter Unständen rund 1000 tr-Elemente wobei ich nur 2 oder drei aufdecken will.
Mit dieser Funktion bekommst du eine Sammlung von Elementen, diese kannst du natürlich in einer Schleife durchlaufen und du kannst auf jedes Objekt die Funktion anwenden
document.getElementById('xxx').getElementsByTagName('a');
jetzt hast du alle Links die innerhalb des Elementes mit der ID 'xxx' sind.
Jetzt eher verstanden?
Ich hab dich schon vorher verstanden.
Struppi.
document.getElementById('xxx').getElementsByTagName('a');
Dann haben wir vielleicht auch nur aneinander vorbeigeredet. der TagName bringt mich nur in keinster weise weiter, da ich ALLE entsprechenden Felder innerhalb von tr Tags habe.
Ich weiß zwar nicht warum es geht aber ich habe es jetzt so gelöst und das klappt:
document.write("<tr style='display:none;' id='contentElement" + data[i]["Material"] + "'>");
-------------------------------
var e = document.getElementsByName(layerName);
for(var j=0; j<e.length; j++) {
e[j].style.display = ((e[j].style.display == "block") ? "none" : "block");
}
Ich gebe es als ID an und Frage es über Name ab. Sei es nun konform oder nicht. Es geht.
Hell-O!
Ich gebe es als ID an und Frage es über Name ab. Sei es nun konform oder nicht. Es geht.
Aber nur im IE, siehe https://forum.selfhtml.org/?t=137715&m=894766.
Siechfred
gruss Markus, hallo Lesende,
document.getElementById('xxx').getElementsByTagName('a');
... der TagName bringt mich nur in keinster weise weiter, da ich ALLE entsprechenden Felder innerhalb von tr Tags habe.
Ich weiß zwar nicht warum es geht aber ich habe es jetzt so gelöst und das klappt: ... ... Ich gebe es als ID an und Frage es über Name ab. Sei es nun konform oder nicht. Es geht.
<q class="altvaeterlich">
das mag Dir jetzt helfen, aber die haltung dahinter zeugt nicht vom
wunsch nach wirklichem verstaendnis der materie.
</q>
schade, dass Du so schnell aufgegeben hast. Struppi haette Dir auf alle faelle weiter beigestanden und Dir haeppchenweise die informationen verabreicht, die Dir bei der erarbeitung einer sauberen loesung von nutzen gewesen waeren.
@alle interessierten:
molily hat seit ende letzten jahrens im und ueber das weblog von SELFHTML in mehreren artikeln das thema JavaScript breit aufgefaechert und meiner meinung nach hinreichen genug ausgeleuchtet. wenn ich mir den von molily gesponnenen roten faden so betrachte, warte ich eigentlich nur noch auf einen direkt an den letzten artikel (saubere namensraeume) anknuepfenden beitrag ueber objektorientiertes programmieren und die vielen moeglichen vererbungsarten in JavaScript. dieser koennte dann auch den vorlaeufigen abschluss des fast ein jahr waehrenden reviews bilden.
ich finde Markus' beispiel steht fuer einen guten mittelwert hinsichlich loesungskomplexitaet und anforderungen an das DOM-Scripting, so wie es heute von der breiten masse an neulingen, fortgeschrittenen und profis betrieben wird.
hat man sich nun im letzten jahr nur durch folgende beitraege von molily gearbeitet ...
- Der sinnvolle Einsatz von JavaScript vom 17.12.2005, - DHTML ist tot vom 01.04.2006, - JavaScript und Webstandards vom 19.04.2006 und - Neuer Artikel: Organisation von JavaScripten vom 25.08.2006 bzw. direkt: - Organisation von JavaScripten
... koennte eine der moeglichen loesungen fuer die vom OP vorgegebene aufgabe so aussehen (viel kommentierter quael-code):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<meta http-equiv="content-script-type" content="text/javascript" />
<meta http-equiv="content-style-type" content="text/css" />
<title>hide-and-show-table-rows.html</title>
<script type="text/javascript">
/*
das [TableRowController]-Singleton ist eine
sich selbst initialisierende kontrollstruktur
fuer tabellenzwischenueberschriften und deren
zugeordneten tabellenzeilen.
jede tabelle die einem dem beispiel entsprechenden
aufbau folgt, wird von diesem controller erfasst.
dabei bedarf es keiner verrenkungen ueber
html-attribute wie "name", "id" oder "class".
das singleton-muster wurde gewaehlt, um die kapselung
privater und oeffentlicher eigenschaften und methoden
auf genau einem objekt zu gewaehrleisten.
*/
var TableRowController = new function () { /* der new-operator erzeugt im zusammenspiel
mit der ihm folgenden anonymen funktion
ein objekt. die referenz auf diesen
anonymen objekt-konstruktor muss dann
innerhalb desselben maskiert werden.
*/
this.constructor = Object; /* verhindert, dass ein anderes controller-objekt erzeugt
werden kann -
var otherController = new TableRowController.constructor();
fuehrt nicht mehr zum gewuenschten ergebnis.
*/
var isOnDisplay = function (obj) { // private hilfsmethode.
var display = "";
if (document.defaultView && document.defaultView.getComputedStyle) {
display = document.defaultView.getComputedStyle(obj, "").getPropertyValue("display");
} else if (obj.currentStyle) {
display = obj.currentStyle["display"];
}
return ((display == "none") ? (false) : (true));
};
this.toggleRows = function (obj) { /* oeffentliche methode, die zuvor durch den
prozess "TableRowController.initialize"
fuer jeden passenden tabellenheader-knoten
dessem "onclick"-handler zugewiesen wurde;
steuert das aus- und einklappen der zu diesem
header gehoerenden tabellenzeilen.
*/
var i, rows = [], node = obj.parentNode.nextSibling;
while (node) {
if ((node.nodeType == 1) && (node.nodeName.toLowerCase() == "tr")) {
if (node.getElementsByTagName("th").length === 0) {
rows.push(node);
} else {
break;
}
}
node = node.nextSibling;
}
for (i=0; i<rows.length; ++i) {
node = rows[i];
if (isOnDisplay(node)) {
node.style.display = "none";
} else {
node.style.display = ((window.attachEvent && !window.addEventListener) ? ("block") : ("table-row"));
}
}
};
this.initialize = function () { /* oeffentliche methode, die auf den "onload"-
event-handler des browserfensters angemeldet
wurde; parst die DOM-struktur, um fuer die
steuerung passende tabellenheader-knoten
zu finden.
*/
var i, obj, isSubHeader, thCollection = document.getElementsByTagName("th");
for (i = 0; i<thCollection.length; ++i) {
obj = thCollection[i].parentNode;
isSubHeader = true;
while (obj && (obj.nodeName.toLowerCase() != "table")) {
if (obj.nodeName.toLowerCase() == "thead") {
isSubHeader = false;
}
obj = obj.parentNode;
}
if (isSubHeader) {
thCollection[i].onclick = function () {
TableRowController.toggleRows(this);
};
}
}
};
}(); // call-operator; fuehrt den anonymen konstruktor gleich nach dessen initialsierung aus.
if (window.addEventListener) { // initialisierung des controllers anmelden.
window.addEventListener("load", TableRowController.initialize, true);
} else if (window.attachEvent) {
window.attachEvent("onload", TableRowController.initialize);
}
</script>
<style type="text/css">
* {
margin: 0;
padding: 0;
border: none;
}
body {
font-size: 80%;
font-family: Verdana, Geneva, Helvetica, Arial, sans-serif;
background-color: #fafafa;
color: #000;
}
table {
margin: 10px;
border: 1px solid #000;
border-collapse: collapse;
}
tr, td, th {
padding: 10px;
border: 1px solid #000;
}
tbody th:hover {
cursor: pointer;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th colspan="3">hide and show table rows</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="3">sub header 01</th>
</tr>
<tr>
<td>content 01-a-01</td>
<td>content 01-a-02</td>
<td>content 01-a-03</td>
</tr>
<tr>
<td>content 01-b-01</td>
<td>content 01-b-02</td>
<td>content 01-b-03</td>
</tr>
<tr>
<th colspan="3">sub header 02</th>
</tr>
<tr>
<td>content 02-a-01</td>
<td>content 02-a-02</td>
<td>content 02-a-03</td>
</tr>
<tr>
<td>content 02-b-01</td>
<td>content 02-b-02</td>
<td>content 02-b-03</td>
</tr>
<tr>
<td>content 02-c-01</td>
<td>content 02-c-02</td>
<td>content 02-c-03</td>
</tr>
<tr>
<th colspan="3">sub header 03</th>
</tr>
<tr>
<td>content 03-a-01</td>
<td>content 03-a-02</td>
<td>content 03-a-03</td>
</tr>
</tbody>
</table>
</body>
</html>
aehm ... ja. - peterS. - pseliger@gmx.net
schade, dass Du so schnell aufgegeben hast. Struppi haette Dir auf alle
faelle weiter beigestanden und Dir haeppchenweise die informationen
verabreicht, die Dir bei der erarbeitung einer sauberen loesung von
nutzen gewesen waeren.
Jaja, ich war gestern auch nur relativ kurz am Rechner und hatte mich (noch) nicht intensiv mit der Fragestellung auseinander gesetzt
... koennte eine der moeglichen loesungen fuer die vom OP
vorgegebene aufgabe so aussehen (viel kommentierter quael-code):
... hätte ich anders gemacht (das ist immer interessant an JS, das es jedesmal sehr viele Wege gibt), aber es zeigt dass meine Vermutung richtig war, dass kein Attribut nötig ist, für die funktionalität.
Wie immer sehr schöner Code, Herr Seliger ;-)
Struppi.
hallo Struppi
... koennte eine der moeglichen loesungen fuer die vom OP
vorgegebene aufgabe so aussehen (viel kommentierter quael-code):... hätte ich anders gemacht ...
ja - beschreib mal ganz kurz Deinen loesungsansatz, denn
... (das ist immer interessant an JS, das
es jedesmal sehr viele Wege gibt), ...
die vielen möglichkeiten ergeben sich ja aus den unterschiedlichen
sicht- und herangehensweisen auf bzw. an ein problem - auf andere
leute *denke* bin ich immer neugierig.
... aber es zeigt dass meine Vermutung
richtig war, dass kein Attribut nötig ist, für die funktionalität.
by(t)e by(t)e - peterS. - pseliger@gmx.net
... hätte ich anders gemacht ...
ja - beschreib mal ganz kurz Deinen loesungsansatz, denn
... (das ist immer interessant an JS, das
es jedesmal sehr viele Wege gibt), ...die vielen möglichkeiten ergeben sich ja aus den unterschiedlichen
sicht- und herangehensweisen auf bzw. an ein problem - auf andere
leute *denke* bin ich immer neugierig.
Argg nööö, heute nicht, ich bin verkatert und kann nicht sinnvoll arbeiten %-/
Struppi.
Hi,
ja - beschreib mal ganz kurz Deinen loesungsansatz, denn
Eine (von JS aus gesehen) einfachere Möglichkeit wäre es vielleicht, alle Bereiche in *einzelne* TBODYs zu packen. Die TBODYs mit nur einem TR (bzw. einer "COLSPAN-TD") sind die "Klick-Areas", die dafür sorgen, daß der jeweils nachfolgende TBODY (und damit ale TRs darin) eingeklappt wird.
... aber es zeigt dass meine Vermutung
richtig war, dass kein Attribut nötig ist, für die funktionalität.
Das ist auch eigentlich nie der Fall - wenn man eine spezielle HTML-Syntax einhält, oder das Script speziell für die verwendete Syntax konstruiert, kann man auch noch weitaus komplexere Dinge ohne Attribute erledigen.
Gruß, Cybaer
Da hast du dir aber Mühe gegeben. Auf jeden Fall sehr nett. Ich werde es mir mal zu Gemüte führen.
Hell-O!
Denn im Gegensatz zur ID darf ein Name mehrfach in einem HTML-Dokument vorkommen.
Im Gegensatz zu ID ist die Menge der Elemente, die ein name-Attribut haben, ziemlich begrenzt.
Verwechsle nicht HTML und Javascript. Letzterem ist die Validität des verwendeten HTML ziemlich schnuppe. Abgesehen von dem IE-Bug hinsichtlich getElementsByName (für den besten Browser der Welt sind Element-ID und Elementname eins) funktioniert es tadellos:
Javascript:
isIE = (window.external ? true : false);
isOpera = (window.opera ? true : false);
visible = (isIE ? 'block' : 'table-row');
function getElementsByName_fix(eTag, eName) {
var elem = document.getElementsByTagName(eTag);
var arr = new Array();
for(i = 0; i < elem.length; i++) {
att = elem[i].getAttribute('name');
if(att == eName) arr.push(elem[i]);
}
return arr;
}
function base_init() {
var trColl = document.getElementsByTagName('tr');
for(i = 0; i < trColl.length; i++) trColl[i].style.display = visible;
}
function blenden(n) {
var trColl = ((isIE || isOpera) ? getElementsByName_fix('tr', n) : document.getElementsByName(n));
for(i=0; i<trColl.length; i++)
trColl[i].style.display = (trColl[i].style.display==visible ? "none" : visible);
}
Und das (nicht valide) HTML dazu:
<body onload="base_init();">
<table>
<tr colspan="2"><td onclick="blenden('t1')">Teil 1</td></tr>
<tr name="t1"><td>1</td><td>1</td></tr>
<tr name="t1"><td>1</td><td>1</td></tr>
<tr colspan="2"><td onclick="blenden('t2')">Teil 2</td></tr>
<tr name="t2"><td>2</td><td>2</td></tr>
<tr name="t2"><td>2</td><td>2</td></tr>
<tr name="t2"><td>2</td><td>2</td></tr>
<tr colspan="2"><td onclick="blenden('t3')">Teil 3</td></tr>
<tr name="t3"><td>3</td><td>3</td></tr>
<tr name="t3"><td>3</td><td>3</td></tr>
<tr colspan="2"><td onclick="blenden('t4')">Teil 4</td></tr>
<tr name="t4"><td>4</td><td>4</td></tr>
</table>
<body>
Funktioniert so im Firefox 1.5, IE 6.0 und Opera 8.5 unter Win2k. So, jetzt dürfen mich alle Validatorgläubigen peitschen ;-)
Siechfred
hi,
Verwechsle nicht HTML und Javascript. Letzterem ist die Validität des verwendeten HTML ziemlich schnuppe. Abgesehen von dem IE-Bug hinsichtlich getElementsByName
Gerade der IE wählt über getElementsByName _keine_ Elemente aus, die in HTML kein name-Attribut haben dürfen.
funktioniert es tadellos:
Ja, gut - wenn man dafür so einen komplexen Workaround basteln und auch noch invalides HTML in Kauf nehmen möchte ...
gruß,
wahsaga
Hell-O!
Gerade der IE wählt über getElementsByName _keine_ Elemente aus, die in HTML kein name-Attribut haben dürfen.
Darüber hinaus wählt der IE bei getElementsByName keine HTML-Elemente aus, die ihren Namen über Javascript verpasst bekommen haben bzw. wählt auch Elemente aus, welche den gesuchten Namen als ID haben, deshalb gibt's ja diesen Workaround.
funktioniert es tadellos:
Ja, gut - wenn man dafür so einen komplexen Workaround basteln und auch noch invalides HTML in Kauf nehmen möchte ...
Ersteres halte ich nicht wirklich für komplex, weil man anderenfalls auch die IDs aller Elemente durchgehen und mit dem gewünschten Teil abgleichen müsste, und zweiteres sehe ich in diesem Fall als nicht problematisch an, da es praktisch keine Auswirkungen hat - jedenfalls sind mir keine bekannt.
Siechfred