Skip to content

Instantly share code, notes, and snippets.

@elvanja
Created November 4, 2014 21:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elvanja/ed543c02b8e24637cd8c to your computer and use it in GitHub Desktop.
Save elvanja/ed543c02b8e24637cd8c to your computer and use it in GitHub Desktop.
A take on jQuery UI Slider with slide handle adapting to dynamically generated content. See it in action @ http://codepen.io/elvanja/pen/pqrFG
var DynamicSlider = function() {
var config = {
wrapperSelector: '#slider-bar-wrap',
barSelector: '#slider-bar',
paneSelector: '#slider-pane',
contentSelector: '#slider-content',
paddingRight: 0,
focus: true
};
var wrapper;
var bar;
var pane;
var content;
var slider;
var init = function(_config) {
$.extend(true, config, _config);
wrapper = $(config.wrapperSelector);
bar = $(config.barSelector);
pane = $(config.paneSelector);
content = $(config.contentSelector);
content.size() == 0 ? hide() : apply();
};
var apply = function() {
var itemCount = content.find('>div').length;
var itemWidth = content.find('>div:eq(0)').outerWidth(true);
var totalWidth = itemCount * itemWidth;
if (totalWidth > pane.outerWidth()) {
content.width(totalWidth);
show();
} else {
hide();
}
};
var show = function() {
build();
resetValue();
sizeScrollbar();
reflowContent();
};
var build = function() {
wrapper.data('visible', 'visible').attr('data-visible', 'visible');
// create slider if not there already
if (bar.children('.ui-handle-helper-parent').size() == 0) {
bar.append("<div class='ui-handle-helper-parent'></div>");
}
bar.addClass('ui-widget ui-widget-content ui-corner-all'); // normally added by jQueryUI slider
// fix for clicking the bar outside the slider
bar.click(function (event) {
var mouseX = event.pageX;
var sliderX = slider.offset().left;
if (mouseX < sliderX || mouseX > (sliderX + slider.width())) {
var handleWidth = slider.find(".ui-slider-handle").first().width();
var barX = bar.offset().left;
var percentage = Math.round(((mouseX - handleWidth / 2) - barX) / (bar.width() - handleWidth) * 100);
slider.slider("value", percentage); // value < min && value > max are OK with slider, no need to fix
}
});
slider = bar.find('.ui-handle-helper-parent').first();
slider.css({
"border-width": 0,
"background-color": 'transparent'
});
slider.slider({
slide: slide, // reacts to mouse drag
change: slide // reacts to setting the value from code, @see bar click fix above
});
if (config.focus === true) {
slider.find(".ui-slider-handle").focus();
}
};
var slide = function(event, ui) {
var position = 0;
if (content.width() > pane.width()) {
var remainder = pane.width() - content.width() + config.paddingRight;
position = Math.round(ui.value / 100 * remainder);
}
content.css("margin-left", position + 'px');
};
var resetValue = function() {
var remainder = pane.width() - content.width();
var position = content.css("margin-left") === "auto" ? 0 : parseInt(content.css("margin-left"));
var percentage = Math.round(position / remainder * 100);
slider.slider("value", percentage);
};
var sizeScrollbar = function() {
var proportion = Math.min(pane.width() / content.width(), 1);
var handleWidth = bar.width() * proportion;
var handleParentWidth = bar.width() - handleWidth;
slider.css({
width: handleParentWidth + 'px'
});
slider.find(".ui-slider-handle").css({
width: handleWidth + 'px',
"margin-left": -(handleWidth / 2) + 'px'
});
};
var reflowContent = function() {
var showing = content.width() + parseInt(content.css("margin-left"), 10);
var gap = pane.width() - showing;
if (gap > 0) {
content.css("margin-left", parseInt(content.css("margin-left"), 10) + gap);
}
};
var hide = function() {
wrapper.data('visible', 'hidden').attr('data-visible', 'hidden');
if (slider && slider.slider('instance')) {
slider.slider("destroy").empty();
}
content.css("margin-left", '0px'); // return to normal position
};
var unbindEvents = function() {
$(window).off('resize');
};
var bindEvents = function() {
$(window).on('resize', function() {
apply();
});
};
unbindEvents();
bindEvents();
return {
init: init
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment