HTML5: ¿Control deslizante con dos entradas posibles?

99

¿Es posible crear un control deslizante HTML5 con dos valores de entrada, por ejemplo, para seleccionar un rango de precios? Si es así, ¿cómo se puede hacer esto?

frecuente
fuente

Respuestas:

64

No, la entrada del rango HTML5 solo acepta una entrada. Le recomendaría que use algo como el control deslizante de rango jQuery UI para esa tarea.

Martín Buberl
fuente
Gracias por el enlace y la información. Tengo que comprobar si puedo ejecutar esto en dispositivos móviles.
frecuente el
33
Hace algún tiempo ... pero me las arreglé para "simular" un control deslizante doble colocando dos controles deslizantes exactamente uno encima del otro. Uno comienza en el valor mínimo, el otro comienza en el valor máximo. Supongo que es una trampa, pero ... funciona para mí.
frecuente
WhatWG está al menos discutiendo su implementación: html.spec.whatwg.org/multipage/…
kunambi
7
Me gusta ionRangeSlider un poco más que el control deslizante de jQuery UI: ionden.com/a/plugins/ion.rangeSlider/en.html
Charlotte
4
Otro enfoque consiste en "falsificar" el control deslizante doble con controles de entrada de lado a lado: simple.gy/blog/range-slider-two-handles
SimplGy
79

He estado buscando un control deslizante doble liviano y sin dependencias durante algún tiempo (parecía una locura importar jQuery solo para esto) y no parece haber muchos por ahí. Terminé modificando un poco el código de @ Wildhoney y me gustó mucho.

Gary
fuente
Desafortunadamente, no funciona con el navegador Android 4.0.4 Mobile Safari 4.0. :-(
erik
@erik Realmente no tengo una buena manera de probar esas versiones, pero me funciona en Android 5.0 con la última versión de Safari (que Google Play dice que es 1.2, así que estoy confundido acerca de tu 4.0). Si lo averiguas, me encantaría saberlo.
Gary
1
¡Eso es realmente inteligente! Me pregunto cómo no está marcado como la respuesta correcta, ya que resuelve el problema con elegancia sin ningún tipo de dependencia. Agregar jQuery solo para hacer eso es obviamente una exageración.
zanona
@zanona Gracias, pero la respuesta correcta se marcó 4 años antes, así que no creo que al OP le importara mucho otra solución.
Gary
11
Realmente me gusta su enfoque e intenté adaptarlo a mi caso de uso, pero tuve que renunciar a él cuando me di cuenta de que algunas de las especificaciones de diseño que tengo (por ejemplo, colorear la parte "activa" del rango de manera diferente al resto de la pista ) no son posibles de implementar con esto. Así que busqué otra solución y encontré este proyecto realmente genial : refreshless.com/nouislider No tiene dependencias, tiene una API agradable y limpia, es compatible con AMD y ofrece muchas opciones. Hasta ahora estoy bastante contento con eso.
Felix Wienberg
37

Llega tarde, pero noUiSlider evita tener una dependencia jQuery-ui, que la respuesta aceptada no tiene. Su única "advertencia" es que la compatibilidad con IE es para IE9 y versiones posteriores, si el IE heredado es un factor decisivo para usted.

También es gratuito, de código abierto y se puede utilizar en proyectos comerciales sin restricciones.

Instalación: descargue noUiSlider, extraiga el archivo CSS y JS en algún lugar del sistema de archivos de su sitio, y luego vincule al CSS desde el encabezado y a JS desde el cuerpo:

<!-- In <head> -->
<link href="nouislider.min.css" rel="stylesheet">

<!-- In <body> -->
<script src="nouislider.min.js"></script>

Ejemplo de uso: crea un control deslizante que va de 0 a 100 y comienza a 20-80.

HTML:

<div id="slider">
</div>

JS:

var slider = document.getElementById('slider');

noUiSlider.create(slider, {
    start: [20, 80],
    connect: true,
    range: {
        'min': 0,
        'max': 100
    }
});
dario_ramos
fuente
¡¡Increible!! ¡Esto es exactamente lo que necesitábamos y está maravillosamente desarrollado! WHITOUT jQuery
DavidTaubmann
Sin embargo, debería ser bastante fácil agregarlo usted mismo y enviar una solicitud de extracción al proyecto.
dario_ramos
3
No profundicé en él, pero podría usar el control deslizante con el teclado, así que creo que está implementado ahora @ptrin :)
Edu Ruiz
21

Claro, puede simplemente usar dos controles deslizantes superpuestos entre sí y agregar un poco de javascript (en realidad no más de 5 líneas) para que los selectores no excedan los valores mínimo / máximo (como en la solución @Garys).

Adjunto encontrará un breve fragmento adaptado de un proyecto actual que incluye algunos estilos CSS3 para mostrar lo que puede hacer (solo webkit). También agregué algunas etiquetas para mostrar los valores seleccionados.

Utiliza JQuery, pero una versión vanillajs no es mágica.

    (function() {

        function addSeparator(nStr) {
            nStr += '';
            var x = nStr.split('.');
            var x1 = x[0];
            var x2 = x.length > 1 ? '.' + x[1] : '';
            var rgx = /(\d+)(\d{3})/;
            while (rgx.test(x1)) {
                x1 = x1.replace(rgx, '$1' + '.' + '$2');
            }
            return x1 + x2;
        }

        function rangeInputChangeEventHandler(e){
            var rangeGroup = $(this).attr('name'),
                minBtn = $(this).parent().children('.min'),
                maxBtn = $(this).parent().children('.max'),
                range_min = $(this).parent().children('.range_min'),
                range_max = $(this).parent().children('.range_max'),
                minVal = parseInt($(minBtn).val()),
                maxVal = parseInt($(maxBtn).val()),
                origin = $(this).context.className;

            if(origin === 'min' && minVal > maxVal-5){
                $(minBtn).val(maxVal-5);
            }
            var minVal = parseInt($(minBtn).val());
            $(range_min).html(addSeparator(minVal*1000) + ' €');


            if(origin === 'max' && maxVal-5 < minVal){
                $(maxBtn).val(5+ minVal);
            }
            var maxVal = parseInt($(maxBtn).val());
            $(range_max).html(addSeparator(maxVal*1000) + ' €');
        }

     $('input[type="range"]').on( 'input', rangeInputChangeEventHandler);
})();
body{
font-family: sans-serif;
font-size:14px;
}
input[type='range'] {
  width: 210px;
  height: 30px;
  overflow: hidden;
  cursor: pointer;
    outline: none;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
    background: none;
}
input[type='range']::-webkit-slider-runnable-track {
  width: 200px;
  height: 1px;
  background: #003D7C;
}

input[type='range']:nth-child(2)::-webkit-slider-runnable-track{
  background: none;
}

input[type='range']::-webkit-slider-thumb {
  position: relative;
  height: 15px;
  width: 15px;
  margin-top: -7px;
  background: #fff;
  border: 1px solid #003D7C;
  border-radius: 25px;
  z-index: 1;
}


input[type='range']:nth-child(1)::-webkit-slider-thumb{
  z-index: 2;
}

.rangeslider{
    position: relative;
    height: 60px;
    width: 210px;
    display: inline-block;
    margin-top: -5px;
    margin-left: 20px;
}
.rangeslider input{
    position: absolute;
}
.rangeslider{
    position: absolute;
}

.rangeslider span{
    position: absolute;
    margin-top: 30px;
    left: 0;
}

.rangeslider .right{
   position: relative;
   float: right;
   margin-right: -5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="rangeslider">
                                <input class="min" name="range_1" type="range" min="1" max="100" value="10" />
                                <input class="max" name="range_1" type="range" min="1" max="100" value="90" />
                                <span class="range_min light left">10.000 €</span>
                                <span class="range_max light right">90.000 €</span>
                            </div>

usuario1532132
fuente
7
¡Oye, se ve genial! pero no funciona en Firefox, solo puedes arrastrar la entrada máxima. ¿Lograste arreglarlo?
Toni Michel Caubet
5
Oh hombre. ¡Vine aquí para agregar casi exactamente lo mismo! simple.gy/blog/range-slider-two-handles Mi versión coloca las entradas una al lado de la otra, pero también usa entradas duales.
SimplGy
5

En realidad, usé mi script en html directamente. Pero en javascript, cuando agrega un detector de eventos de entrada para este evento, proporciona los datos automáticamente. Solo necesita asignar el valor según sus requisitos.

[slider] {
  width: 300px;
  position: relative;
  height: 5px;
  margin: 45px 0 10px 0;
}

[slider] > div {
  position: absolute;
  left: 13px;
  right: 15px;
  height: 5px;
}
[slider] > div > [inverse-left] {
  position: absolute;
  left: 0;
  height: 5px;
  border-radius: 10px;
  background-color: #CCC;
  margin: 0 7px;
}

[slider] > div > [inverse-right] {
  position: absolute;
  right: 0;
  height: 5px;
  border-radius: 10px;
  background-color: #CCC;
  margin: 0 7px;
}


[slider] > div > [range] {
  position: absolute;
  left: 0;
  height: 5px;
  border-radius: 14px;
  background-color: #d02128;
}

[slider] > div > [thumb] {
  position: absolute;
  top: -7px;
  z-index: 2;
  height: 20px;
  width: 20px;
  text-align: left;
  margin-left: -11px;
  cursor: pointer;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
  background-color: #FFF;
  border-radius: 50%;
  outline: none;
}

[slider] > input[type=range] {
  position: absolute;
  pointer-events: none;
  -webkit-appearance: none;
  z-index: 3;
  height: 14px;
  top: -2px;
  width: 100%;
  opacity: 0;
}

div[slider] > input[type=range]:focus::-webkit-slider-runnable-track {
  background: transparent;
  border: transparent;
}

div[slider] > input[type=range]:focus {
  outline: none;
}

div[slider] > input[type=range]::-webkit-slider-thumb {
  pointer-events: all;
  width: 28px;
  height: 28px;
  border-radius: 0px;
  border: 0 none;
  background: red;
  -webkit-appearance: none;
}

div[slider] > input[type=range]::-ms-fill-lower {
  background: transparent;
  border: 0 none;
}

div[slider] > input[type=range]::-ms-fill-upper {
  background: transparent;
  border: 0 none;
}

div[slider] > input[type=range]::-ms-tooltip {
  display: none;
}

[slider] > div > [sign] {
  opacity: 0;
  position: absolute;
  margin-left: -11px;
  top: -39px;
  z-index:3;
  background-color: #d02128;
  color: #fff;
  width: 28px;
  height: 28px;
  border-radius: 28px;
  -webkit-border-radius: 28px;
  align-items: center;
  -webkit-justify-content: center;
  justify-content: center;
  text-align: center;
}

[slider] > div > [sign]:after {
  position: absolute;
  content: '';
  left: 0;
  border-radius: 16px;
  top: 19px;
  border-left: 14px solid transparent;
  border-right: 14px solid transparent;
  border-top-width: 16px;
  border-top-style: solid;
  border-top-color: #d02128;
}

[slider] > div > [sign] > span {
  font-size: 12px;
  font-weight: 700;
  line-height: 28px;
}

[slider]:hover > div > [sign] {
  opacity: 1;
}
<div slider id="slider-distance">
  <div>
    <div inverse-left style="width:70%;"></div>
    <div inverse-right style="width:70%;"></div>
    <div range style="left:0%;right:0%;"></div>
    <span thumb style="left:0%;"></span>
    <span thumb style="left:100%;"></span>
    <div sign style="left:0%;">
      <span id="value">0</span>
    </div>
    <div sign style="left:100%;">
      <span id="value">100</span>
    </div>
  </div>
  <input type="range" value="0" max="100" min="0" step="1" oninput="
  this.value=Math.min(this.value,this.parentNode.childNodes[5].value-1);
  let value = (this.value/parseInt(this.max))*100
  var children = this.parentNode.childNodes[1].childNodes;
  children[1].style.width=value+'%';
  children[5].style.left=value+'%';
  children[7].style.left=value+'%';children[11].style.left=value+'%';
  children[11].childNodes[1].innerHTML=this.value;" />

  <input type="range" value="100" max="100" min="0" step="1" oninput="
  this.value=Math.max(this.value,this.parentNode.childNodes[3].value-(-1));
  let value = (this.value/parseInt(this.max))*100
  var children = this.parentNode.childNodes[1].childNodes;
  children[3].style.width=(100-value)+'%';
  children[5].style.right=(100-value)+'%';
  children[9].style.left=value+'%';children[13].style.left=value+'%';
  children[13].childNodes[1].innerHTML=this.value;" />
</div>

Himabindu
fuente