function SvgList(root, cfg, width, minItemWidth, updated, clicked) { 'use strict'; var self; var shapes = cfg.symbols; var cols = Math.floor(width / minItemWidth); var itemWidth = Math.floor((width + cfg.fontSize) / cols); var data; var previousData = []; function selection(o, n) { root.selectAll('g').data(o ? [o, n] : [n], function (d) { return d && d.properties ? d.properties.id : null; }) .style('font-weight', function (d) { return ((d === n) && (n !== o)) ? 'bold' : null; }) .selectAll('text') .each(wrap); } function update(topo) { data = topo.features; self.filtered = data; var lastRow = Math.ceil(data.length / cols); var height = lastRow * cfg.lineHeight; updated(height); enter(data, previousData); previousData = data; } function filter(l) { var filtered = data.filter(function (d) { var t = d.properties.description; return !l[t].off; }); enter(filtered, previousData); previousData = filtered; cfg.filtered = filtered; } function enter(filtered, previousData) { var lastRow = Math.ceil(filtered.length / cols); var g = root.selectAll('g').data(filtered, function (d) { return d.properties.id; }); g.exit().remove(); g.transition().attr('transform', function (d, i) { var row = i % lastRow; var col = (i - row) / lastRow; return 'translate(' + [col * itemWidth, row * cfg.lineHeight] + ')'; }); var a = g.enter().append('g') .attr('class', 'item') .style('opacity', previousData.length ? 0 : 1) .attr('transform', function (d, i) { var row = i % lastRow; var col = (i - row) / lastRow; return 'translate(' + [col * itemWidth, row * cfg.lineHeight] + ')'; }) .on('click', clicked); a.transition().delay(previousData.length ? 250 : 0) .style('opacity', 1); a.append('path') .attr('class', function (d) { return 'symbol ' + d.properties.description; }) .attr('transform', 'translate(' + [cfg.fontSize / 2, cfg.lineMid] + ')') .attr('d', function (d) { var s = cfg.sizes[d.properties.description]; return d3.svg.symbol().size(s).type(shapes[d.properties.description])(); }); a.append('text') .attr('dy', cfg.fontSize) .attr('dx', cfg.fontSize + cfg.lineMid) .text(function (d) { return d.properties.name; }) .each(wrap); } function wrap() { var self = d3.select(this); var text = self.data()[0].properties.name; self.text(text); var textLength = self.node().getComputedTextLength(); while (textLength > (itemWidth - 50) && text.length > 0) { text = text.slice(0, -1); self.text(text + '…'); textLength = self.node().getComputedTextLength(); } self.text(self.text().replace(' …', '…')); } self = { update: update, filter: filter, selection: selection }; return self; }