react-slider
Advanced tools
Comparing version 0.3.2 to 0.3.3
{ | ||
"name": "react-slider", | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"description": "Slider component for React", | ||
@@ -5,0 +5,0 @@ "main": "react-slider.js", |
@@ -23,45 +23,3 @@ (function (root, factory) { | ||
// These functions allow to treat a single value and an array of values equally: | ||
// e.g. map(5, x => x + 1) returns 6 | ||
// map([5, 6, 7], x => x + 1) returns [6, 7, 8] | ||
/** | ||
* Apply `f` to each value in `v` or call `f` with `v` directly if it is a single value. | ||
*/ | ||
function map(v, f, context) { | ||
return (v && v.map) ? v.map(f, context) : f.call(context, v, 0); | ||
} | ||
/** | ||
* Reduce `v` with `f` and `init` or call `f` directly with `init` and `v` if it is a single value. | ||
*/ | ||
function reduce(v, f, init) { | ||
return (v && v.reduce) ? v.reduce(f, init) : f(init, v, 0); | ||
} | ||
/** | ||
* Returns the size of `v` if it is an array, or 1 if it is a single value or 0 if it does not exists. | ||
*/ | ||
function size(v) { | ||
return v != null ? v.length ? v.length : 1 : 0; | ||
} | ||
/** | ||
* Returns the value at `i` if `v` is an array. Just returns the value otherwise. | ||
*/ | ||
function at(v, i) { | ||
return v && v.map ? v[i] : v; | ||
} | ||
/** | ||
* Compares `a` and `b` which can be either single values or an array of values. | ||
*/ | ||
function is(a, b) { | ||
return size(a) === size(b) && | ||
reduce(a, function (res, v, i) { | ||
return res && v === at(b, i) | ||
}, true); | ||
} | ||
/** | ||
* Spreads `count` values equally between `min` and `max`. | ||
@@ -78,14 +36,10 @@ */ | ||
/** | ||
* If `v` is an array, returns a copy of `v` with the `i`th element set to `newv`. Otherwise returns `newv`. | ||
*/ | ||
function insteadOf(v, i, newv) { | ||
if (v.length) { | ||
v = v.slice(); | ||
v[i] = newv; | ||
return v; | ||
} else | ||
return newv; | ||
function ensureArray(x) { | ||
return Array.isArray(x) ? x : [x]; | ||
} | ||
function undoEnsureArray(x) { | ||
return x.length === 1 ? x[0] : x; | ||
} | ||
var ReactSlider = React.createClass({ | ||
@@ -138,13 +92,15 @@ displayName: 'ReactSlider', | ||
getInitialState: function () { | ||
//var value = this._or(this.props.value, this.props.defaultValue); | ||
var value = map(this._or(this.props.value, this.props.defaultValue), this._trimAlignValue); | ||
var value = ensureArray(this.props.value); | ||
var defaultValue = ensureArray(this.props.defaultValue); | ||
value = this._or(value, defaultValue).map(function (v) { | ||
return this._trimAlignValue(v, this.props); | ||
}, this); | ||
return { | ||
index: -1, // TODO: find better solution | ||
min: this._trimAlignValue(this.props.min), | ||
max: this._trimAlignValue(this.props.max), | ||
index: -1, | ||
upperBound: 0, | ||
sliderLength: 0, | ||
value: value, | ||
zIndices: reduce(value, function (acc, x, i) { | ||
zIndices: value.reduce(function (acc, x, i) { | ||
acc.push(i); | ||
@@ -159,5 +115,7 @@ return acc; | ||
componentWillReceiveProps: function (newProps) { | ||
this.state.value = map(this._or(newProps.value, this.state.value), this._trimAlignValue); | ||
this.state.min = this._trimAlignValue(newProps.min); | ||
this.state.max = this._trimAlignValue(newProps.max); | ||
var value = this._or(ensureArray(newProps.value), this.state.value); | ||
this.state.value = value.map(function (v) { | ||
return this._trimAlignValue(v, newProps); | ||
}, this); | ||
}, | ||
@@ -173,8 +131,8 @@ | ||
return value != null ? value : defaultValue; | ||
case size(value): | ||
case value.length: | ||
return value; | ||
case size(defaultValue): | ||
case defaultValue.length: | ||
return defaultValue; | ||
default: | ||
if (size(value) !== count || size(defaultValue) !== count) { | ||
if (value.length !== count || defaultValue.length !== count) { | ||
console.warn("ReactSlider: Number of values does not match number of children."); | ||
@@ -189,7 +147,2 @@ } | ||
this._handleResize(); | ||
// values could have changed due to `this._trimAlignValue`. | ||
if (this.props.onChange && !is(this.props.value, this.state.value)) { | ||
this.props.onChange(this.state.value); | ||
} | ||
}, | ||
@@ -202,3 +155,3 @@ | ||
getValue: function () { | ||
return this.state.value | ||
return undoEnsureArray(this.state.value); | ||
}, | ||
@@ -211,9 +164,6 @@ | ||
var size = { | ||
horizontal: 'clientWidth', | ||
vertical: 'clientHeight' | ||
}[this.props.orientation]; | ||
var size = this._sizeKey(); | ||
var sliderMax = rect[this._max()] - handle[size]; | ||
var sliderMin = rect[this._min()]; | ||
var sliderMax = rect[this._posMaxKey()] - handle[size]; | ||
var sliderMin = rect[this._posMinKey()]; | ||
@@ -230,3 +180,3 @@ this.setState({ | ||
_calcOffset: function (value) { | ||
var ratio = (value - this.state.min) / (this.state.max - this.state.min); | ||
var ratio = (value - this.props.min) / (this.props.max - this.props.min); | ||
return ratio * this.state.upperBound; | ||
@@ -242,22 +192,18 @@ }, | ||
_buildHandleStyle: function (offset, i) { | ||
var transform = 'translate' + this._axis() + '(' + offset + 'px)'; | ||
return { | ||
WebkitTransform: transform, | ||
MozTransform: transform, | ||
msTransform: transform, | ||
OTransform: transform, | ||
transform: transform, | ||
var style = { | ||
position: 'absolute', | ||
willChange: this.state.index >= 0 ? 'transform' : '', | ||
willChange: this.state.index >= 0 ? this._posMinKey() : '', | ||
zIndex: this.state.zIndices.indexOf(i) + 1 | ||
} | ||
}; | ||
style[this._posMinKey()] = offset + 'px'; | ||
return style; | ||
}, | ||
_buildBarStyle: function (minMax) { | ||
_buildBarStyle: function (min, max) { | ||
var obj = { | ||
position: 'absolute', | ||
willChange: this.state.index >= 0 ? this._min() + ',' + this._max() : '' | ||
willChange: this.state.index >= 0 ? this._posMinKey() + ',' + this._posMaxKey() : '' | ||
}; | ||
obj[this._min()] = minMax.min; | ||
obj[this._max()] = minMax.max; | ||
obj[this._posMinKey()] = min; | ||
obj[this._posMaxKey()] = max; | ||
return obj; | ||
@@ -268,3 +214,3 @@ }, | ||
// TODO: No need to iterate all | ||
return reduce(this.state.value, function (min, value, i) { | ||
return this.state.value.reduce(function (min, value, i) { | ||
var minDist = min[1]; | ||
@@ -286,35 +232,51 @@ | ||
var nextValue = this._trimAlignValue(this._calcValue(pixelOffset)); | ||
var value = this.state.value; | ||
value[closestIndex] = nextValue; | ||
this.setState({ | ||
value: insteadOf(this.state.value, closestIndex, nextValue) | ||
}, function () { | ||
if (typeof callback === 'function') | ||
callback(closestIndex); | ||
}); | ||
this.setState({value: value}, callback.bind(this, closestIndex)); | ||
}, | ||
_dragStart: function (i) { | ||
if (this.props.disabled) return; | ||
_getMousePosition: function (e) { | ||
return e['page' + this._axisKey()]; | ||
}, | ||
return function (e) { | ||
var position = e['page' + this._axis()]; | ||
this._start(i, position); | ||
_getTouchPosition: function (e) { | ||
var last = e.changedTouches[e.changedTouches.length - 1]; | ||
return last['page' + this._axisKey()]; | ||
}, | ||
document.addEventListener('mousemove', this._dragMove, false); | ||
document.addEventListener('mouseup', this._dragEnd, false); | ||
_getMouseEventMap: function () { | ||
return { | ||
'mousemove': this._onMouseMove, | ||
'mouseup': this._onMouseUp | ||
} | ||
}, | ||
pauseEvent(e); | ||
}.bind(this); | ||
_getTouchEventMap: function () { | ||
return { | ||
'touchmove': this._onTouchMove, | ||
'tochend': this._onTouchEnd | ||
} | ||
}, | ||
_touchStart: function (i) { | ||
_createOnMouseDown: function (i) { | ||
return this._createOnStart(i, this._getMousePosition, this._getMouseEventMap()) | ||
}, | ||
_createOnTouchStart: function (i) { | ||
return this._createOnStart(i, this._getTouchPosition, this._getTouchEventMap()) | ||
}, | ||
_createOnStart: function (i, getPosition, eventMap) { | ||
if (this.props.disabled) return; | ||
return function (e) { | ||
var last = e.changedTouches[e.changedTouches.length - 1]; | ||
var position = last['page' + this._axis()]; | ||
document.activeElement.blur(); | ||
var position = getPosition(e); | ||
this._start(i, position); | ||
document.addEventListener('touchmove', this._touchMove, false); | ||
document.addEventListener('touchend', this._touchEnd, false); | ||
for (var key in eventMap) { | ||
document.addEventListener(key, eventMap[key], false); | ||
} | ||
@@ -331,3 +293,3 @@ pauseEvent(e); | ||
this.setState({ | ||
startValue: at(this.state.value, i), | ||
startValue: this.state.value[i], | ||
startPosition: position, | ||
@@ -339,59 +301,53 @@ index: i, | ||
_dragEnd: function () { | ||
document.removeEventListener('mousemove', this._dragMove, false); | ||
document.removeEventListener('mouseup', this._dragEnd, false); | ||
this._end(); | ||
_onMouseUp: function () { | ||
this._onEnd(this._getMouseEventMap()); | ||
}, | ||
_touchEnd: function () { | ||
document.removeEventListener('touchmove', this._touchMove, false); | ||
document.removeEventListener('touchend', this._touchEnd, false); | ||
this._end(); | ||
_onTouchEnd: function () { | ||
this._onEnd(this._getTouchEventMap()); | ||
}, | ||
_end: function () { | ||
this.setState({ | ||
index: -1 | ||
}); | ||
_onEnd: function (eventMap) { | ||
for (var key in eventMap) { | ||
document.removeEventListener(key, eventMap[key], false); | ||
} | ||
if (this.props.onChanged) { | ||
this.props.onChanged(this.state.value); | ||
} | ||
this.setState({index: -1}); | ||
this._fireEvent('onChanged'); | ||
}, | ||
_dragMove: function (e) { | ||
var position = e['page' + this._axis()]; | ||
_onMouseMove: function (e) { | ||
var position = this._getMousePosition(e); | ||
this._move(this.state.index, position); | ||
}, | ||
_touchMove: function (e) { | ||
var last = e.changedTouches[e.changedTouches.length - 1]; | ||
var position = last['page' + this._axis()]; | ||
_onTouchMove: function (e) { | ||
var position = this._getTouchPosition(e); | ||
this._move(this.state.index, position); | ||
e.preventDefault(); | ||
}, | ||
_move: function (i, position) { | ||
_move: function (index, position) { | ||
if (this.props.disabled) return; | ||
var lastValue = this.state.value; | ||
var nextValue = map(this.state.value, function (value, j) { | ||
if (i !== j) return value; | ||
var nextValue = this.state.value.map(function (v, i) { | ||
if (index !== i) return v; | ||
var diffPosition = position - this.state.startPosition; | ||
var diffValue = (diffPosition / this.state.sliderLength) * (this.state.max - this.state.min); | ||
var nextValue = this._trimAlignValue(this.state.startValue + diffValue); | ||
var diffValue = (diffPosition / this.state.sliderLength) * (this.props.max - this.props.min); | ||
var nv = this.state.startValue + diffValue; | ||
if (!this.props.pearling) { | ||
if (i > 0) { | ||
var valueBefore = at(this.state.value, i - 1); | ||
if (nextValue < valueBefore + this.props.minDistance) { | ||
nextValue = this._trimAlignValue(valueBefore + this.props.minDistance); | ||
if (index > 0) { | ||
var valueBefore = this.state.value[index - 1]; | ||
if (nv < valueBefore + this.props.minDistance) { | ||
nv = valueBefore + this.props.minDistance; | ||
} | ||
} | ||
if (i < size(this.state.value) - 1) { | ||
var valueAfter = at(this.state.value, i + 1); | ||
if (nextValue > valueAfter - this.props.minDistance) { | ||
nextValue = this._trimAlignValue(valueAfter - this.props.minDistance); | ||
if (index < this.state.value.length - 1) { | ||
var valueAfter = this.state.value[index + 1]; | ||
if (nv > valueAfter - this.props.minDistance) { | ||
nv = valueAfter - this.props.minDistance; | ||
} | ||
@@ -401,3 +357,4 @@ } | ||
return nextValue; | ||
return this._trimAlignValue(nv); | ||
}, this); | ||
@@ -407,8 +364,8 @@ | ||
var n = nextValue.length; | ||
if (n && n > 1) { | ||
if (nextValue[i] > lastValue[i]) { | ||
this._pearlNext(i, nextValue); | ||
if (n > 1) { | ||
if (nextValue[index] > lastValue[index]) { | ||
this._pearlNext(index, nextValue); | ||
this._limitNext(n, nextValue); | ||
} else if (nextValue[i] < lastValue[i]) { | ||
this._pearlPrev(i, nextValue); | ||
} else if (nextValue[index] < lastValue[index]) { | ||
this._pearlPrev(index, nextValue); | ||
this._limitPrev(n, nextValue); | ||
@@ -419,6 +376,8 @@ } | ||
var changed = !is(nextValue, lastValue); | ||
if (changed) { | ||
this.setState({value: nextValue}); | ||
if (this.props.onChange) this.props.onChange(nextValue); | ||
var isEqual = nextValue.reduce(function (isEqual, v, i) { | ||
return isEqual && v === lastValue[i]; | ||
}, true); | ||
if (!isEqual) { | ||
this.setState({value: nextValue}, this._fireEvent.bind(this, 'onChange')); | ||
} | ||
@@ -428,4 +387,5 @@ }, | ||
_pearlNext: function (i, nextValue) { | ||
if (nextValue[i + 1] && nextValue[i] + this.props.minDistance > nextValue[i + 1]) { | ||
nextValue[i + 1] = this._trimAlignValue(nextValue[i] + this.props.minDistance); | ||
var padding = nextValue[i] + this.props.minDistance; | ||
if (nextValue[i + 1] && padding > nextValue[i + 1]) { | ||
nextValue[i + 1] = this._alignValue(padding); | ||
this._pearlNext(i + 1, nextValue); | ||
@@ -437,4 +397,5 @@ } | ||
for (var i = 0; i < n; i++) { | ||
if (nextValue[n - 1 - i] > this.state.max - i * this.props.minDistance) { | ||
nextValue[n - 1 - i] = this.state.max - i * this.props.minDistance; | ||
var padding = this.props.max - i * this.props.minDistance; | ||
if (nextValue[n - 1 - i] > padding) { | ||
nextValue[n - 1 - i] = padding; | ||
} | ||
@@ -445,4 +406,5 @@ } | ||
_pearlPrev: function (i, nextValue) { | ||
if (nextValue[i - 1] && nextValue[i] - this.props.minDistance < nextValue[i - 1]) { | ||
nextValue[i - 1] = this._trimAlignValue(nextValue[i] - this.props.minDistance); | ||
var padding = nextValue[i] - this.props.minDistance; | ||
if (nextValue[i - 1] && padding < nextValue[i - 1]) { | ||
nextValue[i - 1] = this._alignValue(padding); | ||
this._pearlPrev(i - 1, nextValue); | ||
@@ -454,4 +416,5 @@ } | ||
for (var i = 0; i < n; i++) { | ||
if (nextValue[i] < this.state.min + i * this.props.minDistance) { | ||
nextValue[i] = this.state.min + i * this.props.minDistance; | ||
var padding = this.props.min + i * this.props.minDistance; | ||
if (nextValue[i] < padding) { | ||
nextValue[i] = padding; | ||
} | ||
@@ -461,3 +424,3 @@ } | ||
_axis: function () { | ||
_axisKey: function () { | ||
return { | ||
@@ -469,3 +432,3 @@ 'horizontal': 'X', | ||
_min: function () { | ||
_posMinKey: function () { | ||
return { | ||
@@ -477,3 +440,3 @@ 'horizontal': 'left', | ||
_max: function () { | ||
_posMaxKey: function () { | ||
return { | ||
@@ -485,11 +448,30 @@ 'horizontal': 'right', | ||
_trimAlignValue: function (val) { | ||
if (val <= this.props.min) val = this.props.min; | ||
if (val >= this.props.max) val = this.props.max; | ||
_sizeKey: function () { | ||
return { | ||
horizontal: 'clientWidth', | ||
vertical: 'clientHeight' | ||
}[this.props.orientation]; | ||
}, | ||
var valModStep = (val - this.props.min) % this.props.step; | ||
_trimAlignValue: function (val, props) { | ||
return this._alignValue(this._trimValue(val, props), props); | ||
}, | ||
_trimValue: function (val, props) { | ||
props = props || this.props; | ||
if (val <= props.min) val = props.min; | ||
if (val >= props.max) val = props.max; | ||
return val; | ||
}, | ||
_alignValue: function (val, props) { | ||
props = props || this.props; | ||
var valModStep = (val - props.min) % props.step; | ||
var alignValue = val - valModStep; | ||
if (Math.abs(valModStep) * 2 >= this.props.step) { | ||
alignValue += (valModStep > 0) ? this.props.step : (-this.props.step); | ||
if (Math.abs(valModStep) * 2 >= props.step) { | ||
alignValue += (valModStep > 0) ? props.step : (-props.step); | ||
} | ||
@@ -511,7 +493,5 @@ | ||
className: className, | ||
style: at(styles, i), | ||
onMouseDown: this._dragStart(i), | ||
onTouchStart: this._touchStart(i) | ||
//onTouchMove: this._touchMove, | ||
//onTouchEnd: this._onTouchEnd | ||
style: styles[i], | ||
onMouseDown: this._createOnMouseDown(i), | ||
onTouchStart: this._createOnTouchStart(i) | ||
}, | ||
@@ -525,9 +505,10 @@ child | ||
_renderHandles: function (offset) { | ||
var styles = map(offset, this._buildHandleStyle, this); | ||
var styles = offset.map(this._buildHandleStyle); | ||
if (React.Children.count(this.props.children) > 0) { | ||
return React.Children.map(this.props.children, this._renderHandle(styles), this); | ||
return React.Children.map(this.props.children, this._renderHandle(styles)); | ||
} else { | ||
return map(offset, function (offset, i) { | ||
return this._renderHandle(styles)(null, i); | ||
var renderHandle = this._renderHandle(styles); | ||
return offset.map(function (offset, i) { | ||
return renderHandle(null, i); | ||
}, this); | ||
@@ -543,6 +524,3 @@ } | ||
className: this.props.barClassName + ' ' + this.props.barClassName + '-' + i, | ||
style: this._buildBarStyle({ | ||
min: offsetFrom, | ||
max: this.state.upperBound - offsetTo | ||
}) | ||
style: this._buildBarStyle(offsetFrom, this.state.upperBound - offsetTo) | ||
}) | ||
@@ -554,5 +532,5 @@ ); | ||
var bars = []; | ||
var lastIndex = size(offset) - 1; | ||
var lastIndex = offset.length - 1; | ||
bars.push(this._renderBar(0, 0, at(offset, 0))); | ||
bars.push(this._renderBar(0, 0, offset[0])); | ||
@@ -563,3 +541,3 @@ for (var i = 0; i < lastIndex; i++) { | ||
bars.push(this._renderBar(lastIndex + 1, at(offset, lastIndex), this.state.upperBound)); | ||
bars.push(this._renderBar(lastIndex + 1, offset[lastIndex], this.state.upperBound)); | ||
@@ -569,18 +547,16 @@ return bars; | ||
// Handle mouseDown events on the slider. | ||
_onSliderMouseDown: function (e) { | ||
_onSliderStart: function (e, getPosition, eventMap) { | ||
if (this.props.disabled) return; | ||
var position = e['page' + this._axis()]; | ||
document.activeElement.blur(); | ||
var position = getPosition(e); | ||
this._forceValueFromPosition(position, function (i) { | ||
// Set up a drag operation. | ||
if (this.props.onChange) { | ||
this.props.onChange(this.state.value); | ||
} | ||
this._fireEvent('onChange'); | ||
this._start(i, position); | ||
document.addEventListener('mousemove', this._dragMove, false); | ||
document.addEventListener('mouseup', this._dragEnd, false); | ||
for (var key in eventMap) { | ||
document.addEventListener(key, eventMap[key], false); | ||
} | ||
}.bind(this)); | ||
@@ -591,26 +567,18 @@ | ||
// Handle touchStart events on the slider. | ||
_onSliderMouseDown: function (e) { | ||
this._onSliderStart(e, this._getMousePosition, this._getMouseEventMap()); | ||
}, | ||
_onSliderTouchStart: function (e) { | ||
if (this.props.disabled) return; | ||
this._onSliderStart(e, this._getTouchPosition, this._getTouchEventMap()); | ||
}, | ||
var last = e.changedTouches[e.changedTouches.length - 1]; | ||
var position = last['page' + this._axis()]; | ||
this._forceValueFromPosition(position, function (i) { | ||
// Set up a drag operation. | ||
if (this.props.onChange) { | ||
this.props.onChange(this.state.value); | ||
} | ||
this._start(i, position); | ||
document.addEventListener('touchmove', this._touchMove, false); | ||
document.addEventListener('touchend', this._touchEnd, false); | ||
}.bind(this)); | ||
pauseEvent(e); | ||
_fireEvent: function (event) { | ||
if (this.props[event]) { | ||
this.props[event](undoEnsureArray(this.state.value)); | ||
} | ||
}, | ||
render: function () { | ||
var offset = map(this.state.value, this._calcOffset, this); | ||
var offset = this.state.value.map(this._calcOffset); | ||
@@ -624,3 +592,3 @@ var bars = this.props.withBars ? this._renderBars(offset) : null; | ||
style: {position: 'relative'}, | ||
className: this.props.className, | ||
className: this.props.className + (this.props.disabled ? ' disabled' : ''), | ||
onMouseDown: this._onSliderMouseDown, | ||
@@ -627,0 +595,0 @@ onTouchStart: this._onSliderTouchStart |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
3
0
25392
6
471