Toggla div'ar på en webbsida

Toggla div'ar på en webbsida

Jag har en massa objekt (div'var) på min sida jag skulle kunna vilja toggla med css (d.v.s byta "visibility") via typ JavaScript men jag vill inte loopa igenom alla objekt utan har önskan om att bara kunna pilla på css'en på nått sätt så alla objekt som har den specifika klassen uppdateras på en gång.
Google hjälper mig inte jättemycket eller så är min "Google Fu" för dålig.
Nån som har några brilijanta idéer?
Tack på förhand

Skrivet av oRBIT2002:

Jag har en massa objekt (div'var) på min sida jag skulle kunna vilja toggla med css (d.v.s byta "visibility") via typ JavaScript men jag vill inte loopa igenom alla objekt utan har önskan om att bara kunna pilla på css'en på nått sätt så alla objekt som har den specifika klassen uppdateras på en gång.
Google hjälper mig inte jättemycket eller så är min "Google Fu" för dålig.
Nån som har några brilijanta idéer?
Tack på förhand

Citat:

<div>
<button><label for="greger">Greger</label></button>
<input type="checkbox" id="greger">
<div class="hide">
<p>Hej greger</p>
</div>
</div>

<div>
<button><label for="sven">Sven</label></button>
<input type="checkbox" id="sven">
<div class="hide">
<p>Hej Sven</p>
</div>
</div>

Citat:

input {
display: none;
}
.hide {
display: none;
}
input[type="checkbox"]:checked + div {
display: initial;
}

Något sådant då?

@Toke:
Jag hänger inte riktigt med på din kod. Det jag vill göra i korthet är alltså att gömma/visa en stor mängd divvar med så lite kod som möjligt.

@zaibuf:
Nej inte riktigt

Kan du visa med ett exempel? Typ bild på före och efter?

Det lättaste är nog att med JS byta klass på de divar du vill ändra. Om du inte vill kodduplicera för mycket så skapar du en yttre div med en gemensam klass, och en inre som du ändrar med en event listener i JS. T ex:

<div class="outer"> <div class="inner-type1"> Synligt innan klick </div> <div class="inner-type2"> Osynligt innan klick </div> </div>

Här finns en tråd om att byta klass på divar:
https://stackoverflow.com/questions/195951/how-can-i-change-a...

Skrivet av oRBIT2002:

Jag har en massa objekt (div'var) på min sida jag skulle kunna vilja toggla med css (d.v.s byta "visibility") via typ JavaScript men jag vill inte loopa igenom alla objekt utan har önskan om att bara kunna pilla på css'en på nått sätt så alla objekt som har den specifika klassen uppdateras på en gång.
Google hjälper mig inte jättemycket eller så är min "Google Fu" för dålig.
Nån som har några brilijanta idéer?
Tack på förhand

Gör du jQuery eller liknande på sidan? Vad är det för css klass dessa divar har så kan jag hjälpa skriva ihop ett exempel

@oRBIT2002:
Jag tyckte @Tokes exempel verkade ganska bra. Du kan ju koppla flera divs till en och samma knapp eller element som du vill ska utlysa bytet. Knäckfrågan är kanske hur du vill att togglandet ska triggas?

Nån typ av psuedokod ser ut enligt nedan. Om VisaMinKlass körs med false ska alla element med css-klassen MinKlass gömmas, eller visas om parametern är true.

<div class="MinKlass">xxx</div>
<div class="MinKlass">xxx</div>
<div class="MinKlass">xxx</div>
...

<script type="text/javascript">
function VisaMinKlass(value) {
if value=true
GömMinKlass() /Alla divvar syns nu
else
VisaMinKlass() // Alla divvar är nu dolda
}

</script>

Skrivet av oRBIT2002:

Nån typ av psuedokod ser ut enligt nedan. Om VisaMinKlass körs med false ska alla element med css-klassen MinKlass gömmas, eller visas om parametern är true.

<div class="MinKlass">xxx</div>
<div class="MinKlass">xxx</div>
<div class="MinKlass">xxx</div>
...

<script type="text/javascript">
function VisaMinKlass(value) {
if value=true
GömMinKlass() /Alla divvar syns nu
else
VisaMinKlass() // Alla divvar är nu dolda
}

</script>

Med querySelectorAll kan du selecta alla divar med den klassen och med spread kan du direkt skapa en array.

Med style visibility kan du med en turnary sätta det till visible eller hidden beroende på värdet av boolen.

I slutet av metoden så togglar jag om boolen för att kunna visa exemplet för att visa alla igen.
Detta är dock inget du behöver göra om du hela tiden skickar in boolen från olika anrop.

const btn = document.querySelector("button"); const divs = [...document.querySelectorAll(".MinKlass")]; let val = false; btn.addEventListener("click", () => toggleDiv(val)); function toggleDiv(display){ const visibility = display ? "visible" : "hidden"; divs.forEach(e => { e.style.visibility = visibility; }); val = !display; }

fiddle

Senast redigerat 2020-03-20 20:25

@zaibuf:
Okej en intressant lösning, en teknik jag inte använt förut, kul! Jag hade iofs velat få bort loopen med.
Kompletterande fråga till din lösning dock, om det tillkommer flera divvar med MinKlass efter att kodraden nedan har körts, de kommer inte automatiskt med i urvalet du gör vid själva "togglingen"?
const divs = [...document.querySelectorAll(".MinKlass")];
utan det uttrycket behöver köras igen isåfall för att få en uppdaterad lista med divvar?

Jag hade velat modda css'en men det verkar inte vara trivialt. nått i stil med (psuedokod).

MinKlass.Display = None

Och that's it liksom så hade alla divv'ar uppdaterats automagiskt (fantiserar jag om iaf)

Senast redigerat 2020-03-20 21:57
Skrivet av oRBIT2002:

@zaibuf:
Okej en intressant lösning, en teknik jag inte använt förut, kul! Jag hade iofs velat få bort loopen med.
Kompletterande fråga till din lösning dock, om det tillkommer flera divvar med MinKlass efter att kodraden nedan har körts, de kommer inte automatiskt med i urvalet du gör vid själva "togglingen"?
const divs = [...document.querySelectorAll(".MinKlass")];
utan det uttrycket behöver köras igen isåfall för att få en uppdaterad lista med divvar?

Jag hade velat modda css'en men det verkar inte vara trivialt. nått i stil med (psuedokod).

MinKlass.Display = None

Och that's it liksom så hade alla divv'ar uppdaterats automagiskt (fantiserar jag om iaf)

Precis, den kör igenom hela DOM initialt och cachar alla objekten. Så om du t.ex. gör ajax anrop eller appendar nya divs så kommer de inte med. Då behöver du flytta in querySelectorn i själva funktionen för toggleDiv.

Beroende på vad du har för tillgång till koden, så är ett alternativ att sätta en wrapper runt alla dina divar och sen byta ut en klass på den som i sin tur gömmer allt.

Har du tillgång till jQuery kan du göra det ännu mindre genom att göra en plugin som togglar. Första klicket gömmer alla, andra klicket visar. Då behöver du inte skicka in någon bool heller. Den utgår från nuvarande värdet bara.

$("button").click(toggleDiv); function toggleDiv(){ $(".MinKlass").visibilityToggle(); } jQuery.fn.visibilityToggle = function() { return this.css('visibility', function(i, visibility) { return (visibility == 'visible') ? 'hidden' : 'visible'; }); };

fiddle

Varför vill du undvika en loop dock? Om du inte har något groteskt antal med divar du vill toggla så kommer det inte att märkas av.
En forEach loop med 10 000 objekt tar ~77ms att köra igenom (källa). Om du har 10 000 divar i din DOM så har du ett helt galet dokument.
Är performance jätte viktigt så kan du göra om det till en for-loop, dock drar det ner på läslighet av koden. Då kan du få ner performance till ~10ms.

Senast redigerat 2020-03-21 11:02

Css är statisk när du väl kompilerat och kör. Det du måste göra är att antingen manipulera style attributet eller ändra i class listan för respektive html element. Eller, som i ditt fall, ta bort elementet från DOMen helt.
Ändra style eller class gör du genom att hämta elementet med .getElementById/Classname/tag eller querySelectors. Peta bort från DOM gör du genom att ändra i parent children list.

Skrivet av zaibuf:

Varför vill du undvika en loop dock? Om du inte har något groteskt antal med divar du vill toggla så kommer det inte att märkas av.
En forEach loop med 10 000 objekt tar ~77ms att köra igenom (källa). Om du har 10 000 divar i din DOM så har du ett helt galet dokument.
Är performance jätte viktigt så kan du göra om det till en for-loop, dock drar det ner på läslighet av koden. Då kan du få ner performance till ~10ms.

Tajmingen du nämner stämmer säkert i ren beräkningsprestanda men ska du uppdatera utseendet för 10,000 divvar i en loop så löser man det nog inte på 77ms.

Lustigt att du nämner 10,000 divar, jag kommer nog ha ännu mer faktiskt i det projektet jag grejar med, och ja, det är galet.
Hursomhelst så är jag nog ändå nöjd med foreach-loop-varianten så, tack.

Skrivet av oRBIT2002:

Tajmingen du nämner stämmer säkert i ren beräkningsprestanda men ska du uppdatera utseendet för 10,000 divvar i en loop så löser man det nog inte på 77ms.

Lustigt att du nämner 10,000 divar, jag kommer nog ha ännu mer faktiskt i det projektet jag grejar med, och ja, det är galet.
Hursomhelst så är jag nog ändå nöjd med foreach-loop-varianten så, tack.

Här är ett exempel med 9792 divs och då laggar sidan jsfiddle riktigt extremt.
Trots det kör den togglingen på runt 10-15ms med en forEach. Detta är med den cachade arrayen från den initiala selectorn.
https://jsfiddle.net/az6u9yqh/

Flyttar du in querySelectorn så att den hämtar alla element vid varje anrop och byter ut forEach till en for-loop.
https://jsfiddle.net/az6u9yqh/1/

Så ger det fortfarande en performance på 15-25ms per toggling med 9792 divs.

Vet inte om du kan kräva så mycket mer.

Senast redigerat 2020-03-21 15:44

Det blir bra, tackar för assistans.

Skrivet av zaibuf:

Här är ett exempel med 9792 divs och då laggar sidan jsfiddle riktigt extremt.
Trots det kör den togglingen på runt 10-15ms med en forEach. Detta är med den cachade arrayen från den initiala selectorn.
https://jsfiddle.net/az6u9yqh/

Flyttar du in querySelectorn så att den hämtar alla element vid varje anrop och byter ut forEach till en for-loop.
https://jsfiddle.net/az6u9yqh/1/

Så ger det fortfarande en performance på 15-25ms per toggling med 9792 divs.

Vet inte om du kan kräva så mycket mer.

Ehm, med det underlaget skulle jag snarare påstå att TS har en väldigt god anledning att undvika en sådan lösning.

Jag forkade din och bytte metod till det TS efterfrågat hela tiden, att inte behöva loopa igenom massa grejer.
https://jsfiddle.net/hw0tzsax/1/

Vill du klara dig utan javascript kan du göra något likt följande precis som Toke föreslog:
https://jsfiddle.net/e3xft812/1/

Sedan gav jag dig tips om vad som triggar repaints och inte: https://csstriggers.com/

Webbläsare gillar inte större dom träd och du bör använda virtuella listor för flera tusen rader (du kan även ha miljontals rader) använder det själv i ett projekt och du kan filtrera dessa på millisekunder. Dock kan du inte göra det med ett så stort DOM träd; är begränsningar i webbläsarna.

Därför många plottar grafer på canvas för att även om SVG är fantastiskt så adderar de ytterligare dom element. Då är det inte responsive längre och man får ofta göra en repaint vid resize och attachea window listeners.

Du kan enkelt se overall performance med t.ex. lighthouse, sedan kolla med paint on scroll etc för att göra din webbplats så rapp som möjligt.

EDIT:
Ska vi gå in på detalj så ska bara huvudtråden vara ansvarig för att visa innehållet på sidan. Du ska helst knappt spendera någon tid med beräkningar och framförallt inte filtreringar över miljontals rader som kan låsa UI:t. Då bör du bryta ut det i en WebWorker som körs på en annan tråd. Däremot så är inte denna tråden någon snabbare, utan det är fortfarande javascript som körs. Vill du pressa prestandan ytterligare så föreslår jag i att denna WebWorkern att du även lyfter in en WebAssembly modul som kör beräkningarna om det är riktigt tunga grejer som ska ske och du vill kunna göra beräkningar på individuella entries.

Hoppas det hjälper något. Tveka inte att hojta till om du har ytterligare frågor då jag är lite besatt av sådant här och älskar att pressa varenda millisekund till vardags

Senast redigerat 2020-03-21 20:44
Skrivet av LemonIllusion:

Ehm, med det underlaget skulle jag snarare påstå att TS har en väldigt god anledning att undvika en sådan lösning.

Jag forkade din och bytte metod till det TS efterfrågat hela tiden, att inte behöva loopa igenom massa grejer.
https://jsfiddle.net/hw0tzsax/1/

Intressant! Tänkte inte ens på att man kan skapa en style tag och sätta nya värden på klasserna. Helt klart ett bättre val.
Men ska inte style appendas på head istället för body?

Skrivet av zaibuf:

Intressant! Tänkte inte ens på att man kan skapa en style tag och sätta nya värden på klasserna. Helt klart ett bättre val.
Men ska inte style appendas på head istället för body?

Style i head ska sättas om du vill att den ska ha utseendet förberett redan när allt annat laddas in. Finns en viss risk för FOC annars. Men i det här fallet så spelar det inte någon roll.

Skrivet av JeanC:

Vill du klara dig utan javascript kan du göra något likt följande precis som Toke föreslog:
https://jsfiddle.net/e3xft812/1/

Sedan gav jag dig tips om vad som triggar repaints och inte: https://csstriggers.com/

Webbläsare gillar inte större dom träd och du bör använda virtuella listor för flera tusen rader (du kan även ha miljontals rader) använder det själv i ett projekt och du kan filtrera dessa på millisekunder. Dock kan du inte göra det med ett så stort DOM träd; är begränsningar i webbläsarna.

Därför många plottar grafer på canvas för att även om SVG är fantastiskt så adderar de ytterligare dom element. Då är det inte responsive längre och man får ofta göra en repaint vid resize och attachea window listeners.

Du kan enkelt se overall performance med t.ex. lighthouse, sedan kolla med paint on scroll etc för att göra din webbplats så rapp som möjligt.

EDIT:
Ska vi gå in på detalj så ska bara huvudtråden vara ansvarig för att visa innehållet på sidan. Du ska helst knappt spendera någon tid med beräkningar och framförallt inte filtreringar över miljontals rader som kan låsa UI:t. Då bör du bryta ut det i en WebWorker som körs på en annan tråd. Däremot så är inte denna tråden någon snabbare, utan det är fortfarande javascript som körs. Vill du pressa prestandan ytterligare så föreslår jag i att denna WebWorkern att du även lyfter in en WebAssembly modul som kör beräkningarna om det är riktigt tunga grejer som ska ske och du vill kunna göra beräkningar på individuella entries.

Hoppas det hjälper något. Tveka inte att hojta till om du har ytterligare frågor då jag är lite besatt av sådant här och älskar att pressa varenda millisekund till vardags

Om man vill bli lite mer fri i placeringen av checkboxen i trädet kan man göra samma sak med ett markör-element och lite JS att limma ihop med. Kräver dock fortfarande att alla divvar är syskon med markör-elementet.
https://jsfiddle.net/y9ob8frx/

Skrivet av LemonIllusion:

Om man vill bli lite mer fri i placeringen av checkboxen i trädet kan man göra samma sak med ett markör-element och lite JS att limma ihop med. Kräver dock fortfarande att alla divvar är syskon med markör-elementet.
https://jsfiddle.net/y9ob8frx/

Du kan göra samma sak med complexa layouter där togglen ligger lite varstans och gömma den och ha custom layouter etc. Visst CSSen kan se lite "complex ut" och jag kan förstå att många tycker det är mer lättläst med javascript koden.

Såklart ska ens kod vara lättläst, men så är det ju lite med allt man gör: det är enkelt när man förstår sig på det.

Det är dock ett neat litet trick när man vill kunna toggla saker som ska fungera även för folk som inte har javascript aktiverat (crazy right?)

Skrivet av JeanC:

Du kan göra samma sak med complexa layouter där togglen ligger lite varstans och gömma den och ha custom layouter etc. Visst CSSen kan se lite "complex ut" och jag kan förstå att många tycker det är mer lättläst med javascript koden.

Såklart ska ens kod vara lättläst, men så är det ju lite med allt man gör: det är enkelt när man förstår sig på det.

Det är dock ett neat litet trick när man vill kunna toggla saker som ska fungera även för folk som inte har javascript aktiverat (crazy right?)

Japp. Jag är också ett starkt fan av den javascriptfria lösningen. Hade inte reflekterat över att man kunde göra den typen av manövrar i ren CSS innan jag läste första inlägget i den här tråden. Nu till att kombinera det med CSS-animationer och göra ett bildspel med animerade övergångar helt utan JS.

Skrivet av LemonIllusion:

Japp. Jag är också ett starkt fan av den javascriptfria lösningen. Hade inte reflekterat över att man kunde göra den typen av manövrar i ren CSS innan jag läste första inlägget i den här tråden. Nu till att kombinera det med CSS-animationer och göra ett bildspel med animerade övergångar helt utan JS.

Det är riktigt kul faktiskt! Knappen kan man ju placera lite varstans t.ex. med <label for='checkbox-id'>

Visst, HTML strukturen skulle väl inte "validera" men det är ju sällan WebbApplikationer förhåller sig till det idag ändå.

Ett annat Usecase är t.ex. nu när :focus-within existerar så kan man använda det likadant fast när man har fokus i t.ex. en sökruta så kan en helt annan del av designen ändras längre ner på sidan; med bara ren CSS

Aja nu kanske det blir lite off-topic, men siblings selectorn är riktigt användbar och första gången jag stötte på den så struntade jag i den tills jag såg ett användningsområde för det. Sedan blev det lite av en "när man har en hammare så är allt en spik" tills man kände att man behärskade det ^^

Skrivet av JeanC:

Vill du klara dig utan javascript kan du göra något likt följande precis som Toke föreslog:
https://jsfiddle.net/e3xft812/1/

Sedan gav jag dig tips om vad som triggar repaints och inte: https://csstriggers.com/

Intressant variant, men hur triggar jag detta via JavaScript?
Förövrigt är jag tyvärr begränsad till IE11 rörande funktionalitet, om det spelar nån roll...

Kul att se alla idéer som ramlar in här.

Skrivet av JeanC:

Det är riktigt kul faktiskt! Knappen kan man ju placera lite varstans t.ex. med <label for='checkbox-id'>

Visst, HTML strukturen skulle väl inte "validera" men det är ju sällan WebbApplikationer förhåller sig till det idag ändå.

Ett annat Usecase är t.ex. nu när :focus-within existerar så kan man använda det likadant fast när man har fokus i t.ex. en sökruta så kan en helt annan del av designen ändras längre ner på sidan; med bara ren CSS

Aja nu kanske det blir lite off-topic, men siblings selectorn är riktigt användbar och första gången jag stötte på den så struntade jag i den tills jag såg ett användningsområde för det. Sedan blev det lite av en "när man har en hammare så är allt en spik" tills man kände att man behärskade det ^^

Hehe, så blir det alltid för mig när jag lär mig något nytt. Jag vill använda det i alla lägen, även där det är direkt olämpligt.
Anyway: jag lovade ett bildspel https://jsfiddle.net/k0Lbsn3g/ (inte vackert gjort, ville bara testa runt lite)

Skrivet av oRBIT2002:

Intressant variant, men hur triggar jag detta via JavaScript?
Förövrigt är jag tyvärr begränsad till IE11 rörande funktionalitet, om det spelar nån roll...

Kul att se alla idéer som ramlar in här.

Kolla på mina två jsfiddles. De har båda javascript-triggers.
https://jsfiddle.net/6b4u9ojr/
https://jsfiddle.net/y9ob8frx/

Skrivet av LemonIllusion:

Hehe, så blir det alltid för mig när jag lär mig något nytt. Jag vill använda det i alla lägen, även där det är direkt olämpligt.
Anyway: jag lovade ett bildspel https://jsfiddle.net/k0Lbsn3g/ (inte vackert gjort, ville bara testa runt lite)

Snyggt Well done! Hojta till om du någon gång söker nytt jobb ^ Gillar folk med driv