@@ -708,6 +708,7 @@ function testBehaviour(parsed, entry) {
708708 var snap = entry . indexOf ( "snap" ) >= 0 ;
709709 var hover = entry . indexOf ( "hover" ) >= 0 ;
710710 var unconstrained = entry . indexOf ( "unconstrained" ) >= 0 ;
711+ var invertConnects = entry . indexOf ( "invert-connects" ) >= 0 ;
711712 var dragAll = entry . indexOf ( "drag-all" ) >= 0 ;
712713 var smoothSteps = entry . indexOf ( "smooth-steps" ) >= 0 ;
713714 if ( fixed ) {
@@ -717,6 +718,9 @@ function testBehaviour(parsed, entry) {
717718 // Use margin to enforce fixed state
718719 testMargin ( parsed , parsed . start [ 1 ] - parsed . start [ 0 ] ) ;
719720 }
721+ if ( invertConnects && parsed . handles !== 2 ) {
722+ throw new Error ( "noUiSlider: 'invert-connects' behaviour must be used with 2 handles" ) ;
723+ }
720724 if ( unconstrained && ( parsed . margin || parsed . limit ) ) {
721725 throw new Error ( "noUiSlider: 'unconstrained' behaviour cannot be used with margin or limit" ) ;
722726 }
@@ -729,6 +733,7 @@ function testBehaviour(parsed, entry) {
729733 snap : snap ,
730734 hover : hover ,
731735 unconstrained : unconstrained ,
736+ invertConnects : invertConnects ,
732737 } ;
733738}
734739function testTooltips ( parsed , entry ) {
@@ -899,6 +904,7 @@ function scope(target, options, originalOptions) {
899904 // Slider DOM Nodes
900905 var scope_Target = target ;
901906 var scope_Base ;
907+ var scope_ConnectBase ;
902908 var scope_Handles ;
903909 var scope_Connects ;
904910 var scope_Pips ;
@@ -910,6 +916,7 @@ function scope(target, options, originalOptions) {
910916 var scope_HandleNumbers = [ ] ;
911917 var scope_ActiveHandlesCount = 0 ;
912918 var scope_Events = { } ;
919+ var scope_ConnectsInverted = false ;
913920 // Document Nodes
914921 var scope_Document = target . ownerDocument ;
915922 var scope_DocumentElement = options . documentElement || scope_Document . documentElement ;
@@ -966,17 +973,17 @@ function scope(target, options, originalOptions) {
966973 }
967974 // Add handles to the slider base.
968975 function addElements ( connectOptions , base ) {
969- var connectBase = addNodeTo ( base , options . cssClasses . connects ) ;
976+ scope_ConnectBase = addNodeTo ( base , options . cssClasses . connects ) ;
970977 scope_Handles = [ ] ;
971978 scope_Connects = [ ] ;
972- scope_Connects . push ( addConnect ( connectBase , connectOptions [ 0 ] ) ) ;
979+ scope_Connects . push ( addConnect ( scope_ConnectBase , connectOptions [ 0 ] ) ) ;
973980 // [::::O====O====O====]
974981 // connectOptions = [0, 1, 1, 1]
975982 for ( var i = 0 ; i < options . handles ; i ++ ) {
976983 // Keep a list of all added handles.
977984 scope_Handles . push ( addOrigin ( base , i ) ) ;
978985 scope_HandleNumbers [ i ] = i ;
979- scope_Connects . push ( addConnect ( connectBase , connectOptions [ i + 1 ] ) ) ;
986+ scope_Connects . push ( addConnect ( scope_ConnectBase , connectOptions [ i + 1 ] ) ) ;
980987 }
981988 }
982989 // Initialize a single slider.
@@ -1925,8 +1932,26 @@ function scope(target, options, originalOptions) {
19251932 var translation = transformDirection ( to , 0 ) - scope_DirOffset ;
19261933 var translateRule = "translate(" + inRuleOrder ( translation + "%" , "0" ) + ")" ;
19271934 scope_Handles [ handleNumber ] . style [ options . transformRule ] = translateRule ;
1935+ // sanity check for at least 2 handles (e.g. during setup)
1936+ if ( options . events . invertConnects && scope_Locations . length > 1 ) {
1937+ // check if handles passed each other, but don't match the ConnectsInverted state
1938+ var handlesAreInOrder = scope_Locations . every ( function ( position , index , locations ) {
1939+ return index === 0 || position >= locations [ index - 1 ] ;
1940+ } ) ;
1941+ if ( scope_ConnectsInverted !== ! handlesAreInOrder ) {
1942+ // invert connects when handles pass each other
1943+ invertConnects ( ) ;
1944+ // invertConnects already updates all connect elements
1945+ return ;
1946+ }
1947+ }
19281948 updateConnect ( handleNumber ) ;
19291949 updateConnect ( handleNumber + 1 ) ;
1950+ if ( scope_ConnectsInverted ) {
1951+ // When connects are inverted, we also have to update adjacent connects
1952+ updateConnect ( handleNumber - 1 ) ;
1953+ updateConnect ( handleNumber + 2 ) ;
1954+ }
19301955 }
19311956 // Handles before the slider middle are stacked later = higher,
19321957 // Handles after the middle later is lower
@@ -1956,13 +1981,20 @@ function scope(target, options, originalOptions) {
19561981 if ( ! scope_Connects [ index ] ) {
19571982 return ;
19581983 }
1984+ // Create a copy of locations, so we can sort them for the local scope logic
1985+ var locations = scope_Locations . slice ( ) ;
1986+ if ( scope_ConnectsInverted ) {
1987+ locations . sort ( function ( a , b ) {
1988+ return a - b ;
1989+ } ) ;
1990+ }
19591991 var l = 0 ;
19601992 var h = 100 ;
19611993 if ( index !== 0 ) {
1962- l = scope_Locations [ index - 1 ] ;
1994+ l = locations [ index - 1 ] ;
19631995 }
19641996 if ( index !== scope_Connects . length - 1 ) {
1965- h = scope_Locations [ index ] ;
1997+ h = locations [ index ] ;
19661998 }
19671999 // We use two rules:
19682000 // 'translate' to change the left/top offset;
@@ -2154,6 +2186,7 @@ function scope(target, options, originalOptions) {
21542186 "format" ,
21552187 "pips" ,
21562188 "tooltips" ,
2189+ "connect" ,
21572190 ] ;
21582191 // Only change options that we're actually passed to update.
21592192 updateAble . forEach ( function ( name ) {
@@ -2191,6 +2224,32 @@ function scope(target, options, originalOptions) {
21912224 // Invalidate the current positioning so valueSet forces an update.
21922225 scope_Locations = [ ] ;
21932226 valueSet ( isSet ( optionsToUpdate . start ) ? optionsToUpdate . start : v , fireSetEvent ) ;
2227+ // Update connects only if it was set
2228+ if ( optionsToUpdate . connect ) {
2229+ updateConnectOption ( ) ;
2230+ }
2231+ }
2232+ function updateConnectOption ( ) {
2233+ // IE supported way of removing children including event handlers
2234+ while ( scope_ConnectBase . firstChild ) {
2235+ scope_ConnectBase . removeChild ( scope_ConnectBase . firstChild ) ;
2236+ }
2237+ // Adding new connects according to the new connect options
2238+ for ( var i = 0 ; i <= options . handles ; i ++ ) {
2239+ scope_Connects [ i ] = addConnect ( scope_ConnectBase , options . connect [ i ] ) ;
2240+ updateConnect ( i ) ;
2241+ }
2242+ // re-adding drag events for the new connect elements
2243+ // to ignore the other events we have to negate the 'if (!behaviour.fixed)' check
2244+ bindSliderEvents ( { drag : options . events . drag , fixed : true } ) ;
2245+ }
2246+ // Invert options for connect handles
2247+ function invertConnects ( ) {
2248+ scope_ConnectsInverted = ! scope_ConnectsInverted ;
2249+ testConnect ( options ,
2250+ // inverse the connect boolean array
2251+ options . connect . map ( function ( b ) { return ! b ; } ) ) ;
2252+ updateConnectOption ( ) ;
21942253 }
21952254 // Initialization steps
21962255 function setupSlider ( ) {
0 commit comments