添加过滤,搜索和分页到实时流表

时间:2015-05-30 18:42:19

标签: javascript node.js d3.js

我有一个表,可以使用节点实时提供的数据进行更新。该表使用d3.js进行渲染。

我的问题是我不知道如何使用d3.js向表中添加过滤,搜索和分页功能。我是一名初学者,无法理解放置代码的最佳位置。我一直在考虑使用外部库来实现它,但如果我找到一种方法来使用d3.js,它会更好更清洁。

这是我的代码:

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 is 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)
});

1 个答案:

答案 0 :(得分:2)

看起来你的主要D3图表渲染方法已经设置为使用General Update Pattern,所以你应该很高兴去那里。

您最好选择过滤和搜索可能只是使用本机JavaScript解决方案。只需使用过滤后的数据集调用setupData方法,图表就会更新。例如:

var allData;

var loadItems = function(items) {
    var item;

    allData = [];
    for (item in items) {
        allData.push(item);
    }
}

var filterMatching = function(matcher) {
    var item;
    var filteredData = [];
    for (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); });

分页有点棘手,但仍然很简单。你只需要做一些数学运算。

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);
}

现在让这些人很好地合作可能需要一些努力。

或者,您可以考虑应用像Crossfilter这样的库,它可以很好地与D3一起使用。您的过滤和分页在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 a dimension
conversion_rate.filterRange([0.5, 1]);
title.filterFunction(function (d) { return /foobar/.test(d); });

// take the top x of a dimension
conversion.group().top(5);

如果您要过滤大量数据,那么使用Crossfilter会快得多。但是,由于你无论如何都要在开始时绘制所有数据,所以看起来你并没有那么多,所以用原生JavaScript手工绘制它可能就好了。