Slider: add support for crossing multiple handles

With this patch, a slider which has both "range = true" and
"allowCrossingHandles = true" automatically determines the handlers
starting and stopping the range. Handlers can freely cross each other.
This commit is contained in:
Sylvain Henry 2018-08-14 12:54:21 +02:00
parent 74f8a0ac95
commit c7facf847f
3 changed files with 55 additions and 14 deletions

View File

@ -22,6 +22,7 @@ common.testWidget( "slider", {
step: 1, step: 1,
value: 0, value: 0,
values: null, values: null,
allowCrossingHandles: false,
// Callbacks // Callbacks
create: null, create: null,

View File

@ -401,4 +401,24 @@ QUnit.test( "range", function( assert ) {
element.slider( "destroy" ); element.slider( "destroy" );
} ); } );
QUnit.test( "allowCrossingHandles", function( assert ) {
assert.expect( 1 );
element = $( "<div></div>" ).slider( {
range: true,
min: 0,
max: 100,
values: [ 25, 75 ],
allowCrossingHandles: true
} );
assert.deepEqual( element.slider( "values" ), [ 25, 75 ], "values" );
// var handles = element.find( ".ui-slider-handle" );
// handles.eq( 0 ).simulate( "drag", { dx: 1000 } );
// assert.deepEqual( element.slider( "values" ), [ 100, 75 ], "values" );
element.slider( "destroy" );
} );
} ); } );

View File

@ -53,6 +53,7 @@ return $.widget( "ui.slider", $.ui.mouse, {
min: 0, min: 0,
orientation: "horizontal", orientation: "horizontal",
range: false, range: false,
allowCrossingHandles: false,
step: 1, step: 1,
value: 0, value: 0,
values: null, values: null,
@ -330,11 +331,14 @@ return $.widget( "ui.slider", $.ui.mouse, {
newValues = this.values(); newValues = this.values();
if ( this._hasMultipleValues() ) { if ( this._hasMultipleValues() ) {
otherVal = this.values( index ? 0 : 1 ); if ( !this.options.allowCrossingHandles ) {
currentValue = this.values( index ); otherVal = this.values( index ? 0 : 1 );
currentValue = this.values( index );
if ( this.options.values.length === 2 && this.options.range === true ) { if ( this.options.values.length === 2 && this.options.range === true ) {
newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); newVal = index === 0 ? Math.min( otherVal, newVal )
: Math.max( otherVal, newVal );
}
} }
newValues[ index ] = newVal; newValues[ index ] = newVal;
@ -473,6 +477,7 @@ return $.widget( "ui.slider", $.ui.mouse, {
this._animateOff = false; this._animateOff = false;
break; break;
case "range": case "range":
case "allowCrossingHandles":
this._animateOff = true; this._animateOff = true;
this._refresh(); this._refresh();
this._animateOff = false; this._animateOff = false;
@ -590,7 +595,9 @@ return $.widget( "ui.slider", $.ui.mouse, {
}, },
_refreshValue: function() { _refreshValue: function() {
var lastValPercent, valPercent, value, valueMin, valueMax, var valPercent, value, valueMin, valueMax,
rangeStartIndex = 0,
rangeStopIndex = 1,
oRange = this.options.range, oRange = this.options.range,
o = this.options, o = this.options,
that = this, that = this,
@ -599,34 +606,48 @@ return $.widget( "ui.slider", $.ui.mouse, {
if ( this._hasMultipleValues() ) { if ( this._hasMultipleValues() ) {
this.handles.each( function( i ) { this.handles.each( function( i ) {
valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - if ( that.values( i ) > that.values( rangeStopIndex ) ) {
that._valueMin() ) * 100; rangeStopIndex = i;
}
if ( that.values( i ) < that.values( rangeStartIndex ) ) {
rangeStartIndex = i;
}
} );
this.handles.each( function( i ) {
var valPercentStart;
var computeValPercent = function( idx ) {
return ( that.values( idx ) - that._valueMin() ) / ( that._valueMax() -
that._valueMin() ) * 100;
};
valPercent = computeValPercent( i );
_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
if ( that.options.range === true ) { if ( that.options.range === true ) {
if ( that.orientation === "horizontal" ) { if ( that.orientation === "horizontal" ) {
if ( i === 0 ) { if ( i === rangeStartIndex ) {
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
left: valPercent + "%" left: valPercent + "%"
}, o.animate ); }, o.animate );
} }
if ( i === 1 ) { if ( i === rangeStopIndex ) {
valPercentStart = computeValPercent( rangeStartIndex );
that.range[ animate ? "animate" : "css" ]( { that.range[ animate ? "animate" : "css" ]( {
width: ( valPercent - lastValPercent ) + "%" width: Math.abs ( valPercent - valPercentStart ) + "%"
}, { }, {
queue: false, queue: false,
duration: o.animate duration: o.animate
} ); } );
} }
} else { } else {
if ( i === 0 ) { if ( i === rangeStartIndex ) {
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
bottom: ( valPercent ) + "%" bottom: ( valPercent ) + "%"
}, o.animate ); }, o.animate );
} }
if ( i === 1 ) { if ( i === rangeStopIndex ) {
valPercentStart = computeValPercent( rangeStartIndex );
that.range[ animate ? "animate" : "css" ]( { that.range[ animate ? "animate" : "css" ]( {
height: ( valPercent - lastValPercent ) + "%" height: Math.abs ( valPercent - valPercentStart ) + "%"
}, { }, {
queue: false, queue: false,
duration: o.animate duration: o.animate
@ -634,7 +655,6 @@ return $.widget( "ui.slider", $.ui.mouse, {
} }
} }
} }
lastValPercent = valPercent;
} ); } );
} else { } else {
value = this.value(); value = this.value();