Introducción

slider slider Hay veces que necesitamos un valor numérico en una página que será introducido por el usuario en un elemento <input type="text">. Dado que es un número es posible que luego hagamos cálculos y por lo tanto debemos controlar que está dentro de un rango determinado. Otras veces sólo necesitamos introducir un número aproximado sin ni siquiera tener que conocerlo.

Para esos están los slider o barras deslizadoras como las que aparecen en las imágenes. Los nuevos tipos de HTML5 number y range para el elemento <input> nos ayudan en estas tareas. Algún navegador como Firefox 10.0 aún no ha implementado alguna de estas cosas, por lo que construiremos un par de slider sólo con Javascript (que incluso funciona en Explorer 8).

Controles input de números con HTML5: el tipo number

Empezamos con el nuevo tipo number de HTML5 para introducir números en el elemento <input>. En la documentación oficial de WHATWG <input type="number"> tenenemos la información. Vea estos ejemplos de aplicación:

Ejemplo:

  1. Rango 10 a 20 controlando con JavaScript
  2. HTML5: Rango 10 a 20 con paso 1
  3. HTML5: Rango 10 a 20 con paso 0.5
Octubre 2013:

Aún algunos navegadores no implementan el tipo number y sobre todo en los móviles. He realizado un teclado auxiliar para el input type number.

El primer ejemplo es un clásico <input type="text"> al que se le agrega el evento onchange"limitaValor(this,'entero',10,20)". Esta función la tengo en módulo de JavaScript General con funciones de uso corriente.

En el segundo tenemos <input type="number" min="10" max="20" value="15" /> para un rango 10..20. Cuando no se incluye se entiende que usará el atributo step="1" de tal forma que se desplaza en saltos de una unidad. En el tercer ejemplo ponemos step="0.5". Aunque con los botones podemos desplazarnos hasta los límites, aún es posible poner cualquier valor tecleando directamente dentro del cuadro. Por lo tanto haría falta controlar externamente ese valor.

Barra deslizadora o slider con input tipo range de HTML5

Hay aplicaciones donde el usuario necesita introducir sólo un valor aproximado. O bien incluso sin tener que conocer el valor que está introduciendo. Por lo tanto no tiene que estar escribiendo ningún número. Es similar a los controles de volumen de un aparato de música. Se trata de la barra deslizadora o slider que también contempla HTML-5 con WHATWG <input type="range">

Ejemplo:

Entero 1 a 25:
Real -3.5 a 5.2:

El control <input type="range"> es sólo del slider. El resto se lo he agregado para comprobar el cambio de valor al desplazar el cursor. Simplemente ponemos un evento

    
onchange="document.getElementById('text1').value=this.value"

en el slider que modificará el cuadro de texto con la posición del cursor. El cuadro lleva a su vez otro evento onchange que cambiará la posición del cursor. Este tipo range es simple pero aún Firefox 10 no lo ha implementado.

Barra deslizadora o slider con JavaScript

Actualizado en Octubre 2013 para que funcione en móviles.

Si necesitamos un slider podemos hacernos uno. Vea estos ejemplos:

Ejemplo:

Rango entero:
Rango real:
Rango logarítmico:
Ocultando el contenido anexo:

El siguiente es un slider de enteros con el rango 4..150, identificado con id="este-id" y con el atributo data-hidden, por lo que sólo mostrará la barra deslizadora. El cuadro de texto <input> sigue existiendo con type="hidden".

Podemos usar las funciones setSlider() y getSlider() parar poner y sacar el valor.

  • Ver el valor con . Esto es lo mismo que hacer document.getElementById("este-id").value
  • Poner este valor con miSlider.setSlider("este-id",this.value)

Estas barras deslizadoras se controlan con los módulos sliderwx.js y sliderwx.css. En el HTML sólo tenemos que poner lo siguiente (para el primer ejemplo):

    
<div class="sliderwx"
data-id="entero" data-title="Entero 1 a 25:"
data-width="250" data-type="int" data-decimal="0"
data-min="1" data-max="25"></div>

Todos las barras se cargan con la función iniciarSliderWx() ejecutada en el window.onload de la página. Si vamos a interactuar con el slider esa función devuelve los métodos setSlider(id) y getSlider(id,valor) para obtener el valor numérico o editarlo respectivamente. En esta página lo he asignado como var miSlider = iniciarSlider(). La función inicializadora incorpora elementos <div> para construir las partes de la barra, el título y cuadro de texto. Tras eso tendremos el siguiente HTML generado dinámicamente para el primer ejemplo:

Actualización Octubre 2013:

He agregado dos argumentos opcionales a la función que inicializa el slider:

iniciarSliderWx([nuevoAnchoCursor[, tituloAntes]])
  • nuevoAnchoCursor (Entero): Si no se pasa o se pasa null se usará un ancho de 6px para el cursor. En otro caso se modificará el ancho del cursor al valor que se le pase. Esto es útil en los casos en que podamos detectar dispositivos móviles y así poder aumentar el tamaño del cursor para hacerlo más usable.
  • tituloAntes (Booleano): Si no se pasa este argumento o se pasa false se pondrá el texto del atributo data-title después de la barra deslizadora y antes del <input> con el valor númerico. Si se pasa el argumento será con valor true en cuyo caso se ubicará ese título antes de la barra deslizadora.
<div class="sliderwx" data-id="entero" data-title="Entero 1 a 25:"
data-width="250" data-type="int" data-decimal="0" data-min="1"
data-max="25" data-num="0" unselectable="on"
onselectstart="return false;" style="-webkit-user-select: none;">
    <div class="sliderwx-principal">
        <div class="sliderwx-fondo" onselectstart="return false;"
        unselectable="on" style="width: 262px;">
            <div class="sliderwx-barra" onselectstart="return false;"
            unselectable="on" data-num="0" style="height: 28px;
            margin-top: -14px; width: 262px;"></div>
            <div class="sliderwx-cursor" onselectstart="return false;"
            unselectable="on" style="height: 24px; width: 12px;
            margin-top: -12px; left: 0px;"></div>
        </div>
    </div>
    <div class="sliderwx-anexo" unselectable="on">
        <span unselectable="on">Entero 1 a 25:</span>
        <input type="text" id="entero" value="1" data-num="0" size="3"
        style="width: 4em;">
    </div>
</div>
Este código HTML lo obtuve con el Developer Tools que viene con el Chrome (menú Herramienta para desarrolladores o menú contextual Inspeccionar Elemento ), una buena herramienta para ayudar al desarrollo de una página.

Se incorporan los atributos unselectable y el evento onselectstart para impedir la selección de algún contenido al mover el ratón cuando deslizamos el cursor. También usamos la propiedad user-select para lo mismo, pues el comportamiento de los navegadores no es exactamente el mismo con esto de impedir la selección de contenido. En el JavaScript la incorporamos haciendo uso del gestor de prefijos vpForCss que incorpora automáticamente la propiedad con prefijo en el elemento. Si no se usa este componente (que está en el archivo general.js) debe incluir esa propiedad con los prefijos que sean necesarios.

En HTML5 los atributos que empiezan por WHATWG data-* son reservados para el programador. Así podemos utilizarlos desde JavaScript con elemento.getAttribute("data-xxx"). Para el slider necesitamos los siguientes atributos:

  • data-id es un tipo ID con el que se identificará el slider. El elemento <input> a generar será identificado en su atributo id con este valor.
  • data-title es un string para el título que se pone antes del cuadro de texto.
  • data-width es el ancho en píxeles del slider
  • data-type es un string con los valores int, float, log para tipo entero, real y logarítmico.
  • data-decimal es un entero para el número de decimales que se mostrarán con los tipos real y logarítmico.
  • data-min y data-max para los límites del rango

Además hay unos atributos opcionales que son de la forma data-input-* y que se transfieren al elemento <input> a generar.

  • data-input-value para dotar de un valor inicial al control. Si se omite se pone data-min como valor inicial.
  • data-input-type para el tipo de cuadro de control. Tiene sentido si queremos ocultar el cuadro de texto poniendo data-input-type="hidden". Así sólo se muestra la barra sin el título ni el cuadro de texto, aunque este sigue existiendo pues estará con type="hidden".
  • Podemos incluir cualesquiera otros atributos de un <input> como size, maxlength, title, etc.

Por lo tanto el cuadro de texto porta el valor, es decir, si un slider tiene su atributo data-id="xx" entonces el cuadro de texto tendrá el atributo id="xx". Así podemos acceder al atributo value del cuadro de texto para obtener el valor del slider. También podemos cambiar el cuadro de texto modificando su atributo value, pero esta acción no modificará el cursor del slider. En todo caso las funciones setSlider(id, valor) y getSlider(id) nos permiten poner y extraer un valor de un slider con ese data-id.

El rango logarítmico resulta muy interesante cuando tenemos uno como el del ejemplo 0.1 .. 1000. Si usáramos la escala real los valores quedarían proporcionalmente repartidos, por lo que apenas podríamos acceder a valores por debajo de la unidad. En el del ejemplo que tiene un ancho de 250 px y para el tamaño del rango 1000-0.1 = 999.9 resultan tramos de 999.9/250 = 3.9996. Por lo tanto cuando movamos 1 píxel tendremos el valor 3.9996+min=3.9996+0.1=4.0996, no pudiendo obtener ningún valor entre 0.1 y ese 4.0996

Con el logarítmico la distancia para una posición del cursor a x píxeles desde la izquierda resultará en un valor v de

v = ex·log(max-min+1)/ancho+min-1

Por lo tanto para un valor dado su posición será

x = ancho·log(v-min+1)/log(max-min+1)

Para v=1 la posición será

x = 250·log(1-0.1+1)/log(1000-0.1) = 23.22 px

Así tenemos unos 23 píxeles para recorrer la distancia que va desde 0.1 a 1.

Barra deslizadora o slider con scroll y JavaScript

Por último también podemos aprovechar las barras de desplazamiento o scroll de los elementos HTML para hacer un slider. Vea estos dos ejemplos:

Ejemplo:

Esto funciona en Chrome 17.0, Safari 5.1, Opera 11.61 y en Firefox 10.0. Los móviles pueden soportar una mecanismo de scroll, pero no resulta práctico para este propósito.

En este caso no existe la opción logarítmica. Usamos el mecanismo de scroll que se incluye en un elemento de bloque con la propiedad de estilo {overflow-x} y con un contenido cuyo ancho es mayor que el contenedor que lo alberga. El script está en el módulo slider-scroll.js y el estilo en slider-scroll.css. El HTML del primer caso es este:

    
<div class="wscroll"
data-width="250" data-id="sc1" data-title="Entero 1 a 25:"
data-min="1" data-max="25" data-type="int"></div> 

El estilo es muy simple:

div.wscroll div.wscrolla {
    overflow-x: scroll;
    overflow-y: hidden;
    height: 20px;
    vertical-align: top;
    display: inline-block;
    }
div.wscroll div.wscrollz {
    top: 0;
    overflow: hidden;
    display: inline-block;
    padding-left: 0.2em;
    }
div.wscrollz input {
    border: 0;
    background-color: transparent;
    }

Con el window.onload de la carga de la página iniciamos las barras con iniciarScrolles(). Se crean elementos <div> así como el título y cuadro de texto. Para el primero de los ejemplos anteriores el HTML finalmente creado será este:

<div class="wscroll" data-width="250" data-id="sc1"
data-title="Entero 1 a 25:" data-min="1" data-max="25"
data-type="int">
    <div class="wscrolla" style="width: 250px;">
        <div style="width: 6250px;">&nbsp;</div>
    </div>
    <div class="wscrollz" style="left: 250px;">
        Entero 1 a 25:
        <input type="text" id="sc1" value="0">
    </div>
</div>

Hay un <div> de 250 píxeles y otro que se calcula con la expresión ancho×(max-min+1), dándonos 250×(25-1+1)=6250 píxeles. El contenedor de 250 píxeles lleva overflow-x: scroll activándose la barra pues el contenido interior es más ancho. Con el estilo se ajusta la altura para que sólo se vea la barra de desplazamiento del contenedor exterior. Las funciones setScroll(id, valor) y getScroll(id) permiten poner y extraer un valor del slider si se necesitará interactuar externamente.

Detalles de los script

En los códigos de sliderwx.js y slider-scroll.js se usan algunas funciones que aparecen en general.js para la compatibilidad con navegadores más antiguos.

El módulo general.js contiene más cosas, por lo que puede extraer estas funciones si no desea vincular el módulo completo.