Skip to content

Commit

Permalink
Merge pull request #5 from walterra/event-api-2
Browse files Browse the repository at this point in the history
Refactor event API to recover from layout regressions.
  • Loading branch information
walterra authored Oct 25, 2018
2 parents e51f727 + 6106c6e commit 236ea54
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 63 deletions.
123 changes: 64 additions & 59 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export default function milestones(selector) {
}
function eventMouseOver(d) {
if (typeof callBackMouseOver === 'function') {
dom.select(this).classed('milestones__group__label__text__event--hover', true);
callBackMouseOver(d);
}
return d;
Expand All @@ -94,6 +95,7 @@ export default function milestones(selector) {
}
function eventMouseLeave(d) {
if (typeof callBackMouseOver === 'function') {
dom.select(this).classed('milestones__group__label__text__event--hover', false);
callBackMouseLeave(d);
}
return d;
Expand Down Expand Up @@ -336,72 +338,75 @@ export default function milestones(selector) {
const labelRightMargin = 6;
const finalWidth = Math.min(labelMaxWidth, (Math.max(0, availableWidth - labelRightMargin)));
return finalWidth + 'px';
});
// .html(d => {
// const above = isAbove(d.index);

// const group = '<span class="' + cssTitleClass + '">' + labelFormat(aggregateFormatParse(d.key)) + '</span>';
// const lines = d.values.map(d => {
// const t = d[mapping.text];
// // test if text is an image filename,
// // if so return an image tag with the filename as the source
// if (['jpg', 'jpeg', 'gif', 'png'].indexOf(t.split('.').pop()) > -1) {
// return '<img class="milestones-image-label" src="' + t + '" height="100" />';
// }
// return t;
// });

// (above) ? lines.push(group) : lines.unshift(group);

// return lines.join('<br />');
// });

// delete textEnter children on chart update
textEnter.selectAll('*').remove();

// add textEnter title if above
textEnter.append('div')
.attr('class', cssTitleClass)
.text(d => {
if (!isAbove(d.index)) {
return labelFormat(aggregateFormatParse(d.key));
})
.each(function(d) {
const above = isAbove(d.index);

const element = dom.select(this);
element.empty();

if (!above) {
element.append('span')
.classed(cssTitleClass, true)
.text(labelFormat(aggregateFormatParse(d.key)));
element.append('br');
}
return '';
});

// add textEnter event
textEnter.selectAll('.' + cssEventClass)
.data(d => {
return d.values.map(v => {
return {
d.values.map((v, i) => {
if (i > 0) {
element.append('br');
}

const t = v[mapping.text];
let item;
// test if text is an image filename,
// if so return an image tag with the filename as the source
if (['jpg', 'jpeg', 'gif', 'png'].indexOf(t.split('.').pop()) > -1) {
item = element.append('img')
.classed('milestones-label', true)
.classed('milestones-image-label', true)
.attr('height', '100')
.attr('src', t);
} else {
item = element.append('span')
.classed('milestones-label', true)
.classed('milestones-text-label', true)
.text(t);
}

item.datum({
text: v[mapping.text],
timestamp: v[mapping.timestamp],
attributes: v, // original value of an object passed to the milestone
};
});

if (
typeof callbackClick === 'function'
|| typeof callBackMouseLeave === 'function'
|| typeof callBackMouseOver === 'function'
) {
item.classed(cssEventClass, true);
}

if (typeof callbackClick === 'function') {
item.on('click', eventClick);
}

if (typeof callBackMouseLeave === 'function') {
item.on('mouseleave', eventMouseLeave);
}

if (typeof callBackMouseOver === 'function') {
item.on('mouseover', eventMouseOver);
}
});
})
.enter()
.append('div')
.on('click', eventClick)
.on('mouseleave', eventMouseLeave)
.on('mouseover', eventMouseOver)
.attr('class', cssEventClass)
.attr('data-date', d => d.timestamp)
.html(d => {
if (['jpg', 'jpeg', 'gif', 'png'].indexOf(d.text.split('.').pop()) > -1) {
return '<img class="milestones-image-label" src="' + d.text + '" height="100" />';
}
return d.text;
});

// add textEnter title if bottom
textEnter.append('div')
.attr('class', cssTitleClass)
.text(d => {
if (isAbove(d.index)) {
return labelFormat(aggregateFormatParse(d.key));

if (above) {
element.append('br');
element.append('span')
.classed(cssTitleClass, true)
.text(labelFormat(aggregateFormatParse(d.key)));
}
return '';
});

const textMerge = text.merge(textEnter);
Expand Down
6 changes: 2 additions & 4 deletions src/styles/styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,9 @@
white-space: nowrap;
}
.milestones__group__label__text__event {
color: #000;
padding: 5px 0;
cursor: pointer;
}
.milestones__group__label__text__event:hover {
.milestones__group__label__text__event--hover {
background: #efefef;
color: #313131;
}
}
58 changes: 58 additions & 0 deletions test/event-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import tape from 'tape';
import milestones from '../src/main';
import * as d3 from 'd3-selection';

tape('should render a minimal milestones chart with attached events', t => {
document.body.insertAdjacentHTML(
'afterbegin',
'<div id="wrapper"></div>'
);

const data = [
{ 'timestamp': '2012-09-09T00:00', 'detail': 'v1.0.0' },
{ 'timestamp': '2012-09-10T00:00', 'detail': 'v1.0.1' },
{ 'timestamp': '2012-09-12T00:00', 'detail': 'v1.1.0' }
];

const timeline = milestones('#wrapper')
.onEventClick((d) => {
t.equal(d.text, 'v1.0.0', 'click event text should match label text');
})
.onEventMouseOver((d) => {
t.equal(d.text, 'v1.0.0', 'mouseover event text should match label text');
})
.onEventMouseLeave((d) => {
t.equal(d.text, 'v1.0.0', 'mouseover event text should match label text');
})
.mapping({
timestamp: 'timestamp',
text: 'detail'
});

timeline
.parseTime('%Y-%m-%dT%H:%M')
.aggregateBy('second')
.optimize(true)
.render(data);

t.plan(3);

d3.select('#wrapper .milestones-text-label').each(function (d, i) {
var onClickFunc = d3.select(this).on('click');
onClickFunc.apply(this, [d, i]);
});

d3.select('#wrapper .milestones-text-label').each(function (d, i) {
var onClickFunc = d3.select(this).on('mouseover');
onClickFunc.apply(this, [d, i]);
});

d3.select('#wrapper .milestones-text-label').each(function (d, i) {
var onClickFunc = d3.select(this).on('mouseleave');
onClickFunc.apply(this, [d, i]);
});

t.end();

document.body.innerHTML = '';
});
2 changes: 2 additions & 0 deletions test/milestones-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ tape('should render a minimal milestones chart', t => {
t.equal(d3.selectAll('#wrapper .milestones .milestones__group').size(), 3, 'should render 3 .milestones__group elements');

t.end();

document.body.innerHTML = '';
});

0 comments on commit 236ea54

Please sign in to comment.