jQuery UI is now a main stream user interface toolkit. It works most everywhere, but touch devices currently struggle with some of it’s widgets, including the Slider. The problem is touch and drag events can get mixed up between the web page and the browser. In other words when does a swipe indicate to scroll the page or slider adjustment. Currently after a couple searches there are a couple attempts to fix this without much effort beyond including a javascript file:
Essentially these two plugins listen for touch events and pass the event on to jQuery UI so they can be processed. But still these can be cumbersome in my findings. So I’ve come up with a quick solution.
When we use a slider, and touch events are available we know it is a touch device, so we can insert a couple jQuery UI buttons to increment and decrement the sliders.
Adding this ability can be as simple as one more method chained after your slider:
$('#slider').slider().sliderAccess();
On top of that if you want it to always show, even when it’s not a touch enabled device, you can specify that as well:
$('#slider').slider().sliderAccess({ touchonly : false });
Ok, so you this is easy enough to use, lets see the goods:
/*
* jQuery UI Slider Access
* By: Trent Richardson [http://trentrichardson.com]
* Version 0.2
* Last Modified: 12/12/2011
*
* Copyright 2011 Trent Richardson
* Dual licensed under the MIT and GPL licenses.
* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
*
*/
(function ($) {
$.fn.extend({
sliderAccess: function (options) {
options = options || {};
options.touchonly = options.touchonly !== undefined ? options.touchonly : true; // by default only show it if touch device
if (options.touchonly === true && !("ontouchend" in document))
return $(this);
return $(this).each(function (i, obj) {
var $t = $(this),
o = $.extend({}, {
where: 'after',
step: $t.slider('option', 'step'),
upIcon: 'ui-icon-plus',
downIcon: 'ui-icon-minus',
text: false,
upText: '+',
downText: '-',
buttonset: true,
buttonsetTag: 'span',
speed: 150
}, options),
$buttons = $('<' + o.buttonsetTag + ' class="ui-slider-access">' +
'<button data-icon="' + o.downIcon + '" data-step="-' + o.step + '">' + o.downText + '</button>' +
'<button data-icon="' + o.upIcon + '" data-step="' + o.step + '">' + o.upText + '</button>' +
'</' + o.buttonsetTag + '>');
$buttons.children('button').each(function (j, jobj) {
var $jt = $(this),
timeout = null,
increment = function($jt, $t, e) {
var step = $jt.data('step'),
curr = $t.slider('value'),
newval = curr += step * 1,
minval = $t.slider('option', 'min'),
maxval = $t.slider('option', 'max');
e.preventDefault();
if (newval < minval || newval > maxval)
return;
$t.slider('value', newval);
$t.slider("option", "slide").call($t, null, { value: newval });
};
$jt.button({
text: o.text,
icons: { primary: $jt.data('icon') }
})
.bind('touchstart mousedown', function (e) {
increment($jt, $t, e);
timeout = setInterval(function () {
increment($jt, $t, e);
}, o.speed);
});
$(document).bind('touchend mouseup', function () {
clearInterval(timeout);
return false;
});
});
// before or after
$t[o.where]($buttons);
if (o.buttonset) {
$buttons.removeClass('ui-corner-right').removeClass('ui-corner-left').buttonset();
$buttons.eq(0).addClass('ui-corner-left');
$buttons.eq(1).addClass('ui-corner-right');
}
// adjust the width so we don't break the original layout
var bOuterWidth = $buttons.css({
marginLeft: (o.where == 'after' ? 10 : 0),
marginRight: (o.where == 'before' ? 10 : 0)
}).outerWidth(true) + 5;
var tOuterWidth = $t.outerWidth(true);
$t.css('display', 'inline-block').width(tOuterWidth - bOuterWidth);
});
}
});
})(jQuery);
A quick look at the source and you will notice I also threw in a few options to make things more versital. The options are:
- touchonly – true/false – Show this control Only for touch devices.
- where – before/after – Show this control before or after the slider.
- step – [0-9]+ – How much each button press increments. Defaults to slider step.
- upIcon – one of ui icon names – defaults to “ui-icon-plus”.
- downIcon – one of ui icon names – defaults to “ui-icon-minus”.
- text – true/false – Show text in buttons?
- upText – string – Text of up button, default is “+”.
- downText – string – Text of down button, default is “-”.
- buttonset – true – Wrap the button in a button set?
- buttonsetTag – tagName – element type to wrap the buttons with, default is “span”.
- speed – [0-9]+ – Interval speed on touch-hold or click-hold to increment, default is 150
It should also be noted that for this plugin to work you will need to include the button widget in your jQueryUI build. From there we handle the rest. When a button is clicked the change event will be fired through the slider, however the slide event will not. This plugin makes no attempt to stop the click event on the buttons, so if you need to catch these events since there is not slide event you may do it the natural way.
One final note for this plugin. It is small, I will likely not be making many updates to it. If you need to tweak something feel free, and if you like post your changes here. I may integrate it if I see the need. The downfall and updside is as time passes jQueryUI will likely improve their support, so this plugin will become irrelevant. Enjoy!
Last updated: 2012-09-23 – SliderAccess Now has a dedicated documentation page and GitHub repository


16 Responses
Dana
Nov 30, 2011May I suggest adding another option for “where”, that being “split” — put the minus to the left of the slider, and the plus to the right of the slider?
Also, how would this be implemented with your .timepicker addon since it uses sliders for the time?
Dana
Dec 01, 2011I’ve been attempting to make this work with your timepicker addon and have encountered a few issues with the timepicker addon that I wanted to bring up. Do with it what you will.
In the timepicker addon, you calculate hourMax, minMax, secMax, and millisecMax in a couple of places and use these values when you set the sliders. The problem is you are calling .toFixed(n) on the calculations, which makes the variables into string objects instead of numbers. Doesn’t make any sense to me either but it does.
This in effect makes the “max” value of the slider be “59″ instead of 59. Under normal operations this isn’t causing a problem because of how our friend JavaScript handles normal operators. 58 < "59" will be true just as much as 58 “50″ so it always returns.
The root fix for all of this is to make sure your hourMax, minMax, etc. stay numbers. In the timepicker addon, wrap the calculations in parseFloat(). Two places – around line 344, and again around 735.
The other problem is that the buttons don’t evoke the slide() function so you need to add a change() function to your timepicker sliders to intercept it. You set these sliders up around line 468. Adding this is sufficient:
change: function(event, ui) { tp_inst._onTimeChange(); },You can then add your .sliderAccess() to the end of these same declarations and the buttons will behave as intended.
However.. the styling of the buttons cause visual issues inside the timepicker – at least in IE9 and FF8. I haven’t had time to look at the markup and figure out how to correct it yet. If I do, I’ll post back.
I obviously love your work and want to see it improve. =)
Dana
Dec 01, 2011No edit comment feature on here, eh. A paragraph got cut out of there for some reason, and jumbled up.
This mess:
“This in effect makes the “max” value of the slider be “59″ instead of 59. Under normal operations this isn’t causing a problem because of how our friend JavaScript handles normal operators. 58 < "59" will be true just as much as 58 “50″ so it always returns."
was written as:
This in effect makes the “max” value of the slider be “59″ instead of 59. Under normal operations this isn’t causing a problem because of how our friend JavaScript handles normal operators. 58 < "59" will be true just as much as 58 “50″ so it always returns.
Dana
Dec 01, 2011Oh bloody hell.. the comment was interpreting my use of a lesser than and further along a greater than as one big tag. Sorry for the spam. Replacing the lesserthan sign with an !lt!. Also replacing quotes with apostrophes. This woulda been easier by email.
Here:
This in effect makes the max value of the slider be ’59′ instead of 59. Under normal operations this isn’t causing a problem because of how our friend JavaScript handles normal operators.
58 !lt! ’59′ will be true just as much as 58 !lt! 59.
The problem comes in with the math used by sliderAccess to calculate new values. If the slider isn’t maxed out, you’re fine. The current value is a number. Once you hit max on the slider however, the current value becomes a string.
If the step is 10, for example, the new value will become ’59-10′ or ’59+10′. When it comes to the evaluation, ’59-10′ !gt! ’59′ so it always returns.
brxxt
Dec 11, 2011Thanks for this.
I’m having some trouble getting it to work though. The + and – buttons are displayed, but when I click on them the slider gets stuck and just says aN:aN pm…
Please let me know how to get this work.
Much appreciation!
brxxt
Dec 11, 2011Ah, nevermind. I was calling an old version of jquery. Fixed!
Thanks again
Oscar Villarreal
Jan 16, 2012Thank you for this post!
I recently experienced the same problem when I tried implementing jquery UI sliders and have them work in iPads. I did end up finding this jquery mobile slider which helped me incredibly.
Hope this helps!
jDeppen
Jan 17, 2012I’ve messed with speed and step but no matter what, the buttons move 2 positions every time on the iPhone (10:00 to 12:00 etc). They work fine on chrome etc. Is anyone else having this issue?
ALEXANDRE gregoire
Mar 27, 2012hi,
i have a probleme with dateTimePicker and slider addon. When i change my minutes values, i never have the good time and my firebug say:
“alignValue.toFixed is not a function
parseFloat( alignValue.toFixed(5) )”
i don’t find why. Any personn have a soluce?
ALEXANDRE gregoire
Mar 27, 2012problem solved the probleme is:
stepMinute:’5′ could be stepMinute:parseInt(5).
Jack
May 24, 2012Where can I download the jquery-ui-sliderAccess.js file?
Jack
May 24, 2012Nevermind. I found it.
Kris
Aug 06, 2012I am trying to use the datetime picker with bootstrap. We moved our app to use bootstrap which is bundled with jquery (v 1.7.1). I am having trouble getting the date time picker to work with it.
We are doing as in the bootstrap example and loading the jquery.js file at the end of the page (In fact it seems that some functionality doesn’t work (eg menu drop down) if loaded in . I have tried a few things eg loading datetimepicker after jquery but no luck.
!! This is quite urgent please let me know if there is a work around !!
trent
Aug 06, 2012Sounds like your libraries aren’t loaded before you try to use them, even with your drop down. If your scripts are loaded at the end of the page then any logic requiring those plugins still needs to come after them. Be sure to use
$(document).ready(function(){ /*… */ }) //AFTER the scripts, it is dependent on jquery
or
window.onload = function(){ /*… */ } // anywhere, this is native js
Kris
Aug 06, 2012Thanks that fixed it. btw does dateTimePicker have a dependency on jquery ui?
I have a couple of other questions
1. I am trying to get the +/- touch controls on the date time picker. I have included
I have the following includes.
<link rel="stylesheet" href="” type=”text/css”>
<script src="”>
<script src="”>
inputElement.datetimepicker({
addSliderAccess: true,
sliderAccessArgs: { touchonly: false },
….other options …
})
The touch controls do not show up. Am i missing something here?
2. Also is how to get the time to display in local time on the date time picker
So intead of showing 8:35pm +10:00 have it show 6:35am AEST because when I demo’d the
app to a client it seemed painful to have them calculate off GST when the website is only
for Australia. Is it possible to display local time with timezone?
Kris
Aug 06, 2012Please disregard the first question about touch controls. It works now .. I guess something was cached.
I still need to figure out how to display local time though.