Skip to content

Commit

Permalink
Started work on #208, #221, #236, #265
Browse files Browse the repository at this point in the history
  • Loading branch information
leongersen committed May 18, 2014
1 parent cdeac7a commit e9b34ab
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 88 deletions.
17 changes: 16 additions & 1 deletion Link.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,19 @@ var
return;
}

// Store the numerical value.
this.actual = value;

// Format values for display.
value = this.format( value );

// Store the numerical value.
// Store the formatted value.
this.saved = value;

// Store parameters for use in reset()
this.resetHandle = handle;
this.resetSlider = slider;

// Branch between serialization to a function or an object.
if ( typeof this.method === 'function' ) {
// When target is undefined, the target was a function.
Expand Down Expand Up @@ -375,11 +380,21 @@ var
return this.formatting.to(a);
};

// Allow calling the 'write' method from cache.
Link.prototype.reset = function ( update ) {
this.write( this.actual, this.resetHandle, this.resetSlider, update );
};

// Converts a formatted value back to a real number.
Link.prototype.getValue = function ( a ) {
return this.formatting.from(a);
};

// Return saved (formatted) value.
Link.prototype.getSaved = function ( a ) {
return this.saved;
};

// We can now test for Link.init to be an instance of Link.
Link.prototype.init.prototype = Link.prototype;

Expand Down
205 changes: 118 additions & 87 deletions jquery.nouislider.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,25 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
return isPercentage([va, vb], (value - pa) * subRangeRatio (pa, pb));
}

// (percentage) Get the step that applies at a certain value.
function getStep ( options, value ){
// (j) Get the applicable step position.
function getStepPoint ( options, value ) {

var j = 1, a, b;
var j = 1;

// Find the proper step for rtl sliders by search in inverse direction.
// Fixes issue #262.
while ( (options.dir ? (100 - value) : value) >= options.xPct[j] ){
j++;
}

return j;
}

// (percentage) Get the step that applies at a certain value.
function getStep ( options, value ){

var j = getStepPoint( options, value ), a, b;

if ( options.snap ) {

a = options.xPct[j-1];
Expand Down Expand Up @@ -323,6 +331,9 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
}
});

// Store the actual step values.
parsed.xNumSteps = parsed.xSteps.slice(0);

$.each(parsed.xSteps, function(i,n){

// Ignore 'false' stepping.
Expand Down Expand Up @@ -512,10 +523,11 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
object, to make sure all values can be correctly looped elsewhere. */

var parsed = {
xPct: []
,xVal: []
,xSteps: [ false ]
,margin: 0
xPct: [],
xVal: [],
xSteps: [ false ],
xNumSteps: [ false ],
margin: 0
}, tests;

// Tests are executed in the order they are presented here.
Expand Down Expand Up @@ -552,6 +564,7 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
// be handled properly. E.g. wrapping integers in arrays.
$.each( tests, function( name, test ){

// If the option isn't set, but it is required, throw an error.
if ( options[name] === undefined ) {

if ( test.r ) {
Expand Down Expand Up @@ -717,8 +730,9 @@ function closure ( target, options, originalOptions ){
}


// External event handling
// Helpers

// External event handling
function fireEvents ( events ) {

// Use the external api to get the values.
Expand All @@ -731,37 +745,47 @@ function closure ( target, options, originalOptions ){
}
}

// Check if the range is effectively 0.
function isNullRange ( ) {
return options.xVal.length === 2 && options.xVal[0] === options.xVal[1];
}


// Handle placement

// Test suggested values and apply margin, step.
function setHandle ( handle, to, delimit ) {
function setHandle ( handle, to ) {

var n = handle[0] !== $Handles[0][0] ? 1 : 0,
lower = $Locations[0] + options.margin,
upper = $Locations[1] - options.margin;

// Don't delimit range dragging.
if ( delimit && $Handles.length > 1 ) {
to = n ? Math.max( to, lower ) : Math.min( to, upper );
}
// Check if the slider has no range. If so, lock in the center.
if ( isNullRange() ) {

// Handle the step option.
if ( to < 100 ){
to = getStep(options, to);
}
to = 50;

} else {

// For sliders with multiple handles,
// limit movement to the other handle.
if ( $Handles.length > 1 ) {
to = n ? Math.max( to, lower ) : Math.min( to, upper );
}

// Handle the step option.
if ( to < 100 ){
to = getStep(options, to);
}

// Limit to 0/100 for .val input, trim anything beyond 7 digits, as
// JavaScript has some issues in its floating point implementation.
to = limit(parseFloat(to.toFixed(7)));
// Limit to 0/100 for .val input, trim anything beyond 7 digits, as
// JavaScript has some issues in its floating point implementation.
to = limit(parseFloat(to.toFixed(7)));

// Return falsy if handle can't move. False for 0 or 100 limit,
// '0' for limiting by another handle.
if ( to === $Locations[n] ) {
if ( $Handles.length === 1 ) {
// Return false if handle can't move.
if ( to === $Locations[n] ) {
return false;
}
return ( to === lower || to === upper ) ? 0 : false;
}

// Set the handle to the new position.
Expand Down Expand Up @@ -823,7 +847,7 @@ function closure ( target, options, originalOptions ){
}

// Move the handle to the new position.
setHandle( handle, to, false );
setHandle( handle, to );

fireEvents(['slide', 'set', 'change']);
}
Expand All @@ -834,20 +858,27 @@ function closure ( target, options, originalOptions ){
// Handler for attaching events trough a proxy.
function attach ( events, element, callback, data ) {

// This function can be used to 'filter' events to the slider.

// Add the noUiSlider namespace to all events.
events = events.replace( /\s/g, namespace + ' ' ) + namespace;

// Bind a closure on the target.
return element.on( events, function( e ){

// jQuery and Zepto handle unset attributes differently.
var disabled = $Target.attr('disabled');
disabled = !( disabled === undefined || disabled === null );
// jQuery and Zepto (1) handle unset attributes differently,
// but always falsy; #208
if ( !!$Target.attr('disabled') ) {
return false;
}

// Stop if an active 'tap' transition is taking place.
if ( $Target.hasClass( Classes[14] ) ) {
return false;
}

// Test if there is anything that should prevent an event
// from being handled, such as a disabled state or an active
// 'tap' transition.
if( $Target.hasClass( Classes[14] ) || disabled ) {
// Ignore all events if the range is effectively 0. #236
if ( isNullRange() ) {
return false;
}

Expand All @@ -869,10 +900,10 @@ function closure ( target, options, originalOptions ){
// Calculate relative positions for the handles.
positions = getPositions( proposal, data.positions, handles.length > 1);

state = setHandle ( handles[0], positions[h], handles.length === 1 );
state = setHandle ( handles[0], positions[h] );

if ( handles.length > 1 ) {
state = setHandle ( handles[1], positions[h?0:1], false ) || state;
state = setHandle ( handles[1], positions[h?0:1] ) || state;
}

// Fire the 'slide' event if any handle moved.
Expand Down Expand Up @@ -1041,6 +1072,38 @@ function closure ( target, options, originalOptions ){
}


// Helpers

// Set handles from the .val method.
function loopValues ( i, values, link, update ) {

// Use the passed link, or default to the first one,
// which stores the value.
link = link || $Serialization[i%2][0];

var to = link.getValue( values[i%2] );

if ( to !== false ) {

// Calculate the new handle position
to = toStepping( options, to );

// Invert the value if this is a right-to-left slider.
if ( options.dir ) {
to = 100 - to;
}

// Set the handle.
if ( setHandle( $Handles[i%2], to ) === true ) {
return;
}
}

// If it the handle cannot be set, correct the Link.
link.reset( update );
}


// Initialize slider

// Throw an error if the slider was already initialized.
Expand Down Expand Up @@ -1068,19 +1131,13 @@ function closure ( target, options, originalOptions ){
target.vSet = function ( ) {

var args = Array.prototype.slice.call( arguments, 0 ),
callback, link, update, animate,
i, count, actual, to, values = asArray( args[0] );

// Extract modifiers for value method.
if ( typeof args[1] === 'object' ) {
callback = args[1]['set'];
link = args[1]['link'];
update = args[1]['update'];
animate = args[1]['animate'];
i, count, values = asArray( args[0] );

// Support the 'true' option.
} else if ( args[1] === true ) {
callback = true;
if ( args[1] === true ) {
args[1] = { 'set': true };
} else if ( typeof args[1] !== 'object' ) {
args[1] = {};
}

// The RTL settings is implemented by reversing the front-end,
Expand All @@ -1090,7 +1147,7 @@ function closure ( target, options, originalOptions ){
}

// Animation is optional.
if ( animate ) {
if ( args[1]['animate'] ) {
addClassFor( $Target, Classes[14], 300 );
}

Expand All @@ -1104,46 +1161,11 @@ function closure ( target, options, originalOptions ){
// mechanism twice for the first handle, to make sure it
// can be bounced of the second one properly.
for ( i = 0; i < count; i++ ) {

to = link || $Serialization[i%2][0];
to = to.getValue( values[i%2] );

if ( to === false ) {
continue;
}

// Calculate the new handle position
to = toStepping( options, to );

// Invert the value if this is a right-to-left slider.
if ( options.dir ) {
to = 100 - to;
}

// Force delimitation.
if ( setHandle( $Handles[i%2], to, true ) === true ) {
continue;
}

// Reset the input if it doesn't match the slider.
$($Serialization[i%2]).each(function(index){

if (!index) {
actual = this.actual;
return true;
}

this.write(
actual,
$Handles[i%2].children(),
$Target,
update
);
});
loopValues( i, values, args[1]['link'], args[1]['update'] );
}

// Optionally fire the 'set' event.
if( callback === true ) {
if ( args[1]['set'] === true ) {
fireEvents(['set']);
}

Expand All @@ -1158,7 +1180,7 @@ function closure ( target, options, originalOptions ){

// Get the value from all handles.
for ( i = 0; i < options.handles; i++ ){
retour[i] = $Serialization[i][0].saved;
retour[i] = $Serialization[i][0].getSaved();
}

// If only one handle is used, return a single value.
Expand Down Expand Up @@ -1197,8 +1219,17 @@ function closure ( target, options, originalOptions ){
return originalOptions;
};

// Get the current step size for the slider.
/** @expose */
target.getStep = function ( ) {

// Check all locations, map them to their stepping point.
return $.map($Locations, function( value ){
// Get the step point, then find it in the input list.
return options.xNumSteps[getStepPoint(options, value) - 1];
});
};

// Value setting

// Use the public value method to set the start values.
$Target.val( options.start );
Expand Down Expand Up @@ -1255,7 +1286,7 @@ function closure ( target, options, originalOptions ){

// Override the .val() method. Test every element. Is it a slider? Go to
// the slider value handling. No? Use the standard method.
// Note how $.fn.val extects 'this' to be an instance of $. For convenience,
// Note how $.fn.val expects 'this' to be an instance of $. For convenience,
// the above 'value' function does too.
$.fn.val = function ( ) {

Expand Down
Loading

0 comments on commit e9b34ab

Please sign in to comment.