2009-09-06 15 views
5

Quiero permitir que el usuario haga clic en un punto de inicio y luego haga clic en un punto final y pueda manipular varios elementos de formulario entre los dos puntos que se seleccionaron.¿Cómo atravesaría elementos entre dos elementos conocidos en la dom usando jquery?

La página es una tabla con numerosas filas y cada fila contiene la información relevante para manipular/guardar una respuesta a la pregunta en esa fila. Cada fila tiene una entrada oculta para el valor, así como botones de opción Sí/No, principalmente para usuarios no capacitados. La celda TD con la pregunta permite al usuario hacer clic o alternar entre Sí, No, Vacío. Básicamente dejé los botones de opción en la página para mostrar Sí/No y uso un campo oculto para almacenar un valor de (1,0, -1)

Esto es lo que uso para establecer la respuesta cuando la celda de pregunta se hace clic.

$(".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); 
    }); 

Ahora quiero permitir que el usuario haga clic en un punto de partida y tienen que rellenar toda respuesta a la siguiente pregunta hasta donde se hace clic sobre el segundo punto. Podría estar a 10 preguntas de distancia, o 20 preguntas, es una variable desconocida. Puede haber una página con 130 preguntas y 20 preguntas seguidas pueden ser "Sí". Como se indicó anteriormente, cada fila tiene una celda de "Pregunta" y la celda anterior es la celda del elemento.

Sé cómo establecer el elemento de inicio y el elemento de finalización basado en un selector/función jquery vinculado a un evento click/dblclick enumerado a continuación.

Lo que no estoy seguro es cómo atravesar el dom o seleccionar todos los elementos que necesito manipular entre los dos puntos seleccionados en la página.

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); 
     } 
    }); 

Respuesta

2

La mejor manera en mi humilde opinión es hacer algo como a continuación. Puede recorrer la colección de elementos con el nombre de clase "elemento" y cuando encuentre su elemento de inicio puede comenzar a hacer el procesamiento que describió. Como tiene 'esto', puede tomar esa identificación y hacer lo que estaba haciendo en su función 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

Pude utilizar esto para hacer lo que necesitaba. – Breadtruck

0

Parece que la forma más simple sería agregar una clase de inicio al elemento de inicio y una clase de fin al elemento de fin. Luego, al atravesar los elementos entre el inicio y el final, puede verificar el nombre de la clase de inicio o fin y realizar/evitar las acciones apropiadas.

EDIT:

Algo como este plugin lo hará. El complemento supone que ambos elementos que definen los límites del rango tienen el mismo elemento primario y son del mismo tipo de elemento (nodeName). Puede usar sus propios nombres de clase de inicio y finalización, o simplemente usar el predeterminado 'inicio' y 'final'.

(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); 

y luego se puede utilizar como tal

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

Aquí hay una Working Demo. Si desea ver el código, agregue /edit al final de la URL. Estaba pensando en escribir una utilidad para devolver un objeto jQuery basado en los parámetros startClass, endClass y element type para incluir, pero eso sería excesivo para lo que necesita.

EDIT 2:

A la luz de su comentario, puedo hablar a través de él

  1. conseguir un objeto jQuery que contiene los elementos en cuestión que en su caso creo que es entradas de texto , por lo que sería algo como $('parent > input:text') donde parent es el elemento principal (entrada de entrada: el texto por sí solo no funcionará correctamente si tiene otras entradas de texto en la página fuera del elemento principal ya que el complemento se basa en índices).

  2. Puede pasar de un objeto opciones a rangeSelector con diferentes nombres de inicio y fin de la clase si quieres (como .rangeSelector({ start: "myStartClass", end: "myEndClass"}), o simplemente utilizar el valor por defecto start y end en cuyo caso no es necesario pasar en cualquier objeto.

  3. la variable de configuración fusiona los valores por defecto (que se definen como propiedades de un objeto) con las propiedades de la aprobada en opciones objeto (o un objeto sin propiedades si no se define ningún objeto opción).

  4. calcular el tipo de elementos con los que tratamos en el objeto jQuery y almacenarlos en name variable. Esto se hace dividiendo la cadena nodeName del primer elemento en el objeto jQuery en una matriz y asignando nombre al valor del último elemento de cadena en la matriz.

  5. Calcule los índices de inicio y final de los elementos marcados con start y . El índice en este caso se refiere a la posición basada en 0 del elemento dentro de su elemento primario.

  6. devuelva solo los elementos en el objeto jQuery entre el índice inicial y el final (inclusive) como un objeto jQuery (para que puedan encadenarse más comandos jQuery). Utiliza el comando slice(), que funciona igual en un objeto jQuery que Array.slice() en las matrices.

+0

Así qué método utilizaría para atravesar, sé lo que es el eleme porque estoy estableciendo el elemento de inicio y fin dentro de mi código. – Breadtruck

+0

@Russ: utilicé el código de Matt para hackear lo que tenía que hacer, pero volveré a revisar tus cosas, ¡porque tu camino podría ser una solución más elegante una vez que tenga tiempo para pensarlo bien! – Breadtruck

0

La pregunta es un poco viejo, pero aquí está la solución que utilizo para mis proyectos:

selector jQuery

(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); 

Uso

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