2010-07-26 6 views
2

J'ai créé un formulaire avec Formulaire Plugin malsup dans lequel il soumet à la modification des entrées. J'ai mis en place mon script jQuery pour indexer les menus déroulants et les entrées visibles, et utilise cet index pour déterminer si keydown of tab devrait déplacer focus sur l'élément suivant ou le premier élément, et de même avec shift + tab keydown. Cependant, au lieu de déplacer le focus sur le premier élément du dernier élément sur le clavier comme je le souhaite, il déplace le focus sur le second élément. Comment puis-je le changer pour mettre le focus sur le premier et le dernier élément? Voici un lien direct vers mon formulaire: http://www.presspound.org/calculator/ajax/sample.php. Merci à tous ceux qui essaient d'aider. Voici mon script:Cycle Focus vers le premier élément de formulaire à partir du dernier élément et Vice Versa

$(document).ready(function() { 
var options = { 
    target: '#c_main', 
    success: setFocus 
}; 
$('#calculator').live('submit', function() { 
    $(this).ajaxSubmit(options); 
    return false; 
}); 
$(this).focusin(function(event) { 
    var shiftDown = false; 
    $('input, select').each(function (i) { 
     $(this).data('initial', $(this).val()); 
    }); 
    $('input, select').keyup(function(event) { 
     if (event.keyCode==16) { 
      shiftDown = false; 
      $('#shiftCatch').val(shiftDown); 
     } 
    }); 
    $('input, select').keydown(function(event) { 
     if (event.keyCode==16) { 
      shiftDown = true; 
      $('#shiftCatch').val(shiftDown); 
     } 
     if (event.keyCode==13) { 
      $('#captured').val(event.target.id); 
     } else if (event.keyCode==9 && shiftDown==false) { 
      return $(event.target).each(function() { 
       var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible'); 
       var index = fields.index(this); 
       var nextEl = fields.eq(index+1).attr('id'); 
       var firstEl = fields.eq(0).attr('id'); 
       var focusEl = '#'+firstEl; 
       if (index>-1 && (index+1)<fields.length) { 
        $('#captured').val(nextEl); 
       } else if(index+1>=fields.length) { 
        if ($(this).val() != $(this).data('initial')) { 
         $('#captured').val(firstEl); 
        } else { 
         event.preventDefault(); 
         $(focusEl).focus(); 
        } 
       } 
       return false; 
      }); 
     } else  if (event.keyCode==9 && shiftDown==true) { 
      return $(event.target).each(function() { 
       var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible'); 
       var index = fields.index(this); 
       var prevEl = fields.eq(index-1).attr('id'); 
       var lastEl = fields.eq(fields.length-1).attr('id'); 
       var focusEl = '#'+lastEl; 
       if (index<fields.length && (index-1)>-1) { 
        $('#captured').val(prevEl); 
       } else if (index==0) { 
        if ($(this).val() != $(this).data('initial')) { 
         $('#captured').val(lastEl); 
        } else { 
         event.preventDefault(); 
         $(focusEl).select(); 
        } 
       } 
       return false; 
      }); 
     } 
    }); 
}); 

}); function setFocus() { avec (document.calculator) var recap = document.getElementById (recaptured.value); si (récapituler! = Null) { setTimeout (function() { if (recap.getAttribute ('type') == 'text') { recap.select();} else { recap.focus () } }, 100); }}

Edit # 1: J'ai fait quelques modifications mineures au code, ce qui m'a apporté un peu plus de ma fonctionnalité prévue du script. Cependant, j'ai seulement fait un changement au code relatif à la mise au point: j'ai essayé de désactiver la touche de tabulation quand on appuie sur le dernier élément (et aussi le décalage + tabulation sur le premier élément) pour essayer de forcer le focus l'élément que je veux sans le sauter comme il l'a fait. C'est le code que j'ai ajouté:

$(this).one('keydown', function (event) { 
    return !(event.keyCode==9 && shiftDown==true); 
}); 

Ce type de travaux. Après le chargement de la page, si l'utilisateur appuie sur l'onglet sur le dernier élément sans modifier sa valeur, le focus sera défini sur le deuxième élément. Cependant, la deuxième fois que l'utilisateur appuie sur l'onglet sur le dernier élément sans modifier sa valeur, et chaque fois par la suite, le focus sera placé sur le premier élément, comme je le souhaite.

Modifier # 2: J'ai remplacé le code dans l'édition n ° 1, avec du code utilisant event.preventDefault(), qui fonctionne mieux. Alors que si un utilisateur fait un shift + tab keydown dans le premier élément, le focus se déplace vers le dernier élément comme il se doit. Cependant, si l'utilisateur continue de maintenir la touche Maj enfoncée et appuie de nouveau sur la touche, la mise au point sera rétablie sur le premier élément. Et si l'utilisateur continue de maintenir la touche Maj encore enfoncée et touche l'onglet, le focus revient au dernier élément. La mise au point se déplace entre le premier et le dernier élément jusqu'à ce que l'utilisateur lève la touche Maj. Ce problème ne se produit pas en appuyant uniquement sur l'onglet. Voici le nouvel extrait de code:

event.preventDefault(); 
$(focusEl).focus(); 

Répondre

1

Voici la solution, que je n'aurais pas pu atteindre sans l'aide de Simen. Merci encore, Simen.

$(document).ready(function() { 
    var options = { 
     target: '#c_main', 
     success: setFocus 
    }; 
    $('#calculator').live('submit', function() { 
     $(this).ajaxSubmit(options); 
     return false; 
    }); 
    $(this).focusin(function(event) { 
     $('#calculator :input:visible').each(function (i) { 
      $(this).data('initial', $(this).val()); 
     }); 
     return $(event.target).each(function() { 
      $('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){ 
       var elements = $("#calculator :input:visible"); 
       var n = elements.length; 
       var currentIndex = elements.index(this); 
       if (event.keyCode == 13) { //if enter 
        var focusElement = elements.eq(currentIndex).attr('id'); 
        $('#captured').val(focusElement); 
       } else if (event.keyCode == 9) { //if tab 
        var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n; 
        var el = elements.eq(newIndex); 
        var focusElement = el.attr('id'); 
        if ($(this).val() != $(this).data('initial')) { 
         $('#captured').val(focusElement); 
        } else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) { 
         event.preventDefault(); 
         if (el.attr('type')=='text') { 
          $.browser.msie ? "" : $(window).scrollTop(5000); 
          el.select().delay(800); 
         } else { 
          $.browser.msie ? "" : $(window).scrollTop(-5000); 
          el.focus().delay(800); 
         } 
        } else if (el.is('select')) { 
         event.preventDefault(); 
         if (el.attr('type')=='text') { 
          el.select(); 
         } else { 
          el.focus(); 
         } 
        } 
       } 
      }); 
     }); 
    }); 
}); 

function setFocus() { 
    with (document.calculator) 
    var recap = document.getElementById(recaptured.value); 
    if (recap!=null) { 
     setTimeout(function() { 
      if (recap.getAttribute('type')=='text') { 
       recap.select(); 
      } else { 
       recap.focus(); 
      } 
     }, 1 ); 
    } 
} 

Je mis mes fichiers disponibles en téléchargement dans mon lien direct: http://www.presspound.org/calculator/ajax/sample.php

1

Vous avez beaucoup de code que je n'ai pas aperçu complet sur, donc je ne sais pas si je manqué certaines fonctionnalités que vous vouliez intégré, mais pour le tabbing/changement -tabbing à travers des éléments de formulaire, ce qui devrait faire le travail:

var elements = $("#container :input:visible"); 
var n = elements.length; 
elements 
.keydown(function(event){ 
    if (event.keyCode == 9) { //if tab 
     var currentIndex = elements.index(this); 
     var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n; 
     var el = elements.eq(newIndex); 
     if (el.attr("type") == "text") 
      elements.eq(newIndex).select(); 
     else 
      elements.eq(newIndex).focus(); 
     event.preventDefault(); 
    } 
}); 

elements sera l'objet jQuery contenant tous les champs d'entrée, dans mon exemple, il est tous les champs d'entrée à l'intérieur du div #container Voici une démo: http://jsfiddle.net/rA3L9/

+0

Merci pour votre réponse, Simen. Votre script fonctionne parfaitement pour la mise au point cyclique à travers les éléments de formulaire lorsque l'utilisateur ne change pas les valeurs des entrées. Cependant, l'une des fonctions clés de mon formulaire est qu'il doit être soumis lors d'un changement, puis réappliquer le focus sur l'élément correct lors du rappel post-envoi. J'accomplissais cela en capturant l'ID de l'élément correct dans un champ de texte, en publiant cette valeur dans un autre champ de texte, puis en appelant une fonction pour utiliser cette valeur pour appliquer le focus à l'élément correct pendant le rappel. – Daniel

+0

Peut-être n'a-t-il pas répondu exactement à la question OP, mais comme solution générale, c'est génial! Je me débattais avec ce comportement étrange (se concentrer sur le deuxième contrôle au lieu de la première). Merci, Simen! –

Questions connexes