2017-07-29 4 views
2

Ich habe das Gefühl, das ist so offensichtlich, ich werde mich schämen, wenn (wenn) gelöst - aber ich kann es einfach nicht funktionieren.Gruppierung vars in Funktion

Ich habe eine html + Javascript-Seite mit mehreren Elementen, die alle über Benutzer-Klicks angezeigt oder ausgeblendet werden müssen. So habe ich x Höhe von divs wie:

<div id="myDIVA" style="display:none;">blabla 1</div> 
<div id="myDIVB" style="display:none;">blabla 2</div> 
<div id="myDIVC" style="display:none;">blabla 3</div> 

und sie sind versteckt und/oder dargestellt durch divs klicken:

<div onClick="myClickFunctionA()">Show only ONE</div> 
<div onClick="myClickFunctionB()">Show only TWO</div> 
<div onClick="myClickFunctionC()">Show only THREE</div> 

Einfache Skript geht:

<script> 
    var a = document.getElementById('myDIVA'); 
    var b = document.getElementById('myDIVB'); 
    var c = document.getElementById('myDIVC'); 
function myClickFunctionA() { 
     a.style.display = 'block'; 
     b.style.display = 'none'; 
     c.style.display = 'none'; 
} 
function myClickFunctionB() { 
     a.style.display = 'none'; 
     b.style.display = 'block'; 
     c.style.display = 'none'; 
} 
</script> 

Was würde ich zu tun ist in der Lage, die Vars zu gruppieren, so dass ich eine Funktion wie haben könnte:

Ich habe viele div's! Das mag albern klingen, aber es würde mir viel Sinn machen, Vars für eine einfachere Bearbeitung gruppieren zu können.

So hoffe ich, jemand ist für eine einfache Lösung up :-) Dank

+2

Darn in der Nähe von allein für die erste Zeile upvoted. So oft scheinen die Leute von sich selbst erfüllt zu sein, nett jemanden mit Demut zu sehen. –

Antwort

1

Wahrscheinlich ein gutes usecase für ein Array:

var elemsById = ["myDIVA","myDIVB","myDIVC"] 
.map(id=>[id,document.getElementById(id)]); 

Also, wenn wir eines dieser Elemente zeigen, wollen wir iterieren alle von ihnen, und verstecken/zeigen sie, abhängig von ihrer ID:

function showThisAndHideRest(showId){ 
    elemsById.forEach(function([id,el]){ 
    el.style.display=id===showId?"block":"none"; 
    }); 
} 

So können Sie tun:

showThisAndHideRest("myDIVA"); 

Hinweis: Die obere verwendet einige coole ES6-Funktionen, die noch nicht von allen Browsern unterstützt werden. Und Theres eigentlich keine Notwendigkeit ID im Array zu speichern, wie der bereits Teil von el (el.id), aber ich wollte nur einige Parameter Destrukturierung verwenden ...

Run

+0

Nicht sicher, wo es schief geht, aber wenn ich versuche, diesen Code auszuführen, bekomme ich keine Show. Ich nehme an, ich sollte tun;

Show NEW VERSION
?? ... (((Ich teste das auf Firefox 52.2.1 (32-Bit) und Chrome 49.0.2623.112 - beide nicht die neuesten)) – morganF

+0

@morganF genau! Ich werde ein Schnipsel hinzufügen ... –

+0

@morganF Oh nein! Eigentlich ist es weil "myDivA"! == "myDIVA" ... Es tut mir leid für das:/ –

1

ich Sie davon ausgehen, nicht möchten für jede div eine separate Funktion haben. Und das musst du nicht. :-) Sie können eine einzelne Funktion haben, die die Klicks behandelt und mit einem Array von divs arbeitet.

Lassen Sie uns zunächst eine Reihe von diesen divs erhalten:

var divs = Array.prototype.slice.call(document.querySelectorAll("[id^=myDIV]")); 

(.. Es wäre besser, wenn wir ihnen eine gemeinsame Klasse geben könnte, die packt sie von Beginn ihrer IDs)

dann lassen sie uns haben die klickbare divs sagen, welche div sie beziehen sich auf:

<div onClick="myClickFunction('myDIVA')">Show only ONE</div> 

dann lassen sie uns eine einzige Funktion haben, die Klicks Griffe:

function myClickFunction(id) { 
    divs.forEach(function(div) { 
     div.style.display = div.id === id ? "block" : "none"; 
    }); 
} 

(Siehe Kompatibilitätshinweise am Ende.)

Allerdings, mit onxyz -Attribut-Stil Event Handler ist in der Regel eine schlechte Idee. Sie erfordern, dass die Funktionen, die Sie verwenden, global sind, zum einen.

Stattdessen wollen wir sie dynamisch anschließen, und verwenden Sie ein data-* Attribut zu sagen, welche Ziel sie beziehen sich auf:

// Scoping function to avoid globals 
 
(function() { 
 
    var divs = Array.prototype.slice.call(document.querySelectorAll(".showable")); 
 
    Array.prototype.forEach.call(document.querySelectorAll("div[data-show]"), function(dshow) { 
 
     dshow.addEventListener("click", myClickFunction, false); 
 
    }); 
 

 
    function myClickFunction() { 
 
    var idToShow = this.getAttribute("data-show"); 
 
    divs.forEach(function(div) { 
 
     div.style.display = div.id === idToShow ? "block" : "none"; 
 
    }); 
 
    } 
 
})();
<div data-show="myDIVA">Show A</div> 
 
<div data-show="myDIVB">Show B</div> 
 
<div data-show="myDIVC">Show C</div> 
 
<div class="showable" id="myDIVA">A</div> 
 
<div class="showable" id="myDIVB" style="display: none">B</div> 
 
<div class="showable" id="myDIVC" style="display: none">C</div>

Jetzt haben wir keine globalen Funktionen haben, und das Markup definiert die Beziehung zwischen den Elementen.


Hinweise zur Kompatibilität:

Wenn Sie veraltete Browser unterstützen, die (viele tun wie IE8   — und leider) nicht addEventListener haben, hat this answer eine Cross-Browser-Funktion hookEvent Sie eine Verwendung.

Beachten Sie, dass, wenn Sie IE8 sind unterstützt, finden Sie auch eine for Schleife statt Array.prototype.forEach verwenden müssen, da IE8 es nicht und Sie können nicht vernünftig es Shim (weil IE8 auch nicht unterstützen Hinzufügen einer nicht aufzählbaren Eigenschaft zu einem JavaScript-Objekt).

+0

@Jonasw: Ja, gerade erwischt, dass ein Live-Beispiel mit der richtigen Ereignisbehandlung hinzugefügt wurde. :-) Vielen Dank. –

+0

Und konnten Sie die nodeList zu Array cconversion nicht weglassen? –

+0

@ Jonasw: Ich sehe keinen Grund zu. Wenn wir es wie ein Array verwenden, erscheint es einmal vernünftig, ein Array zu erstellen. Sonst müssen wir jedes Mal '.call' benutzen, wenn wir es" für's "wollen. –

0

Hier ist eine Lösung mit addEventListener, dass die Notwendigkeit für onclick Attribute entfernt:

// Select the buttons and items 
 
var buttons = Array.prototype.slice.call(document.querySelectorAll('.showhidebutton')) 
 
var items = Array.prototype.slice.call(document.querySelectorAll('.showhideitem')) 
 

 
// Add a click eventListener for each button 
 
buttons.forEach(function(button, i) { 
 
    button.addEventListener('click', function() { 
 
    // When a button is clicked, loop through the items 
 
    items.forEach(function(item, j) { 
 
     // If this is the item that should be shown, show it 
 
     if (i === j) item.style.display = 'block' 
 
     // Otherwise, hide it 
 
     else item.style.display = 'none' 
 
    }) 
 
    }) 
 
}) 
 

 
// This code hides all but item 1 on pageload 
 
// can remove this code if you don't want that 
 
items.forEach(function(item, j) { 
 
    // Arrays are zero-indexed in JS, so the first item is 0 
 
    if (i === 0) return 
 
    // Hide all the other items 
 
    else item.style.display = 'none' 
 
})
<div class="showhideitem">blabla 1</div> 
 
<div class="showhideitem">blabla 2</div> 
 
<div class="showhideitem">blabla 3</div> 
 

 
<div class="showhidebutton">Show only ONE</div> 
 
<div class="showhidebutton">Show only TWO</div> 
 
<div class="showhidebutton">Show only THREE</div>

+0

querySelectorAll gibt eine NodeList zurück, die bereits eine forEach-Methode hat ... –

+1

Es gibt einen nicht standardmäßigen 'forEach', der jedoch nicht in IE unterstützt wird: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach – RyanZim

+0

@RyanZim Wenn Sie sich das Ende dieses Artikels ansehen, werden Standards zitiert. Schön zu sehen, dass sie das zum Standard hinzugefügt haben! Und man könnte es leicht auf IE8 + shim. Aber ja, das kleine Detail, dass ** keine ** Version von IE es unterstützt (was mit der Veröffentlichung vor dem Hinzufügen war) ist ein Problem, das nicht weggelassen werden sollte, wenn man es empfiehlt ('@' Jonas). –

0

Sie können für jedes der Elemente eine gemeinsame Klasse definieren, wo click Ereignis erwartet wird, mit .querySelectorAll() mit Wahl ".myClickFunction", iterieren Sie die NodeList mit for Schleife; Setzen Sie Element.dataset jedes Elements auf den aktuellen Iterationsindex; fügen Sie dem Element click Handler hinzu; Verwenden Sie erneut .querySelectorAll() mit Selektor "[id^myDIV]", um alle Elemente auszuwählen, bei denen id mit "myDIV" beginnt; unter click Ereignissatz jeweils "myDIV".style zu "display:none"; Set "myDIV" bei Index Element.dataset.style zu "display:block".

for (var i = 0, el = document.querySelectorAll(".myClickFunction") 
 
    ; i < el.length; i++) { 
 
    el[i].dataset.index = i; 
 
    el[i].onclick = function(event) { 
 
    for (var n = 0, el_ = document.querySelectorAll("[id^=myDIV]") 
 
    ; n < el_.length; n++) { 
 
     el_[n].style.display = "none" 
 
    } 
 
    document.querySelectorAll("[id^=myDIV]")[event.target.dataset.index] 
 
     .style.display = "block" 
 
    } 
 
}
<div id="myDIVA" style="display:none;">blabla 1</div> 
 
<div id="myDIVB" style="display:none;">blabla 2</div> 
 
<div id="myDIVC" style="display:none;">blabla 3</div> 
 
and they are hidden and/or shown by clicking div's: 
 

 
<div class="myClickFunction">Show only ONE</div> 
 
<div class="myClickFunction">Show only TWO</div> 
 
<div class="myClickFunction">Show only THREE</div>