# blockenberg/2.0.7/blocks/data-table/index.js

Blockenberg — 600+ Advanced Gutenberg Blocks &amp; AI Agent for WordPress Block Editor, version 2.0.7. 686 lines.

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/data-table/index.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/data-table/index.js
- Modified: 2026-03-06T12:32:40+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/blockenberg/2.0.7/code/blocks/data-table/index.js#L10-L20`.

```javascript
( function () {
    var el = wp.element.createElement;
    var Fragment = wp.element.Fragment;
    var __ = wp.i18n.__;
    var registerBlockType = wp.blocks.registerBlockType;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var useBlockProps = wp.blockEditor.useBlockProps;
    var PanelBody = wp.components.PanelBody;
    var PanelColorSettings = wp.blockEditor.PanelColorSettings;
    var Button = wp.components.Button;
    var ToggleControl = wp.components.ToggleControl;
    var RangeControl = wp.components.RangeControl;
    var SelectControl = wp.components.SelectControl;
    var TextControl = wp.components.TextControl;
    var TextareaControl = wp.components.TextareaControl;

    var _dtTC, _dtTV;
    function _tc() { return _dtTC || (_dtTC = window.bkbgTypographyControl); }
    function _tv(obj, prefix) { var fn = _dtTV || (_dtTV = window.bkbgTypoCssVars); return fn ? fn(obj, prefix) : {}; }

    registerBlockType('blockenberg/data-table', {
        title: __('Data Table', 'blockenberg'),
        icon: 'editor-table',
        category: 'bkbg-charts',
        description: __('Interactive data table with sorting, search, pagination and export.', 'blockenberg'),

        edit: function (props) {
            var attributes = props.attributes;
            var setAttributes = props.setAttributes;
            var a = attributes;

            // Update cell
            function updateCell(rowIndex, colIndex, value) {
                var newRows = a.rows.map(function (row, ri) {
                    if (ri === rowIndex) {
                        return row.map(function (cell, ci) {
                            return ci === colIndex ? value : cell;
                        });
                    }
                    return row;
                });
                setAttributes({ rows: newRows });
            }

            // Update header
            function updateHeader(colIndex, value) {
                var newHeaders = a.headers.map(function (h, i) {
                    return i === colIndex ? value : h;
                });
                setAttributes({ headers: newHeaders });
            }

            // Add row at end
            function addRow() {
                var newRow = new Array(a.columns).fill('');
                setAttributes({ rows: a.rows.concat([newRow]) });
            }

            // Insert row at specific position
            function insertRow(index, position) {
                var newRow = new Array(a.columns).fill('');
                var newRows = a.rows.slice();
                var insertAt = position === 'before' ? index : index + 1;
                newRows.splice(insertAt, 0, newRow);
                setAttributes({ rows: newRows });
            }

            // Remove row
            function removeRow(index) {
                if (a.rows.length <= 1) return;
                setAttributes({ rows: a.rows.filter(function (_, i) { return i !== index; }) });
            }

            // Add column at end
            function addColumn() {
                var newHeaders = a.headers.concat([__('Column', 'blockenberg') + ' ' + (a.columns + 1)]);
                var newRows = a.rows.map(function (row) {
                    return row.concat(['']);
                });
                setAttributes({
                    columns: a.columns + 1,
                    headers: newHeaders,
                    rows: newRows
                });
            }

            // Insert column at specific position
            function insertColumn(index, position) {
                var insertAt = position === 'before' ? index : index + 1;
                var newHeaders = a.headers.slice();
                newHeaders.splice(insertAt, 0, __('Column', 'blockenberg'));
                var newRows = a.rows.map(function (row) {
                    var newRow = row.slice();
                    newRow.splice(insertAt, 0, '');
                    return newRow;
                });
                setAttributes({
                    columns: a.columns + 1,
                    headers: newHeaders,
                    rows: newRows
                });
            }

            // Remove column
            function removeColumn(index) {
                if (a.columns <= 1) return;
                var newHeaders = a.headers.filter(function (_, i) { return i !== index; });
                var newRows = a.rows.map(function (row) {
                    return row.filter(function (_, i) { return i !== index; });
                });
                setAttributes({
                    columns: a.columns - 1,
                    headers: newHeaders,
                    rows: newRows
                });
            }

            // Move row
            function moveRow(index, direction) {
                var newIndex = index + direction;
                if (newIndex < 0 || newIndex >= a.rows.length) return;
                var newRows = a.rows.slice();
                var temp = newRows[index];
                newRows[index] = newRows[newIndex];
                newRows[newIndex] = temp;
                setAttributes({ rows: newRows });
            }

            // Move column
            function moveColumn(index, direction) {
                var newIndex = index + direction;
                if (newIndex < 0 || newIndex >= a.columns) return;
                var newHeaders = a.headers.slice();
                var tempH = newHeaders[index];
                newHeaders[index] = newHeaders[newIndex];
                newHeaders[newIndex] = tempH;
                var newRows = a.rows.map(function (row) {
                    var newRow = row.slice();
                    var temp = newRow[index];
                    newRow[index] = newRow[newIndex];
                    newRow[newIndex] = temp;
                    return newRow;
                });
                setAttributes({ headers: newHeaders, rows: newRows });
            }

            // Import CSV
            function importCsv(csvText) {
                if (!csvText.trim()) return;
                // Normalize line endings
                var normalizedText = csvText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
                var lines = normalizedText.trim().split('\n');
                if (lines.length < 1) return;
                
                var parseRow = function(line) {
                    var result = [];
                    var current = '';
                    var inQuotes = false;
                    for (var i = 0; i < line.length; i++) {
                        var char = line[i];
                        if (char === '"') {
                            if (inQuotes && line[i + 1] === '"') {
                                // Escaped quote inside quoted field
                                current += '"';
                                i++;
                            } else {
                                inQuotes = !inQuotes;
                            }
                        } else if (char === ',' && !inQuotes) {
                            result.push(current.trim());
                            current = '';
                        } else {
                            current += char;
                        }
                    }
                    result.push(current.trim());
                    return result;
                };

                var headers = parseRow(lines[0]);
                var rows = [];
                for (var i = 1; i < lines.length; i++) {
                    if (lines[i].trim()) {
                        rows.push(parseRow(lines[i]));
                    }
                }
                if (rows.length === 0) {
                    rows = [new Array(headers.length).fill('')];
                }
                setAttributes({
                    columns: headers.length,
                    headers: headers,
                    rows: rows
                });
            }

            // Style options
            var styleOptions = [
                { label: __('Default', 'blockenberg'), value: 'default' },
                { label: __('Bordered', 'blockenberg'), value: 'bordered' },
                { label: __('Minimal', 'blockenberg'), value: 'minimal' }
            ];

            var responsiveOptions = [
                { label: __('Horizontal Scroll', 'blockenberg'), value: 'scroll' },
                { label: __('Stack on Mobile', 'blockenberg'), value: 'stack' }
            ];

            var alignOptions = [
                { label: __('Left', 'blockenberg'), value: 'left' },
                { label: __('Center', 'blockenberg'), value: 'center' },
                { label: __('Right', 'blockenberg'), value: 'right' }
            ];

            var captionPosOptions = [
                { label: __('Top', 'blockenberg'), value: 'top' },
                { label: __('Bottom', 'blockenberg'), value: 'bottom' }
            ];

            var fontWeightOptions = [
                { label: '400', value: 400 },
                { label: '500', value: 500 },
                { label: '600', value: 600 },
                { label: '700', value: 700 }
            ];

            // State for CSV import
            var csvInput = wp.element.useState('');
            var csvText = csvInput[0];
            var setCsvText = csvInput[1];

            // Inspector
            var inspector = el(InspectorControls, {},
                // Features
                el(PanelBody, { title: __('Features', 'blockenberg'), initialOpen: true },
                    el(ToggleControl, {
                        label: __('Enable Search', 'blockenberg'),
                        checked: a.searchEnabled,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ searchEnabled: v }); }
                    }),
                    a.searchEnabled && el(TextControl, {
                        label: __('Search Placeholder', 'blockenberg'),
                        value: a.searchPlaceholder,
                        onChange: function (v) { setAttributes({ searchPlaceholder: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Enable Sorting', 'blockenberg'),
                        checked: a.sortingEnabled,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ sortingEnabled: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Enable Pagination', 'blockenberg'),
                        checked: a.paginationEnabled,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ paginationEnabled: v }); }
                    }),
                    a.paginationEnabled && el(RangeControl, {
                        label: __('Items Per Page', 'blockenberg'),
                        value: a.itemsPerPage,
                        min: 5,
                        max: 100,
                        step: 5,
                        onChange: function (v) { setAttributes({ itemsPerPage: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Enable Export', 'blockenberg'),
                        checked: a.exportEnabled,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ exportEnabled: v }); }
                    }),
                    a.exportEnabled && el(TextControl, {
                        label: __('Export Button Text', 'blockenberg'),
                        value: a.exportCsvText,
                        onChange: function (v) { setAttributes({ exportCsvText: v }); }
                    })
                ),

                // Layout
                el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
                    el(ToggleControl, {
                        label: __('Sticky Header', 'blockenberg'),
                        checked: a.stickyHeader,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ stickyHeader: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Sticky First Column', 'blockenberg'),
                        checked: a.stickyFirstColumn,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ stickyFirstColumn: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Zebra Striping', 'blockenberg'),
                        checked: a.zebraStriping,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ zebraStriping: v }); }
                    }),
                    el(ToggleControl, {
                        label: __('Row Hover Highlight', 'blockenberg'),
                        checked: a.rowHoverHighlight,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ rowHoverHighlight: v }); }
                    }),
                    el(SelectControl, {
                        label: __('Responsive Mode', 'blockenberg'),
                        value: a.responsiveMode,
                        options: responsiveOptions,
                        onChange: function (v) { setAttributes({ responsiveMode: v }); }
                    }),
                    el(TextControl, {
                        label: __('Caption', 'blockenberg'),
                        value: a.caption,
                        onChange: function (v) { setAttributes({ caption: v }); }
                    }),
                    a.caption && el(SelectControl, {
                        label: __('Caption Position', 'blockenberg'),
                        value: a.captionPosition,
                        options: captionPosOptions,
                        onChange: function (v) { setAttributes({ captionPosition: v }); }
                    })
                ),

                // Style
                el(PanelBody, { title: __('Style', 'blockenberg'), initialOpen: false },
                    el(SelectControl, {
                        label: __('Table Style', 'blockenberg'),
                        value: a.tableStyle,
                        options: styleOptions,
                        onChange: function (v) { setAttributes({ tableStyle: v }); }
                    }),
                    el(RangeControl, {
                        label: __('Cell Padding', 'blockenberg'),
                        value: a.cellPadding,
                        min: 6,
                        max: 24,
                        onChange: function (v) { setAttributes({ cellPadding: v }); }
                    }),
                    el(RangeControl, {
                        label: __('Border Width', 'blockenberg'),
                        value: a.borderWidth,
                        min: 0,
                        max: 3,
                        onChange: function (v) { setAttributes({ borderWidth: v }); }
                    }),
                    el(RangeControl, {
                        label: __('Border Radius', 'blockenberg'),
                        value: a.borderRadius,
                        min: 0,
                        max: 16,
                        onChange: function (v) { setAttributes({ borderRadius: v }); }
                    })
                ),

                // Typography
                el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
                    _tc() && el(_tc(), { label: __('Header', 'blockenberg'), value: a.typoHeader, onChange: function (v) { setAttributes({ typoHeader: v }); } }),
                    _tc() && el(_tc(), { label: __('Cell', 'blockenberg'),   value: a.typoCell,   onChange: function (v) { setAttributes({ typoCell: v }); } })
                ),

                // Colors
                el(PanelColorSettings, {
                    title: __('Header Colors', 'blockenberg'),
                    initialOpen: false,
                    colorSettings: [
                        { value: a.headerBg, onChange: function (c) { setAttributes({ headerBg: c }); }, label: __('Background', 'blockenberg') },
                        { value: a.headerColor, onChange: function (c) { setAttributes({ headerColor: c }); }, label: __('Text', 'blockenberg') },
                        { value: a.headerBorderColor, onChange: function (c) { setAttributes({ headerBorderColor: c }); }, label: __('Border', 'blockenberg') }
                    ]
                }),

                el(PanelColorSettings, {
                    title: __('Cell Colors', 'blockenberg'),
                    initialOpen: false,
                    colorSettings: [
                        { value: a.cellBg, onChange: function (c) { setAttributes({ cellBg: c }); }, label: __('Background', 'blockenberg') },
                        { value: a.cellBgAlt, onChange: function (c) { setAttributes({ cellBgAlt: c }); }, label: __('Alt Background', 'blockenberg') },
                        { value: a.cellColor, onChange: function (c) { setAttributes({ cellColor: c }); }, label: __('Text', 'blockenberg') },
                        { value: a.cellBorderColor, onChange: function (c) { setAttributes({ cellBorderColor: c }); }, label: __('Border', 'blockenberg') },
                        { value: a.hoverBg, onChange: function (c) { setAttributes({ hoverBg: c }); }, label: __('Hover Background', 'blockenberg') },
                        { value: a.accentColor, onChange: function (c) { setAttributes({ accentColor: c }); }, label: __('Accent', 'blockenberg') }
                    ]
                }),

                // Import
                el(PanelBody, { title: __('Import Data', 'blockenberg'), initialOpen: false },
                    el(TextareaControl, {
                        label: __('Paste CSV Data', 'blockenberg'),
                        help: __('First row will be used as headers.', 'blockenberg'),
                        value: csvText,
                        onChange: function (v) { setCsvText(v); },
                        rows: 6
                    }),
                    el('div', { className: 'bkbg-dt-import-actions' },
                        el(Button, {
                            variant: 'secondary',
                            onClick: function () { importCsv(csvText); },
                            disabled: !csvText.trim()
                        }, __('Import CSV', 'blockenberg')),
                        el(Button, {
                            variant: 'tertiary',
                            onClick: function () { setCsvText(''); }
                        }, __('Clear', 'blockenberg'))
                    )
                )
            );

            // CSS variables
            var wrapStyle = Object.assign({
                '--bkbg-dt-header-bg': a.headerBg,
                '--bkbg-dt-header-color': a.headerColor,
                '--bkbg-dt-header-border': a.headerBorderColor,
                '--bkbg-dt-cell-bg': a.cellBg,
                '--bkbg-dt-cell-bg-alt': a.cellBgAlt,
                '--bkbg-dt-cell-color': a.cellColor,
                '--bkbg-dt-cell-border': a.cellBorderColor,
                '--bkbg-dt-hover-bg': a.hoverBg,
                '--bkbg-dt-accent': a.accentColor,
                /* legacy fallback vars */
                '--bkbg-dt-header-font-size': a.headerFontSize + 'px',
                '--bkbg-dt-header-font-weight': a.headerFontWeight,
                '--bkbg-dt-cell-font-size': a.cellFontSize + 'px',
                '--bkbg-dt-cell-font-weight': a.cellFontWeight,
                '--bkbg-dt-cell-padding': a.cellPadding + 'px',
                '--bkbg-dt-brd-w': a.borderWidth + 'px',
                '--bkbg-dt-radius': a.borderRadius + 'px'
            }, _tv(a.typoHeader || {}, '--bkbg-dt-hdr-'), _tv(a.typoCell || {}, '--bkbg-dt-cel-'));

            // Build editor table
            var headerCells = a.headers.map(function (header, colIndex) {
                return el('th', { className: 'bkbg-dt-th bkbg-dt-editor-th', key: 'th-' + colIndex },
                    el('input', {
                        className: 'bkbg-dt-editor-input',
                        type: 'text',
                        value: header,
                        onChange: function (e) { updateHeader(colIndex, e.target.value); },
                        placeholder: __('Header', 'blockenberg')
                    }),
                    el('div', { className: 'bkbg-dt-col-actions' },
                        el(Button, {
                            icon: 'table-col-before',
                            label: __('Insert column before', 'blockenberg'),
                            onClick: function () { insertColumn(colIndex, 'before'); },
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'arrow-left-alt2',
                            label: __('Move left', 'blockenberg'),
                            onClick: function () { moveColumn(colIndex, -1); },
                            disabled: colIndex === 0,
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'arrow-right-alt2',
                            label: __('Move right', 'blockenberg'),
                            onClick: function () { moveColumn(colIndex, 1); },
                            disabled: colIndex === a.columns - 1,
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'table-col-after',
                            label: __('Insert column after', 'blockenberg'),
                            onClick: function () { insertColumn(colIndex, 'after'); },
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'trash',
                            label: __('Remove column', 'blockenberg'),
                            onClick: function () { removeColumn(colIndex); },
                            isDestructive: true,
                            isSmall: true,
                            disabled: a.columns <= 1
                        })
                    )
                );
            });

            var bodyRows = a.rows.map(function (row, rowIndex) {
                var cells = row.map(function (cell, colIndex) {
                    return el('td', { className: 'bkbg-dt-td bkbg-dt-editor-td', key: 'td-' + colIndex },
                        el('input', {
                            className: 'bkbg-dt-editor-input',
                            type: 'text',
                            value: cell,
                            onChange: function (e) { updateCell(rowIndex, colIndex, e.target.value); },
                            placeholder: ''
                        })
                    );
                });

                return el('tr', { className: 'bkbg-dt-editor-tr', key: 'tr-' + rowIndex },
                    cells,
                    el('td', { className: 'bkbg-dt-row-actions' },
                        el(Button, {
                            icon: 'table-row-before',
                            label: __('Insert row before', 'blockenberg'),
                            onClick: function () { insertRow(rowIndex, 'before'); },
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'arrow-up-alt2',
                            label: __('Move up', 'blockenberg'),
                            onClick: function () { moveRow(rowIndex, -1); },
                            disabled: rowIndex === 0,
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'arrow-down-alt2',
                            label: __('Move down', 'blockenberg'),
                            onClick: function () { moveRow(rowIndex, 1); },
                            disabled: rowIndex === a.rows.length - 1,
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'table-row-after',
                            label: __('Insert row after', 'blockenberg'),
                            onClick: function () { insertRow(rowIndex, 'after'); },
                            isSmall: true
                        }),
                        el(Button, {
                            icon: 'trash',
                            label: __('Remove row', 'blockenberg'),
                            onClick: function () { removeRow(rowIndex); },
                            isDestructive: true,
                            isSmall: true,
                            disabled: a.rows.length <= 1
                        })
                    )
                );
            });

            var blockProps = useBlockProps({
                className: 'bkbg-editor-wrap',
                'data-block-label': 'Data Table'
            });

            return el('div', blockProps,
                inspector,
                el('div', {
                    className: 'bkbg-dt-wrap',
                    style: wrapStyle,
                    'data-style': a.tableStyle,
                    'data-zebra': a.zebraStriping ? '1' : '0',
                    'data-hover': a.rowHoverHighlight ? '1' : '0'
                },
                    el('div', { className: 'bkbg-dt-container' },
                        el('table', { className: 'bkbg-dt-editor-table' },
                            el('thead', {},
                                el('tr', {}, headerCells)
                            ),
                            el('tbody', {}, bodyRows)
                        )
                    )
                ),
                el('div', { className: 'bkbg-editor-actions' },
                    el(Button, { variant: 'secondary', icon: 'plus-alt2', onClick: addRow }, __('Add Row', 'blockenberg')),
                    el(Button, { variant: 'secondary', icon: 'plus-alt2', onClick: addColumn }, __('Add Column', 'blockenberg'))
                )
            );
        },

        save: function (props) {
            var a = props.attributes;

            var wrapStyle = Object.assign({
                '--bkbg-dt-header-bg': a.headerBg,
                '--bkbg-dt-header-color': a.headerColor,
                '--bkbg-dt-header-border': a.headerBorderColor,
                '--bkbg-dt-cell-bg': a.cellBg,
                '--bkbg-dt-cell-bg-alt': a.cellBgAlt,
                '--bkbg-dt-cell-color': a.cellColor,
                '--bkbg-dt-cell-border': a.cellBorderColor,
                '--bkbg-dt-hover-bg': a.hoverBg,
                '--bkbg-dt-accent': a.accentColor,
                /* legacy fallback vars */
                '--bkbg-dt-header-font-size': a.headerFontSize + 'px',
                '--bkbg-dt-header-font-weight': a.headerFontWeight,
                '--bkbg-dt-cell-font-size': a.cellFontSize + 'px',
                '--bkbg-dt-cell-font-weight': a.cellFontWeight,
                '--bkbg-dt-cell-padding': a.cellPadding + 'px',
                '--bkbg-dt-brd-w': a.borderWidth + 'px',
                '--bkbg-dt-radius': a.borderRadius + 'px'
            }, _tv(a.typoHeader || {}, '--bkbg-dt-hdr-'), _tv(a.typoCell || {}, '--bkbg-dt-cel-'));

            // Search icon SVG
            var searchIcon = el('svg', {
                className: 'bkbg-dt-search-icon',
                viewBox: '0 0 24 24',
                fill: 'none',
                stroke: 'currentColor',
                strokeWidth: '2'
            },
                el('circle', { cx: '11', cy: '11', r: '8' }),
                el('path', { d: 'M21 21l-4.35-4.35' })
            );

            // Export icon
            var exportIcon = el('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2' },
                el('path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' }),
                el('polyline', { points: '7 10 12 15 17 10' }),
                el('line', { x1: '12', y1: '15', x2: '12', y2: '3' })
            );

            // Sort icon
            var sortIcon = el('span', { className: 'bkbg-dt-sort-icon' },
                el('svg', { viewBox: '0 0 24 24', fill: 'currentColor' },
                    el('path', { d: 'M7 10l5 5 5-5z' })
                )
            );

            // Controls bar
            var controls = (a.searchEnabled || a.exportEnabled) && el('div', { className: 'bkbg-dt-controls' },
                a.searchEnabled && el('div', { className: 'bkbg-dt-search' },
                    searchIcon,
                    el('input', {
                        type: 'text',
                        className: 'bkbg-dt-search-input',
                        placeholder: a.searchPlaceholder,
                        'data-search': '1'
                    })
                ),
                a.exportEnabled && el('div', { className: 'bkbg-dt-export-btns' },
                    el('button', { className: 'bkbg-dt-btn', 'data-export': 'csv' },
                        exportIcon,
                        a.exportCsvText
                    )
                )
            );

            // Table header
            var headerCells = a.headers.map(function (header, index) {
                return el('th', {
                    className: 'bkbg-dt-th',
                    key: 'th-' + index,
                    'data-col': index
                },
                    header,
                    a.sortingEnabled && sortIcon
                );
            });

            // Table body
            var bodyRows = a.rows.map(function (row, rowIndex) {
                var cells = row.map(function (cell, colIndex) {
                    return el('td', {
                        className: 'bkbg-dt-td',
                        key: 'td-' + colIndex,
                        'data-label': a.headers[colIndex] || ''
                    }, cell);
                });
                return el('tr', { className: 'bkbg-dt-tr', key: 'tr-' + rowIndex }, cells);
            });

            // Caption
            var caption = a.caption && el('caption', { className: 'bkbg-dt-caption' }, a.caption);

            return el('div', {
                className: 'bkbg-dt-wrap',
                style: wrapStyle,
                'data-style': a.tableStyle,
                'data-sortable': a.sortingEnabled ? '1' : '0',
                'data-paginate': a.paginationEnabled ? '1' : '0',
                'data-per-page': a.itemsPerPage,
                'data-zebra': a.zebraStriping ? '1' : '0',
                'data-hover': a.rowHoverHighlight ? '1' : '0',
                'data-sticky-header': a.stickyHeader ? '1' : '0',
                'data-sticky-col': a.stickyFirstColumn ? '1' : '0',
                'data-responsive': a.responsiveMode,
                'data-caption-pos': a.captionPosition
            },
                controls,
                el('div', { className: 'bkbg-dt-container' },
                    el('table', { className: 'bkbg-dt-table' },
                        caption,
                        el('thead', { className: 'bkbg-dt-thead' },
                            el('tr', {}, headerCells)
                        ),
                        el('tbody', { className: 'bkbg-dt-tbody' }, bodyRows)
                    )
                )
            );
        }
    });
}() );

```
