# learnpress/4.4.8/assets/src/js/admin/statistics/data-table.js

LearnPress – WordPress LMS Plugin for Create and Sell Online Courses, version 4.4.8. 111 lines.

- Page: https://pluginprobe.com/plugins/learnpress/4.4.8/code/assets/src/js/admin/statistics/data-table.js
- Raw: https://pluginprobe.com/plugins/learnpress/4.4.8/raw/assets/src/js/admin/statistics/data-table.js
- Modified: 2026-09-18T11:22:50+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/learnpress/4.4.8/code/assets/src/js/admin/statistics/data-table.js#L10-L20`.

```javascript
/**
 * Data table renderer — createElement/textContent only, no innerHTML.
 *
 * Emits the plugin's shared table markup ( .lp-table-wrap > table.lp-list-table,
 * per TableListTemplate ) so the dashboard widgets match every other LearnPress
 * table. The extra lp-stats-table class carries the stats-only behaviours
 * ( row hover/highlight, clickable performance rows, empty state ).
 *
 * Column definition:
 * { key, label,
 *   format?: ( value, row ) => string|Node  // Node for links etc.
 *   badge?:  ( row ) => 'green'|'yellow'|'red'|''  // wraps the cell value
 *   csv?:    ( row ) => string  // plain value for CSV export (Nodes can't export)
 * }
 *
 * @since 4.4.2
 * @version 1.1.0
 */

import { getStatsI18n } from './api.js';

/**
 * @param {Element} elContainer Container emptied and refilled.
 * @param {Array}   columns     Column definitions.
 * @param {Array}   rows        Row objects keyed by column key.
 * @param {Object}  options     { emptyText?: string }.
 * @return {Object} { columns, rows } handle for csv/modal reuse.
 */
export const renderDataTable = (
	elContainer,
	columns = [],
	rows = [],
	options = {}
) => {
	if ( ! elContainer ) {
		return { columns, rows };
	}

	elContainer.textContent = '';

	const wrap = document.createElement( 'div' );
	wrap.className = 'lp-table-wrap';

	const table = document.createElement( 'table' );
	table.className = 'lp-list-table lp-stats-table';

	const thead = document.createElement( 'thead' );
	const headRow = document.createElement( 'tr' );
	columns.forEach( ( column ) => {
		const th = document.createElement( 'th' );
		th.textContent = column.label ?? '';
		headRow.appendChild( th );
	} );
	thead.appendChild( headRow );
	table.appendChild( thead );

	const tbody = document.createElement( 'tbody' );

	if ( ! rows.length ) {
		const tr = document.createElement( 'tr' );
		const td = document.createElement( 'td' );
		td.colSpan = columns.length || 1;
		td.className = 'lp-stats-table__empty';
		td.textContent =
			options.emptyText || getStatsI18n( 'noData', 'No data for this period.' );
		tr.appendChild( td );
		tbody.appendChild( tr );
	} else {
		rows.forEach( ( row ) => {
			const tr = document.createElement( 'tr' );
			columns.forEach( ( column ) => {
				const td = document.createElement( 'td' );
				const raw = row[ column.key ];
				const output =
					'function' === typeof column.format
						? column.format( raw, row )
						: raw;

				let cellNode;
				if ( output instanceof Node ) {
					cellNode = output;
				} else {
					cellNode = document.createTextNode(
						null == output ? '' : String( output )
					);
				}

				const badgeColor =
					'function' === typeof column.badge ? column.badge( row ) : '';
				if ( badgeColor ) {
					const badge = document.createElement( 'span' );
					badge.className = `lp-badge lp-badge--${ badgeColor }`;
					badge.appendChild( cellNode );
					td.appendChild( badge );
				} else {
					td.appendChild( cellNode );
				}

				tr.appendChild( td );
			} );
			tbody.appendChild( tr );
		} );
	}

	table.appendChild( tbody );
	wrap.appendChild( table );
	elContainer.appendChild( wrap );

	return { columns, rows };
};

```
