diff --git a/src/components/rangeslider/draw.js b/src/components/rangeslider/draw.js index 4d235cd8dfb..b3ea4b1ecc0 100644 --- a/src/components/rangeslider/draw.js +++ b/src/components/rangeslider/draw.js @@ -12,14 +12,18 @@ var d3 = require('d3'); var Plotly = require('../../plotly'); var Plots = require('../../plots/plots'); -var Axes = require('../../plots/cartesian/axes'); + var Lib = require('../../lib'); +var Drawing = require('../drawing'); +var Color = require('../color'); + +var Cartesian = require('../../plots/cartesian'); +var Axes = require('../../plots/cartesian/axes'); var dragElement = require('../dragelement'); var setCursor = require('../../lib/setcursor'); var constants = require('./constants'); -var rangePlot = require('./range_plot'); module.exports = function(gd) { @@ -55,7 +59,14 @@ module.exports = function(gd) { .classed(constants.containerClassName, true) .attr('pointer-events', 'all'); - rangeSliders.exit().remove(); + // remove exiting sliders and their corresponding clip paths + rangeSliders.exit().each(function(axisOpts) { + var rangeSlider = d3.select(this), + opts = axisOpts[constants.name]; + + rangeSlider.remove(); + fullLayout._topdefs.select('#' + opts._clipId).remove(); + }); // remove push margin object(s) if(rangeSliders.exit().size()) clearPushMargins(gd); @@ -82,6 +93,8 @@ module.exports = function(gd) { domain = axisOpts.domain; opts._id = constants.name + axisOpts._id; + opts._clipId = opts._id + '-' + fullLayout._uid; + opts._width = graphSize.w * (domain[1] - domain[0]); opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness; opts._offsetShift = Math.floor(opts.borderwidth / 2); @@ -95,6 +108,7 @@ module.exports = function(gd) { rangeSlider .call(drawBg, gd, axisOpts, opts) + .call(addClipPath, gd, axisOpts, opts) .call(drawRangePlot, gd, axisOpts, opts) .call(drawMasks, gd, axisOpts, opts) .call(drawSlideBox, gd, axisOpts, opts) @@ -279,17 +293,102 @@ function drawBg(rangeSlider, gd, axisOpts, opts) { }); } -function drawRangePlot(rangeSlider, gd, axisOpts, opts) { - var rangePlots = rangePlot(gd, opts._width, opts._height); +function addClipPath(rangeSlider, gd, axisOpts, opts) { + var fullLayout = gd._fullLayout; - var gRangePlot = rangeSlider.selectAll('g.' + constants.rangePlotClassName) + var clipPath = fullLayout._topdefs.selectAll('#' + opts._clipId) .data([0]); - gRangePlot.enter().append('g') - .classed(constants.rangePlotClassName, true); + clipPath.enter().append('clipPath') + .attr('id', opts._clipId) + .append('rect') + .attr({ x: 0, y: 0 }); + + clipPath.select('rect').attr({ + width: opts._width, + height: opts._height + }); +} + +function drawRangePlot(rangeSlider, gd, axisOpts, opts) { + var subplotData = Axes.getSubplots(gd, axisOpts), + calcData = gd.calcdata; + + var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName) + .data(subplotData, Lib.identity); + + rangePlots.enter().append('g') + .attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; }) + .call(Drawing.setClipUrl, opts._clipId); + + rangePlots.order(); + + rangePlots.exit().remove(); + + var mainplotinfo; + + rangePlots.each(function(id, i) { + var plotgroup = d3.select(this), + isMainPlot = (i === 0); + + var oppAxisOpts = Axes.getFromId(gd, id, 'y'), + oppAxisName = oppAxisOpts._name; + + var mockFigure = { + data: [], + layout: { + xaxis: { + domain: [0, 1], + range: opts.range.slice() + }, + width: opts._width, + height: opts._height, + margin: { t: 0, b: 0, l: 0, r: 0 } + } + }; + + mockFigure.layout[oppAxisName] = { + domain: [0, 1], + range: oppAxisOpts.range.slice() + }; + + Plots.supplyDefaults(mockFigure); + + var xa = mockFigure._fullLayout.xaxis, + ya = mockFigure._fullLayout[oppAxisName]; + + var plotinfo = { + id: id, + plotgroup: plotgroup, + xaxis: xa, + yaxis: ya + }; + + if(isMainPlot) mainplotinfo = plotinfo; + else { + plotinfo.mainplot = 'xy'; + plotinfo.mainplotinfo = mainplotinfo; + } + + Cartesian.rangePlot(gd, plotinfo, filterRangePlotCalcData(calcData, id)); + + if(isMainPlot) plotinfo.bg.call(Color.fill, opts.bgcolor); + }); +} + +function filterRangePlotCalcData(calcData, subplotId) { + var out = []; + + for(var i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i], + trace = calcTrace[0].trace; + + if(trace.xaxis + trace.yaxis === subplotId) { + out.push(calcTrace); + } + } - gRangePlot.html(null); - gRangePlot.node().appendChild(rangePlots); + return out; } function drawMasks(rangeSlider, gd, axisOpts, opts) { diff --git a/src/components/rangeslider/helpers.js b/src/components/rangeslider/helpers.js deleted file mode 100644 index 23ea06e24ca..00000000000 --- a/src/components/rangeslider/helpers.js +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Copyright 2012-2016, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -exports.setAttributes = function setAttributes(el, attributes) { - for(var key in attributes) { - el.setAttribute(key, attributes[key]); - } -}; - - -exports.appendChildren = function appendChildren(el, children) { - for(var i = 0; i < children.length; i++) { - if(children[i]) { - el.appendChild(children[i]); - } - } -}; diff --git a/src/components/rangeslider/range_plot.js b/src/components/rangeslider/range_plot.js deleted file mode 100644 index 36798287ea1..00000000000 --- a/src/components/rangeslider/range_plot.js +++ /dev/null @@ -1,179 +0,0 @@ -/** -* Copyright 2012-2016, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = require('d3'); - -var Lib = require('../../lib'); -var Symbols = require('../drawing/symbol_defs'); -var Drawing = require('../drawing'); - -var helpers = require('./helpers'); -var svgNS = require('../../constants/xmlns_namespaces').svg; - -module.exports = function rangePlot(gd, w, h) { - - var fullLayout = gd._fullLayout, - traces = gd._fullData, - xaxis = fullLayout.xaxis, - yaxis = fullLayout.yaxis, - minX = xaxis.rangeslider.range[0], - maxX = xaxis.rangeslider.range[1], - minY = yaxis.range[0], - maxY = yaxis.range[1]; - - - // create elements for plot and its clip - var clipPath = document.createElementNS(svgNS, 'path'); - clipPath.setAttribute('d', ['M0,0', w + ',0', w + ',' + h, '0,' + h, 'Z'].join(' ')); - - var clip = document.createElementNS(svgNS, 'clipPath'); - clip.setAttribute('id', 'range-clip-path'); - clip.appendChild(clipPath); - - var clipDefs = document.createElementNS(svgNS, 'defs'); - clipDefs.appendChild(clip); - - var rangePlot = document.createElementNS(svgNS, 'g'); - d3.select(rangePlot).call(Drawing.setClipUrl, 'range-clip-path'); - rangePlot.appendChild(clipDefs); - - - // for now, only scatter traces are supported - var allowedTypes = ['scatter']; - - for(var i = 0; i < traces.length; i++) { - - var trace = traces[i], - pointPairs = []; - - if(allowedTypes.indexOf(trace.type) < 0) { - Lib.warn('Trace type ' + trace.type + ' not supported for range slider!'); - continue; - } - - var x = makeLinearData(trace, xaxis), - y = makeLinearData(trace, yaxis); - - for(var k = 0; k < x.length; k++) { - - var posX = w * (x[k] - minX) / (maxX - minX), - posY = h * (1 - (y[k] - minY) / (maxY - minY)); - - if(!isNaN(posX) && !isNaN(posY)) { - pointPairs.push([posX, posY]); - } - } - - // more trace type range plots can be added here - helpers.appendChildren(rangePlot, makeScatter(trace, pointPairs, w, h)); - } - - - return rangePlot; -}; - -function makeLinearData(trace, axis) { - var data = axis.makeCalcdata(trace || [], axis._id[0]); - - for(var i = 0; i < data.length; i++) { - data[i] = axis.c2l(data[i]); - } - - return data; -} - - -function makeScatter(trace, pointPairs, w, h) { - - // create the line - var line, markers, fill; - - if(trace.line) { - line = document.createElementNS(svgNS, 'path'); - - var linePath = Drawing.smoothopen(pointPairs, trace.line.smoothing || 0); - - helpers.setAttributes(line, { - 'd': linePath, - 'fill': 'none', - 'stroke': trace.line ? trace.line.color : 'transparent', - 'stroke-width': trace.line.width / 2 || 1, - 'opacity': 1 - }); - } - - // create points if there's markers - if(trace.marker) { - markers = document.createElementNS(svgNS, 'g'); - - var points = pointPairs.map(function(p, i) { - var point = document.createElementNS(svgNS, 'g'), - symbol = document.createElementNS(svgNS, 'path'), - size; - - if(Array.isArray(trace.marker.size)) { - size = typeof trace.marker.size[i] === 'number' ? - Math.max(trace.marker.size[i] / (trace.marker.sizeref || 1) / 15, 0) : - 0; - } else { - size = Math.max(trace.marker.size / 15, 2); - } - - helpers.setAttributes(symbol, { - 'd': Symbols[trace.marker.symbol].f(size), - 'fill': trace.marker.color, - 'stroke': trace.marker.line.color, - 'stroke-width': trace.marker.line.width, - 'opacity': trace.marker.opacity - }); - - helpers.setAttributes(point, { - 'transform': 'translate(' + p[0] + ',' + p[1] + ')' - }); - - point.appendChild(symbol); - - return point; - }); - - helpers.appendChildren(markers, points); - } - - - // create fill if set - if(trace.fill !== 'none') { - fill = document.createElementNS(svgNS, 'path'); - - switch(trace.fill) { - case 'tozeroy': - pointPairs.unshift([pointPairs[0][0], h]); - pointPairs.push([pointPairs[pointPairs.length - 1][0], h]); - break; - - case 'tozerox': - pointPairs.unshift([0, pointPairs[pointPairs.length - 1][1]]); - break; - - default: - Lib.warn('Fill type ' + trace.fill + ' not supported for range slider! (yet...)'); - break; - } - - var fillPath = Drawing.smoothopen(pointPairs, trace.line.smoothing || 0); - - helpers.setAttributes(fill, { - 'd': fillPath, - 'fill': trace.fillcolor || 'transparent' - }); - } - - - return [line, markers, fill]; -} diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 77aa2c6d2e8..2b2aa98ddf8 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -30,17 +30,16 @@ exports.attributes = require('./attributes'); exports.transitionAxes = require('./transition_axes'); exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { - var cdSubplot, cd, trace, i, j, k; - var fullLayout = gd._fullLayout, subplots = Plots.getSubplotIds(fullLayout, 'cartesian'), calcdata = gd.calcdata, - modules = fullLayout._modules; + i; + // If traces is not provided, then it's a complete replot and missing + // traces are removed if(!Array.isArray(traces)) { - // If traces is not provided, then it's a complete replot and missing - // traces are removed traces = []; + for(i = 0; i < calcdata.length; i++) { traces.push(i); } @@ -51,11 +50,12 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { subplotInfo = fullLayout._plots[subplot]; // Get all calcdata for this subplot: - cdSubplot = []; + var cdSubplot = []; var pcd; - for(j = 0; j < calcdata.length; j++) { - cd = calcdata[j]; - trace = cd[0].trace; + + for(var j = 0; j < calcdata.length; j++) { + var cd = calcdata[j], + trace = cd[0].trace; // Skip trace if whitelist provided and it's not whitelisted: // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue; @@ -81,37 +81,45 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { } } - // remove old traces, then redraw everything - // TODO: scatterlayer is manually excluded from this since it knows how - // to update instead of fully removing and redrawing every time. The - // remaining plot traces should also be able to do this. Once implemented, - // we won't need this - which should sometimes be a big speedup. - if(subplotInfo.plot) { - subplotInfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove(); - } + plotOne(gd, subplotInfo, cdSubplot, transitionOpts, makeOnCompleteCallback); + } +}; + +function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout, + modules = fullLayout._modules; + + // remove old traces, then redraw everything + // + // TODO: scatterlayer is manually excluded from this since it knows how + // to update instead of fully removing and redrawing every time. The + // remaining plot traces should also be able to do this. Once implemented, + // we won't need this - which should sometimes be a big speedup. + if(plotinfo.plot) { + plotinfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove(); + } - // Plot all traces for each module at once: - for(j = 0; j < modules.length; j++) { - var _module = modules[j]; + // plot all traces for each module at once + for(var j = 0; j < modules.length; j++) { + var _module = modules[j]; - // skip over non-cartesian trace modules - if(_module.basePlotModule.name !== 'cartesian') continue; + // skip over non-cartesian trace modules + if(_module.basePlotModule.name !== 'cartesian') continue; - // plot all traces of this type on this subplot at once - var cdModule = []; - for(k = 0; k < cdSubplot.length; k++) { - cd = cdSubplot[k]; + // plot all traces of this type on this subplot at once + var cdModule = []; + for(var k = 0; k < cdSubplot.length; k++) { + var cd = cdSubplot[k], trace = cd[0].trace; - if((trace._module === _module) && (trace.visible === true)) { - cdModule.push(cd); - } + if((trace._module === _module) && (trace.visible === true)) { + cdModule.push(cd); } - - _module.plot(gd, subplotInfo, cdModule, transitionOpts, makeOnCompleteCallback); } + + _module.plot(gd, plotinfo, cdModule, transitionOpts, makeOnCompleteCallback); } -}; +} exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { var oldModules = oldFullLayout._modules || [], @@ -198,6 +206,12 @@ exports.drawFramework = function(gd) { }); }; +exports.rangePlot = function(gd, plotinfo, cdSubplot) { + makeSubplotLayer(plotinfo); + plotOne(gd, plotinfo, cdSubplot); + Plots.style(gd); +}; + function makeSubplotData(gd) { var fullLayout = gd._fullLayout, subplots = Axes.getSubplots(gd); diff --git a/test/image/baselines/range_slider.png b/test/image/baselines/range_slider.png index a70059ec3e2..942bb6b9909 100644 Binary files a/test/image/baselines/range_slider.png and b/test/image/baselines/range_slider.png differ diff --git a/test/image/baselines/range_slider_axes_double.png b/test/image/baselines/range_slider_axes_double.png new file mode 100644 index 00000000000..e2d04a225cc Binary files /dev/null and b/test/image/baselines/range_slider_axes_double.png differ diff --git a/test/image/baselines/range_slider_box.png b/test/image/baselines/range_slider_box.png new file mode 100644 index 00000000000..983d97aa3e0 Binary files /dev/null and b/test/image/baselines/range_slider_box.png differ diff --git a/test/image/baselines/range_slider_initial_expanded.png b/test/image/baselines/range_slider_initial_expanded.png index 0dbc81bef79..e2347407ca5 100644 Binary files a/test/image/baselines/range_slider_initial_expanded.png and b/test/image/baselines/range_slider_initial_expanded.png differ diff --git a/test/image/baselines/range_slider_initial_valid.png b/test/image/baselines/range_slider_initial_valid.png index 11714c34422..bd90642f2bc 100644 Binary files a/test/image/baselines/range_slider_initial_valid.png and b/test/image/baselines/range_slider_initial_valid.png differ diff --git a/test/image/mocks/range_slider_axes_double.json b/test/image/mocks/range_slider_axes_double.json new file mode 100644 index 00000000000..12f21651b03 --- /dev/null +++ b/test/image/mocks/range_slider_axes_double.json @@ -0,0 +1,60 @@ +{ + "data": [ + { + "x": [ + 1, + 2, + 3 + ], + "y": [ + 40, + 50, + 60 + ], + "name": "yaxis data", + "type": "scatter" + }, + { + "x": [ + 2, + 3, + null, + 4, + 5 + ], + "y": [ + 4, + 5, + null, + 7, + 8 + ], + "name": "yaxis2 data", + "yaxis": "y2", + "type": "scatter" + } + ], + "layout": { + "title": "Double Y Axis Example", + "xaxis": { + "title": "Wavelength (nm)", + "rangeslider": { + "thickness": 0.2 + } + }, + "yaxis": { + "title": "yaxis title" + }, + "yaxis2": { + "title": "yaxis2 title", + "titlefont": { + "color": "rgb(148, 103, 189)" + }, + "tickfont": { + "color": "rgb(148, 103, 189)" + }, + "side": "right", + "overlaying": "y" + } + } +} diff --git a/test/image/mocks/range_slider_box.json b/test/image/mocks/range_slider_box.json new file mode 100644 index 00000000000..4b5da1fe2b8 --- /dev/null +++ b/test/image/mocks/range_slider_box.json @@ -0,0 +1,610 @@ +{ + "data": [ + { + "y": [ + 2.143298776630495, + 1.546437498536346, + 3.1996026127943633, + -3.2721650039744277, + -1.7378623476100585, + -2.5941532378644188, + 1.1336988134622026, + 0.39713737515117814, + -0.27839421470206477, + 3.9406531966094187 + ], + "name": "450", + "marker": { + "color": "rgb(223, 32, 190)" + }, + "type": "box" + }, + { + "y": [ + -0.5513570147410131, + 1.6941884418515312, + -1.035989600357754, + -1.6734746830784588, + -0.1903379250550108, + 0.42160414146603786, + -0.5683499968674645, + 0.7828243804727615, + -2.738657648646538, + -0.4024106513052623 + ], + "name": "457", + "marker": { + "color": "rgb(217, 32, 223)" + }, + "type": "box" + }, + { + "y": [ + -1.3901652371943087, + 2.4214887682900743, + 1.147569881528752, + 2.2351841831713792, + -0.24820700567182885, + -1.6126248595047912, + -0.015222585493234297, + -1.7751807888116073, + 4.415229463381031, + -1.4285566690889238 + ], + "name": "465", + "marker": { + "color": "rgb(177, 32, 223)" + }, + "type": "box" + }, + { + "y": [ + 0.4975138182534743, + 1.215757991855703, + -0.04780629861353569, + 0.0014301521180146715, + -0.011693084658796149, + -2.906881977464424, + 4.8510748670522705, + 0.8040846867796213, + -1.4106428462482774, + 2.3887864346532606 + ], + "name": "472", + "marker": { + "color": "rgb(137, 32, 223)" + }, + "type": "box" + }, + { + "y": [ + 5.309088102098384, + 1.5954979624142749, + 1.1399594723769164, + 1.2685192423716043, + 1.9891077747658914, + 4.479183247169927, + -0.4656503273673507, + 3.5133936404325956, + 1.2851237031303082, + 1.065354380602242 + ], + "name": "480", + "marker": { + "color": "rgb(98, 32, 223)" + }, + "type": "box" + }, + { + "y": [ + 1.793070030728234, + 3.29213458092582, + 2.1625259961030734, + 0.9007411507925231, + -0.916683837898133, + 5.4977152470055, + 1.6836217999830234, + 3.380671777397879, + 4.165609313750686, + 1.0184343366894293 + ], + "name": "487", + "marker": { + "color": "rgb(58, 32, 223)" + }, + "type": "box" + }, + { + "y": [ + 3.235861441555429, + 2.1411292546692486, + 3.8381308213835887, + 2.727752293571505, + 4.017975902072184, + 0.5695736013091188, + 1.535514508643867, + 1.6962832108823964, + 0.28895804542641246, + 2.5786826869714696 + ], + "name": "495", + "marker": { + "color": "rgb(32, 45, 223)" + }, + "type": "box" + }, + { + "y": [ + -0.016115579695300752, + 2.531199154443878, + 2.188462171876345, + 1.8555942771726135, + 0.2876025775176916, + 2.5299915024344273, + 2.56353105045906, + -0.04959351109352372, + 5.0485171134766444, + 2.6482490469234374 + ], + "name": "503", + "marker": { + "color": "rgb(32, 85, 223)" + }, + "type": "box" + }, + { + "y": [ + 2.4365302731146445, + 0.7848896009704163, + 0.36007001248524295, + 3.357942698060853, + 3.7843191029141785, + 2.3943649408085133, + 5.803538252311307, + 3.9205732619959197, + 1.1238016024864932, + 0.02428909483070507 + ], + "name": "510", + "marker": { + "color": "rgb(32, 124, 223)" + }, + "type": "box" + }, + { + "y": [ + 4.7441997160566345, + 0.7515838547336324, + 1.8461593107504688, + 4.937748255274713, + 2.464649682835375, + 3.5933123140369934, + 4.568459375427043, + 5.322171359439542, + 0.980257484548269, + 4.9888859397884975 + ], + "name": "518", + "marker": { + "color": "rgb(32, 164, 223)" + }, + "type": "box" + }, + { + "y": [ + 4.107617413889171, + 1.823598893064229, + 4.442565600424697, + 4.4215444267782935, + 2.3597001037476826, + 1.5009649279909203, + 3.428920172680855, + 3.696492763065793, + 1.8448075591657191, + 4.674810996174651 + ], + "name": "525", + "marker": { + "color": "rgb(32, 203, 223)" + }, + "type": "box" + }, + { + "y": [ + 3.6559413766345292, + 5.218123953992757, + 4.082994231037061, + 4.724350438211446, + 6.520301038717292, + 4.0269504946482355, + 2.111689104940635, + 3.426173805884625, + 2.4041213983920686, + 3.7558771830255986 + ], + "name": "533", + "marker": { + "color": "rgb(32, 223, 203)" + }, + "type": "box" + }, + { + "y": [ + 3.6207323323056206, + 2.92217135200816, + 4.457314990351299, + 4.738588564045884, + 2.2502191884477187, + 3.0920972252203103, + 1.7770707068519265, + 3.082033226287514, + 1.266449386074287, + 6.162474112512239 + ], + "name": "541", + "marker": { + "color": "rgb(32, 223, 164)" + }, + "type": "box" + }, + { + "y": [ + 1.2002602313809807, + 4.326957937078774, + 3.831624202706361, + 6.470696868730711, + 8.385697218240262, + 3.378927427138537, + 1.0100011719208175, + 3.059657183194205, + 3.45662135588293, + 1.8005146791153082 + ], + "name": "548", + "boxpoints": false, + "whiskerwidth": 0.75, + "marker": { + "color": "rgb(32, 223, 124)" + }, + "line": { + "width": 1 + }, + "type": "box" + }, + { + "y": [ + 3.916814324730089, + 1.1822314723354634, + 2.6838499750862366, + 3.9047897374529525, + 3.2646310457952747, + 3.494345580357663, + 4.85068215147808, + 3.21632919185715, + 4.543453196746212, + 4.304948860307396 + ], + "name": "556", + "marker": { + "color": "rgb(32, 223, 85)" + }, + "type": "box" + }, + { + "y": [ + 7.188869064393717, + 2.969613080027406, + 2.861887894692491, + 1.9339807896829542, + 5.916747428886293, + 3.7862988306773264, + 3.365480207639184, + 4.840355678120315, + 5.467164053423591, + 5.102661041557068 + ], + "name": "563", + "marker": { + "color": "rgb(32, 223, 45)" + }, + "type": "box" + }, + { + "y": [ + 2.023828346393208, + 4.3933555087541585, + 6.172651079392306, + 3.2182077662451865, + 4.890593997097495, + 0.19897657320179274, + 4.3726706934050625, + 4.245739954374094, + 3.3852788348198035, + 4.873691579297628 + ], + "name": "571", + "marker": { + "color": "rgb(58, 223, 32)" + }, + "type": "box" + }, + { + "y": [ + 1.3883512495925547, + 2.8579471237790264, + 4.8663809840475984, + 5.1951118805760625, + 4.205722291898466, + 4.5553567442938085, + 6.200717614751488, + 4.708467697352261, + 4.357794178274319, + 3.6873288890259586 + ], + "name": "578", + "marker": { + "color": "rgb(98, 223, 32)" + }, + "type": "box" + }, + { + "y": [ + 5.023381822090899, + 2.4160739470924977, + 6.839803818089738, + 3.8121261015654513, + 2.266919394391742, + 4.223121388019584, + 2.358904599837688, + 5.479564877537197, + 4.372792152115252, + 4.078049952346909 + ], + "name": "586", + "marker": { + "color": "rgb(137, 223, 32)" + }, + "type": "box" + }, + { + "y": [ + 4.364265628125186, + 3.637151936860906, + 4.340102390620965, + 3.8253415529586503, + 3.84445134734876, + 2.789086489665339, + 2.990753771535526, + 2.2238138482703986, + 4.067840176264388, + 3.390657214377273 + ], + "name": "594", + "marker": { + "color": "rgb(177, 223, 32)" + }, + "type": "box" + }, + { + "y": [ + 3.944128530705616, + 4.299027748180328, + 3.559320048683847, + 3.953395160076097, + 4.951561324824724, + 0.28423798817635415, + 1.703079084515436, + 2.1233249084555856, + 4.50899816468616, + 2.90914860672678 + ], + "name": "601", + "marker": { + "color": "rgb(217, 223, 32)" + }, + "type": "box" + }, + { + "y": [ + 1.4987245004945127, + 3.4988764107954573, + 1.035666193651728, + 3.698078313017795, + 2.8601991008463807, + 4.59108686634301, + 1.6416602569201257, + 2.620692910978377, + 4.352271873131939, + 3.387796281522468 + ], + "name": "609", + "marker": { + "color": "rgb(223, 190, 32)" + }, + "type": "box" + }, + { + "y": [ + 3.886588759281743, + 4.09639467114146, + 3.781059716978851, + 3.8506624719056455, + 3.2983203880390692, + 2.7906038044537773, + 1.9089288355943315, + 3.741375625088334, + 4.7920177887664, + 3.8756714538590957 + ], + "name": "616", + "marker": { + "color": "rgb(223, 151, 32)" + }, + "type": "box" + }, + { + "y": [ + 3.7930929392545725, + 2.9595815901683897, + 4.278816973575015, + 4.12873578159929, + 3.2452722246603787, + 2.2228796432055917, + 3.1117613387871432, + 4.700202930162271, + 3.7364376410841977, + 2.624246824503665 + ], + "name": "624", + "marker": { + "color": "rgb(223, 111, 32)" + }, + "type": "box" + }, + { + "y": [ + 2.688817168538662, + 2.2647900378206796, + 2.794030735666634, + 2.5557136986888924, + 3.2975536939952153, + 1.464310183835455, + 4.79675367384749, + 2.721293236786012, + 1.3407340944698982, + 2.7925891550565827 + ], + "name": "632", + "marker": { + "color": "rgb(223, 71, 32)" + }, + "type": "box" + }, + { + "y": [ + 3.302664391056707, + 3.8779275997242513, + 2.5606073377558447, + 2.172284155005903, + 4.986094304920282, + 2.585843158431967, + 1.55578389553859, + 1.9354736601919273, + 1.6906489597225358, + 3.8132044950220774 + ], + "name": "639", + "marker": { + "color": "rgb(223, 32, 32)" + }, + "type": "box" + }, + { + "y": [ + 1.2757796572946754, + 3.5749547405713544, + 2.213564040974323, + 2.622646077414124, + 1.9695916314640103, + 2.237719685949837, + 3.5117622169738114, + 1.9529579923485183, + 1.9350848528531803, + 1.9228718838389787 + ], + "name": "647", + "boxpoints": false, + "whiskerwidth": 0.75, + "marker": { + "color": "rgb(223, 32, 32)" + }, + "line": { + "width": 1 + }, + "type": "box" + }, + { + "y": [ + 2.112951496740204, + 3.9406157111578675, + 2.2747354097753396, + 3.8932852199747097, + 0.7139956340270186, + 1.5278830689466767, + 2.401168983865303, + 3.281033802949576, + 1.565578801322196, + 2.7721094415950764 + ], + "name": "654", + "marker": { + "color": "rgb(223, 32, 71)" + }, + "type": "box" + }, + { + "y": [ + 0.12123446809023997, + 3.3306394911873394, + 0.38816372142868594, + 2.4404379445719204, + 0.5699057463324029, + 2.1574477293800833, + 4.342293935187394, + 1.126581491394398, + 0.03028431816905841, + -0.769753202505036 + ], + "name": "662", + "marker": { + "color": "rgb(223, 32, 111)" + }, + "type": "box" + }, + { + "y": [ + 0.9002461908620343, + 0.8892524414281886, + 2.4450446737565454, + 2.4648528013844877, + 0.8404729335174261, + 0.6925337622570281, + 0.5882537991503783, + 1.2618587377404258, + 1.388487877092837, + 1.565283315273657 + ], + "name": "670", + "marker": { + "color": "rgb(223, 32, 151)" + }, + "type": "box" + } + ], + "layout": { + "title": "Spectral Box Plot with Range Slider", + "titlefont": { + "size": 18 + }, + "font": { + "family": "Arial, sans-serif", + "size": 12, + "color": "rgb(67, 67, 67)" + }, + "showlegend": false, + "autosize": false, + "width": 600, + "height": 400, + "xaxis": { + "title": "Wavelength (nm)", + "rangeslider": { + "thickness": 0.1 + } + }, + "yaxis": { + "title": "Response (mV)" + }, + "paper_bgcolor": "rgb(233, 233, 233)", + "plot_bgcolor": "rgb(233, 233, 233)" + } +} diff --git a/test/jasmine/tests/range_slider_test.js b/test/jasmine/tests/range_slider_test.js index 99f82f71d4d..60b7ef88444 100644 --- a/test/jasmine/tests/range_slider_test.js +++ b/test/jasmine/tests/range_slider_test.js @@ -5,6 +5,7 @@ var RangeSlider = require('@src/components/rangeslider'); var constants = require('@src/components/rangeslider/constants'); var mock = require('../../image/mocks/range_slider.json'); +var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var mouseEvent = require('../assets/mouse_event'); @@ -26,6 +27,12 @@ describe('the range slider', function() { return document.getElementsByClassName(className)[0]; } + function countRangeSliderClipPaths() { + return d3.selectAll('defs').selectAll('*').filter(function() { + return this.id.indexOf('rangeslider') !== -1; + }).size(); + } + function testTranslate1D(node, val) { var transformParts = node.getAttribute('transform').split('('); @@ -308,6 +315,7 @@ describe('the range slider', function() { .then(function() { var rangeSlider = getRangeSlider(); expect(rangeSlider).toBeDefined(); + expect(countRangeSliderClipPaths()).toEqual(1); }) .then(done); }); @@ -318,6 +326,7 @@ describe('the range slider', function() { .then(function() { var rangeSlider = getRangeSlider(); expect(rangeSlider).not.toBeDefined(); + expect(countRangeSliderClipPaths()).toEqual(0); }) .then(done); });