Skip to content

Commit

Permalink
generalize .attrs(resolves #7)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmpolis committed Sep 18, 2016
1 parent 0c94a5b commit 8ecec5e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 27 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ If you use NPM, `npm install d3-annotate`. Otherwise, download the [latest relea

```js
var annotation = d3.annoate()
.container(svg.append('g'))
.key((d) => d.id) // if annotation will be applied to data selection
.container(svg.append('g')) // parent of annotation <text> elements
.key((d) => d.id) // must be serializable, array index by default(a la d3.data)
.text((d) => `${d.name}: ${d.score}`)
.show((d) => d.score > 100); // can be true, false or fn
// TODO: .dx(), .dy(), .canWrite, .canMove, .canDelete
.attr('dx', 10)
.attr('text-anchor', 'start'); // .attr calls cary over to <text>

// TODO
annotation.editMode(true); // enable controls, true by default

var bubbles = d3.selectAll('circle').data(teams, (d) => d.id);
var bubbles = d3.selectAll('circle').data(teams);
bubbles.enter().append('circle').....

bubbles.call(annotation);
Expand Down
2 changes: 2 additions & 0 deletions demo/iris.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@
annotation = window.annotation = d3.annotate()
.show(false) // .show((d) => d.species !== "versicolor")
.text((d) => `${d.species}: ${d.sepalWidth.toFixed(1)} x ${d.sepalLength.toFixed(1)}`)
.attr('text-anchor', 'start')
.attr('dx', 4)
.container(annotationG);

svg.selectAll('.dot').call(annotation);
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
"url": "https://github.com/cmpolis/d3-annotate.git"
},
"scripts": {
"pretest": "rm -rf build && mkdir build && rollup -g d3-drag:d3,d3-selection:d3 -f umd -n d3 -o build/d3-annotate.js -- index.js",
"pretest": "rm -rf build && mkdir build && rollup -g d3-drag:d3,d3-selection:d3,d3-selection-multi:d3 -f umd -n d3 -o build/d3-annotate.js -- index.js",
"test": "tape 'test/**/*-test.js'",
"prepublish": "npm run test && ./node_modules/.bin/babel build/d3-annotate.js -o build/d3-annotate-es5.js && uglifyjs build/d3-annotate-es5.js -c -m -o build/d3-annotate.min.js",
"postpublish": "zip -j build/d3-annotate.zip -- LICENSE README.md build/d3-annotate.js build/d3-annotate.min.js"
},
"dependencies": {
"d3-drag": "1.0",
"d3-selection": "1.0"
"d3-selection": "1.0",
"d3-selection-multi": "1.0"
},
"devDependencies": {
"babel-cli": "^6.14.0",
Expand Down
48 changes: 27 additions & 21 deletions src/annotate.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import {drag} from "d3-drag";
import {event, select} from "d3-selection";
import {event, select, selection} from "d3-selection";

// hacky :( could not get rollup to play nice with d3-selection-multi. << TODO
// import "d3-selection-multi";
import selection_attrs from "./attrs";
selection.prototype.attrs = selection_attrs;

export default function() {
var keyFn = (_, ndx) => ndx,
textFn = (d) => d,
container,
x = (d) => d.box.x + (d.box.width / 2),
y = (d) => d.box.y + (d.box.height / 2),
textAnchor = 'middle',
displayAttrs = {
x: (d) => d.box.x + (d.box.width / 2),
y: (d) => d.box.y + (d.box.height / 2),
'text-anchor': 'middle'
},
show = true,
dragControl = drag()
.on("start", function() { this.classList.add('dragging'); })
Expand All @@ -18,12 +25,13 @@ export default function() {
el.attr('y', +el.attr('y') + event.dy);
});


//
// serialize keys, bind click to add text, add text if `show` is T or fn
function annotate(selection) {
selection.nodes().forEach((el, ndx) => el.__key__ = keyFn(el.__data__, ndx));
selection.on('click', function() { appendText(select(this)); });
if(show) { appendText(selection, true); }
function annotate(_selection) {
_selection.nodes().forEach((el, ndx) => el.__key__ = keyFn(el.__data__, ndx));
_selection.on('click', function() { appendText(select(this)); });
if(show) { appendText(_selection, true); }
}

//
Expand All @@ -40,8 +48,7 @@ export default function() {
textSelection.enter().append('text')
.text(_textFn)
.attr('class', 'annotation with-data')
.attr('x', x).attr('y', y)
.attr('text-anchor', textAnchor)
.attrs(displayAttrs)
.call(dragControl)
.on('click', function() {
if(event.metaKey) { this.remove(); }
Expand Down Expand Up @@ -100,17 +107,16 @@ export default function() {
if(!arguments.length) return show;
show = _; return annotate;
};
annotate.textAnchor = function(_) {
if(!arguments.length) return textAnchor;
textAnchor = _; return annotate;
};
annotate.x = function(_) {
if(!arguments.length) return x;
x = _; return annotate;
};
annotate.y = function(_) {
if(!arguments.length) return y;
y = _; return annotate;
annotate.attr = function() {
if(!arguments.length) {
return displayAttrs;
} else if(arguments.length === 1) {
return displayAttrs[arguments[0]];
} else {
arguments[1] === null ? (delete displayAttrs[arguments[0]]) :
(displayAttrs[arguments[0]] = arguments[1]);
return annotate;
}
};

return annotate;
Expand Down
18 changes: 18 additions & 0 deletions src/attrs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// https://github.com/d3/d3-selection-multi/blob/master/src/selection/attrs.js
import {select} from "d3-selection";

function attrsFunction(selection, map) {
return selection.each(function() {
var x = map.apply(this, arguments), s = select(this);
for (var name in x) s.attr(name, x[name]);
});
}

function attrsObject(selection, map) {
for (var name in map) selection.attr(name, map[name]);
return selection;
}

export default function(map) {
return (typeof map === "function" ? attrsFunction : attrsObject)(this, map);
}

0 comments on commit 8ecec5e

Please sign in to comment.