Commit 4a4f7d06 authored by Valentin Hervieu's avatar Valentin Hervieu

Merge pull request #100 from coxm/draggable-bar

Draggable range
parents 4b1ddca6 e4a7295d
......@@ -106,6 +106,10 @@ $scope.priceSlider = {
> When set to true slider is used in presentation mode. No handle dragging.
**rz-slider-draggable-range**
> When set to true and using a range slider, the range can be dragged by the selection bar.
**rz-slider-translate**
> Custom translate function. Use this if you want to translate values displayed on the slider. For example if you want to display dollar amounts instead of just numbers do this:
......
......@@ -80,6 +80,23 @@
rz-slider-tpl-url="rzSliderTpl.html"></rzslider>
</article>
<article>
<h2>Draggable range example</h2>
Value: <pre>{{ priceSlider | json }}</pre>
<input type="text" ng-model="priceSlider.min"/><br/>
<input type="text" ng-model="priceSlider.max"/><br/>
<rzslider
rz-slider-draggable-range="true"
rz-slider-floor="priceSlider.floor"
rz-slider-ceil="priceSlider.ceil"
rz-slider-model="priceSlider.min"
rz-slider-high="priceSlider.max"
rz-slider-step="5"
rz-slider-tpl-url="rzSliderTpl.html"></rzslider>
</article>
</div>
</body>
......
......@@ -54,7 +54,6 @@ rzslider span.rz-bar {
rzslider span.rz-bar.rz-selection {
z-index: 1;
width: 0;
background: #0db9f0;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
......
/*! jusas-angularjs-slider - v0.1.24 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-12 */
rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:30px 0 15px 0;vertical-align:middle}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider span.rz-base{width:100%;height:100%;padding:0}rzslider span.rz-bar-wrapper{left:0;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider span.rz-bar{left:0;z-index:0;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-bar.rz-selection{z-index:1;width:0;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-pointer{top:-14px;z-index:2;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider span.rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider span.rz-pointer:hover:after{background-color:#fff}rzslider span.rz-pointer.rz-active:after{background-color:#451aff}rzslider span.rz-bubble{top:-32px;padding:1px 3px;color:#55637d;cursor:default}rzslider span.rz-bubble.rz-selection{top:16px}rzslider span.rz-bubble.rz-limit{color:#55637d}
\ No newline at end of file
/*! jusas-angularjs-slider - v0.1.25 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-19 */
rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:30px 0 15px 0;vertical-align:middle}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider span.rz-base{width:100%;height:100%;padding:0}rzslider span.rz-bar-wrapper{left:0;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider span.rz-bar{left:0;z-index:0;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-bar.rz-selection{z-index:1;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-pointer{top:-14px;z-index:2;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider span.rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider span.rz-pointer:hover:after{background-color:#fff}rzslider span.rz-pointer.rz-active:after{background-color:#451aff}rzslider span.rz-bubble{top:-32px;padding:1px 3px;color:#55637d;cursor:default}rzslider span.rz-bubble.rz-selection{top:16px}rzslider span.rz-bubble.rz-limit{color:#55637d}
\ No newline at end of file
This diff is collapsed.
......@@ -17,7 +17,7 @@ angular.module('rzModule', [])
.run(['$templateCache', function($templateCache) {
'use strict';
var template = '<span class="rz-bar-wrapper"><span class="rz-bar"></span></span>' + // 0 The slider bar
'<span class="rz-bar rz-selection"></span>' + // 1 Highlight between two handles
'<span class="rz-bar-wrapper"><span class="rz-bar rz-selection"></span></span>' + // 1 Highlight between two handles
'<span class="rz-pointer"></span>' + // 2 Left slider handle
'<span class="rz-pointer"></span>' + // 3 Right slider handle
'<span class="rz-bubble rz-limit"></span>' + // 4 Floor label
......@@ -115,6 +115,27 @@ function throttle(func, wait, options) {
*/
this.range = attributes.rzSliderHigh !== undefined && attributes.rzSliderModel !== undefined;
/**
* Whether to allow draggable range
*
* @type {boolean} Set to true for draggable range slider
*/
this.dragRange = this.range && attributes.rzSliderDraggableRange === 'true';
/**
* Values recorded when first dragging the bar
*
* @type {Object}
*/
this.dragging = {
active: false,
value: 0,
difference: 0,
offset: 0,
lowDist: 0,
highDist: 0
};
/**
* Half of the width of the slider handles
*
......@@ -510,6 +531,13 @@ function throttle(func, wait, options) {
this.maxH.remove();
this.selBar.remove();
}
// If using draggable range, use appropriate cursor for this.selBar.
if (this.dragRange)
{
this.selBar.css('cursor', 'move');
this.selBar.addClass('rz-draggable');
}
},
/**
......@@ -852,6 +880,26 @@ function throttle(func, wait, options) {
// Events
/**
* Get the X-coordinate of an event
*
* @param {Object} event The event
* @returns {number}
*/
getEventX: function(event)
{
/* http://stackoverflow.com/a/12336075/282882 */
//noinspection JSLint
if('clientX' in event)
{
return event.clientX;
}
return event.originalEvent === undefined ?
event.touches[0].clientX
: event.originalEvent.touches[0].clientX;
},
/**
* Bind mouse and touch events to slider handles
*
......@@ -859,19 +907,34 @@ function throttle(func, wait, options) {
*/
bindEvents: function()
{
var barTracking, barStart, barMove;
if (this.dragRange)
{
barTracking = 'rzSliderDrag';
barStart = this.onDragStart;
barMove = this.onDragMove;
}
else
{
barTracking = 'rzSliderModel';
barStart = this.onStart;
barMove = this.onMove;
}
this.minH.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if(this.range) { this.maxH.on('mousedown', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh')); }
this.fullBar.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.fullBar.on('mousedown', angular.bind(this, this.onMove, this.fullBar));
this.selBar.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.selBar.on('mousedown', angular.bind(this, this.onMove, this.selBar));
this.selBar.on('mousedown', angular.bind(this, barStart, this.minH, barTracking));
this.selBar.on('mousedown', angular.bind(this, barMove, this.selBar));
this.minH.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if(this.range) { this.maxH.on('touchstart', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh')); }
this.fullBar.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.fullBar.on('touchstart', angular.bind(this, this.onMove, this.fullBar));
this.selBar.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.selBar.on('touchstart', angular.bind(this, this.onMove, this.selBar));
this.selBar.on('touchstart', angular.bind(this, barStart, this.minH, barTracking));
this.selBar.on('touchstart', angular.bind(this, barMove, this.selBar));
},
/**
......@@ -899,7 +962,7 @@ function throttle(func, wait, options) {
pointer.addClass('rz-active');
ehMove = angular.bind(this, this.onMove, pointer);
ehMove = angular.bind(this, this.dragging.active ? this.onDragMove : this.onMove, pointer);
ehEnd = angular.bind(this, this.onEnd, ehMove);
$document.on(eventNames.moveEvent, ehMove);
......@@ -915,20 +978,8 @@ function throttle(func, wait, options) {
*/
onMove: function (pointer, event)
{
var eventX, sliderLO, newOffset, newValue;
/* http://stackoverflow.com/a/12336075/282882 */
//noinspection JSLint
if('clientX' in event)
{
eventX = event.clientX;
}
else
{
eventX = event.originalEvent === undefined ?
event.touches[0].clientX
: event.originalEvent.touches[0].clientX;
}
var eventX = this.getEventX(event),
sliderLO, newOffset, newValue;
sliderLO = this.sliderElem.rzsl;
newOffset = eventX - sliderLO - this.handleHalfWidth;
......@@ -955,6 +1006,92 @@ function throttle(func, wait, options) {
this.positionTrackingHandle(newValue, newOffset);
},
/**
* onDragStart event handler
*
* Handles dragging of the middle bar.
*
* @param {Object} pointer The jqLite wrapped DOM element
* @param {string} ref One of the refLow, refHigh values
* @param {Event} event The event
* @returns {undefined}
*/
onDragStart: function(pointer, ref, event)
{
var offset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth;
this.dragging = {
active: true,
value: this.offsetToValue(offset),
difference: this.scope.rzSliderHigh - this.scope.rzSliderModel,
offset: offset,
lowDist: offset - this.minH.rzsl,
highDist: this.maxH.rzsl - offset
};
this.minH.addClass('rz-active');
this.maxH.addClass('rz-active');
this.onStart(pointer, ref, event);
},
/**
* onDragMove event handler
*
* Handles dragging of the middle bar.
*
* @param {jqLite} pointer
* @param {Event} event The event
* @returns {undefined}
*/
onDragMove: function(pointer, event)
{
var newOffset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth,
newMinOffset, newMaxOffset,
newMinValue, newMaxValue;
if (newOffset <= this.dragging.lowDist)
{
if (pointer.rzsl === this.dragging.lowDist) { return; }
newMinValue = this.minValue;
newMinOffset = 0;
newMaxValue = this.dragging.difference;
newMaxOffset = this.valueToOffset(newMaxValue);
}
else if (newOffset >= this.maxLeft - this.dragging.highDist)
{
if (pointer.rzsl === this.dragging.highDist) { return; }
newMaxValue = this.maxValue;
newMaxOffset = this.maxLeft;
newMinValue = this.maxValue - this.dragging.difference;
newMinOffset = this.valueToOffset(newMinValue);
}
else
{
newMinValue = this.offsetToValue(newOffset - this.dragging.lowDist);
newMinValue = this.roundStep(newMinValue);
newMinOffset = this.valueToOffset(newMinValue);
newMaxValue = newMinValue + this.dragging.difference;
newMaxOffset = this.valueToOffset(newMaxValue);
}
this.positionTrackingBar(newMinValue, newMaxValue, newMinOffset, newMaxOffset);
},
/**
* Set the new value and offset for the entire bar
*
* @param {number} newMinValue the new minimum value
* @param {number} newMaxValue the new maximum value
* @param {number} newMinOffset the new minimum offset
* @param {number} newMaxOffset the new maximum offset
*/
positionTrackingBar: function(newMinValue, newMaxValue, newMinOffset, newMaxOffset)
{
this.scope.rzSliderModel = newMinValue;
this.scope.rzSliderHigh = newMaxValue;
this.updateHandles('rzSliderModel', newMinOffset);
this.updateHandles('rzSliderHigh', newMaxOffset);
this.scope.$apply();
},
/**
* Set the new value and offset to the current tracking handle
......@@ -964,7 +1101,7 @@ function throttle(func, wait, options) {
*/
positionTrackingHandle: function(newValue, newOffset)
{
if (this.range)
if(this.range)
{
/* This is to check if we need to switch the min and max handles*/
if (this.tracking === 'rzSliderModel' && newValue >= this.scope.rzSliderHigh)
......@@ -1015,6 +1152,8 @@ function throttle(func, wait, options) {
this.scope.$emit('slideEnded');
this.tracking = '';
this.dragging.active = false;
},
/**
......@@ -1059,6 +1198,7 @@ function throttle(func, wait, options) {
rzSliderPrecision: '@',
rzSliderModel: '=?',
rzSliderHigh: '=?',
rzSliderDraggable: '@',
rzSliderTranslate: '&',
rzSliderHideLimitLabels: '=?',
rzSliderAlwaysShowBar: '=?',
......
......@@ -69,7 +69,6 @@ rzslider span.rz-bar {
}
rzslider span.rz-bar.rz-selection {
width: 0%;
z-index: 1;
background: @barFillColor;
.rounded(@barHeight/2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment