2017-08-29 3 views
1

Cela peut être une question stupide. Je sais que je suis un peu vert. J'étais chargé de modifier la navigation de ce vieux système. Il y a deux barres de navigation. Le second n'a que des boutons de recherche. On m'a demandé de retirer la deuxième barre de navigation, et de la remplacer par une liste déroulante affichant les fonctions de recherche. Je suis limité sur ce que je peux changer en raison de l'âge de ce système. Il n'y a aucune restriction sur le JS que je peux écrire. Ils exécutent jQuery 1.11.1, sur un système Adobe ColdFusion (il y a deux mois, ils sont passés de 1.3.2)plusieurs événements simultanés javascript

Premièrement: lorsque la cible est cliquée, le mouseenter et l'événement click se déclenchent. Le mouseenter tire d'abord. Cela provoque un problème sur un bureau qui est visible pour le spectateur vif, mais sur mobile, cela crée un problème d'utilisabilité horrible. R: D'après ce que je comprends, les événements souris ne se produisent pas sur un appareil mobile, mais le font pour moi. Et B: puisque l'événement mouseenter s'exécute en premier, il active la fonction closeDropDown avant le traitement de l'événement click. Avec le closeDropDown en cours d'exécution, son .on('click', f(...eventstuff...)) entend le clic ouvert qui est destiné à déclencher la fonction openDropDown, ainsi la liste déroulante ne s'ouvre pas.

Voici les fonctions. Les console.log sont pour vérifier ce qui fonctionne quand.

function openDropDown(){ 
    $('div.dropdown').parent().on('click.open mouseenter', function(event){ 

     $subject = $(this).find('.dropdown-menu') 
     // console.log(event.type, $subject, "first o"); 

     if(!$subject.is(":visible")){ 
      // console.log($subject, 'second o'); 

      $subject.show() 
     }else { 
     if(event.type == 'click'){ 
      // console.log('third o'); 

      $subject.toggle() 
     } 
    } 

    closeDropDown($subject) 
    // console.log('open complete'); 
}) 
} 


function closeDropDown($x){ 
    // console.log('first c'); 

    $(document).on("click.close",function(e){ 
     // console.log("second c", e.type, "this type"); 

     if(!$(e.target).closest(".dropdown-menu").parent().length){ 
      // console.log("third c"); 

      if($x.is(":visible")){ 
       // console.log('forth c'); 
       $x.hide() 
      } 
     } 

     $(document).off("click.close") 
     // console.log('complete close'); 
    }) 
} 

openDropDown() 
onSearchClick() 

J'ai lu quelques messages dans l'espoir d'une aide (comme this et that

l'ensemble, je sais que je dois condenser mon code. Je comprends quelques façons de résoudre ce (ajouter un if(... are we on a mobile device...) ou d'un compteur/vérifier qui empêche la closeDropDown de fonctionner lorsque le menu déroulant est fermé)

Je veux vraiment comprendre les fondamentaux des auditeurs d'événement et pourquoi on court avant les autres choses.

Bien que les suggestions sur la façon de résoudre ce problème soient excellentes, je cherche à comprendre les principes fondamentaux de ce que je fais de mal. Tout pointeur fondamental est très utile.

De note: Je viens de lire ceci: .is(':visible') not working. Je vais réécrire le code sans le .is ('visible').

Autres éléments pouvant vous aider: Il s'agit de la console Chrome Dev Tools lorsque tous mes fichiers console.log sont actifs. Tout d'abord, cliquez après le chargement de la page .... enter image description here La liste déroulante s'ouvre et se ferme rapidement.

Deuxième clic .... enter image description here

Merci! Toute votre aide est appréciée!

Répondre

1

Ceci est une question assez vaste. Je vais essayer d'être concis. Je ne pense pas que ColdFusion devrait être étiqueté ici, car il semble que cela ne concerne que HTML/CSS/JS.

Events Configuration

D'abord, je voudrais aborder la façon dont vous avez configuré votre script. Vous apprécieriez probablement de regarder la gestion des événements examples from jquery.

La plupart des personnes créeront des événements tels que les suivants. Il dit simplement que sur un clic pour tout élément du document avec l'ID de "alerter", exécutez la fonction d'alerte.

// Method 1 
$(document).on(click, "#alerter", function(event){ 
    alert("Hi!"); 
}); 

OU

// Method 2 
$(document).on("click", "#alerter", ClickAlerter); 

function ClickAlerter(event) { 
    alert("Hi!"); 
} 

Les deux méthodes sont totalement valables. Cependant, c'est mon opinion que la deuxième méthode est plus lisible et maintenable. Il sépare la délégation d'événement de la logique.

Pour votre code, je recommande fortement de supprimer le mélange de l'attribution d'événements et de la logique. (Il supprime au moins une couche d'imbrication). Par ailleurs, vos écouteurs d'événement ne semblent pas être configurés correctement. Voir the correct syntax et cet exemple de jQuery.

$("#dataTable tbody").on("click", "tr", function() { 
    console.log($(this).text()); 
}); 

En ce qui concerne plusieurs événements

Si vous avez des écouteurs d'événements multiples sur un objet, puis ils seront renvoyés dans l'ordre où ils sont enregistrés. This SO question couvre déjà cela et fournit un exemple.

Cependant, cela ne signifie pas qu'un clic se produira avant un mouseenter. Parce que votre souris doit littéralement entrer dans l'élément pour pouvoir cliquer dessus, l'événement pour mouseenter va être déclenché en premier. En d'autres termes, vous avez au moins 2 facteurs en jeu en pensant à l'ordre des événements.

  1. L'ordre dans lequel le navigateur se déclenche les événements
  2. L'ordre dans lequel ils ont été enregistrés

À cause de cela, il n'y a pas vraiment une chose telle que des événements « simultanés », en soi. Les événements sont déclenchés lorsque le navigateur veut les déclencher, ils passent en revue les événements et lancent les correspondances dans l'ordre que vous leur avez assigné.

Vous avez toujours l'option preventDefault et stopPropagation pour ce type d'événements si vous souhaitez modifier le comportement d'événement par défaut. Cela arrêtera l'action par défaut du navigateur et empêchera l'événement de bouillonner vers les éléments parents, respectivement.

En ce qui concerne Mobile Mouse Events

Les événements de souris absolument se produisent sur les appareils mobiles, et il est dangereux de supposer qu'ils ne le font pas. This article couvre en profondeur la portée des événements qui se déclenchent. Pour citer:

«[Y] vous devez être prudent lors de la conception d'interactions tactiles plus avancées: lorsque l'utilisateur utilise une souris, il répond par un clic, mais lorsque l'utilisateur touche l'écran, touchez et cliquez . événements se produiront pour un seul clic l'ordre des événements est:

touchstart 
touchmove 
touchend 
mouseover 
mousemove 
mousedown 
mouseup 
click 

Je pense que vous pourriez bénéficier de la lecture de cet article Il traite des problèmes et des concepts communs concernant les événements dans des environnements mobiles et non mobiles..Encore une fois, une déclaration pertinente sur votre situation:

Il est intéressant, cependant, le CSS: hover pseudo-classe peut être déclenchée par des interfaces tactiles dans certains cas - en tirant parti d'un élément permet: actif tandis que le doigt est vers le bas, et acquiert également l'état: hover. (Avec Internet Explorer, le: hover est seulement en effet alors que le doigt de l'utilisateur est en panne - les autres navigateurs gardent le: hover en vigueur jusqu'à la prochaine prise ou déplacement de la souris.)

Exemple

J'ai pris tous ces concepts et made an example on jsFiddle pour vous montrer certaines de ces choses en action. Fondamentalement, je suis en train de détecter si l'utilisateur utilise un écran tactile en écoutant l'événement touchstart et en gérant le click différemment dans ce cas. Parce que je n'ai pas votre HTML, j'ai dû créer une interface primitive. Ce sont les directives:

  1. Nous devons déterminer si l'utilisateur dispose d'un écran tactile
  2. Lorsque l'utilisateur plane sur le bouton, le menu doit apparaître
  3. Sur un appareil mobile, lorsqu'un utilisateur robinets le bouton, le menu doit apparaître
  4. Nous devons fermer le menu lorsque l'utilisateur clique en dehors du bouton
  5. Quitter le bouton doit fermer le menu (mobile ou autre)

Comme vous le verrez, j'ai créé tous mes événements en un seul endroit:

$(document).on("mouseover", "#open", $app.mouseOver); 
$(document).on("mouseout", "#open", $app.mouseOut); 
$(document).on("click", "#open", $app.click); 
$(document).on("touchstart", $app.handleTouch); 
$(document).on("touchstart", "#open", $app.click); 

J'ai aussi créé un objet pour envelopper toute la logique, $app qui nous donne une plus grande flexibilité et la lisibilité sur la route . En voici un fragment:

var $app = $app || {}; 
$app = { 

    hasTouchScreen: false, 

    handleTouch:function(e){ 
    // fires on the touchstart event 
    $app.hasTouchScreen = true; 
    $("#hasTouchScreen").html("true"); 
    $(document).off("touchstart", $app.handleTouch);  
    }, 

    click: function(e) { 
    // fires when a click event occurrs on the button 
    if ($app.hasTouchScreen) { 
     e.stopPropagation(); 
     e.preventDefault(); 
     return; 
    } 

    // since we don't have a touchscreen, close on click. 
    $app.toggleMenu(true); 
    }, 

    touch: function(e) { 
    // fires when a touchstart event occurs on the button 
    if ($("#menu").hasClass("showing")) { 
     $app.toggleMenu(true); 
    } else { 
     $app.toggleMenu(); 
    }  
    } 

};