Checkbox in nicht sichtbarer Tabellenzeile ansprechen
Jörg
- javascript
- jquery
0 klawischnigg0 Jörg0 klawischnigg0 Rolf B
0 Rolf B0 Jörg
0 Jörg
Hallo,
ich habe eine Tabelle, in der zeilenweise in der jeweils ersten Spalte (Tabellenzelle) eine Checkbox ist.
Diese Tabelle ist durchsuchbar, d.h. es werden die Zeilen ausgeblendet, die einem Suchbegriff nicht entsprechen.
Zudem hat die Tabelle eine übergeordnete Checkbox, die alle Zeilencheckboxen an-/abhaken kann.
Mein Ziel wäre, nur die sichtbaren Checkboxen an und abzuhaken, deshalb schrieb ich folgendes JQuery.
$(document).ready(function() {
$(".My_all_Check").click(function(event) {
event.stopPropagation();
if($('.myElement').is(':visible')) {
if($('.myElement').prop('checked') == true) {
$('.myElement').prop('checked',false);
} else {
$('.myElement').prop('checked',true);
}
}
});
});
Funktioniert aber nicht. Ich vermute, weil mein if($('.myElement').is(':visible')) {
ja nicht greifen kann, weil das Element ja sichtbar bleibt. Es wird die komplette Tabellenzeile auf display:none gesetzt. Die Checkbox selber innerhalb der nicht sichtbaren Tabellenzeile bleibt aber sichtbar.
Wie gesagt, eine Vermutung.
Aber selbst wenn sie stimmt, weiß ich das nicht aufzudröseln.
Was also muss ich tun, damit die Check-all-Checkbox sich nur auf die Checkboxen in den sichtbaren Tabellenzeilen bezieht, nicht aber auch die Checkboxen in den versteckten Tabellezeilen an- und abhakt?
Jörg
Hi there,
Mein Ziel wäre, nur die sichtbaren Checkboxen an und abzuhaken, deshalb schrieb ich folgendes JQuery.
Was ist ein JQuery? Vielleicht solltest Du es einmal mit Javascript versuche?
$(document).ready(function() { $(".My_all_Check").click(function(event) { event.stopPropagation(); if($('.myElement').is(':visible')) { if($('.myElement').prop('checked') == true) { $('.myElement').prop('checked',false); } else { $('.myElement').prop('checked',true); } } }); });
Funktioniert aber nicht. Ich vermute, weil mein
if($('.myElement').is(':visible')) {
ja nicht greifen kann, weil das Element ja sichtbar bleibt. Es wird die komplette Tabellenzeile auf display:none gesetzt. Die Checkbox selber innerhalb der nicht sichtbaren Tabellenzeile bleibt aber sichtbar.Wie gesagt, eine Vermutung.
Aber selbst wenn sie stimmt, weiß ich das nicht aufzudröseln.
Deine Vermutung ist richtig. "Aufdröseln" kannst Du das auf mehrere Arten und Weisen. Entweder Du "hangelst" Dich durch das DOM und fragst ab, ob die Tabellenzeile sichtbar ist oder, wahrscheinlich einfacher aber weniger elegant, Du vergibst sowohl der Tabellenzeile als auch der Checkbox eine ID, und zwar dergestalt, daß eine Nummer als Index eine Zuordnung und damit ein Erkennen der gewünschten Checkboxen möglich macht. Also zB. <tr id="TR"+nummer ... und die Checkbox in der betreffenden Zeile mit <input type="checkbox" id = "CHK"+nummer... - wobei Du Nummer entweder "zu Fuß" eingibst oder in der Schleife, die vermutlich Deine Tabelle erzeugt (mit PHP oder welcher Sprache Du auch immer das machst...)
Hallo klawischnigg,
Deine Vermutung ist richtig. "Aufdröseln" kannst Du das auf mehrere Arten und Weisen. Entweder Du "hangelst" Dich durch das DOM und fragst ab, ob die Tabellenzeile sichtbar ist oder, wahrscheinlich einfacher aber weniger elegant, Du vergibst sowohl der Tabellenzeile als auch der Checkbox eine ID, und zwar dergestalt, daß eine Nummer als Index eine Zuordnung und damit ein Erkennen der gewünschten Checkboxen möglich macht. Also zB. <tr id="TR"+nummer ... und die Checkbox in der betreffenden Zeile mit <input type="checkbox" id = "CHK"+nummer... - wobei Du Nummer entweder "zu Fuß" eingibst oder in der Schleife, die vermutlich Deine Tabelle erzeugt (mit PHP oder welcher Sprache Du auch immer das machst...)
Ich dachte, man könnte etwas in der Art machen, dass man nach Checkboxen fragt, deren übergeordnetes "tr" sicht- oder unsichtbar ist.
Also zB. <tr id="TR"+nummer ... und die Checkbox in der betreffenden Zeile mit <input type="checkbox" id = "CHK"+nummer...
Und wie frage ich die dann in meinem Jquery-Code als sicht- oder unsichtbar ab?
Was ist ein JQuery? Vielleicht solltest Du es einmal mit Javascript versuche?
Naja, ich verwende Jquery ja für viele andere Dinge eh. Soll heißen, es wird ohnehin mitgeladen. Dann kann ich es ja auch nutzen, oder?
Jörg
Hi there,
Ich dachte, man könnte etwas in der Art machen, dass man nach Checkboxen fragt, deren übergeordnetes "tr" sicht- oder unsichtbar ist.
Ja, eh, das meinte ich mit "hangeln durchs DOM" - Du fragst ab, ob die Zeile sichtbar ist und falls ja, dann muß die Checkbox ja irgendein n-tes Kind von tr sein.
Also zB. <tr id="TR"+nummer ... und die Checkbox in der betreffenden Zeile mit <input type="checkbox" id = "CHK"+nummer...
Und wie frage ich die dann in meinem Jquery-Code als sicht- oder unsichtbar ab?
Naja, irgendwas in der Art:
for (i=0; i < anzahl an Zeilen; i++)
{
if (document.getElementById('TR'+i).style.display!='none')
{
document.getElementById('CHK'+i).checked = 'checked';
}
}
Was ist ein JQuery? Vielleicht solltest Du es einmal mit Javascript versuche?
Naja, ich verwende Jquery ja für viele andere Dinge eh. Soll heißen, es wird ohnehin mitgeladen. Dann kann ich es ja auch nutzen, oder?
Das Problem ist halt, mit jQuery verstellt man sich selbst den Blick auf das Funktionieren der Dinge, und vor allem, eine richtige Berechtigung hat das nicht mehr (so es die je hatte), seit sich die Browser weitgehend an Konventionen halten...
Hallo klawischnigg,
eine richtige Berechtigung hat (jQuery) nicht mehr
Es bringt halt noch ein paar Erweiterungen mit, und einige Dinge sind kompakter formulierbar. Dieses :visible ist allerdings tricky, wie in meinem anderen Beitrag gesagt.
Die $ Funktion zum Bilden eines matched set ist seit Erfindung von querySelectorAll in den meisten Fällen unnötig. Für komplexere Abfragen gibt's aber dann noch die angeflanschten Filterfunktionen, die man auf DOM Ebene umständlicher programmieren muss.
Aber wenn man damit 10 Jahre programmiert hat und dran gewöhnt ist, ist's wie das alte Kopfkissen. Es müffelt, es verliert Federn, aber es ist HÖLLISCH bequem 😂
Rolf
Hi there,
Aber wenn man damit 10 Jahre programmiert hat und dran gewöhnt ist, ist's wie das alte Kopfkissen. Es müffelt, es verliert Federn, aber es ist HÖLLISCH bequem 😂
Wenn ich nur daran denke krieg' ich schon wieder einen Schlaf...😉
Hallo Jörg,
d.h. es werden die Zeilen ausgeblendet
Wie genau tust Du das?
Der :visible Selektor von jQuery prüft, ob ein Element Platz auf dem Bildschirm belegt. Je nach Ausblendetechnik kann es sein, dass :visible das als sichtbar oder unsichtbar einschätzt.
Mein Versuch:
<section>
<div>
Bla
</div>
</section>
Wenn ich der section oder dem div den Style "visibility:hidden" gebe, meldet $("div").is(":visible") trotzdem true.
Setze ich einen style von display:none (egal ob section oder div), meldet es false
Setze ich auf der section height:0 (mit overflow:hidden), ist das div unsichtbar, aber is(":visible") sagt true. Weil das div selbst eine Höhe > 0 behält.
Statt mit :visible könntest Du auch mit dem Mechanismus arbeiten, der deine Tabellenzeilen ausblendet. Damit meine ich dies: Ich habe dienstlich ebenfalls eine durchsuchbare Table mit Checkboxen programmiert. Und ich habe auch eine "check all" Funktion. Da blende ich alle tr per Default aus und die sichtbaren bekommen eine Klasse "match". Die Suchfunktion deselektiert in den Zeilen, wo sie die match-Klasse entfernt, die Checkbox.
"Check all" selektiert die Checkboxen, die auf den Selektor
#myTable tbody tr.match td:first-of-type input[type="checkbox"]
zutreffen.
Ich dachte, man könnte etwas in der Art machen, dass man nach Checkboxen fragt, deren übergeordnetes "tr" sicht- oder unsichtbar ist.
Genau das passiert damit.
Rolf
Hallo Rolf,
Setze ich einen style von display:none (egal ob section oder div), meldet es false
Genau so wirds gemacht.
Jedenfalls erscheint die Zeile im Browser-Inspektor dann als
style="display: none;
Jörg
So scheint es zu funktionieren:
$(document).ready(function() { $(".My_all_Check").click(function(event) { event.stopPropagation(); if($('.myElement').prop('checked') == true) { $('.myElement:visible').prop('checked',false); } else { $('.myElement:visible').prop('checked',true); } }); });
Jörg
So scheint es zu funktionieren:
$(document).ready(function() { $(".My_all_Check").click(function(event) { event.stopPropagation(); if($('.myElement').prop('checked') == true) { $('.myElement:visible').prop('checked',false); } else { $('.myElement:visible').prop('checked',true); } }); });
Jörg
Na, so ganz zuverlässig ist es nicht. Wenn ich eine Suche mache und alle anklicke, funktioniert es. Aber kummuliert suchen und anklicken funktioniert dann nicht.
Da erhalte ich unterschiedliche Fehler, die ich nicht so recht dingfest machen kann.
In Summe also zu undefiniert, das ganze. 😟
Jörg
Hallo Jörg,
ohne Kenntnis Deiner Seite lässt sich da wenig sagen.
Aber eins fällt mir gerade auf:
$(".myElement")
liefert ein wrapped set aller Elemente mit dieser Klasse. Wenn Du also eine Tabelle mit drölftausend Zeilen hast und die Checkbox darin jeweils die Klasse "myElement" hat, liefert $(".myElement")
drölftausend Checkboxen.
$(".myElement").is(":visible")
prüft, ob irgendein Element im matched set sichtbar ist. Hast Du 1000 Zeilen und eine ist sichtbar, ist is(":visible") immer noch true.
$(".myElement").prop("checked")
liefert das checked-Property des ersten Eintrags in diesem wrapped set
$(".myElement").prop("checked", true)
setzt das checked-Property für alle Einträge in diesem wrapped set
Offenbar soll ein Klick auf .My_all_Check den Check-Status aller sichtbaren Checkboxen invertieren. Was zum Namen "My_all_Check" nicht ganz passt, aber das sei mal dahingestellt. Damit das gelingt, musst Du die relevanten Checkboxen einzeln verarbeiten.
$(".myElement:visible").each(function(element) {
// element ist jetzt kein wrapped set, sondern ein HTML Element
element.checked = !element.checked;
});
Ich hab das noch rot gemacht. Aus Gründen.
Dieser Code setzt voraus, dass nur Checkboxen die myElement-Klasse haben. Man sollte das durch einen passenden Selektor klarer machen
:visible ist kein Selektor des Browsers, sondern der Sizzle-Engine von jQuery. Wird er verwendet, kann jQuery nicht mehr auf querySelector zurückgreifen, sondern muss die Elemente von Hand gegen den Selektor matchen. Das ist deutlich langsamer. Die jQuery Doku empfiehlt, dies nicht zu tun. Statt dessen soll man zunächst so selektieren, dass nur Browser-Selektoren verwendet werden, und dann nachfiltern.
$("input[type=checkbox].myElement")
.filter(":visible")
.each(function(element) {
element.checked = !element.checked;
});
wäre also deutlich performanter. Und ich würde es so programmieren:
for (let element of document.querySelectorAll("input[type=checkbox].myElement")) {
if (element.style.display != 'none')
element.checked = !element.checked;
};
Funktioniert in allen halbwegs aktuellen Browsern. Es setzt voraus, dass Du mit style="display:none" ausblendet. Tust Du es anders, muss die Abfrage sich natürlich ändern.
Wenn Du zum Ausblenden eine Klasse verwendest, wie heute nachmittag beschrieben, kannst Du diese Klasse gleich in querySelectorAll verwenden und brauchst gar keinen if.
Ich habe ein Problem. Ich löse es mit X. Jetzt habe ich zwei Probleme.
Dieser Satz gilt (mindestens) für X=Regex und X=jQuery. Manchmal auch für X="einer Frage bei Selfhtml" 😉.
Rolf
Hallo Rolf,
ohne Kenntnis Deiner Seite lässt sich da wenig sagen.
Ja, das ist nachvollziehbar. Deshalb umso mehr Dank für Eure Hilfe bis hierher.
Aber eins fällt mir gerade auf:
$(".myElement")
liefert ein wrapped set aller Elemente mit dieser Klasse. Wenn Du also eine Tabelle mit drölftausend Zeilen hast und die Checkbox darin jeweils die Klasse "myElement" hat, liefert$(".myElement")
drölftausend Checkboxen.
$(".myElement").is(":visible")
prüft, ob irgendein Element im matched set sichtbar ist. Hast Du 1000 Zeilen und eine ist sichtbar, ist is(":visible") immer noch true.
$(".myElement").prop("checked")
liefert das checked-Property des ersten Eintrags in diesem wrapped set
$(".myElement").prop("checked", true)
setzt das checked-Property für alle Einträge in diesem wrapped set
Das erklärt, warum ich für mich undefinierte Ergebnisse erhalten habe.
Offenbar soll ein Klick auf .My_all_Check den Check-Status aller sichtbaren Checkboxen invertieren.
Nicht wirklich. Im Grunde möchte ich Checkboxen kummuliert an- und abhaken können. Das ist mit einem einzigen Button (o.ä.) unmöglich. Ich ahbe es jetzt über 2 verschiedene gelöst, dann ist es recht einfach
$(\"#all_Check\").click(function(event) {
event.stopPropagation();
$('.myElement:visible').prop('checked', true);
});
$(\"#all_NotCheck\").click(function(event) {
event.stopPropagation();
$('.myElement:visible').prop('checked', false);
});
for (let element of document.querySelectorAll("input[type=checkbox].myElement")) { if (element.style.display != 'none') element.checked = !element.checked; };
Wollte bei mir nicht arbeiten. Und hätte wohl auch nicht erreicht, dass ich kummuliert an- und abhake, oder?
Wie gesagt, ich habe es jetzt mit 2 Links (Buttons) gemacht und es funktioniert zuverlässig, wie gewünscht.
IUch habe aber jetzt noch ein ganz anderes Problem. Nämlich möchte ich in meine Tabellensuche eine "Reset-Funktion" einbauen, die bei Klick das Eingabefeld leert, den Focus auf das Eingabefeld setzt und eine neue Suche ermöglicht. Nicht weiter schwierig, wenn da nicht das Problem wäre, dass das Ergebnis der vorherigen Suche beibehalten wird.
Etwas später:
Genau dieses Problem hatte ich doch schonmal. Und siehe da, Du hast es seinerzeit schon gelöst. Ich habe mir alles nochmal durchgelesen und gemerkt, dass ich mit $('.qs_input').val('').trigger('keyup').focus();
auf dem Holzweg war, während $('.qs_input').val('').trigger('keydown').focus();
das erreicht, was ich brauchte.
Also jetzt sind tatsächlich alle Probleme gelöst.
Danke an alle Helfer dieses Thema und an Rolf doppelten Dank wegen der Hilfe seinerzeit.
Jörg
Hallo Jörg,
Check/Uncheck All mit einer einzigen Checkbox?
Hold by beer, be right back
Rolf
Hi Rolf,
Check/Uncheck All mit einer einzigen Checkbox?
Hold by beer, be right back
Hold by my beer 😉
Bin mit meiner lösung jetzt sehr zufrieden, weil sie auch viel selbsterklärender für den User ist.
Einfach 3 Buttons (o.ä.)
Jörg
Hallo Jörg,
look Ma, no jQuery and one checkbox, with live search
https://jsfiddle.net/Rolf_b/7zm3eL59/
49 Minuten 😂 🕐
🍻 Rolf
Hi Rolf,
https://jsfiddle.net/Rolf_b/7zm3eL59/
49 Minuten 😂 🕐
🍻 Rolf
Bin fast begeistert... fast. Denn es funktioniert nicht ganz, wie ich gern hätte. Meine Lösung hingegen schon 😉
Test:
Gib Folgendes ein:
Ergebnis sollte sein, dass alle 5 Einträge angehakt sind. Es sind aber nur die letzten 3 (ic) angehakt. 😉
Trotzdem sauber. 👍 Auch wenn das kummulierte Anhaken nicht so funkt, ich ich persönlich das gerne möchte.
Jörg
Hallo Jörg,
Ergebnis sollte sein, dass alle 5 Einträge angehakt sind. Es sind aber nur die letzten 3 (ic) angehakt. 😉
Nein, sollte es nicht, finde ich. Ich meine, dass Zeilen, die von einer Suche nicht erfasst sind, keinen Haken mehr haben dürfen. Sonst hat man unsichtbare angehakte Zeilen, und dann hast Du eine Mehrdeutigkeit bei der Verarbeitung "alle angehakte Zeilen". ALLE? Oder nur die sichtbaren?
Wenn man die Check-All Checkbox setzt, sollen ja auch nur die sichtbaren Zeilen angehakt werden. Das schafft einen logischen Zusammenhang: "Check-All gesetzt" == "alle sichtbaren Zeilen angehakt".
Aber probier's aus, ich habe das ent-checken ja explizit eingebaut. Nimm diese beiden Zeilen weg:
if (!match)
getRowCheckbox(row).checked = false;
Rolf
Hallo Jörg,
Ergebnis sollte sein, dass alle 5 Einträge angehakt sind. Es sind aber nur die letzten 3 (ic) angehakt. 😉
Nein, sollte es nicht, finde ich. Ich meine, dass Zeilen, die von einer Suche nicht erfasst sind, keinen Haken mehr haben dürfen. Sonst hat man unsichtbare angehakte Zeilen, und dann hast Du eine Mehrdeutigkeit bei der Verarbeitung "alle angehakte Zeilen". ALLE? Oder nur die sichtbaren?
Wenn man die Check-All Checkbox setzt, sollen ja auch nur die sichtbaren Zeilen angehakt werden. Das schafft einen logischen Zusammenhang: "Check-All gesetzt" == "alle sichtbaren Zeilen angehakt".
Hi Rolf,
na klar, wir können uns nun ausdenken, wie es am schönsten oder logischsten ist. Abe rich habe ja eine konkrete Anwendung im Hinterkopf.
Diese besagt, dass ein Kunde aus einer Vielzahl (=Unzahl) an Einträgen einige Gruppen auswählen können muss. Diese Gruppen können untereinander Überschneidungen haben, müssen aber nicht. Also muss der Kunde anzuhakende Einträge kummuliert anhaken können. Dadurch bedingt kann ich nicht über einen Button einfach invertiert an- oder abhaken.
Ob dann dabei eine Bezeichnung "check all" oder "uncheck all" stimmig oder logisch ist, ist zweitrangig. Bei mir heißen die Links auch deshalb "alle sichtbaren Einträge anhaken" sowei "alles sichtbaren einträge abhaken".
Ich finde Deine Lösung klasse, aber für meine Anwendung passt sie nicht ganz so 100%ig wie meine mit 2 Buttons. Ich benötige halt das kummulierte Anhaken vor dem hintergrund von Mehrfachsuchen. Ich wüßte auch nicht, wie man eine Lösung vor diese Aufgabe mit einem Button schaffen soll. Das widerspricht, wie Du richtig anmerkst, komplett der Logik, ist also meiner Meinung nach nicht möglich.
Wie siehst Du das?
Edit: Zudem hoffe ich, dass die Lösung mit 2 Buttons selbsterklärender für den User ist.
Gruß, Jörg
Hallo,
Ob dann dabei eine Bezeichnung "check all" oder "uncheck all" stimmig oder logisch ist, ist zweitrangig. Bei mir heißen die Links auch deshalb "alle sichtbaren Einträge anhaken" sowei "alles sichtbaren einträge abhaken".
genau so würde ich es als Nutzer auch erwarten - also dass meine Eingabe die aktuell nicht sichtbaren Einträge unverändert lässt.
das kummulierte Anhaken
Übrigens: "kumulieren" schreibt sich mit nur einem 'm'. Das kommt vom lateinischen cumulus, was übersetzt etwa Haufen, Anhäufung oder Ansammlung bedeutet.
Möge die Übung gelingen
Martin
Hallo Jörg,
okay - du hast natürlich recht.
Hier gilt wie so oft das Bauhaus-Prinzip: Die Form folgt der Funktion.
Wenn man durch diverse Suchen etwas "einsammeln" können soll, ist deine Lösung die sinnvollere.
Rolf
Hallo Jörg,
okay - du hast natürlich recht.
Hier gilt wie so oft das Bauhaus-Prinzip: Die Form folgt der Funktion.
Wenn man durch diverse Suchen etwas "einsammeln" können soll, ist deine Lösung die sinnvollere.
Hi Rolf,
bin trotzdem von Deiner Lösung angetan. Habe gerade noch etwas damit herumgespielt und Du invertierst nicht einfach munter drauf los.
ergibt nämlich z.b. zwei angehakte Ergebnisse, also genau wie gewünscht. Mal ganz davon abgesehen, dass ich seit Stunden daran sitze und nicht seit 49min. 🤭😇 Zudem gibt es auch andered Anwendungen und dann komme ich sicher nochmal auf Deinen Code zurück (du läßt den doch online?)
Danke auf jeden Fall fürs helfen. 👍
Jörg
Hallo an Alle,
Dank für Eure Hilfe, Anregungen und Diskussionen, auch wenn ich-- zugegebener Weise -- nicht alles verstehe. Macht ja nichts. Lernen kostet zumeist nichts. Ist das Notepad++ wirklich so gut? Ich komme damit schlechter zurecht, als mit dem einfachen windows-editor. Wahrscheinlich eine Gewöhnungsfrage.
Für alle, die es interessiert: ruft mal, am besten mit Handy die Test-Seite: http://michaelschedler.bplaced.net auf. Das ist das Ergebnis von den heutigen fast 6 Stunden Arbeit!
Edit Rolf B: Link korrigiert und zum Link gemacht
In den anderen Auflösungen 601px-1369px und ab 1470px ist noch alles in Unordnung, da ich veraltete CSS- Dateien auf dem Server liegen habe. Auf dem Handy sieht es aber, zumindest bei mir, schon mal brauchbar aus. Da die Navigation auf meinem Handy nicht all zu groß ist, werde ich erstmal kein verstecktes Menü einbauen. Vielleicht dann, wenn die anderen Seiten es erfordern sollten. Aber da bin ich z.Z. noch nicht. Ich versuche jetzt mit den 3 CSS Dateien die Seite wieder zum Laufen zu bringen und danach schaue ich mal, ob ich das irgendwie in einer Datei zusammenfügen kann.
Euch nochmals DANKE und eine gute Nacht! Gruß von Michael
Hi there,
Für alle, die es interessiert: ruft mal, am besten mit Handy die Test-Seite: " michael.schedler.bplaced.net " auf. Das ist das Ergebnis von den heutigen fast 6 Stunden Arbeit!
Für diese Seite hast Du 6 Stunden benötigt:
???
(scnr...😉)
Hallo Michael,
wird Zeit, dass Du ins Bett kommst 😉
Rolf