2009-09-06 16 views
5

Je souhaite autoriser l'utilisateur à cliquer sur un point de départ, puis à cliquer sur un point de fin et à pouvoir manipuler divers éléments de formulaire entre les deux points sélectionnés.Comment je traverserais des éléments entre deux éléments connus dans le dom en utilisant jquery?

La page est un tableau avec de nombreuses lignes et chaque ligne contient les informations pertinentes pour manipuler/enregistrer une réponse à la question dans cette ligne. Chaque ligne a une entrée cachée pour la valeur, ainsi que des boutons radio Oui/Non, principalement pour les utilisateurs non qualifiés. La cellule TD avec la question permet à l'utilisateur de cliquer ou de basculer entre Oui, Non, Vide. Donc, fondamentalement, j'ai laissé les boutons radio sur la page pour afficher Oui/Non et utiliser un champ caché pour stocker une valeur de (1,0, -1)

Ceci est ce que j'utilise pour définir la réponse lorsque la cellule de question est cliqué.

$(".question").bind("click dblclick", function(e) { 

     var newClassName = "AnswerUnknown"; 

     var hiddenAnswerId = $(this).attr('id').replace("question", "answer"); 

     var answer = parseInt($("#" + hiddenAnswerId).val()); 

     var newValue; 

     switch (answer) { 
      case -1: 
       newClassName = "AnswerCorrect"; 
       newValue = 1; 
       $("#" + $(this).attr('id').replace("answer", "radioYes")).attr('checked', 'checked'); 
       $("#" + $(this).attr('id').replace("answer", "radioNo")).attr('checked', ''); 
       break; 
      case 1: 
       newClassName = "AnswerWrong"; 
       newValue = 0; 
       $("#" + $(this).attr('id').replace("answer", "radioYes")).attr('checked', ''); 
       $("#" + $(this).attr('id').replace("answer", "radioNo")).attr('checked', 'checked'); 
       break; 
      default: 
       newClassName = "AnswerEmpty"; 
       newValue = -1; 
       $("#" + $(this).attr('id').replace("answer", "radioYes")).attr('checked', ''); 
       $("#" + $(this).attr('id').replace("answer", "radioNo")).attr('checked', ''); 
     } 
     $("#" + hiddenAnswerId).val(newValue); 
     $(this).removeClass().addClass(newClassName); 
    }); 

Maintenant, je veux permettre à l'utilisateur de cliquer sur un point de départ et ont cette réponse remplir toute la question suivante vers le bas à l'endroit où ils ont cliqué sur le deuxième point. Pourrait être 10 questions de suite, ou 20 questions, c'est une variable inconnue. Il peut y avoir une page avec 130 questions, et 20 questions d'affilée peuvent être "Oui". Comme indiqué ci-dessus chaque ligne a une cellule "Question" et la cellule avant que ce soit la cellule de l'élément.

Je sais comment définir l'élément de départ et l'élément final en fonction d'un sélecteur/fonction jquery lié à un événement click/dblclick répertorié ci-dessous. Ce dont je ne suis pas sûr, c'est comment traverser dom ou sélectionner tous les éléments dont j'ai besoin pour manipuler entre les deux points sélectionnés sur la page.

var StartItem; 
    var EndItem; 

    $(".item").bind("click dblclick", function(e) { 

     var StartClassName = "AnswerUnknown"; 
     var EndClassName = "AnswerUnknown"; 
     var StartAnswerId; 
     var EndAnswerId; 
     var StartAnswer; 

     if (StartItem === undefined) { 
      StartItem = this; 
      StartAnswerId = $(this).attr('id').replace("item", "rs"); 
      StartAnswer = parseInt($("#" + StartAnswerId).val()); 
     } 
     else { 
      if (EndItem === undefined) { 
       EndItem = this; 
       EndAnswerId = $(this).attr('id').replace("item", "rs"); 
       EndAnswer = parseInt($("#" + EndAnswerId).val()); 
      } 
     } 


     if (StartItem == this) { 
      $(this).removeClass().addClass(StartClassName); 
     } 

     if (EndItem == this) { 
      $(this).removeClass().addClass(EndClassName); 
     } 
    }); 

Répondre

2

La meilleure façon à mon humble avis est de faire quelque chose comme ci-dessous. Vous pouvez faire une boucle sur la collection d'éléments avec le nom de classe "item" et quand vous trouvez votre élément de départ, vous pouvez commencer le traitement que vous avez décrit. Puisque vous avez 'ceci' vous pouvez prendre cet identifiant et faire ce que vous faisiez dans votre fonction question.click.

 var counter = 0; 

    // This will loop over each element with classname "item", so make sure you take that into account 
      $('.item').each(function(i) { 
     // function returns this, but you can see what index your on with 'i' 
       if (this == StartItem) { 
        // You can start processing rows 
        counter = 1; 
       } 
       else { 
        if (counter > 0) { 
         // Process rows/items after the first item above 
         counter = counter + 1; 
        } 
       } 
       if (this == EndItem) { 
        counter = 0 
        // Finish up processing if any 
        //Break out of each; 
       } 

      }); 
+0

J'ai été capable d'utiliser ceci pour faire ce dont j'avais besoin. – Breadtruck

0

Il semble que la manière la plus simple serait d'ajouter une classe de début à l'élément de départ et une classe de fin à l'élément de fin. Ensuite, lorsque vous traversez les éléments entre le début et la fin, vous pouvez vérifier le nom du début ou de la fin et exécuter/empêcher les actions appropriées.

EDIT:

Quelque chose comme ce plugin va le faire. Le plugin suppose que les deux éléments qui définissent les limites de la plage ont le même parent et ont le même type d'élément (nodeName). Vous pouvez utiliser vos propres noms de classe de début et de fin, ou simplement utiliser les valeurs par défaut 'start' et 'end'.

(function($) { 

    $.fn.rangeSelector = function(options) { 

    var settings = $.extend({ startClass : 'start', endClass: 'end'},options||{}); 
    var name = this[0].nodeName.split(':'); 
    name = name[name.length -1]; 
    var startIndex = $(name + '.' + settings.startClass).prevAll().length; 
    var endIndex = $(name + '.' + settings.endClass).prevAll().length + 1; 
    return this.slice(startIndex,endIndex); 
    } 

})(jQuery); 

et vous pouvez utiliser comme si

/* 
* will get all textboxes between textboxes 
* with className start and end, inclusive 
*/ 
$('input:text').rangeSelector(); 

Voici un Working Demo. Si vous voulez voir le code, alors ajoutez /éditez à la fin de l'URL. Je pensais à écrire un utilitaire pour renvoyer un objet jQuery basé sur les paramètres startClass, endClass et element type à inclure, mais cela serait excessif pour ce dont vous avez besoin.

EDIT 2:

À la lumière de votre commentaire, je peux vous parler à travers elle

  1. obtenir un objet jQuery contenant les éléments en question qui, dans votre cas, je crois est entrées de texte parent est l'élément parent (passer en entrée: le texte ne fonctionnera pas correctement si vous avez d'autres entrées de texte dans la page en dehors de l'élément parent car le plugin repose sur des index).

  2. Vous pouvez passer dans un choix objectera à rangeSelector avec des noms de classe de début et de fin si vous voulez (comme .rangeSelector({ start: "myStartClass", end: "myEndClass"}), ou simplement utiliser la valeur par défaut start et end dans ce cas, vous n'avez pas besoin de passer dans un objet.

  3. la variable de paramètres fusionne les valeurs par défaut (qui sont définies comme les propriétés d'un objet) avec les propriétés du passé dans les options objet (ou un objet sans propriétés si aucun objet d'option est défini).

  4. calculer le type d'éléments que nous traitons dans l'objet jQuery et stocker dans name variable. Pour ce faire, divisez la chaîne nodeName du premier élément de l'objet jQuery en tableau et attribuez un nom à la valeur du dernier élément de chaîne dans le tableau.

  5. Calculez les index de début et de fin pour les éléments marqués avec les noms de classe start et end. L'index dans ce cas fait référence à la position 0 de l'élément dans son parent.

  6. renvoyer uniquement les éléments de l'objet jQuery entre l'index de début et de fin (inclus) en tant qu'objet jQuery (afin que d'autres commandes jQuery puissent être chaînées). Ceci utilise la commande slice(), qui fonctionne de la même manière sur un objet jQuery que Array.slice() sur les tableaux.

+0

Alors quelle méthode devrais-je utiliser pour traverser, je sais ce que l'eleme nts parce que je mets l'élément start et end dans mon code. – Breadtruck

+0

@Russ: J'ai utilisé le code de Matt pour bidouiller ce que j'avais besoin de faire, mais je reviendrai sur vos affaires, parce que votre chemin pourrait être une solution plus élégante une fois que j'aurai le temps d'y réfléchir! – Breadtruck

0

La question est un peu vieux, mais voici la solution que je l'utilise pour mes projets:

jQuery sélecteur

(function ($) { 
    $.fn.between = function (elm0, elm1) { 
     var index0 = $(this).index(elm0); 
     var index1 = $(this).index(elm1); 

     if (index0 <= index1) 
      return this.slice(index0, index1 + 1); 
     else 
      return this.slice(index1, index0 + 1); 
    } 
})(jQuery); 

Utilisation

$('body').between($('#someid'), $('#someid2')).each(function() { 
    // Do what you want. 
}); 
Questions connexes