Skip to content

Commit 3b5178c

Browse files
committed
Merge pull request #568 from plotly/rangeslider-update
Rangeslider `Plotly.relayout` bugfix
2 parents e369300 + 7fa9243 commit 3b5178c

File tree

4 files changed

+89
-50
lines changed

4 files changed

+89
-50
lines changed

src/components/rangeslider/create_slider.js

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -141,27 +141,49 @@ module.exports = function createSlider(gd) {
141141
window.addEventListener('mouseup', mouseUp);
142142

143143
function mouseMove(e) {
144-
var delta = +e.clientX - startX;
144+
var delta = +e.clientX - startX,
145+
pixelMin,
146+
pixelMax;
145147

146148
switch(target) {
147149
case slideBox:
148150
slider.style.cursor = 'ew-resize';
149-
setPixelRange(+maxVal + delta, +minVal + delta);
151+
152+
pixelMin = +minVal + delta;
153+
pixelMax = +maxVal + delta;
154+
155+
setPixelRange(pixelMin, pixelMax);
156+
setDataRange(pixelToData(pixelMin), pixelToData(pixelMax));
150157
break;
151158

152159
case grabAreaMin:
153160
slider.style.cursor = 'col-resize';
154-
setPixelRange(+minVal + delta, +maxVal);
161+
162+
pixelMin = +minVal + delta;
163+
pixelMax = +maxVal;
164+
165+
setPixelRange(pixelMin, pixelMax);
166+
setDataRange(pixelToData(pixelMin), pixelToData(pixelMax));
155167
break;
156168

157169
case grabAreaMax:
158170
slider.style.cursor = 'col-resize';
159-
setPixelRange(+minVal, +maxVal + delta);
171+
172+
pixelMin = +minVal;
173+
pixelMax = +maxVal + delta;
174+
175+
setPixelRange(pixelMin, pixelMax);
176+
setDataRange(pixelToData(pixelMin), pixelToData(pixelMax));
160177
break;
161178

162179
default:
163180
slider.style.cursor = 'ew-resize';
164-
setPixelRange(offsetX, offsetX + delta);
181+
182+
pixelMin = offsetX;
183+
pixelMax = offsetX + delta;
184+
185+
setPixelRange(pixelMin, pixelMax);
186+
setDataRange(pixelToData(pixelMin), pixelToData(pixelMax));
165187
break;
166188
}
167189
}
@@ -173,6 +195,17 @@ module.exports = function createSlider(gd) {
173195
}
174196
});
175197

198+
function pixelToData(pixel) {
199+
var rangeMin = options.range[0],
200+
rangeMax = options.range[1],
201+
range = rangeMax - rangeMin,
202+
dataValue = pixel / width * range + rangeMin;
203+
204+
dataValue = Lib.constrain(dataValue, rangeMin, rangeMax);
205+
206+
return dataValue;
207+
}
208+
176209

177210
function setRange(min, max) {
178211
min = min || -Infinity;
@@ -187,52 +220,49 @@ module.exports = function createSlider(gd) {
187220
setPixelRange(pixelMin, pixelMax);
188221
}
189222

223+
function setDataRange(dataMin, dataMax) {
224+
225+
if(window.requestAnimationFrame) {
226+
window.requestAnimationFrame(function() {
227+
Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]);
228+
});
229+
} else {
230+
setTimeout(function() {
231+
Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]);
232+
}, 16);
233+
}
234+
}
190235

191-
function setPixelRange(min, max) {
192236

193-
min = Lib.constrain(min, 0, width);
194-
max = Lib.constrain(max, 0, width);
237+
function setPixelRange(pixelMin, pixelMax) {
195238

196-
if(max < min) {
197-
var temp = max;
198-
max = min;
199-
min = temp;
239+
pixelMin = Lib.constrain(pixelMin, 0, width);
240+
pixelMax = Lib.constrain(pixelMax, 0, width);
241+
242+
if(pixelMax < pixelMin) {
243+
var temp = pixelMax;
244+
pixelMax = pixelMin;
245+
pixelMin = temp;
200246
}
201247

202248
helpers.setAttributes(slider, {
203-
'data-min': min,
204-
'data-max': max
249+
'data-min': pixelMin,
250+
'data-max': pixelMax
205251
});
206252

207253
helpers.setAttributes(slideBox, {
208-
'x': min,
209-
'width': max - min
254+
'x': pixelMin,
255+
'width': pixelMax - pixelMin
210256
});
211257

212-
helpers.setAttributes(maskMin, { 'width': min });
258+
helpers.setAttributes(maskMin, { 'width': pixelMin });
213259
helpers.setAttributes(maskMax, {
214-
'x': max,
215-
'width': width - max
260+
'x': pixelMax,
261+
'width': width - pixelMax
216262
});
217263

218-
helpers.setAttributes(grabberMin, { 'transform': 'translate(' + (min - handleWidth - 1) + ')' });
219-
helpers.setAttributes(grabberMax, { 'transform': 'translate(' + max + ')' });
220-
221-
var rangeMin = options.range[0],
222-
rangeMax = options.range[1],
223-
range = rangeMax - rangeMin,
224-
dataMin = min / width * range + rangeMin,
225-
dataMax = max / width * range + rangeMin;
226-
227-
if(window.requestAnimationFrame) {
228-
window.requestAnimationFrame(function() {
229-
Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]);
230-
});
231-
} else {
232-
setTimeout(function() {
233-
Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]);
234-
}, 16);
235-
}
264+
helpers.setAttributes(grabberMin, { 'transform': 'translate(' + (pixelMin - handleWidth - 1) + ')' });
265+
helpers.setAttributes(grabberMax, { 'transform': 'translate(' + pixelMax + ')' });
236266
}
237267

238268

src/lib/index.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -256,17 +256,6 @@ lib.smooth = function(arrayIn, FWHM) {
256256
return arrayOut;
257257
};
258258

259-
// helpers for promises
260-
261-
/**
262-
* promiseError: log errors properly inside promises
263-
* use:
264-
* <promise>.then(undefined,Plotly.Lib.promiseError) (for IE compatibility)
265-
* or <promise>.catch(Plotly.Lib.promiseError)
266-
* TODO: I guess we need another step to send this error to Sentry?
267-
*/
268-
lib.promiseError = function(err) { console.log(err, err.stack); };
269-
270259
/**
271260
* syncOrAsync: run a sequence of functions synchronously
272261
* as long as its returns are not promises (ie have no .then)

src/plot_api/plot_api.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,8 +2438,9 @@ Plotly.relayout = function relayout(gd, astr, val) {
24382438
}
24392439

24402440
function setRange(changes) {
2441-
var newMin = changes['xaxis.range[0]'],
2442-
newMax = changes['xaxis.range[1]'];
2441+
2442+
var newMin = changes['xaxis.range'] ? changes['xaxis.range'][0] : changes['xaxis.range[0]'],
2443+
newMax = changes['xaxis.range'] ? changes['xaxis.range'][1] : changes['xaxis.range[1]'];
24432444

24442445
var rangeSlider = fullLayout.xaxis && fullLayout.xaxis.rangeslider ?
24452446
fullLayout.xaxis.rangeslider : {};

test/jasmine/tests/range_slider_test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,25 @@ describe('the range slider', function() {
137137
expect(rangeDiff3).toBeLessThan(rangeDiff2);
138138
}).then(done);
139139
});
140+
141+
it('should relayout with relayout "array syntax"', function(done) {
142+
Plotly.relayout(gd, 'xaxis.range', [10, 20])
143+
.then(function() {
144+
expect(gd._fullLayout.xaxis.range).toEqual([10, 20]);
145+
expect(+rangeSlider.getAttribute('data-min')).toBeCloseTo(125.51, 0);
146+
expect(+rangeSlider.getAttribute('data-max')).toBeCloseTo(251.02, 0);
147+
})
148+
.then(done);
149+
});
150+
151+
it('should relayout with relayout "element syntax"', function(done) {
152+
Plotly.relayout(gd, 'xaxis.range[0]', 10)
153+
.then(function() {
154+
expect(gd._fullLayout.xaxis.range[0]).toEqual(10);
155+
expect(+rangeSlider.getAttribute('data-min')).toBeCloseTo(125.51, 0);
156+
})
157+
.then(done);
158+
});
140159
});
141160

142161

0 commit comments

Comments
 (0)