Murphy1976
Murphy1976

Reputation: 1475

Mapping an HTML5 range slider min and max to array values

I am putting together an HTML5 form for music teachers so they can classify their music library a bit easier. One of the requested elements is a double handled range slider that would be able to define the range of a particular piece. This is all fine if we were talking 0 to 100, but we're talking G-Flat 3 to B5, a series of arbitrary values that wouldn't normally be found on a range slider.

What I'm thinking of doing is creating an array of all the different note ranges from G-Flat 3 to B5 (lowest to highest), and then somehow mapping those to a double handled range slider. Problem is, I don't know how to do that, nor do I know if it is even possible.

In essence, I would like to create an array:

Array = ['Gb3', 'G3', 'G#3', 'Ab3', 'A3',... 'A#5', 'Bb5', 'B5'];

Somehow match those up to numeric values:

0 = 'Gb3';
1 = 'G3';
2 = 'G#3';

And then map those to a double handle range slider.

Any one know if there is a library, or plugin or magic toadstool that can point me in the right direction?

UPDATE: I want to thank EVERYONE who posted to this. There are so many fantastic answers, I'm having a very difficult time choosing "the" answer.

Upvotes: 2

Views: 2645

Answers (4)

Shannon Scott Schupbach
Shannon Scott Schupbach

Reputation: 1278

A similar question was asked here. The solution offered is to use the jQuery UI Slider.

To answer the part of your question specific to your case, you will probably need to build the array of possible values (like you've done above: notesArr = ['Gb3', 'G3' ... 'Bb5', 'B5']; and in the ui-slider code, set the min to 0 and the max to notesArr.length - 1. In the portion of the code that defines the label, use the integer value of the slider position to index into the array to get the string value to display.

Upvotes: 1

Jordan Running
Jordan Running

Reputation: 106027

I found this polyfill for a now-abandoned proposal to add a multiple attribute to the <input type="range"> spec. It's simple and works well enough, but has an unfortunate bug: Event handlers aren't fired for when the second handle is moved. It's pretty easy to work around, though:

const notes = ['Gb3', 'G3', 'G#3', 'Ab3', 'A3', /* ... */ 'A#5', 'Bb5', 'B5'];

function handleChange() {
  const { valueLow, valueHigh } = this;
  const lowNote = notes[parseInt(valueLow, 10)];
  const highNote = notes[parseInt(valueHigh, 10)];
  console.log('%s to %s', lowNote, highNote);
}

document.addEventListener('DOMContentLoaded', () => {
  const input = document.querySelector('input[type=range]');
  input.addEventListener('input', handleChange);
  input.nextElementSibling.addEventListener('input', handleChange.bind(input));
});
<script src="https://cdn.rawgit.com/LeaVerou/multirange/gh-pages/multirange.js"></script>
<link href="https://cdn.rawgit.com/LeaVerou/multirange/gh-pages/multirange.css" rel="stylesheet"/>

Change me: <input type="range" min="0" value="0,7" max="7" step="1" multiple>

As you can see, I've set the <input>'s min attribute to 0, max to the highest index in notes (notes.length - 1 == 7), and value to 0,7. In addition to adding an 'input' event handler to input, I've added the same handler to input.nextElementSibling. The latter is the generated "ghost" element which renders the second handle. It's necessary to bind the event handler to input because the "ghost" input doesn't have valueLow and valueHigh.

Upvotes: 3

K.G
K.G

Reputation: 131

I would use a javascript object. Here is an example.

HTML

<input type="range" value='0' min='0' max='3'>
<div class='sound'></div>

jQuery

var obj = {
  0 : 'Gb3',
  1 : 'G3',
  2 : 'G#3'
}

$('body').on('change', 'input[type=range]', function(){
  var val = $(this).val();
  $('.sound').text(obj[val])
});

Upvotes: 2

Nico
Nico

Reputation: 7256

Using jquery UI slider you can do something like this fiddle:

    $(function () {
    var note =  ['Gb3', 'G3', 'G#3', 'Ab3', 'A3', 'A#5', 'Bb5', 'B5'];
        $("#slider-range-min").slider({
            range: true,
            values: [0,7],
            min: 0,
            max: 7,          
            step: 1,
            slide: function (event, ui) {           
                $("#amount").val(note[ui.values[0]]+ "-"+note[ui.values[1]]);
            }
        });
        $("#amount").val(note[0]+ "-"+note[7]);

});

Upvotes: 1

Related Questions