javascript - Adding filtering, searching and pagination to realtime streaming table -
i have table updates using data served node in realtime. table rendered using d3.js.
my problem don't know how add filtering, searching , pagination capabilities table using d3.js. i'm begginer , having trouble understanding best place put code. i've been thinking using external library it's better , cleaner if find way d3.js.
this code:
var table = d3.select('#data') table.append('thead') .append('tr') .selectall('th') .data(['title', 'visits', 'sales', 'conversion(%)']) .enter() .append('th') .text(function (d) { return d }) table.append('tbody') function setupdata(data) { var rows = d3.select('tbody') .selectall('tr') .data(data, function(d) { return d.title }) var entertd = rows.enter() .append('tr') .selectall('td') .data(function(d) { return d3.map(d).values() }) .enter() .append('td') entertd.append('div') entertd.append('span') var td = rows.selectall('td') .data(function(d) { return d3.map(d).entries() }) .attr('class', function (d) { return d.key }) td.select('div') .transition() .duration(800) .style('width', function(d) { switch (d.key) { case 'conversion_rate' : // percentage scale static scale = d3.scale.linear() .domain([0, 1]) .range([0, 100]) break; case 'today_visits': case 'sold_today' : scale = d3.scale.linear() .domain(d3.extent(data, function(d1) { return d1[d.key] })) .range([0, 100]) break; default: return '0px' } return scale(d.value) + 'px' }) td.select('span') .text(function(d) { if (d.key == 'conversion_rate') { return math.round(100*d.value).tofixed(2) + '%'; } return d.value }) } var socket = io(); //var data = []; socket.on('sellers-'.concat(<%= seller %>), function(msg){ var data = []; var seller = $.parsejson(msg); var items = seller['items']; for(item in items) { var item_data = items[item]; data.push({'title': item_data['title'], 'today_visits': item_data['today_visits'], 'sold_today': item_data['sold_today'], 'conversion_rate': item_data['conversion_rate']}); } setupdata(data); //setupdata(json.parse(msg).items) });
it looks main d3 chart render method set use general update pattern, should go there.
you're best bet filtering , searching using native javascript solution. call setupdata method filtered data set, , chart update. instance:
var alldata; var loaditems = function(items) { var item; alldata = []; (item in items) { alldata.push(item); } } var filtermatching = function(matcher) { var item; var filtereddata = []; (item in alldata) { if (matcher(item)) filtereddata.push(item); } setupdata(filtereddata); } // filter on conversion rate filtermatching(function(item) { return item.conversion_rate > 0.5; }); // search on title filtermatching(function(item) { return /foobar/.test(item); }); pagination little bit trickier, still pretty straightforward. need little math.
var itemsperpage = 10; var numberofpages() { return math.ceil(alldata.length / itemsperpage); } var gotopage(pagenumber) { var firstindex = (pagenumber - 1) * itemsperpage; var pageitems = alldata.slice(firstindex, firstindex + itemsperpage); setupdata(pageitems); } now getting work nicely may take bit of effort.
alternatively, applying library crossfilter, plays nicely d3. filtering , pagination might in crossfilter:
var filter = crossfilter(records); var conversion_rate = filter.dimension(function(d) { return d.conversion_rate; }); var title = filter.dimension(function(d) { return d.title; }); // filter on dimension conversion_rate.filterrange([0.5, 1]); title.filterfunction(function (d) { return /foobar/.test(d); }); // take top x of dimension conversion.group().top(5); if have lot of data filter using crossfilter faster. however, since you're charting data @ start anyway, doesn't seem have much, hand-rolling native javascript might way go.
Comments
Post a Comment