2010-01-19 17 views
9

Tengo un select multiple Campo de entrada estándar HTML, por ejemplo:¿Cómo se alterna la selección de una opción en una selección múltiple con jQuery?

<select multiple="multiple" size="5" id="mysel" name="countries"> 
    <option value="2">Afghanistan</option> 
    <option value="4">Aland</option> 
</select> 

ya que es una selección múltiple, para seleccionar más de un valor que hay que mantener pulsada la tecla CTRL y seleccione los elementos adicionales. Sin embargo, lo que quiero lograr es que:

  1. Al hacer clic en una opción no seleccionada, ésta se selecciona
  2. Al hacer clic en la opción seleccionada anula la selección de la misma.

La idea es evitar tener que pulsar la tecla CTRL y cambiar la semántica de uso de este campo de entrada. Los elementos solo deben poder seleccionarse y no seleccionarse al hacer clic (es decir, al alternar entre los estados de selección).

Todavía no he podido implementar esto. El pseudo-código debería verse más o menos así.

  1. Catch a Click event.
  2. Compruebe si el elemento al que se hizo clic no estaba seleccionado, luego selecciónelo
  3. O, si el elemento que se hizo clic fue seleccionado, desáréguelo.

¿Cómo debo implementar esto?

Respuesta

11

Usted puede utilizar el siguiente fragmento de lograr el efecto deseado

$("select[multiple] option").mousedown(function(){ 
    var $self = $(this); 

    if ($self.prop("selected")) 
      $self.prop("selected", false); 
    else 
     $self.prop("selected", true); 

    return false; 
}); 

En las versiones anteriores de jQuery, donde prop() no estaba disponible:

$("select[multiple] option").mousedown(function(){ 
    var $self = $(this); 

    if ($self.attr("selected")) 
      $self.attr("selected", ""); 
    else 
     $self.attr("selected", "selected"); 

    return false; 
}); 
+0

Hola TB, ¡Ohh, gracias Million Times !!!! ¡Estupendo! ¡Esto es lo que quería lograr! ¡¡Muchas gracias!! – tim

+3

Sería más conciso hacer '$ self.prop ('selected',! $ Self.prop ('selected'));'. – nilskp

+2

@nilskp también considera '' '$ self.prop ('selected', function (i, old) {! Old});' '' – MoMolog

4

Tiene razón al querer cambiar el comportamiento predeterminado de seleccionar múltiples campos de entrada. Tienden a contribuir negativamente a la experiencia del usuario ya que el propósito no se transmite con claridad y los usuarios pueden no entender cómo usarlos correctamente.

Volver a proponer un cuadro de selección múltiple tampoco está bien. Si está considerando usar seleccionar múltiples, entonces puede que desee refactorizar su diseño. ¿Quizás pueda usar casillas de verificación en su lugar?

He aquí un artículo sobre el tema: http://www.ryancramer.com/journal/entries/select_multiple/

+0

Hola 2020vert. Gracias por tu rápida respuesta. Eso es bastante divertido, la técnica que usted señaló que ya leí (en parte), ya que me metí en este artículo buscando una solución para mi problema. Sería genial encontrar una solución según lo solicitado con el "cambio" del estado. Creo que de alguna manera esto debería ser posible, pero lamentablemente no hay una forma sencilla de consultar el estado de seleccionar/deseleccionar ... gracias – tim

1

Probablemente alguna corrección viene con las nuevas versiones de jQuery:

$("select[multiple] option").mousedown(function(){ 
    var $self = $(this); 

    if ($self.attr("selected")){ 
     $self.removeAttr("selected"); 
    } else { 
     $self.attr("selected", "selected"); 
    } 
    return false; 
}); 
2

Otra variante sin jQuery:

var multiSelect = {}; 

function init() {  
    var s = document.getElementsByTagName('select'); 
    for (var i = 0; i < s.length; i++) { 
    if (s[i].multiple) { 
     var n = s[i].name; 
     multiSelect[n] = []; 
     for (var j = 0; j < s[i].options.length; j++) { 
     multiSelect[n][j] = s[i].options[j].selected; 
     } 
     s[i].onclick = changeMultiSelect; 
    } 
    } 
} 

function changeMultiSelect() { 
    var n = this.name; 
    for (var i=0; i < this.options.length; i++) { 
    if (this.options[i].selected) { 
     multiSelect[n][i] = !multiSelect[n][i]; 
    } 
    this.options[i].selected = multiSelect[n][i]; 
    } 
} 

window.onload = init; 
0

usando jQuery 1.9.1 del código JavaScript es:

$("select[multiple] option").mousedown(function() { 
     var $self = $(this); 
     if ($self.prop("selected")) 
      $self.removeAttr("selected"); 
     else 
      $self.attr("selected", "selected"); 
     return false; 
    }); 
4

simplemente he intentado esta solución y la respuesta seleccionada no funcionó para jQuery 1.9.1

La respuesta de Oscar parecía mucho mejor, pero las propiedades mixtas con atributos y no funciona si se selecciona, de-seleccione a continuación, tratar de seleccionar de nuevo, ya que pone al selecto en un estado inutilizable

he encontrado la respuesta correcta para mí fue la siguiente

$("select[multiple] option").mousedown(function() { 
     if ($(this).prop("selected")) 
      $(this).prop("selected", false); 
     else 
      $(this).prop("selected", true); 
     return false; }); 

espero que esto ayuda a los demás;)

+0

Parece que la respuesta aceptada fue editada por ninja para copiar tu respuesta, pero supongo que no sé lo que era antes. – PrinceTyke

+0

Al menos a alguien le gustó mi solución lo suficiente como para copiar, supongo;) lástima de la historia de la pregunta y de cualquier usuario futuro atascado en pre 1.9.1 jQuery, Thx para notar @PrinceTyke – duindain

1

Javascript (jQuery sin):

var select = document.getElementById('mysel'); 
select.addEventListener('mousedown', function(e){ 
    var opt = e.target; 
    if (opt.selected){ 
     opt.removeAttribute('selected'); 
     opt.selected = false; 
    } else { 
     opt.setAttribute('selected', ''); 
     opt.selected = true; 
    } 
    e.preventDefault(); 
}); 

Veo que la mayoría de las respuestas anteriores vinculan el evento con la opción en lugar de seleccionar. Si mi selección tiene 1000 opciones, se vincularán 1000 eventos, ¿afectará el rendimiento?

Debido a esto, también decido no vincular mi evento en la opción.

Cuestiones relacionadas