Skip to content

Instantly share code, notes, and snippets.

@elvanja
Last active August 29, 2015 14:08
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/e46f28989227e7656053 to your computer and use it in GitHub Desktop.
Save elvanja/e46f28989227e7656053 to your computer and use it in GitHub Desktop.
A Pen by Vanja Radovanović.
// available also @ https://gist.github.com/elvanja/ed543c02b8e24637cd8c
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
};
};
// source: http://css-tricks.com/snippets/javascript/lighten-darken-color/
function LightenDarkenColor(col, amt) {
var usePound = false;
if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}
var num = parseInt(col, 16);
var r = (num >> 16) + amt;
if (r > 255) r = 255;
else if (r < 0) r = 0;
var b = ((num >> 8) & 0x00FF) + amt;
if (b > 255) b = 255;
else if (b < 0) b = 0;
var g = (num & 0x0000FF) + amt;
if (g > 255) g = 255;
else if (g < 0) g = 0;
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// content generator
var Generator = function() {
var generate = function() {
var content = $("#slider-content");
var firstRun = $('.box').size() === 0;
var colors = ['#F00000', '#FF4500', '#FFA500', '#FFD700', '#FFFF00'];
var color = colors[0];
var count = 12;
if (firstRun === false) {
var previousColor = $('.box').first().data('background-color');
colors.splice(colors.indexOf(previousColor), 1);
color = colors[getRandomInt(0, colors.length - 1)];
count = getRandomInt(5, 15);
}
var startColor = color;
content.empty();
for(var i = 0; i < count; i++) {
content.append('<div class="box"/>');
$('.box').last().css('background-color', color);
color = LightenDarkenColor(color, -15);
}
$('.box').first().data('background-color', startColor);
new DynamicSlider().init();
}
return {
generate: generate
};
}
new Generator().generate();
body {
background: #1d1f20;
margin: 0;
padding: 0;
text-align: center;
overflow: hidden;
font-family: "Lucida Grande","Lucida Sans Unicode", Tahoma, Sans-Serif;
color: gray;
}
.centered {
width: 800px;
margin: 0 auto;
text-align: left;
}
#slider-bar-wrap {
width: 100%;
clear: both;
position: relative;
top: 10px;
margin-top: 4px;
height: 10px;
}
#slider-bar-wrap[data-visible="visible"] {
opacity: 1;
visibility: visible;
transition: opacity 150ms linear 0s, visibility 0s linear 0s;
}
#slider-bar-wrap[data-visible="hidden"] {
visibility: hidden;
}
#slider-bar {
height: 100%;
background: none repeat scroll 0% 0% #7F0000;
border: 2px solid #7F0000;
}
#slider-bar-wrap #slider-bar .ui-handle-helper-parent {
position: relative;
width: 100%;
height: 100%;
margin: 0px auto;
background: none;
}
#slider-bar-wrap #slider-bar .ui-slider-handle {
height: 10px;
top: 0px;
border: 0px none;
background: none repeat scroll 0% 0% orange;
outline: medium none;
}
.box {
width: 100px;
height: 100px;
display: inline-block;
margin: 30px 5px 0 5px;
}
#footer {
margin-top: 15px;
padding-left: 5px;
}
a {
color: white;
text-decoration: none;
}
.note {
padding-top: 4px;
font-size: 0.9em;
}
<div class="centered" id="header">
<div id="slider-bar-wrap">
<div id="slider-bar"/>
</div>
</div>
<div class="centered" id="slider-pane">
<div id="slider-content"/>
</div>
<div class="centered" id="footer">
<a href="#" onclick="new Generator().generate();">Generate</a>
<span class="note"><i>click to generate new content to slide, slider should hide/show and adapt per content</i></span>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment