2010-11-21 22 views
8

Tengo este sencillo jQuery UI Slider configuración con un rango y dos valores predeterminados que se superponen. La cosa entera (con algunas campanas y silbidos) se puede encontrar en este jsFiddle: http://jsfiddle.net/yijiang/XeyGS/jQuery UI controles deslizantes: seleccione la superposición de controles deslizantes en función de la dirección de arrastre

$('#slider').slider({ 
    min: 1, 
    max: 11, 
    range: true, 
    values: [4, 4] 
}); 

El problema con esto es que cuando se intenta el arrastre el tirador visible solo a la derecha, se produce un error, porque jQuery UI siempre coloca el mango mínimo en la parte superior. Esto es obviamente malo, por varias razones.

¿Hay alguna manera de permitir que la interfaz de usuario de jQuery elija qué dispositivo arrastrar según la dirección en la que el usuario comienza a arrastrar?

+0

Acabo de actualizar mi respuesta, consulte [aquí] (http://stackoverflow.com/questions/14091747/ui-slider-overlapping-slider-impossible-to-drag/38743988#38743988) –

Respuesta

2

Yo diría que esto es un error, por partida doble, porque ya hay lógica de la prevención de un 'callejón sin salida' suceda cuando ambos mangos deslizantes están en la posición mínima y/o de la izquierda:

// workaround for bug #3736 (if both handles of a range are at 0, 
// the first is always used as the one with least distance, 
// and moving it is obviously prevented by preventing negative ranges) 
if(o.range === true && this.values(1) === o.min) { 
    index += 1; 
    closestHandle = $(this.handles[index]); 
} 

Parece que ticket #3736 todavía está abierto, mencionando el problema específico que estás viendo.

6

Ah, me gusta comer a través de 11k libs, ¿no es así? :)

Nota: La siguiente es para jQuery UI 1.8.5

De todas formas, he aquí una solución bastante limpio:

// add some stuff to the slider instance 
this._handleIndex = null; 
this._handleStartValue = -1; 

// remember the starting values in _mouseCapture 
this._handleStartValue = this.values(this._handleIndex); 
this._mouseDownOffset = this._normValueFromMouse({ x: event.pageX, y: event.pageY }); 


// modify _mouseDrag 
oldValue = this.values(this._handleIndex), 
curValue; 

curValue = this.values(this._handleIndex); 
if (curValue === oldValue && this._handleStartValue !== -1) { 
    if (normValue - this._mouseDownOffset > 0 
     && (curValue === this.values((this._handleIndex + 1) % 2)) 
     && oldValue === this._handleStartValue) { 

     this._handleIndex = (this._handleIndex + 1) % 2; 
    } 

} else { 
    this._handleStartValue = - 1 
} 

// reset everything in _mouseStop 
this._handleIndex = null; 
this._handleStartValue = -1; 

Y eso es todo lo que hay que hacer, oh, cómo funciona Por supuesto:

  1. Guardar el desplazamiento, así como el valor del puntero del ratón a partir seleccionar inicialmente manejar
  2. Al arrastrar, compare el valor anterior con el valor actual del asa activa y también compruebe si la posición de inicio es válida
  3. En caso de que no haya diferencia, verificamos si hubiera una diferencia si el asa activa pudiera arrastrarse
  4. Si ese es el caso, comprobar si las dos asas tienen el mismo valor, eso significa que son una encima de la otra
  5. Ahora comprobamos si el mango del seleccionado en ese momento no ha sido arrastrado todavía
  6. Y, por último, si todo eso es cierto, cambiamos las asas
  7. En caso de que el usuario ahora cambie el valor invalidamos nuestra posición de inicio O que no hay más de conmutación entre los mangos

Y para su placer aquí hay un diff:

9960c9960,9962 
< 
--- 
>  
>  this._handleIndex = null; 
>  this._handleStartValue = -1; 
10215a10218,10219 
>   this._handleStartValue = this.values(this._handleIndex); 
>  this._mouseDownOffset = this._normValueFromMouse({ x: event.pageX, y: event.pageY }); 
10243c10247,10249 
<   normValue = this._normValueFromMouse(position); 
--- 
>   normValue = this._normValueFromMouse(position), 
>   oldValue = this.values(this._handleIndex), 
>   curValue; 
10246c10252,10263 
< 
--- 
>  curValue = this.values(this._handleIndex); 
>  if (curValue === oldValue && this._handleStartValue !== -1) { 
>   if (normValue - this._mouseDownOffset > 0 
>    && (curValue === this.values((this._handleIndex + 1) % 2)) 
>    && oldValue === this._handleStartValue) { 
>    
>    this._handleIndex = (this._handleIndex + 1) % 2; 
>   } 
>   
>  } else { 
>   this._handleStartValue = - 1 
>  } 
10257a10275,10276 
>  this._handleStartValue = -1; 
>  this._handleIndex = null; 

Guardar a ui.diff luego hacer patch -i ui.diff jquery-ui.js.

4

Con disculpas a Ivo allí, de los cuales estoy seguro que me costó mucho crear excellent answer. El problema es que no pude aplicar esa solución, porque ya estoy en 1.8.6, no puedo encontrar las fuentes 1.8.5 en ninguna parte para aplicarla, y de alguna manera simplemente no pude hacer que el parche funcione para 1.8.6, incluso cuando intenté agregar las líneas manualmente.

La siguiente es mi solución al problema. Es más simple que Ivo, pero eso podría deberse a las diferencias entre los dos puntos de lanzamiento. La solución es la siguiente:

  1. empalme en una variable adicional para realizar un seguimiento de los valores originales
  2. Cuando se cumplen las condiciones, (dos asas, el mismo valor, el nuevo valor mayor que la corriente), para voltear una variable interna (_handleIndex) alrededor, lo que provoca que el identificador máximo se use como referencia para la función interna _slide en lugar de la primera.

El diff es el siguiente:

46a47,48 
>  
>  this._originalVal; 
310a313,314 
>  
>  this._originalVal = this.values(); 
323a328,331 
>  
>  if(this._originalVal[0] === this._originalVal[1] && normValue > this._originalVal[0]){ 
>   this._handleIndex = 1; 
>  } 

La primera parte se debe insertar en la zona de la inicialización, donde se declaran las variables, el segundo en la función _mouseCapture justo antes de la llamada a _slide, y la última parte en la función _mouseDrag, también justo antes de llamar a _slide.

Aquí está un ejemplo de trabajo con el parche: http://www.jsfiddle.net/HcGXZ/

Una copia del archivo 1.8.6 deslizante jQuery UI parcheado se puede encontrar aquí: http://dl.dropbox.com/u/1722364/jQuery%20UI%20Slider%20Patch/jquery.ui.slider.patched.js

Como siempre, este parche no ha sido ampliamente probado y no se garantiza que funcione para todos los escenarios.

+0

Impresionante, solo utilizada esto, con la adición de la respuesta del Dr. Gibbs (http://stackoverflow.com/a/5901216/892397) en la última interfaz de usuario jQuery (1.8.18). ¡Gracias! – dazbradbury

2

me trataron con Yi Jiang's solution 1.8.12 y se rompió en una corredera con una sola asa, pero funcionó a la perfección después de cambiar

this._originalVal = this.values(); 

a

this._originalVal = this.options.values === null ? this.value() : this.values(); 
1

Otra solución: prueba para ambos valores y si son lo mismo, regrese al último paso.

$("#slider").slider({ 
      range:true, 
      min:0, 
      max:250, 
      step: 25, 
      slide: function(event, ui) { 
       if (ui.values[0] == ui.values[1]){ 
        return false; 
       }else{ 
        $("#amount").html("&euro;" + ui.values[0] + " - &euro;" + ui.values[1]); 
       } 
      } 
     }); 
2

poner esto en el área de inicialización, donde se declaran las variables:

this._originalVal; 

Pon esto en _mouseCapture la función justo antes de la llamada a _slide:

this._originalVal = this.values(); 

Y esto en la función _mouseDrag, también justo antes de la llamada a _slide

if (this._originalVal[0] === this._originalVal[1] 
     && normValue > this._originalVal[0]) { 
    this._handleIndex = 1; 
} else if (this._originalVal[0] === this._originalVal[1] 
      && normValue < this._originalVal[0]) { 
    this._handleIndex = 0; 
} 

Acabo de añadir un else if que el código anterior; funciona bien en jQuery 1.8.14 para manejadores de botón izquierdo y derecho.

Cuestiones relacionadas