', {
- class: 'cells-container'
- });
- $lane.append($cellsContainer);
- const cellMouseOverFactory = (safeLaneTxt, bucketScore, i, time) => {
- return (e) => {
- cellMouseover(e, safeLaneTxt, bucketScore, i, time);
- };
+ function cellMouseOverFactory(time, i) {
+ // Don't use an arrow function here because we need access to `this`,
+ // which is where d3 supplies a reference to the corresponding DOM element.
+ return function (lane) {
+ const bucketScore = getBucketScore(lane, time);
+ if (bucketScore === 0) { return; }
+ cellMouseover(this, lane, bucketScore, i, time);
};
+ }
- // TODO - mark if zoomed in to bucket width?
- let time = startTime;
- for (let i = 0; i < numBuckets; i++) {
- const $cell = $('
', {
- class: 'sl-cell ',
- css: {
- width: cellWidth + 'px'
- },
- 'data-lane-label': label,
- 'data-time': time,
+ const cellsContainer = d3LanesEnter.append('div').classed('cells-container', true);
+ function getBucketScore(lane, time) {
+ let bucketScore = 0;
+ const point = points.find((p) => {
+ return (p.value > 0 && p.laneLabel === lane && p.time === time);
+ });
+ if (typeof point !== 'undefined') {
+ bucketScore = point.value;
+ }
+ return bucketScore;
+ }
+
+ // TODO - mark if zoomed in to bucket width?
+ let time = startTime;
+ Array(numBuckets || 0).fill(null).forEach((v, i) => {
+ const cell = cellsContainer.append('div')
+ .classed('sl-cell', true)
+ .style('width', `${cellWidth}px`)
+ .attr('data-lane-label', label => mlEscape(label))
+ .attr('data-time', time)
+ .attr('data-bucket-score', (lane) => {
+ return getBucketScore(lane, time);
+ })
+ // use a factory here to bind the `time` and `i` values
+ // of this iteration to the event.
+ .on('mouseover', cellMouseOverFactory(time, i))
+ .on('mouseleave', cellMouseleave)
+ .each(function (laneLabel) {
+ this.__clickData__ = {
+ bucketScore: getBucketScore(laneLabel, time),
+ laneLabel,
+ swimlaneType,
+ time
+ };
});
+ // calls itself with each() to get access to lane (= d3 data)
+ cell.append('div').each(function (lane) {
+ const el = d3.select(this);
+
let color = 'none';
let bucketScore = 0;
- for (let j = 0; j < points.length; j++) {
- // this may break if detectors have the duplicate descriptions
- if (points[j].value > 0 && points[j].laneLabel === lane && points[j].time === time) {
- bucketScore = points[j].value;
- color = colorScore(bucketScore);
- $cell.append($('
', {
- class: 'sl-cell-inner',
- css: {
- 'background-color': color
- }
- }));
- $cell.attr({ 'data-score': bucketScore });
- $cell.find('.sl-cell-inner-dragselect').remove();
- } else if ($cell.find('.sl-cell-inner-dragselect').length === 0 && $cell.find('.sl-cell-inner').length === 0) {
- $cell.append($('
', {
- class: 'sl-cell-inner-dragselect'
- }));
- }
- }
- // Escape single quotes and backslash characters in the HTML for the event handlers.
- $cell.data({
- 'click': {
- bucketScore,
- laneLabel: lane,
- swimlaneType,
- time
- }
+ const point = points.find((p) => {
+ return (p.value > 0 && p.laneLabel === lane && p.time === time);
});
- if (bucketScore > 0) {
- const safeLaneTxt = lane.replace(/(['\\])/g, '\\$1');
- const cellMouseOver = cellMouseOverFactory(safeLaneTxt, bucketScore, i, time);
- $cell.on('mouseover', cellMouseOver);
- $cell.on('mouseleave', () => {
- cellMouseleave();
- });
+ if (typeof point !== 'undefined') {
+ bucketScore = point.value;
+ color = colorScore(bucketScore);
+ el.classed('sl-cell-inner', true)
+ .style('background-color', color);
+ } else {
+ el.classed('sl-cell-inner-dragselect', true);
}
+ });
- $cellsContainer.append($cell);
-
- time += stepSecs;
- }
-
- $swimlanes.append($lane);
+ time += stepSecs;
});
- const laneTimes = d3.select($swimlanes.get(0))
+ // ['x-axis'] is just a placeholder so we have an array of 1.
+ const laneTimes = swimlanes.selectAll('.time-tick-labels').data(['x-axis'])
+ .enter()
.append('div')
.classed('time-tick-labels', true);