Kawałek Kodu

Ku, być może smutkowi niekórych, dziś będziemy się zajmować checkbox'ami znanymi z formularzy HTML. Niestety nie żywymi ptaszkami. Cel do osiągnięcia jest następujący: dla grupy checkbox'ów mamy zablokować możliwość ich kliknięcia powyżej wybranej liczby. Np. mając 10 ptaszków chcemy umożliwić zaznaczenie tylko trzech.

Niech kod HTML będzie taki:

<body>

 <form>
  <fieldset data-max-checked="2">
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
  </fieldset>

  <fieldset data-max-checked="5">
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
   <input type="checkbox"/>
  </fieldset>
 </form>

</body>

a JavaScript taki:

document.querySelectorAll('fieldset[data-max-checked]').forEach(function(fieldset){
    var maxChecked = parseInt(fieldset.getAttribute('data-max-checked'));
    fieldset.querySelectorAll('input[type="checkbox"]').forEach(function(checkbox){
        checkbox.addEventListener('click',function(){
            var checked = fieldset.querySelectorAll('input[type="checkbox"]:checked').length;
            if(checked > maxChecked){
                this.checked = false;
            }       
            fieldset.querySelectorAll('input[type="checkbox"]:not(:checked)').forEach(function(el){
                el.disabled = checked == maxChecked;
            });
        });
    });
});

Jak to działa?

Korzystamy z elementu FIELDSET, który służy właśnie do grupowania elementów formularza. Sam co prawda ich w magiczny sposób nie grupuje, robimy to sami. Grupowane elementy zazwyczaj są powiązane ze sobą w ramach kontekstu. Do FIELDSET dodajemy atrybut max-data-checked, który będzie przechowywał informację o maksymalnej możliwej do kliknięcia checkboxów, w ramach tegoż.

Iterujemy więc po każdym FIELDSET zawierającym ten atrybut, pobieramy wartość max-data-checked i zapamiętujemy ją. W ramach każdego FIELDSET przechadzamy się po jego checkbox'ach. Każdy checkbox dostaje możliwość nasłuchiwania na zdarzenie click (addEventListener).

W listenerze sprawdzamy ilość klikniętych checkboxów - będzie to ilość uwzględniająca klikany aktualnie ptaszek. Jeśli przekroczyliśmy maksymalną ilość, to odznaczamy ten właśnie kliknięty.

Następnie w pętli dla każdego niezaznaczonego checkbox'a ustawiamy atrybut disabled na podstawie warunku checked == maxChecked, czyli disabled przyjmuje wartość true, jeśli osiągnęliśmy maksymalną ilość zaznaczonych.

Pamiętaj o tym, aby kontrolować ilość przesyłanych checkboxów po stronie serwera. A jako że ptaszki mogą być czasem nieużywane, nic nie stoi na przeszkodzie, abyś zablokował wybrane również w momencie generowania HTML.

 

Przydatne linki:
Tag FIELDSET
Scopana metoda, czyli dlaczego selektor > oraz + nie zawsze działa.
"Hello dollar", czyli po co mi jQuery?