Skip to content

Commit 742a2ff

Browse files
arothuisfnando
authored andcommitted
Add an interaction layer to prevent duplicated listeners and support hovering over cursor (#6)
1 parent f40637f commit 742a2ff

File tree

4 files changed

+25
-17
lines changed

4 files changed

+25
-17
lines changed

__snapshots__/sparkline_test.js.snap-shot

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ exports['renders svg for empty values array 1'] = "<svg width=\"100\" height=\"3
44

55
exports['renders svg for 1-item array 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"></svg>"
66

7-
exports['renders interactive svg 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 26 L 4 26 L 50 15 L 96 4\" fill=\"none\"></path><path d=\"M4 26 L 4 26 L 50 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"-1000\" x2=\"-1000\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"-1000\" cy=\"-1000\" r=\"2\"></circle></svg>"
7+
exports['renders interactive svg 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 26 L 4 26 L 50 15 L 96 4\" fill=\"none\"></path><path d=\"M4 26 L 4 26 L 50 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"-1000\" x2=\"-1000\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"-1000\" cy=\"-1000\" r=\"2\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
88

9-
exports['updates interactive svg when mouse moves 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 26 L 4 26 L 50 15 L 96 4\" fill=\"none\"></path><path d=\"M4 26 L 4 26 L 50 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"96\" x2=\"96\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"96\" cy=\"4\" r=\"2\"></circle></svg>"
9+
exports['renders svg with custom cursor 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"4\" x2=\"4\" y1=\"0\" y2=\"30\" stroke-width=\"3\"></line><circle class=\"sparkline--spot\" cx=\"4\" cy=\"15\" r=\"2\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
1010

11-
exports['renders interactive svg based on the nearest edge 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"4\" x2=\"4\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"4\" cy=\"15\" r=\"2\"></circle></svg>"
11+
exports['renders svg with custom spot 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M6 15 L 6 15 L 94 5\" fill=\"none\"></path><path d=\"M6 15 L 6 15 L 94 5 V 30 L 6 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"6\" x2=\"6\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"6\" cy=\"15\" r=\"3\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
1212

13-
exports['renders interactive svg based on the nearest edge 2'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"96\" x2=\"96\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"96\" cy=\"4\" r=\"2\"></circle></svg>"
13+
exports['updates interactive svg when mouse moves 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 26 L 4 26 L 50 15 L 96 4\" fill=\"none\"></path><path d=\"M4 26 L 4 26 L 50 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"96\" x2=\"96\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"96\" cy=\"4\" r=\"2\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
1414

15-
exports['renders svg with custom cursor 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"4\" x2=\"4\" y1=\"0\" y2=\"30\" stroke-width=\"3\"></line><circle class=\"sparkline--spot\" cx=\"4\" cy=\"15\" r=\"2\"></circle></svg>"
15+
exports['renders interactive svg based on the nearest edge 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"4\" x2=\"4\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"4\" cy=\"15\" r=\"2\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
1616

17-
exports['renders svg with custom spot 1'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M6 15 L 6 15 L 94 5\" fill=\"none\"></path><path d=\"M6 15 L 6 15 L 94 5 V 30 L 6 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"6\" x2=\"6\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"6\" cy=\"15\" r=\"3\"></circle></svg>"
17+
exports['renders interactive svg based on the nearest edge 2'] = "<svg width=\"100\" height=\"30\" stroke-width=\"2\"><path d=\"M4 15 L 4 15 L 96 4\" fill=\"none\"></path><path d=\"M4 15 L 4 15 L 96 4 V 30 L 4 30 Z\" stroke=\"none\"></path><line class=\"sparkline--cursor\" x1=\"96\" x2=\"96\" y1=\"0\" y2=\"30\" stroke-width=\"2\"></line><circle class=\"sparkline--spot\" cx=\"96\" cy=\"4\" r=\"2\"></circle><rect width=\"100\" height=\"30\" style=\"fill:transparent;stroke:transparent\" class=\"sparkline--interaction-layer\"></rect></svg>"
1818

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
"main": "dist/sparkline.js",
1010
"module": "src/sparkline.js",
1111
"scripts": {
12-
"test": "mocha --require babel-core/register 'test/**/*_test.js'",
12+
"test": "mocha --require babel-core/register \"test/**/*_test.js\"",
1313
"js:dist:expanded": "webpack",
14-
"js:dist:minified": "NODE_ENV=production webpack",
14+
"js:dist:minified": "env NODE_ENV=production webpack",
1515
"dist": "yarn test && yarn js:dist:expanded && yarn js:dist:minified"
1616
},
1717
"description": "Generate SVG sparklines with JavaScript without any external dependency.",

src/sparkline.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,15 @@ export function sparkline(svg, entries, options) {
151151
svg.appendChild(cursor);
152152
svg.appendChild(spot);
153153

154-
svg.addEventListener("mouseout", event => {
154+
const interactionLayer = buildElement("rect", {
155+
width: svg.attributes.width.value,
156+
height: svg.attributes.height.value,
157+
style: "fill:transparent;stroke:transparent",
158+
class: "sparkline--interaction-layer",
159+
});
160+
svg.appendChild(interactionLayer);
161+
162+
interactionLayer.addEventListener("mouseout", event => {
155163
cursor.setAttribute("x1", offscreen);
156164
cursor.setAttribute("x2", offscreen);
157165

@@ -162,7 +170,7 @@ export function sparkline(svg, entries, options) {
162170
}
163171
});
164172

165-
svg.addEventListener("mousemove", event => {
173+
interactionLayer.addEventListener("mousemove", event => {
166174
const mouseX = event.offsetX;
167175

168176
let nextDataPoint = datapoints.find(entry => {

test/sparkline_test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe("sparkline", () => {
5353
});
5454

5555
event.offsetX = 49;
56-
svg.dispatchEvent(event);
56+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
5757

5858
snapshot(svg.outerHTML);
5959
});
@@ -68,7 +68,7 @@ describe("sparkline", () => {
6868
});
6969

7070
event.offsetX = 49;
71-
svg.dispatchEvent(event);
71+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
7272

7373
snapshot(svg.outerHTML);
7474
});
@@ -83,7 +83,7 @@ describe("sparkline", () => {
8383
});
8484

8585
event.offsetX = 100;
86-
svg.dispatchEvent(event);
86+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
8787

8888
snapshot(svg.outerHTML);
8989
});
@@ -98,11 +98,11 @@ describe("sparkline", () => {
9898
});
9999

100100
event.offsetX = 40;
101-
svg.dispatchEvent(event);
101+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
102102
snapshot(svg.outerHTML);
103103

104104
event.offsetX = 80;
105-
svg.dispatchEvent(event);
105+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
106106
snapshot(svg.outerHTML);
107107
});
108108

@@ -117,7 +117,7 @@ describe("sparkline", () => {
117117
});
118118

119119
event.offsetX = 25;
120-
svg.dispatchEvent(event);
120+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
121121

122122
assert.deepEqual(call[0], event);
123123
assert.deepEqual(call[1].value, 5);
@@ -136,7 +136,7 @@ describe("sparkline", () => {
136136
cancelable: true
137137
});
138138

139-
svg.dispatchEvent(event);
139+
svg.querySelector(".sparkline--interaction-layer").dispatchEvent(event);
140140

141141
assert.deepEqual(call[0], event);
142142
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy