web-dev-qa-db-fra.com

Empêcher la case à cocher de cocher/vérifier COMPLÈTEMENT

On m'a demandé de désactiver le "ticking" d'une case à cocher. Je ne suis pas invité à désactiver la case à cocher, mais simplement à désactiver le "ticking". 

En d'autres termes, un utilisateur pensera qu'une case à cocher peut être cochée, mais ce n'est pas le cas. Au lieu de cela, cliquer sur la case à cocher fera apparaître une boîte de dialogue modale, donnant à l'utilisateur plus d'options pour activer ou désactiver la fonctionnalité représentée par la case à cocher. Si les options choisies dans la boîte de dialogue entraînent l'activation de la fonctionnalité, la case à cocher sera alors cochée.

Maintenant, le vrai problème est que pour une fraction de seconde, vous pouvez toujours voir que la case à cocher est cochée.

J'ai essayé une approche comme celle-ci:

<input type='checkbox' onclick='return false' onkeydown='return false' />

$('input[type="checkbox"]').click(function(event) {
    event.preventDefault();
    alert('Break');
});

Si vous exécutez ceci, l'alerte apparaîtra, indiquant que la coche est visible (l'alerte est juste là pour démontrer qu'elle est toujours cochée, en production, l'alerte n'est pas là). Sur certains utilisateurs avec des machines plus lentes et/ou dans des navigateurs avec des rendus lents/javascript, les utilisateurs peuvent voir un très faible scintillement (le scintillement dure parfois une demi-seconde, ce qui est perceptible).

Un testeur de mon équipe a signalé ce problème comme un défaut et je suis censé le réparer. Je ne sais pas quoi d'autre je peux essayer d'empêcher le coche de cocher!

30
Andrew

Essayer 

event.stopPropagation();

http://jsfiddle.net/DrKfE/3/

18
Zoltan Toth

La meilleure solution que j'ai trouvée:

$('input[type="checkbox"]').click(function(event) {
    var $checkbox = $(this);

    // Ensures this code runs AFTER the browser handles click however it wants.
    setTimeout(function() {
      $checkbox.removeAttr('checked');
    }, 0);

    event.preventDefault();
    event.stopPropagation();
});
14
paulpooch

Je crains que cet effet ne puisse être supprimé. Dès que vous cochez la case, l'état (et le rendu) est modifié. Ensuite, les gestionnaires d'événements seront appelés. Si vous effectuez une opération event.preventDefault(), la case à cocher sera réinitialisée après tous les gestionnaires sont exécutés. Si votre gestionnaire a une longue durée d'exécution (facile à tester avec un modal alert()) et/ou que le moteur de rendu est repeint avant la réinitialisation, la boîte clignotera.

$('input[type="checkbox"]').click(function(event) {
    this.checked = false; // reset first
    event.preventDefault();
    // event.stopPropagation() like in Zoltan's answer would also spare some
    // handler execution time, but is no more needed here

    // then do the heavy processing:
    alert('Break');
});

Cette solution réduira le scintillement au minimum, mais ne peut l’empêcher réellement. Voir la réponse de Thr4wn et RobG pour savoir comment simuler une case à cocher. Je préférerais ce qui suit:

<button id="settings" title="open extended settings">
    <img src="default_checkbox.png" />
</button>
document.getElementById("settings").addEventListener("click", function(e) {
    var img = this.getElementsByTagName("img")[0]);
    openExtendedSettingsDialog(function callbackTick() {
        img.src = "checked_checkbox.png";
    }, function callbackUntick() {
        img.src = "unchecked_checkbox.png";
    });
}, false);
7
Bergi

De mon point de vue, c'est aussi simple que:

$(this).prop('checked', !$(this).prop('checked'));

Fonctionne à la fois pour les cases cochées et non cochées

5
Patartics Milán

Enveloppez la case avec un autre élément qui bloque les événements de pointeur (probablement via CSS). Ensuite, gérez l’événement de clic de wrapper au lieu de la case à cocher. Cela peut être fait de différentes manières, mais voici un exemple de mise en œuvre relativement simple:

$('input[type="checkbox"').parent('.disabled').click( function() {
    
    // Add in whatever functionality you need here
    
    alert('Break');
    
});
/* Insert an invisible element that covers the checkbox */
.disabled {
    position: relative;
}
.disabled::after {
    content: "";
    position: absolute;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<!-- Only wrapped checkboxes are "disabled" -->
<input type="checkbox" />
<span class="disabled"><input type="checkbox" /></span>
<input type="checkbox" />
<span class="disabled"><input type="checkbox" /></span>
<span class="disabled"><input type="checkbox" /></span>
<input type="checkbox" />

Remarque: Vous pouvez également ajouter les éléments d'encapsidation par programmation, si vous le souhaitez.

2
BDawg

Avec CSS, vous pouvez changer l'image de la case à cocher. Voir http://ryanfait.com/resources/custom-checkboxes-and-radio-buttons/ et aussi CSS Styling Checkboxes .

Je voudrais désactiver la case à cocher, mais le remplacer par une image d'une case à cocher de travail. De cette façon, la case à cocher ne semble pas désactivée, mais ne sera pas cliquable.

2
Alexander Bird

Il me semble que vous utilisez le mauvais élément d'interface. Un bouton plus approprié serait un bouton désactivé par défaut, mais activé lorsque cette option est disponible. L'image affichée peut être celle que vous souhaitiez.

<button disabled onclick="doSomething();">Some option</button>

Lorsque les utilisateurs ont sélectionné cette fonctionnalité, activez le bouton. L'image sur le bouton peut être modifiée par CSS selon qu'elle est activée ou non, ou par la fonction activer/désactiver.

par exemple.

<script type="text/javascript">

function setOption(el) {
  var idMap = {option1:'b0', option2: 'b1'};
  document.getElementById(idMap[el.value]).disabled = !el.checked; 
}

</script>

<div><p>Select options</p>
  <input type="checkbox" onclick="setOption(this);" value="option1"> Option 1
  <br>
  <input type="checkbox" onclick="setOption(this);" value="option2"> Option 2
  <br>
</div>
<div>
  <button id="b0" onclick="alert('Select…');" disabled>Option 1 settings</button>
  <button id="b1" onclick="alert('Select…');" disabled>Option 2 settings</button>
</div>
1
RobG

Il est très important d'utiliser return false à la fin.

Quelque chose comme ça:

$("#checkbox").click((e) => {
  e.stopPropagation();
  return false;
});
1
Florian Leitgeb

La méthode Event.preventDefaultdevrait fonctionner pour les événements change, keydown et mousedown, mais pas dans mes tests.

Ma solution à ce problème dans une extension de Mozilla Firefox 53.0 consistait à basculer une classe HTML qui activait/désactivait la déclaration CSS pointer-events: none appliquée à la case à cocher. Cela concerne le cas basé sur le curseur, mais pas le cas basé sur la clé. Voir https://www.w3.org/TR/SVG2/interact.html#PointerEventsProp .

J'ai abordé le cas basé sur la clé en ajoutant/supprimant un attribut HTML tabindex="-1". Voir https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex .

Notez que la désactivation de pointer-events désactivera votre capacité à déclencher des curseurs CSS en survol (par exemple, cursor: not-allowed). Ma case à cocher était déjà encapsulée dans un élément span. J'ai donc ajouté une classe HTML à cet élément span sur lequel j'ai ensuite reciblé ma déclaration CSS cursor.

Notez également que l'ajout d'un attribut tabindex="-1" entraînera pas le focus de la case à cocher. Par conséquent, vous devrez le défocaliser explicitement à l'aide de la méthode HTMLElement.blur() ou en mettant en évidence un autre élément pour empêcher la saisie par clé si la case est l'élément actif. au moment où l'attribut est ajouté. Que la case à cocher soit l'élément ciblé ou non peut être testé avec my_checkbox.isEqualNode(document.activeElement).

0
Patrick Dark