Skip to content

Instantly share code, notes, and snippets.

@mattkelley
Created July 23, 2015 19:47
Show Gist options
  • Save mattkelley/4eee7bc61b645ef0f56b to your computer and use it in GitHub Desktop.
Save mattkelley/4eee7bc61b645ef0f56b to your computer and use it in GitHub Desktop.
range slider module
var on = function(items, scope) {
items.forEach(function(item) {
return item.e.map(function(e) {
item.context.addEventListener(e,item.fn,false)
})
})
}
var off = function(items) {
items.forEach(function(item) {
return item.e.map(function(e) {
item.context.removeEventListener(e,item.fn,false)
})
})
}
// move the element to a percentage point
var to = function(el, percent) {
// This is for sanity but also for visual. The playhead shouldn't leave the progress bar.
var clamp = Math.min(Math.max(percent, 0.2), 99.8);
// Convert this into matrices stuff later
['webkitTransform', 'MozTransform', 'msTransform', 'transform'].forEach(function(v) {
el.style[v] = 'translateX(' + clamp + '%)';
});
}
// calculate the percentage point
var percentage = function(el, event) {
var x = (event.touches) ? event.touches[0].clientX : event.clientX;
var position = x - el.getBoundingClientRect().left;
var percentage = 100 * position / el.offsetWidth;
return Math.min(Math.max(percentage, 0), 100);
}
/**
* Range slider
* Creates a simple UI slider for scrubbing video or volume
* @param {Element} el
*/
function Range(el) {
// store passed element
this._el = el;
// current percentage of the range element
this._position = 0;
// amount of move events in the current range adjustment
this._count = 0;
// create elements, and the event configuration
this.create();
};
// Enable the range slider events
Range.prototype.enable = function() {
on([this._e.start]);
};
// Disable the range slider events
Range.prototype.disable = function() {
off([this._e.start]);
};
// Get the range current position
Range.prototype.get = function() {
return this._position;
};
// Set the range position
Range.prototype.set = function() {
this._position = percent;
to(this._time, this._position);
};
// Handle touchstart and mousedown events
Range.prototype._start = function() {
event.stopPropagation();
on([this._e.move, this._e.stop]);
this.trigger('begin', {type: 'begin', srcEvent: event, percent: this._position});
if (this._position !== percentage(this._bar, event)) {
this.move(event);
}
};
// Handle touchmove and mousemove events
Range.prototype._move = function() {
event.stopPropagation();
this._position = percentage(this._bar, event);
to(this._time, this._position);
this.trigger('move', {type: 'move', srcEvent: event, count: ++this._count, percent: this._position});
};
// Handle touchend and mouseup events
Range.prototype._stop = function() {
event.stopPropagation();
off([this._e.move, this._e.stop]);
this.trigger('end', {type: 'end', srcEvent: event, percent: this._position });
this._count = 0;
};
// Destroy the Range slider elements and remove event listeners
Range.prototype.destroy = function() {
off([this._e.start, this._e.move, this._e.stop]);
this._bar.removeChild(this._time);
this._el.removeChild(this._bar);
this._el.classList.remove('ivp-control-progress');
};
// Create the Range markup and event configuration
Range.prototype.create = function() {
// Bar is the outer element always visibile
this._bar = document.createElement('div');
this._bar.className = 'ivp-progress-bar';
// Time is the inner element which slides
this._time = document.createElement('div');
this._time.className = 'ivp-progress-time';
this._bar.appendChild(this._time);
// @NOTE modifying passed element here - not sure if I like this or not
this._el.classList.add('ivp-control-progress');
this._el.appendChild(this._bar);
var _this = this;
this._e = {
start: {
context: this._bar,
e: ['mousedown', 'touchstart'],
fn: function() {
_this._start.apply(_this, arguments);
}
},
move: {
context: document,
e: ['mousemove', 'touchmove'],
fn: function() {
_this._move.apply(_this, arguments);
}
},
stop: {
context: document,
e: ['mouseup', 'touchend'],
fn: function() {
_this._stop.apply(_this, arguments)
}
}
}
};
// Export the Range class as default
export default Range;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment