From 53c7c11701285ebad3f194686fa1417561406ca0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 28 Sep 2016 18:54:17 +0200 Subject: [PATCH 01/10] test --- test/jasmine/tests/gl2d_click_test.js | 810 ++++++++++++++++++++++++++ 1 file changed, 810 insertions(+) create mode 100644 test/jasmine/tests/gl2d_click_test.js diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js new file mode 100644 index 00000000000..d124fa17fca --- /dev/null +++ b/test/jasmine/tests/gl2d_click_test.js @@ -0,0 +1,810 @@ +var Plotly = require('@lib/index'); +var Lib = require('@src/lib'); +var DBLCLICKDELAY = require('@src/plots/cartesian/constants').DBLCLICKDELAY; + +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); +var mouseEvent = require('../assets/mouse_event'); +var getRectCenter = require('../assets/get_rect_center'); +var customMatchers = require('../assets/custom_matchers'); + +// cartesian click events events use the hover data +// from the mousemove events and then simulate +// a click event on mouseup +var click = require('../assets/click'); +var doubleClick = require('../assets/double_click'); + + +describe('Test click interactions:', function() { + var mock = require('@mocks/14.json'); + + var mockCopy, gd; + + var pointPos = [344, 216], + blankPos = [63, 356]; + + var autoRangeX = [-3.011967491973726, 2.1561305597186564], + autoRangeY = [-0.9910086301469277, 1.389382716298284]; + + beforeAll(function() { + jasmine.addMatchers(customMatchers); + }); + + beforeEach(function() { + gd = createGraphDiv(); + mockCopy = Lib.extendDeep({}, mock); + }); + + afterEach(destroyGraphDiv); + + function drag(fromX, fromY, toX, toY, delay) { + return new Promise(function(resolve) { + mouseEvent('mousemove', fromX, fromY); + mouseEvent('mousedown', fromX, fromY); + mouseEvent('mousemove', toX, toY); + + setTimeout(function() { + mouseEvent('mouseup', toX, toY); + resolve(); + }, delay || DBLCLICKDELAY / 4); + }); + } + + describe('click events', function() { + var futureData; + + beforeEach(function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + + gd.on('plotly_click', function(data) { + futureData = data; + }); + }); + + it('should not be trigged when not on data points', function() { + click(blankPos[0], blankPos[1]); + expect(futureData).toBe(undefined); + }); + + it('should contain the correct fields', function() { + click(pointPos[0], pointPos[1]); + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + expect(Object.keys(pt)).toEqual([ + 'data', 'fullData', 'curveNumber', 'pointNumber', + 'x', 'y', 'xaxis', 'yaxis' + ]); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual(11); + expect(pt.x).toEqual(0.125); + expect(pt.y).toEqual(2.125); + }); + }); + + describe('click event with hoverinfo set to skip - plotly_click', function() { + var futureData = null; + + beforeEach(function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'skip'; + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + .then(done); + + gd.on('plotly_click', function(data) { + futureData = data; + }); + }); + + it('should not register the click', function() { + click(pointPos[0], pointPos[1]); + expect(futureData).toEqual(null); + }); + }); + + describe('click events with hoverinfo set to skip - plotly_hover', function() { + var futureData = null; + + beforeEach(function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'skip'; + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + .then(done); + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }); + + it('should not register the hover', function() { + click(pointPos[0], pointPos[1]); + expect(futureData).toEqual(null); + }); + }); + + describe('click event with hoverinfo set to none - plotly_click', function() { + var futureData; + + beforeEach(function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + .then(done); + + gd.on('plotly_click', function(data) { + futureData = data; + }); + }); + + it('should contain the correct fields despite hoverinfo: "none"', function() { + click(pointPos[0], pointPos[1]); + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + expect(Object.keys(pt)).toEqual([ + 'data', 'fullData', 'curveNumber', 'pointNumber', + 'x', 'y', 'xaxis', 'yaxis' + ]); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual(11); + expect(pt.x).toEqual(0.125); + expect(pt.y).toEqual(2.125); + }); + }); + + describe('click events with hoverinfo set to none - plotly_hover', function() { + var futureData; + + beforeEach(function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + .then(done); + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }); + + it('should contain the correct fields despite hoverinfo: "none"', function() { + click(pointPos[0], pointPos[1]); + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + expect(Object.keys(pt)).toEqual([ + 'data', 'fullData', 'curveNumber', 'pointNumber', + 'x', 'y', 'xaxis', 'yaxis' + ]); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual(11); + expect(pt.x).toEqual(0.125); + expect(pt.y).toEqual(2.125); + }); + }); + + describe('double click events', function() { + var futureData; + + beforeEach(function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + + gd.on('plotly_doubleclick', function(data) { + futureData = data; + }); + + }); + + it('should return null', function(done) { + doubleClick(pointPos[0], pointPos[1]).then(function() { + expect(futureData).toBe(null); + done(); + }); + }); + }); + + describe('drag interactions', function() { + beforeEach(function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + // Do not let the notifier hide the drag elements + var tooltip = document.querySelector('.notifier-note'); + if(tooltip) tooltip.style.display = 'None'; + + done(); + }); + }); + + it('on nw dragbox should update the axis ranges', function(done) { + var node = document.querySelector('rect.nwdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('nwdrag'); + expect(node.classList[2]).toBe('cursor-nw-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.08579746, 2.156130559]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.86546098]); + + return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.10938115]); + + done(); + }); + }); + + it('on ne dragbox should update the axis ranges', function(done) { + var node = document.querySelector('rect.nedrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('nedrag'); + expect(node.classList[2]).toBe('cursor-ne-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.72466470]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.86546098]); + + return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.08350047]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.10938115]); + + done(); + }); + }); + + it('on sw dragbox should update the axis ranges', function(done) { + var node = document.querySelector('rect.swdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('swdrag'); + expect(node.classList[2]).toBe('cursor-sw-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.08579746, 2.15613055]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.36094210, 1.38938271]); + + return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.00958227, 2.15613055]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.71100706, 1.38938271]); + + done(); + }); + }); + + it('on se dragbox should update the axis ranges', function(done) { + var node = document.querySelector('rect.sedrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('sedrag'); + expect(node.classList[2]).toBe('cursor-se-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.72466470]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.36094210, 1.38938271]); + + return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.08350047]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.71100706, 1.38938271]); + + done(); + }); + }); + + it('on ew dragbox should update the xaxis range', function(done) { + var node = document.querySelector('rect.ewdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('ewdrag'); + expect(node.classList[2]).toBe('cursor-ew-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.375918058, 1.792179992]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.15613055]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('on w dragbox should update the xaxis range', function(done) { + var node = document.querySelector('rect.wdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('wdrag'); + expect(node.classList[2]).toBe('cursor-w-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.40349007, 2.15613055]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-2.93933740, 2.15613055]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('on e dragbox should update the xaxis range', function(done) { + var node = document.querySelector('rect.edrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('edrag'); + expect(node.classList[2]).toBe('cursor-e-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.7246647]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.0835004]); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('on ns dragbox should update the yaxis range', function(done) { + var node = document.querySelector('rect.nsdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('nsdrag'); + expect(node.classList[2]).toBe('cursor-ns-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.59427673, 1.78611460]); + + return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('on s dragbox should update the yaxis range', function(done) { + var node = document.querySelector('rect.sdrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('sdrag'); + expect(node.classList[2]).toBe('cursor-s-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.3609421011, 1.3893827]); + + return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.7110070646, 1.3893827]); + + done(); + }); + }); + + it('on n dragbox should update the yaxis range', function(done) { + var node = document.querySelector('rect.ndrag'); + var pos = getRectCenter(node); + + expect(node.classList[0]).toBe('drag'); + expect(node.classList[1]).toBe('ndrag'); + expect(node.classList[2]).toBe('cursor-n-resize'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.991008630, 1.86546098]); + + return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.991008630, 1.10938115]); + + done(); + }); + }); + + }); + + describe('double click interactions', function() { + var setRangeX = [-3, 1], + setRangeY = [-0.5, 1]; + + var zoomRangeX = [-2, 0], + zoomRangeY = [0, 0.5]; + + var update = { + 'xaxis.range[0]': zoomRangeX[0], + 'xaxis.range[1]': zoomRangeX[1], + 'yaxis.range[0]': zoomRangeY[0], + 'yaxis.range[1]': zoomRangeY[1] + }; + + function setRanges(mockCopy) { + mockCopy.layout.xaxis.autorange = false; + mockCopy.layout.xaxis.range = setRangeX.slice(); + + mockCopy.layout.yaxis.autorange = false; + mockCopy.layout.yaxis.range = setRangeY.slice(); + + return mockCopy; + } + + it('when set to \'reset+autorange\' (the default) should work when \'autorange\' is on', function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('when set to \'reset+autorange\' (the default) should reset to set range on double click', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + done(); + }); + }); + + it('when set to \'reset+autorange\' (the default) should autosize on 1st double click and reset on 2nd', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + done(); + }); + }); + + it('when set to \'reset+autorange\' (the default) should autosize on 1st double click and zoom when immediately dragged', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return drag(100, 100, 200, 200, DBLCLICKDELAY / 2); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-2.6480169249531356, -1.920115790911955]); + expect(gd.layout.yaxis.range).toBeCloseToArray([0.4372261777201992, 1.2306899598686027]); + + done(); + }); + }); + + it('when set to \'reset+autorange\' (the default) should follow updated auto ranges', function(done) { + var updateData = { + x: [[1e-4, 0, 1e3]], + y: [[30, 0, 30]] + }; + + var newAutoRangeX = [-4.482371794871794, 3.4823717948717943], + newAutoRangeY = [-0.8892256657741471, 1.6689872212461876]; + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return Plotly.restyle(gd, updateData); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(newAutoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(newAutoRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(newAutoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(newAutoRangeY); + + done(); + }); + }); + + it('when set to \'reset\' should work when \'autorange\' is on', function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('when set to \'reset\' should reset to set range on double click', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + done(); + }); + }); + + it('when set to \'reset\' should reset on all double clicks', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + done(); + }); + }); + + it('when set to \'autosize\' should work when \'autorange\' is on', function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('when set to \'autosize\' should set to autorange on double click', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return Plotly.relayout(gd, update); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + it('when set to \'autosize\' should reset on all double clicks', function(done) { + mockCopy = setRanges(mockCopy); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + + return doubleClick(blankPos[0], blankPos[1]); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + done(); + }); + }); + + }); + + describe('zoom interactions', function() { + beforeEach(function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + }); + + it('on main dragbox should update the axis ranges', function(done) { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(93, 93, 393, 293).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-2.69897000, -0.515266602]); + expect(gd.layout.yaxis.range).toBeCloseToArray([-0.30069513, 1.2862324246]); + + return drag(93, 93, 393, 293); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-2.56671754, -1.644025966]); + expect(gd.layout.yaxis.range).toBeCloseToArray([0.159513853, 1.2174655634]); + + done(); + }); + }); + }); + + describe('scroll zoom interactions', function() { + + beforeEach(function(done) { + Plotly.plot(gd, mockCopy.data, mockCopy.layout, { scrollZoom: true }).then(done); + }); + + it('zooms in on scroll up', function() { + + var plot = gd._fullLayout._plots.xy.plot; + + mouseEvent('mousemove', 393, 243); + mouseEvent('scroll', 393, 243, { deltaX: 0, deltaY: -1000 }); + + var transform = plot.attr('transform'); + + var mockEl = { + attr: function() { + return transform; + } + }; + + var translate = Lib.getTranslate(mockEl), + scale = Lib.getScale(mockEl); + + expect([translate.x, translate.y]).toBeCloseToArray([61.070, 97.712]); + expect([scale.x, scale.y]).toBeCloseToArray([1.221, 1.221]); + }); + }); + + describe('pan interactions', function() { + beforeEach(function(done) { + mockCopy.layout.dragmode = 'pan'; + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + }); + + it('on main dragbox should update the axis ranges', function(done) { + expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); + expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + + drag(93, 93, 393, 293).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-5.19567089, -0.02757284]); + expect(gd.layout.yaxis.range).toBeCloseToArray([0.595918934, 2.976310280]); + + return drag(93, 93, 393, 293); + }).then(function() { + expect(gd.layout.xaxis.range).toBeCloseToArray([-7.37937429, -2.21127624]); + expect(gd.layout.yaxis.range).toBeCloseToArray([2.182846498, 4.563237844]); + + done(); + }); + }); + + + it('should move the plot when panning', function() { + var start = 100, + end = 300, + plot = gd._fullLayout._plots.xy.plot; + + mouseEvent('mousemove', start, start); + mouseEvent('mousedown', start, start); + mouseEvent('mousemove', end, end); + + expect(plot.attr('transform')).toBe('translate(250, 280) scale(1, 1)'); + + mouseEvent('mouseup', end, end); + }); + }); +}); From c4baeb2b3f80fd597e00b18cfacc445e1dba22a8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 29 Sep 2016 15:45:07 +0200 Subject: [PATCH 02/10] hover, unhover --- src/plots/gl2d/scene2d.js | 16 + test/jasmine/assets/hover.js | 5 + test/jasmine/tests/gl2d_click_test.js | 794 +++----------------------- 3 files changed, 86 insertions(+), 729 deletions(-) create mode 100644 test/jasmine/assets/hover.js diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 06180291e91..4d083fb9599 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -522,6 +522,21 @@ proto.draw = function() { glplot.pixelRatio ]; + // this needs to happen before the next block that deletes traceCoord data + // also it's important to copy, otherwise data is lost by the time event data is read + this.graphDiv.emit('plotly_hover', { + points: [{ + trace: nextSelection.trace, + dataCoord: nextSelection.dataCoord.slice(), + traceCoord: nextSelection.traceCoord.slice(), + textLabel: nextSelection.textLabel, + color: nextSelection.color, + name: nextSelection.name, + hoverinfo: nextSelection.hoverinfo, + screenCoord: nextSelection.screenCoord.slice() + }] + }); + var hoverinfo = selection.hoverinfo; if(hoverinfo !== 'all') { var parts = hoverinfo.split('+'); @@ -549,6 +564,7 @@ proto.draw = function() { else if(!result && this.lastPickResult) { this.spikes.update({}); this.lastPickResult = null; + this.graphDiv.emit('plotly_unhover'); Fx.loneUnhover(this.svgContainer); } } diff --git a/test/jasmine/assets/hover.js b/test/jasmine/assets/hover.js new file mode 100644 index 00000000000..0efa6fbb13f --- /dev/null +++ b/test/jasmine/assets/hover.js @@ -0,0 +1,5 @@ +var mouseEvent = require('./mouse_event'); + +module.exports = function hover(x, y) { + mouseEvent('mousemove', x, y); +}; diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index d124fa17fca..5db8fa8468c 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -1,31 +1,21 @@ var Plotly = require('@lib/index'); var Lib = require('@src/lib'); -var DBLCLICKDELAY = require('@src/plots/cartesian/constants').DBLCLICKDELAY; var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); -var mouseEvent = require('../assets/mouse_event'); -var getRectCenter = require('../assets/get_rect_center'); var customMatchers = require('../assets/custom_matchers'); // cartesian click events events use the hover data // from the mousemove events and then simulate // a click event on mouseup -var click = require('../assets/click'); -var doubleClick = require('../assets/double_click'); - +// var click = require('../assets/click'); +var hover = require('../assets/hover'); describe('Test click interactions:', function() { - var mock = require('@mocks/14.json'); + var mock = require('@mocks/gl2d_14.json'); var mockCopy, gd; - var pointPos = [344, 216], - blankPos = [63, 356]; - - var autoRangeX = [-3.011967491973726, 2.1561305597186564], - autoRangeY = [-0.9910086301469277, 1.389382716298284]; - beforeAll(function() { jasmine.addMatchers(customMatchers); }); @@ -37,774 +27,120 @@ describe('Test click interactions:', function() { afterEach(destroyGraphDiv); - function drag(fromX, fromY, toX, toY, delay) { - return new Promise(function(resolve) { - mouseEvent('mousemove', fromX, fromY); - mouseEvent('mousedown', fromX, fromY); - mouseEvent('mousemove', toX, toY); - - setTimeout(function() { - mouseEvent('mouseup', toX, toY); - resolve(); - }, delay || DBLCLICKDELAY / 4); - }); - } - - describe('click events', function() { + describe('hover event is fired on hover', function() { var futureData; - beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - - gd.on('plotly_click', function(data) { - futureData = data; - }); - }); - - it('should not be trigged when not on data points', function() { - click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); - }); - - it('should contain the correct fields', function() { - click(pointPos[0], pointPos[1]); - expect(futureData.points.length).toEqual(1); - - var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'data', 'fullData', 'curveNumber', 'pointNumber', - 'x', 'y', 'xaxis', 'yaxis' - ]); - expect(pt.curveNumber).toEqual(0); - expect(pt.pointNumber).toEqual(11); - expect(pt.x).toEqual(0.125); - expect(pt.y).toEqual(2.125); - }); - }); - - describe('click event with hoverinfo set to skip - plotly_click', function() { - var futureData = null; - - beforeEach(function(done) { + it('in general', function(done) { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); - modifiedMockCopy.data[0].hoverinfo = 'skip'; + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); - gd.on('plotly_click', function(data) { - futureData = data; - }); - }); + .then(new Promise(function() { - it('should not register the click', function() { - click(pointPos[0], pointPos[1]); - expect(futureData).toEqual(null); - }); - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); - describe('click events with hoverinfo set to skip - plotly_hover', function() { - var futureData = null; + hover(654.7712871743302, 316.97670766680994); - beforeEach(function(done) { + window.setTimeout(function() { - var modifiedMockCopy = Lib.extendDeep({}, mockCopy); - modifiedMockCopy.data[0].hoverinfo = 'skip'; - Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + expect(futureData.points.length).toEqual(1); - gd.on('plotly_hover', function(data) { - futureData = data; - }); - }); + var pt = futureData.points[0]; - it('should not register the hover', function() { - click(pointPos[0], pointPos[1]); - expect(futureData).toEqual(null); - }); - }); + expect(Object.keys(pt)).toEqual([ + 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', + 'name', 'hoverinfo', 'screenCoord' + ]); - describe('click event with hoverinfo set to none - plotly_click', function() { - var futureData; + expect(pt.traceCoord).toEqual([15.772, 0.387]); - beforeEach(function(done) { + done(); + }, 250); + })); - var modifiedMockCopy = Lib.extendDeep({}, mockCopy); - modifiedMockCopy.data[0].hoverinfo = 'none'; - Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); - gd.on('plotly_click', function(data) { - futureData = data; - }); }); - it('should contain the correct fields despite hoverinfo: "none"', function() { - click(pointPos[0], pointPos[1]); - expect(futureData.points.length).toEqual(1); - - var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'data', 'fullData', 'curveNumber', 'pointNumber', - 'x', 'y', 'xaxis', 'yaxis' - ]); - expect(pt.curveNumber).toEqual(0); - expect(pt.pointNumber).toEqual(11); - expect(pt.x).toEqual(0.125); - expect(pt.y).toEqual(2.125); - }); - }); - - describe('click events with hoverinfo set to none - plotly_hover', function() { - var futureData; - - beforeEach(function(done) { + it('even when hoverinfo (== plotly tooltip) is set to none', function(done) { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'none'; - Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); - - gd.on('plotly_hover', function(data) { - futureData = data; - }); - }); - - it('should contain the correct fields despite hoverinfo: "none"', function() { - click(pointPos[0], pointPos[1]); - expect(futureData.points.length).toEqual(1); - - var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'data', 'fullData', 'curveNumber', 'pointNumber', - 'x', 'y', 'xaxis', 'yaxis' - ]); - expect(pt.curveNumber).toEqual(0); - expect(pt.pointNumber).toEqual(11); - expect(pt.x).toEqual(0.125); - expect(pt.y).toEqual(2.125); - }); - }); - - describe('double click events', function() { - var futureData; - - beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - - gd.on('plotly_doubleclick', function(data) { - futureData = data; - }); - - }); - - it('should return null', function(done) { - doubleClick(pointPos[0], pointPos[1]).then(function() { - expect(futureData).toBe(null); - done(); - }); - }); - }); - - describe('drag interactions', function() { - beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - // Do not let the notifier hide the drag elements - var tooltip = document.querySelector('.notifier-note'); - if(tooltip) tooltip.style.display = 'None'; - - done(); - }); - }); - - it('on nw dragbox should update the axis ranges', function(done) { - var node = document.querySelector('rect.nwdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('nwdrag'); - expect(node.classList[2]).toBe('cursor-nw-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.08579746, 2.156130559]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.86546098]); - - return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.10938115]); - - done(); - }); - }); - - it('on ne dragbox should update the axis ranges', function(done) { - var node = document.querySelector('rect.nedrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('nedrag'); - expect(node.classList[2]).toBe('cursor-ne-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.72466470]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.86546098]); - - return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.08350047]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.99100863, 1.10938115]); - - done(); - }); - }); - - it('on sw dragbox should update the axis ranges', function(done) { - var node = document.querySelector('rect.swdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('swdrag'); - expect(node.classList[2]).toBe('cursor-sw-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.08579746, 2.15613055]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.36094210, 1.38938271]); - - return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.00958227, 2.15613055]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.71100706, 1.38938271]); - - done(); - }); - }); - - it('on se dragbox should update the axis ranges', function(done) { - var node = document.querySelector('rect.sedrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('sedrag'); - expect(node.classList[2]).toBe('cursor-se-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.72466470]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.36094210, 1.38938271]); - - return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.08350047]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.71100706, 1.38938271]); - - done(); - }); - }); - - it('on ew dragbox should update the xaxis range', function(done) { - var node = document.querySelector('rect.ewdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('ewdrag'); - expect(node.classList[2]).toBe('cursor-ew-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.375918058, 1.792179992]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.15613055]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('on w dragbox should update the xaxis range', function(done) { - var node = document.querySelector('rect.wdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('wdrag'); - expect(node.classList[2]).toBe('cursor-w-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.40349007, 2.15613055]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-2.93933740, 2.15613055]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('on e dragbox should update the xaxis range', function(done) { - var node = document.querySelector('rect.edrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('edrag'); - expect(node.classList[2]).toBe('cursor-e-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 50, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 1.7246647]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - return drag(pos[0], pos[1], pos[0] - 50, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-3.01196749, 2.0835004]); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('on ns dragbox should update the yaxis range', function(done) { - var node = document.querySelector('rect.nsdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('nsdrag'); - expect(node.classList[2]).toBe('cursor-ns-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.59427673, 1.78611460]); - - return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('on s dragbox should update the yaxis range', function(done) { - var node = document.querySelector('rect.sdrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('sdrag'); - expect(node.classList[2]).toBe('cursor-s-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.3609421011, 1.3893827]); - - return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.7110070646, 1.3893827]); - - done(); - }); - }); - - it('on n dragbox should update the yaxis range', function(done) { - var node = document.querySelector('rect.ndrag'); - var pos = getRectCenter(node); - - expect(node.classList[0]).toBe('drag'); - expect(node.classList[1]).toBe('ndrag'); - expect(node.classList[2]).toBe('cursor-n-resize'); - - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(pos[0], pos[1], pos[0] + 10, pos[1] + 50).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.991008630, 1.86546098]); - - return drag(pos[0], pos[1], pos[0] - 10, pos[1] - 50); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.991008630, 1.10938115]); - - done(); - }); - }); - - }); - - describe('double click interactions', function() { - var setRangeX = [-3, 1], - setRangeY = [-0.5, 1]; - - var zoomRangeX = [-2, 0], - zoomRangeY = [0, 0.5]; - - var update = { - 'xaxis.range[0]': zoomRangeX[0], - 'xaxis.range[1]': zoomRangeX[1], - 'yaxis.range[0]': zoomRangeY[0], - 'yaxis.range[1]': zoomRangeY[1] - }; - - function setRanges(mockCopy) { - mockCopy.layout.xaxis.autorange = false; - mockCopy.layout.xaxis.range = setRangeX.slice(); - - mockCopy.layout.yaxis.autorange = false; - mockCopy.layout.yaxis.range = setRangeY.slice(); - - return mockCopy; - } - - it('when set to \'reset+autorange\' (the default) should work when \'autorange\' is on', function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('when set to \'reset+autorange\' (the default) should reset to set range on double click', function(done) { - mockCopy = setRanges(mockCopy); - - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); - }); - - it('when set to \'reset+autorange\' (the default) should autosize on 1st double click and reset on 2nd', function(done) { - mockCopy = setRanges(mockCopy); - - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); - }); - - it('when set to \'reset+autorange\' (the default) should autosize on 1st double click and zoom when immediately dragged', function(done) { - mockCopy = setRanges(mockCopy); - - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return drag(100, 100, 200, 200, DBLCLICKDELAY / 2); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-2.6480169249531356, -1.920115790911955]); - expect(gd.layout.yaxis.range).toBeCloseToArray([0.4372261777201992, 1.2306899598686027]); - - done(); - }); - }); - - it('when set to \'reset+autorange\' (the default) should follow updated auto ranges', function(done) { - var updateData = { - x: [[1e-4, 0, 1e3]], - y: [[30, 0, 30]] - }; - - var newAutoRangeX = [-4.482371794871794, 3.4823717948717943], - newAutoRangeY = [-0.8892256657741471, 1.6689872212461876]; - - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return Plotly.restyle(gd, updateData); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(newAutoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(newAutoRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(newAutoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(newAutoRangeY); - - done(); - }); - }); - - it('when set to \'reset\' should work when \'autorange\' is on', function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); - - it('when set to \'reset\' should reset to set range on double click', function(done) { - mockCopy = setRanges(mockCopy); - - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); - }); - - it('when set to \'reset\' should reset on all double clicks', function(done) { - mockCopy = setRanges(mockCopy); - - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'reset' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); - }); - - it('when set to \'autosize\' should work when \'autorange\' is on', function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); - - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); - }); + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - it('when set to \'autosize\' should set to autorange on double click', function(done) { - mockCopy = setRanges(mockCopy); + .then(new Promise(function() { - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + gd.on('plotly_hover', function(data) { + futureData = data; + }); - return Plotly.relayout(gd, update); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(zoomRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(zoomRangeY); + hover(654.7712871743302, 316.97670766680994); - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + window.setTimeout(function() { - done(); - }); - }); + expect(futureData.points.length).toEqual(1); - it('when set to \'autosize\' should reset on all double clicks', function(done) { - mockCopy = setRanges(mockCopy); + var pt = futureData.points[0]; - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { doubleClick: 'autosize' }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); + expect(Object.keys(pt)).toEqual([ + 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', + 'name', 'hoverinfo', 'screenCoord' + ]); - return doubleClick(blankPos[0], blankPos[1]); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + expect(pt.traceCoord).toEqual([15.772, 0.387]); - done(); - }); - }); + done(); + }, 250); + })); - }); - describe('zoom interactions', function() { - beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); }); - it('on main dragbox should update the axis ranges', function(done) { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - drag(93, 93, 393, 293).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-2.69897000, -0.515266602]); - expect(gd.layout.yaxis.range).toBeCloseToArray([-0.30069513, 1.2862324246]); - - return drag(93, 93, 393, 293); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-2.56671754, -1.644025966]); - expect(gd.layout.yaxis.range).toBeCloseToArray([0.159513853, 1.2174655634]); - - done(); - }); - }); - }); + it('unhover happens', function(done) { - describe('scroll zoom interactions', function() { + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; - beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout, { scrollZoom: true }).then(done); - }); + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - it('zooms in on scroll up', function() { + .then(new Promise(function() { - var plot = gd._fullLayout._plots.xy.plot; + futureData = undefined; - mouseEvent('mousemove', 393, 243); - mouseEvent('scroll', 393, 243, { deltaX: 0, deltaY: -1000 }); + gd.on('plotly_unhover', function() { + futureData = 'emitted plotly_unhover'; + }); - var transform = plot.attr('transform'); + hover(654.7712871743302, 316.97670766680994); - var mockEl = { - attr: function() { - return transform; - } - }; + // fairly realistic simulation of moving with the cursor + window.setTimeout(function() { - var translate = Lib.getTranslate(mockEl), - scale = Lib.getScale(mockEl); + var x = 654, y = 316; // we start here + var canceler = window.setInterval(function() { + hover(x--, y++); // move the cursor + }, 10); - expect([translate.x, translate.y]).toBeCloseToArray([61.070, 97.712]); - expect([scale.x, scale.y]).toBeCloseToArray([1.221, 1.221]); - }); - }); + window.setTimeout(function() { + window.clearInterval(canceler); // stop the mouse at some point + }, 250); - describe('pan interactions', function() { - beforeEach(function(done) { - mockCopy.layout.dragmode = 'pan'; + window.setTimeout(function() { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - }); + expect(futureData).toEqual('emitted plotly_unhover'); - it('on main dragbox should update the axis ranges', function(done) { - expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); - expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); + done(); - drag(93, 93, 393, 293).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-5.19567089, -0.02757284]); - expect(gd.layout.yaxis.range).toBeCloseToArray([0.595918934, 2.976310280]); + }, 250); - return drag(93, 93, 393, 293); - }).then(function() { - expect(gd.layout.xaxis.range).toBeCloseToArray([-7.37937429, -2.21127624]); - expect(gd.layout.yaxis.range).toBeCloseToArray([2.182846498, 4.563237844]); + }, 250); + })); - done(); - }); }); - it('should move the plot when panning', function() { - var start = 100, - end = 300, - plot = gd._fullLayout._plots.xy.plot; - - mouseEvent('mousemove', start, start); - mouseEvent('mousedown', start, start); - mouseEvent('mousemove', end, end); - - expect(plot.attr('transform')).toBe('translate(250, 280) scale(1, 1)'); - - mouseEvent('mouseup', end, end); - }); }); }); From 359d50aff3aca4085cebece2b3d19162df9a9f4e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 30 Sep 2016 10:39:49 +0200 Subject: [PATCH 03/10] adds click emission; adds test cases; uses hasWebGLSupport --- src/plots/gl2d/scene2d.js | 23 +++- test/jasmine/assets/timed_click.js | 17 +++ test/jasmine/tests/gl2d_click_test.js | 147 +++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 test/jasmine/assets/timed_click.js diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 4d083fb9599..43023e5091e 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -58,6 +58,9 @@ function Scene2D(options, fullLayout) { outerFill: true }); + // last button state + this.lastButtonState = 0; + // last pick result this.pickResult = null; @@ -463,8 +466,11 @@ proto.draw = function() { var glplot = this.glplot, camera = this.camera, mouseListener = camera.mouseListener, + mouseUp = this.lastButtonState === 1 && mouseListener.buttons === 0, fullLayout = this.fullLayout; + this.lastButtonState = mouseListener.buttons; + this.cameraChanged(); var x = mouseListener.x * glplot.pixelRatio; @@ -494,8 +500,23 @@ proto.draw = function() { (y / glplot.pixelRatio) - (size.t + (1 - domainY[1]) * size.h) ); + var nextSelection = result && result.object._trace.handlePick(result); + + if(nextSelection && mouseUp) { + this.graphDiv.emit('plotly_click', { + points: [{ + trace: nextSelection.trace, + dataCoord: nextSelection.dataCoord.slice(), + traceCoord: nextSelection.traceCoord.slice(), + textLabel: nextSelection.textLabel, + color: nextSelection.color, + name: nextSelection.name, + hoverinfo: nextSelection.hoverinfo + }] + }); + } + if(result && result.object._trace.hoverinfo !== 'skip' && fullLayout.hovermode) { - var nextSelection = result.object._trace.handlePick(result); if(nextSelection && ( !this.lastPickResult || diff --git a/test/jasmine/assets/timed_click.js b/test/jasmine/assets/timed_click.js new file mode 100644 index 00000000000..b8806f2bd52 --- /dev/null +++ b/test/jasmine/assets/timed_click.js @@ -0,0 +1,17 @@ +var mouseEvent = require('./mouse_event'); + +module.exports = function click(x, y) { + mouseEvent('mousemove', x, y, {buttons: 0}); + + window.setTimeout(function() { + + mouseEvent('mousedown', x, y, {buttons: 1}); + + window.setTimeout(function() { + + mouseEvent('mouseup', x, y, {buttons: 0}); + + }, 50); + + }, 150); +}; diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index 5db8fa8468c..270181265d1 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -4,14 +4,18 @@ var Lib = require('@src/lib'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var customMatchers = require('../assets/custom_matchers'); +var hasWebGLSupport = require('../assets/has_webgl_support'); // cartesian click events events use the hover data // from the mousemove events and then simulate // a click event on mouseup -// var click = require('../assets/click'); +var click = require('../assets/timed_click'); var hover = require('../assets/hover'); describe('Test click interactions:', function() { + + if(!hasWebGLSupport('gl2d_click_test')) return; + var mock = require('@mocks/gl2d_14.json'); var mockCopy, gd; @@ -97,6 +101,41 @@ describe('Test click interactions:', function() { })); + }); + + it('event happens even on a click interaction', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + + click(654.7712871743302, 316.97670766680994); + + window.setTimeout(function() { + + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual([ + 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', + 'name', 'hoverinfo', 'screenCoord' + ]); + + expect(pt.traceCoord).toEqual([15.772, 0.387]); + + done(); + }, 250); + })); + + }); it('unhover happens', function(done) { @@ -143,4 +182,110 @@ describe('Test click interactions:', function() { }); + + describe('click event is fired on click', function() { + var futureData; + + it('in general', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_click', function(data) { + futureData = data; + }); + + click(654.7712871743302, 316.97670766680994); + + window.setTimeout(function() { + expect(futureData.points[0].traceCoord).toEqual([15.772, 0.387]); + + done(); + + }, 350); + })); + + }); + + it('even when hoverinfo (== plotly tooltip) is set to none', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + + hover(654.7712871743302, 316.97670766680994); + + window.setTimeout(function() { + + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual([ + 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', + 'name', 'hoverinfo', 'screenCoord' + ]); + + expect(pt.traceCoord).toEqual([15.772, 0.387]); + + done(); + }, 250); + })); + + + }); + + it('unhover happens', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mockCopy); + modifiedMockCopy.data[0].hoverinfo = 'none'; + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + futureData = undefined; + + gd.on('plotly_unhover', function() { + futureData = 'emitted plotly_unhover'; + }); + + hover(654.7712871743302, 316.97670766680994); + + // fairly realistic simulation of moving with the cursor + window.setTimeout(function() { + + var x = 654, y = 316; // we start here + var canceler = window.setInterval(function() { + hover(x--, y++); // move the cursor + }, 10); + + window.setTimeout(function() { + window.clearInterval(canceler); // stop the mouse at some point + }, 250); + + window.setTimeout(function() { + + expect(futureData).toEqual('emitted plotly_unhover'); + + done(); + + }, 250); + + }, 250); + })); + + }); + + }); }); From 1e56d7f1eeaac3735d4c2c987b236040ab55dffc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 3 Oct 2016 13:59:58 +0200 Subject: [PATCH 04/10] PR feedback: enriching event callback data --- src/plots/gl2d/scene2d.js | 35 ++++++++------- test/jasmine/tests/gl2d_click_test.js | 63 +++++++++++++++++---------- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 43023e5091e..69432c8618e 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -33,6 +33,7 @@ function Scene2D(options, fullLayout) { this.staticPlot = !!options.staticPlot; this.fullLayout = fullLayout; + this.fullData = null; this.updateAxes(fullLayout); this.makeFramework(); @@ -49,6 +50,7 @@ function Scene2D(options, fullLayout) { // trace set this.traces = {}; + this._inputs = {}; // create axes spikes this.spikes = createSpikes(this.glplot); @@ -335,6 +337,8 @@ proto.destroy = function() { this.container.removeChild(this.svgContainer); this.container.removeChild(this.mouseContainer); + this.fullData = null; + this._inputs = null; this.glplot = null; this.stopped = true; }; @@ -425,6 +429,8 @@ proto.updateTraces = function(fullData, calcData) { var traceIds = Object.keys(this.traces); var i, j, fullTrace; + this.fullData = fullData; + // remove empty traces trace_id_loop: for(i = 0; i < traceIds.length; i++) { @@ -446,7 +452,7 @@ proto.updateTraces = function(fullData, calcData) { // update / create trace objects for(i = 0; i < fullData.length; i++) { fullTrace = fullData[i]; - + this._inputs[fullTrace.uid] = fullTrace._input; var calcTrace = calcData[i], traceObj = this.traces[fullTrace.uid]; @@ -505,13 +511,12 @@ proto.draw = function() { if(nextSelection && mouseUp) { this.graphDiv.emit('plotly_click', { points: [{ - trace: nextSelection.trace, - dataCoord: nextSelection.dataCoord.slice(), - traceCoord: nextSelection.traceCoord.slice(), - textLabel: nextSelection.textLabel, - color: nextSelection.color, - name: nextSelection.name, - hoverinfo: nextSelection.hoverinfo + x: nextSelection.traceCoord[0], + y: nextSelection.traceCoord[1], + data: this._inputs[nextSelection.trace.uid], + fullData: this.fullData, + xaxis: this.xaxis, + yaxis: this.yaxis }] }); } @@ -547,14 +552,12 @@ proto.draw = function() { // also it's important to copy, otherwise data is lost by the time event data is read this.graphDiv.emit('plotly_hover', { points: [{ - trace: nextSelection.trace, - dataCoord: nextSelection.dataCoord.slice(), - traceCoord: nextSelection.traceCoord.slice(), - textLabel: nextSelection.textLabel, - color: nextSelection.color, - name: nextSelection.name, - hoverinfo: nextSelection.hoverinfo, - screenCoord: nextSelection.screenCoord.slice() + x: nextSelection.traceCoord[0], + y: nextSelection.traceCoord[1], + data: this._inputs[nextSelection.trace.uid], + fullData: this.fullData, + xaxis: this.xaxis, + yaxis: this.yaxis }] }); diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index 270181265d1..3b721b6e2f1 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -12,7 +12,7 @@ var hasWebGLSupport = require('../assets/has_webgl_support'); var click = require('../assets/timed_click'); var hover = require('../assets/hover'); -describe('Test click interactions:', function() { +describe('Test hover and click interactions', function() { if(!hasWebGLSupport('gl2d_click_test')) return; @@ -54,12 +54,14 @@ describe('Test click interactions:', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', - 'name', 'hoverinfo', 'screenCoord' - ]); + expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - expect(pt.traceCoord).toEqual([15.772, 0.387]); + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); done(); }, 250); @@ -89,12 +91,14 @@ describe('Test click interactions:', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', - 'name', 'hoverinfo', 'screenCoord' - ]); + expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - expect(pt.traceCoord).toEqual([15.772, 0.387]); + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); done(); }, 250); @@ -124,12 +128,15 @@ describe('Test click interactions:', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', - 'name', 'hoverinfo', 'screenCoord' - ]); + expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); + + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); - expect(pt.traceCoord).toEqual([15.772, 0.387]); done(); }, 250); @@ -201,7 +208,17 @@ describe('Test click interactions:', function() { click(654.7712871743302, 316.97670766680994); window.setTimeout(function() { - expect(futureData.points[0].traceCoord).toEqual([15.772, 0.387]); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); + + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); done(); @@ -231,12 +248,14 @@ describe('Test click interactions:', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual([ - 'trace', 'dataCoord', 'traceCoord', 'textLabel', 'color', - 'name', 'hoverinfo', 'screenCoord' - ]); + expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - expect(pt.traceCoord).toEqual([15.772, 0.387]); + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); done(); }, 250); From 2e8db74b0a5d354f6138d4e534b1dd7503d7e13a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 3 Oct 2016 17:20:52 +0200 Subject: [PATCH 05/10] PR feedback: enriching event callback data - indices --- src/plots/gl2d/scene2d.js | 13 ++++-- src/traces/scattergl/convert.js | 1 + test/jasmine/tests/gl2d_click_test.js | 61 +++++++++------------------ 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 69432c8618e..9a1979fbb41 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -452,7 +452,7 @@ proto.updateTraces = function(fullData, calcData) { // update / create trace objects for(i = 0; i < fullData.length; i++) { fullTrace = fullData[i]; - this._inputs[fullTrace.uid] = fullTrace._input; + this._inputs[fullTrace.uid] = i; var calcTrace = calcData[i], traceObj = this.traces[fullTrace.uid]; @@ -507,13 +507,17 @@ proto.draw = function() { ); var nextSelection = result && result.object._trace.handlePick(result); + var curveIndex; if(nextSelection && mouseUp) { + curveIndex = this._inputs[nextSelection.trace.uid]; this.graphDiv.emit('plotly_click', { points: [{ x: nextSelection.traceCoord[0], y: nextSelection.traceCoord[1], - data: this._inputs[nextSelection.trace.uid], + curveNumber: curveIndex, + pointNumber: nextSelection.pointIndex, + data: this.fullData[curveIndex]._input, fullData: this.fullData, xaxis: this.xaxis, yaxis: this.yaxis @@ -550,11 +554,14 @@ proto.draw = function() { // this needs to happen before the next block that deletes traceCoord data // also it's important to copy, otherwise data is lost by the time event data is read + curveIndex = this._inputs[nextSelection.trace.uid]; this.graphDiv.emit('plotly_hover', { points: [{ x: nextSelection.traceCoord[0], y: nextSelection.traceCoord[1], - data: this._inputs[nextSelection.trace.uid], + curveNumber: curveIndex, + pointNumber: nextSelection.pointIndex, + data: this.fullData[curveIndex]._input, fullData: this.fullData, xaxis: this.xaxis, yaxis: this.yaxis diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js index 95053e5ac5b..fe7a44ebaf3 100644 --- a/src/traces/scattergl/convert.js +++ b/src/traces/scattergl/convert.js @@ -128,6 +128,7 @@ proto.handlePick = function(pickResult) { this.color[index] : this.color, name: this.name, + pointIndex: index, hoverinfo: this.hoverinfo }; }; diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index 3b721b6e2f1..fa81f1cff19 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -20,6 +20,21 @@ describe('Test hover and click interactions', function() { var mockCopy, gd; + function check(pt) { + expect(Object.keys(pt)).toEqual([ + 'x', 'y', 'curveNumber', 'pointNumber', 'data', 'fullData', 'xaxis', 'yaxis' + ]); + + expect(pt.x).toEqual(15.772); + expect(pt.y).toEqual(0.387); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual(33); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); + } + beforeAll(function() { jasmine.addMatchers(customMatchers); }); @@ -54,14 +69,7 @@ describe('Test hover and click interactions', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - - expect(pt.x).toEqual(15.772); - expect(pt.y).toEqual(0.387); - expect(pt.fullData.length).toEqual(1); - expect(typeof pt.data.uid).toEqual('string'); - expect(pt.xaxis.domain.length).toEqual(2); - expect(pt.yaxis.domain.length).toEqual(2); + check(pt); done(); }, 250); @@ -91,14 +99,7 @@ describe('Test hover and click interactions', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - - expect(pt.x).toEqual(15.772); - expect(pt.y).toEqual(0.387); - expect(pt.fullData.length).toEqual(1); - expect(typeof pt.data.uid).toEqual('string'); - expect(pt.xaxis.domain.length).toEqual(2); - expect(pt.yaxis.domain.length).toEqual(2); + check(pt); done(); }, 250); @@ -128,15 +129,7 @@ describe('Test hover and click interactions', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - - expect(pt.x).toEqual(15.772); - expect(pt.y).toEqual(0.387); - expect(pt.fullData.length).toEqual(1); - expect(typeof pt.data.uid).toEqual('string'); - expect(pt.xaxis.domain.length).toEqual(2); - expect(pt.yaxis.domain.length).toEqual(2); - + check(pt); done(); }, 250); @@ -211,14 +204,7 @@ describe('Test hover and click interactions', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - - expect(pt.x).toEqual(15.772); - expect(pt.y).toEqual(0.387); - expect(pt.fullData.length).toEqual(1); - expect(typeof pt.data.uid).toEqual('string'); - expect(pt.xaxis.domain.length).toEqual(2); - expect(pt.yaxis.domain.length).toEqual(2); + check(pt); done(); @@ -248,14 +234,7 @@ describe('Test hover and click interactions', function() { var pt = futureData.points[0]; - expect(Object.keys(pt)).toEqual(['x', 'y', 'data', 'fullData', 'xaxis', 'yaxis']); - - expect(pt.x).toEqual(15.772); - expect(pt.y).toEqual(0.387); - expect(pt.fullData.length).toEqual(1); - expect(typeof pt.data.uid).toEqual('string'); - expect(pt.xaxis.domain.length).toEqual(2); - expect(pt.yaxis.domain.length).toEqual(2); + check(pt); done(); }, 250); From 9f77c11449e52ab4c8a83ee96cd362c117f91574 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 3 Oct 2016 18:27:16 +0200 Subject: [PATCH 06/10] DRY up event emission --- src/plots/gl2d/scene2d.js | 47 +++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 9a1979fbb41..f644fa46cd6 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -464,6 +464,24 @@ proto.updateTraces = function(fullData, calcData) { } }; +proto.emitPointAction = function(nextSelection, eventType) { + + var curveIndex = this._inputs[nextSelection.trace.uid]; + + this.graphDiv.emit(eventType, { + points: [{ + x: nextSelection.traceCoord[0], + y: nextSelection.traceCoord[1], + curveNumber: curveIndex, + pointNumber: nextSelection.pointIndex, + data: this.fullData[curveIndex]._input, + fullData: this.fullData, + xaxis: this.xaxis, + yaxis: this.yaxis + }] + }); +}; + proto.draw = function() { if(this.stopped) return; @@ -507,22 +525,9 @@ proto.draw = function() { ); var nextSelection = result && result.object._trace.handlePick(result); - var curveIndex; if(nextSelection && mouseUp) { - curveIndex = this._inputs[nextSelection.trace.uid]; - this.graphDiv.emit('plotly_click', { - points: [{ - x: nextSelection.traceCoord[0], - y: nextSelection.traceCoord[1], - curveNumber: curveIndex, - pointNumber: nextSelection.pointIndex, - data: this.fullData[curveIndex]._input, - fullData: this.fullData, - xaxis: this.xaxis, - yaxis: this.yaxis - }] - }); + this.emitPointAction(nextSelection, 'plotly_click'); } if(result && result.object._trace.hoverinfo !== 'skip' && fullLayout.hovermode) { @@ -554,19 +559,7 @@ proto.draw = function() { // this needs to happen before the next block that deletes traceCoord data // also it's important to copy, otherwise data is lost by the time event data is read - curveIndex = this._inputs[nextSelection.trace.uid]; - this.graphDiv.emit('plotly_hover', { - points: [{ - x: nextSelection.traceCoord[0], - y: nextSelection.traceCoord[1], - curveNumber: curveIndex, - pointNumber: nextSelection.pointIndex, - data: this.fullData[curveIndex]._input, - fullData: this.fullData, - xaxis: this.xaxis, - yaxis: this.yaxis - }] - }); + this.emitPointAction(nextSelection, 'plotly_hover'); var hoverinfo = selection.hoverinfo; if(hoverinfo !== 'all') { From 2e54a992457390e96f8289a2882b3edfc71f6755 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 4 Oct 2016 16:18:39 +0200 Subject: [PATCH 07/10] PR feedback - cover the other gl2d plot types --- src/traces/contourgl/convert.js | 16 ++++++++++------ src/traces/heatmapgl/convert.js | 15 ++++++++++----- src/traces/pointcloud/convert.js | 1 + 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/traces/contourgl/convert.js b/src/traces/contourgl/convert.js index 4d2061aa50a..022ed1b7698 100644 --- a/src/traces/contourgl/convert.js +++ b/src/traces/contourgl/convert.js @@ -60,20 +60,24 @@ function Contour(scene, uid) { var proto = Contour.prototype; proto.handlePick = function(pickResult) { - var index = pickResult.pointId, - options = this.heatmapOptions, - shape = options.shape; + var options = this.heatmapOptions, + shape = options.shape, + index = pickResult.pointId, + xIndex = index % shape[0], + yIndex = Math.floor(index / shape[0]), + zIndex = index; return { trace: this, dataCoord: pickResult.dataCoord, traceCoord: [ - options.x[index % shape[0]], - options.y[Math.floor(index / shape[0])], - options.z[index] + options.x[xIndex], + options.y[yIndex], + options.z[zIndex] ], textLabel: this.textLabels[index], name: this.name, + pointIndex: [xIndex, yIndex, zIndex], hoverinfo: this.hoverinfo }; }; diff --git a/src/traces/heatmapgl/convert.js b/src/traces/heatmapgl/convert.js index 714073c7aae..d86bb815d2b 100644 --- a/src/traces/heatmapgl/convert.js +++ b/src/traces/heatmapgl/convert.js @@ -46,19 +46,24 @@ function Heatmap(scene, uid) { var proto = Heatmap.prototype; proto.handlePick = function(pickResult) { - var index = pickResult.pointId, - shape = this.options.shape; + var options = this.options, + shape = options.shape, + index = pickResult.pointId, + xIndex = index % shape[0], + yIndex = Math.floor(index / shape[0]), + zIndex = index; return { trace: this, dataCoord: pickResult.dataCoord, traceCoord: [ - this.options.x[index % shape[0]], - this.options.y[Math.floor(index / shape[0])], - this.options.z[index] + options.x[xIndex], + options.y[yIndex], + options.z[zIndex] ], textLabel: this.textLabels[index], name: this.name, + pointIndex: [xIndex, yIndex, zIndex], hoverinfo: this.hoverinfo }; }; diff --git a/src/traces/pointcloud/convert.js b/src/traces/pointcloud/convert.js index 2c7374c8a14..efc86dd0f65 100644 --- a/src/traces/pointcloud/convert.js +++ b/src/traces/pointcloud/convert.js @@ -63,6 +63,7 @@ proto.handlePick = function(pickResult) { this.textLabels, color: this.color, name: this.name, + pointIndex: index, hoverinfo: this.hoverinfo }; }; From 57cec8cc8966c186d76038868e22b15f9d1eaf78 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 4 Oct 2016 21:57:48 +0200 Subject: [PATCH 08/10] PR feedback - cover the other gl2d plot types - other plot type tests --- test/jasmine/tests/gl2d_click_test.js | 158 ++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index fa81f1cff19..6da3991c373 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -17,6 +17,79 @@ describe('Test hover and click interactions', function() { if(!hasWebGLSupport('gl2d_click_test')) return; var mock = require('@mocks/gl2d_14.json'); + var mock2 = require('@mocks/gl2d_pointcloud-basic.json'); + var mock3 = { + 'data': [ + { + 'type': 'contourgl', + 'z': [ + [ + 10, + 10.625, + 12.5, + 15.625, + 20 + ], + [ + 5.625, + 6.25, + 8.125, + 11.25, + 15.625 + ], + [ + 2.5, + 3.125, + 5, + 8.125, + 12.5 + ], + [ + 0.625, + 1.25, + 3.125, + 6.25, + 10.625 + ], + [ + 0, + 0.625, + 2.5, + 5.625, + 10 + ] + ], + 'colorscale': 'Jet', + 'contours': { + 'start': 2, + 'end': 10, + 'size': 1 + }, + 'uid': 'ad5624', + 'zmin': 0, + 'zmax': 20 + } + ], + 'layout': { + 'xaxis': { + 'range': [ + 0, + 4 + ], + 'autorange': true + }, + 'yaxis': { + 'range': [ + 0, + 4 + ], + 'autorange': true + }, + 'height': 450, + 'width': 1000, + 'autosize': true + } + }; var mockCopy, gd; @@ -183,6 +256,91 @@ describe('Test hover and click interactions', function() { }); + describe('hover event is fired for other gl2d plot types', function() { + var futureData; + + it('pointcloud', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mock2); + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + + hover(540, 150); + + window.setTimeout(function() { + + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual([ + 'x', 'y', 'curveNumber', 'pointNumber', 'data', 'fullData', 'xaxis', 'yaxis' + ]); + + expect(pt.x).toEqual(4.5); + expect(pt.y).toEqual(9); + expect(pt.curveNumber).toEqual(2); + expect(pt.pointNumber).toEqual(1); + expect(pt.fullData.length).toEqual(3); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); + + done(); + }, 350); + })); + + + }); + + it('heatmapgl', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mock3); + modifiedMockCopy.data[0].type = 'heatmapgl'; + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + + hover(540, 150); + + window.setTimeout(function() { + + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual([ + 'x', 'y', 'curveNumber', 'pointNumber', 'data', 'fullData', 'xaxis', 'yaxis' + ]); + + expect(pt.x).toEqual(2); + expect(pt.y).toEqual(3); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual([2, 3, 17]); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); + + done(); + }, 350); + })); + + + }); + }); + describe('click event is fired on click', function() { var futureData; From a9b8b3e670953ee86ff6a7337362a4a2a12d6f17 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 5 Oct 2016 19:07:25 +0200 Subject: [PATCH 09/10] PR feedback - cover the other gl2d plot types - contourgl plot type test --- test/jasmine/tests/gl2d_click_test.js | 42 +++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index 6da3991c373..c1c1cc973d5 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -60,11 +60,11 @@ describe('Test hover and click interactions', function() { ] ], 'colorscale': 'Jet', - 'contours': { +/* 'contours': { 'start': 2, 'end': 10, 'size': 1 - }, + },*/ 'uid': 'ad5624', 'zmin': 0, 'zmax': 20 @@ -339,6 +339,44 @@ describe('Test hover and click interactions', function() { }); + + it('contourgl', function(done) { + + var modifiedMockCopy = Lib.extendDeep({}, mock3); + + Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) + + .then(new Promise(function() { + + gd.on('plotly_hover', function(data) { + futureData = data; + }); + + hover(540, 150); + + window.setTimeout(function() { + + expect(futureData.points.length).toEqual(1); + + var pt = futureData.points[0]; + + expect(Object.keys(pt)).toEqual([ + 'x', 'y', 'curveNumber', 'pointNumber', 'data', 'fullData', 'xaxis', 'yaxis' + ]); + + expect(pt.x).toEqual(2); + expect(pt.y).toEqual(3); + expect(pt.curveNumber).toEqual(0); + expect(pt.pointNumber).toEqual([2, 3, 17]); + expect(pt.fullData.length).toEqual(1); + expect(typeof pt.data.uid).toEqual('string'); + expect(pt.xaxis.domain.length).toEqual(2); + expect(pt.yaxis.domain.length).toEqual(2); + + done(); + }, 350); + })); + }); }); describe('click event is fired on click', function() { From c1abd3e2a9422c2cd899ee5b0a78f634a330cabd Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 5 Oct 2016 19:23:42 +0200 Subject: [PATCH 10/10] PR feedback - return [x, y] only --- src/traces/contourgl/convert.js | 2 +- src/traces/heatmapgl/convert.js | 2 +- test/jasmine/tests/gl2d_click_test.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/contourgl/convert.js b/src/traces/contourgl/convert.js index 022ed1b7698..c042e76fc62 100644 --- a/src/traces/contourgl/convert.js +++ b/src/traces/contourgl/convert.js @@ -77,7 +77,7 @@ proto.handlePick = function(pickResult) { ], textLabel: this.textLabels[index], name: this.name, - pointIndex: [xIndex, yIndex, zIndex], + pointIndex: [xIndex, yIndex], hoverinfo: this.hoverinfo }; }; diff --git a/src/traces/heatmapgl/convert.js b/src/traces/heatmapgl/convert.js index d86bb815d2b..f8a47b6fa0c 100644 --- a/src/traces/heatmapgl/convert.js +++ b/src/traces/heatmapgl/convert.js @@ -63,7 +63,7 @@ proto.handlePick = function(pickResult) { ], textLabel: this.textLabels[index], name: this.name, - pointIndex: [xIndex, yIndex, zIndex], + pointIndex: [xIndex, yIndex], hoverinfo: this.hoverinfo }; }; diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index c1c1cc973d5..9e75816aeaa 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -327,7 +327,7 @@ describe('Test hover and click interactions', function() { expect(pt.x).toEqual(2); expect(pt.y).toEqual(3); expect(pt.curveNumber).toEqual(0); - expect(pt.pointNumber).toEqual([2, 3, 17]); + expect(pt.pointNumber).toEqual([2, 3]); expect(pt.fullData.length).toEqual(1); expect(typeof pt.data.uid).toEqual('string'); expect(pt.xaxis.domain.length).toEqual(2); @@ -367,7 +367,7 @@ describe('Test hover and click interactions', function() { expect(pt.x).toEqual(2); expect(pt.y).toEqual(3); expect(pt.curveNumber).toEqual(0); - expect(pt.pointNumber).toEqual([2, 3, 17]); + expect(pt.pointNumber).toEqual([2, 3]); expect(pt.fullData.length).toEqual(1); expect(typeof pt.data.uid).toEqual('string'); expect(pt.xaxis.domain.length).toEqual(2);