Created
November 4, 2014 21:48
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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