/** * Data grid is a simple widget designed to list the filtered records, providing * a simple way to define how the items are displayed. * * Note: Unlike other charts, the data grid chart (and data table) use the group attribute as a keying function * for {@link https://github.com/mbostock/d3/wiki/Arrays#-nest nesting} the data together in groups. * Do not pass in a crossfilter group as this will not work. * * Examples: * - {@link http://europarl.me/dc.js/web/ep/index.html List of members of the european parliament} * @class dataGrid * @memberof dc * @mixes dc.baseMixin * @param {String|node|d3.selection} parent - Any valid * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying * a dom block element such as a div; or a dom element or d3 selection. * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. * Interaction with a chart will only trigger events and redraws within the chart's group. * @return {dc.dataGrid} */ dc.dataGrid = function (parent, chartGroup) { var LABEL_CSS_CLASS = 'dc-grid-label'; var ITEM_CSS_CLASS = 'dc-grid-item'; var GROUP_CSS_CLASS = 'dc-grid-group'; var GRID_CSS_CLASS = 'dc-grid-top'; var _chart = dc.baseMixin({}); var _size = 999; // shouldn't be needed, but you might var _html = function (d) { return 'you need to provide an html() handling param: ' + JSON.stringify(d); }; var _sortBy = function (d) { return d; }; var _order = d3.ascending; var _beginSlice = 0, _endSlice; var _htmlGroup = function (d) { return '

' + _chart.keyAccessor()(d) + '

'; }; _chart._doRender = function () { _chart.selectAll('div.' + GRID_CSS_CLASS).remove(); renderItems(renderGroups()); return _chart; }; function renderGroups () { var groups = _chart.root().selectAll('div.' + GRID_CSS_CLASS) .data(nestEntries(), function (d) { return _chart.keyAccessor()(d); }); var itemGroup = groups .enter() .append('div') .attr('class', GRID_CSS_CLASS); if (_htmlGroup) { itemGroup .html(function (d) { return _htmlGroup(d); }); } groups.exit().remove(); return itemGroup; } function nestEntries () { var entries = _chart.dimension().top(_size); return d3.nest() .key(_chart.group()) .sortKeys(_order) .entries(entries.sort(function (a, b) { return _order(_sortBy(a), _sortBy(b)); }).slice(_beginSlice, _endSlice)); } function renderItems (groups) { var items = groups.order() .selectAll('div.' + ITEM_CSS_CLASS) .data(function (d) { return d.values; }); items.enter() .append('div') .attr('class', ITEM_CSS_CLASS) .html(function (d) { return _html(d); }); items.exit().remove(); return items; } _chart._doRedraw = function () { return _chart._doRender(); }; /** * Get or set the index of the beginning slice which determines which entries get displayed by the widget. * Useful when implementing pagination. * @method beginSlice * @memberof dc.dataGrid * @instance * @param {Number} [beginSlice=0] * @return {Number} * @return {dc.dataGrid} */ _chart.beginSlice = function (beginSlice) { if (!arguments.length) { return _beginSlice; } _beginSlice = beginSlice; return _chart; }; /** * Get or set the index of the end slice which determines which entries get displayed by the widget * Useful when implementing pagination. * @method endSlice * @memberof dc.dataGrid * @instance * @param {Number} [endSlice] * @return {Number} * @return {dc.dataGrid} */ _chart.endSlice = function (endSlice) { if (!arguments.length) { return _endSlice; } _endSlice = endSlice; return _chart; }; /** * Get or set the grid size which determines the number of items displayed by the widget. * @method size * @memberof dc.dataGrid * @instance * @param {Number} [size=999] * @return {Number} * @return {dc.dataGrid} */ _chart.size = function (size) { if (!arguments.length) { return _size; } _size = size; return _chart; }; /** * Get or set the function that formats an item. The data grid widget uses a * function to generate dynamic html. Use your favourite templating engine or * generate the string directly. * @method html * @memberof dc.dataGrid * @instance * @example * chart.html(function (d) { return '
'+data.exampleString+'
';}); * @param {Function} [html] * @return {Function} * @return {dc.dataGrid} */ _chart.html = function (html) { if (!arguments.length) { return _html; } _html = html; return _chart; }; /** * Get or set the function that formats a group label. * @method htmlGroup * @memberof dc.dataGrid * @instance * @example * chart.htmlGroup (function (d) { return '

'.d.key . 'with ' . d.values.length .' items

'}); * @param {Function} [htmlGroup] * @return {Function} * @return {dc.dataGrid} */ _chart.htmlGroup = function (htmlGroup) { if (!arguments.length) { return _htmlGroup; } _htmlGroup = htmlGroup; return _chart; }; /** * Get or set sort-by function. This function works as a value accessor at the item * level and returns a particular field to be sorted. * @method sortBy * @memberof dc.dataGrid * @instance * @example * chart.sortBy(function(d) { * return d.date; * }); * @param {Function} [sortByFunction] * @return {Function} * @return {dc.dataGrid} */ _chart.sortBy = function (sortByFunction) { if (!arguments.length) { return _sortBy; } _sortBy = sortByFunction; return _chart; }; /** * Get or set sort order function. * @method order * @memberof dc.dataGrid * @instance * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} * @example * chart.order(d3.descending); * @param {Function} [order=d3.ascending] * @return {Function} * @return {dc.dataGrid} */ _chart.order = function (order) { if (!arguments.length) { return _order; } _order = order; return _chart; }; return _chart.anchor(parent, chartGroup); };