HTML5: Slider avec deux entrées possible?

102

Est-il possible de créer un curseur HTML5 avec deux valeurs d'entrée, par exemple pour sélectionner une fourchette de prix? Si tel est le cas, comment cela peut-il se faire?

fréquent
la source

Réponses:

65

Non, l' entrée de plage HTML5 n'accepte qu'une seule entrée. Je vous recommande d'utiliser quelque chose comme le curseur de plage de l'interface utilisateur jQuery pour cette tâche.

Martin Buberl
la source
Merci pour le lien et l'information. Je dois vérifier si je peux faire fonctionner cela sur les appareils mobiles.
fréquent le
34
Il y a quelque temps ... mais j'ai réussi à "simuler" un double curseur en plaçant deux curseurs exactement l'un sur l'autre. L'un à partir de la valeur min, l'autre à partir de la valeur max. Je suppose que c'est de la triche mais ... ça marche pour moi.
fréquent le
WhatWG discute au moins de sa mise en œuvre: html.spec.whatwg.org/multipage/…
kunambi
7
J'aime ionRangeSlider un peu mieux que le curseur de l'interface utilisateur jQuery moi-même: ionden.com/a/plugins/ion.rangeSlider/en.html
Charlotte
4
Une autre approche consiste à "simuler" le double curseur avec des contrôles d'entrée côte à côte: simple.gy/blog/range-slider-two-handles
SimplGy
81

Je cherchais depuis un certain temps un double curseur léger et sans dépendance (il semblait fou d'importer jQuery juste pour cela) et il ne semble pas y en avoir beaucoup. J'ai fini par modifier un peu le code de @ Wildhoney et je l'aime vraiment.

Gary
la source
Malheureusement, cela ne fonctionne pas avec le navigateur Android 4.0.4 Mobile Safari 4.0. :-(
erik
@erik Je n'ai pas vraiment de bon moyen de tester ces versions, mais cela fonctionne pour moi sur Android 5.0 avec la dernière version de Safari (ce que google play dit est 1.2, donc je suis confus à propos de votre 4.0). Si vous le comprenez, j'aimerais le savoir.
Gary le
1
C'est vraiment intelligent! Je me demande comment ce n'est pas marqué comme la bonne réponse car il résout le problème gracieusement sans aucune sorte de dépendance. Ajouter jQuery juste pour faire cela est évidemment excessif.
zanona
@zanona Merci mais la bonne réponse a été notée 4 ans auparavant, donc je ne pense pas que l'OP se souciait beaucoup d'une autre solution.
Gary
12
J'aime beaucoup votre approche et j'ai essayé de l'adapter à mon cas d'utilisation, mais j'ai dû abandonner quand j'ai réalisé que certaines des spécifications de conception que j'avais (par exemple, la coloration de la partie "active" de la gamme différemment du reste de la piste ) ne sont pas possibles à mettre en œuvre avec cela. J'ai donc cherché une autre solution et j'ai trouvé ce projet vraiment sympa : refreshless.com/nouislider Il est sans dépendance, possède une API agréable et propre, est compatible AMD et offre de nombreuses options. Jusqu'à présent, j'en suis assez content.
Felix Wienberg
38

Arriver en retard, mais pas d' UiSlider évite d'avoir une dépendance jQuery-ui, ce que la réponse acceptée ne fait pas. Sa seule "mise en garde" est que le support d'IE est pour IE9 et plus récent, si IE hérité est un facteur décisif pour vous.

Il est également gratuit, open source et peut être utilisé dans des projets commerciaux sans restrictions.

Installation: Téléchargez noUiSlider, extrayez le fichier CSS et JS quelque part dans le système de fichiers de votre site, puis créez un lien vers le CSS depuis la tête et vers JS depuis le corps:

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

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

Exemple d'utilisation: crée un curseur qui va de 0 à 100 et commence à 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
la source
Waouh incroyable!! C'est exactement ce dont nous avions besoin et c'est merveilleusement développé! WHITOUT jQuery
DavidTaubmann
Cela devrait être assez facile de l'ajouter vous-même et d'envoyer une pull request au projet, cependant?
dario_ramos
3
Je n'ai pas creusé dedans, mais je pourrais utiliser le curseur avec le clavier, donc je pense qu'il est maintenant implémenté @ptrin :)
Edu Ruiz
21

Bien sûr, vous pouvez simplement utiliser deux curseurs se superposant et ajouter un peu de javascript (en fait pas plus de 5 lignes) pour que les sélecteurs ne dépassent pas les valeurs min / max (comme dans @Garys).

Vous trouverez ci-joint un court extrait adapté d'un projet en cours, comprenant un style CSS3 pour montrer ce que vous pouvez faire (kit Web uniquement). J'ai également ajouté quelques étiquettes pour afficher les valeurs sélectionnées.

Il utilise JQuery mais une version vanillajs n'est pas magique.

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

user1532132
la source
7
Hey a l'air génial! mais cela ne fonctionne pas dans Firefox, vous ne pouvez faire glisser que l'entrée max. Avez-vous réussi à résoudre ce problème?
Toni Michel Caubet
5
Oh mec. Je suis venu ici pour ajouter presque exactement la même chose! simple.gy/blog/range-slider-two-handles Ma version met les entrées côte à côte, mais utilise également des entrées doubles.
SimplGy
6

En fait, j'ai utilisé mon script en html directement. Mais en javascript, lorsque vous ajoutez un écouteur d'événement oninput pour cet événement, il donne les données automatiquement.Il vous suffit d'attribuer la valeur selon vos besoins.

[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
la source