Learn how to convert a HTML table into a json array and filter for one and many columns.
Watch the video below for explanation:
Just put the below in a javascript file and you are all set
(function( $ ) {
'use strict';
$.fn.tableToJSON = function(opts) {
// Set options
var defaults = {
ignoreColumns: [],
onlyColumns: null,
ignoreHiddenRows: true,
ignoreEmptyRows: false,
headings: null,
allowHTML: false,
includeRowId: false,
textDataOverride: 'data-override',
textExtractor: null
};
opts = $.extend(defaults, opts);
var notNull = function(value) {
return value !== undefined && value !== null;
};
var ignoredColumn = function(index) {
if( notNull(opts.onlyColumns) ) {
return $.inArray(index, opts.onlyColumns) === -1;
}
return $.inArray(index, opts.ignoreColumns) !== -1;
};
var arraysToHash = function(keys, values) {
var result = {}, index = 0;
$.each(values, function(i, value) {
// when ignoring columns, the header option still starts
// with the first defined column
if ( index < keys.length && notNull(value) ) { result[ keys[index] ] = value; index++; } }); return result; }; var cellValues = function(cellIndex, cell, isHeader) { var $cell = $(cell), // textExtractor extractor = opts.textExtractor, override = $cell.attr(opts.textDataOverride); // don't use extractor for header cells if ( extractor === null || isHeader ) { return $.trim( override || ( opts.allowHTML ? $cell.html() : cell.textContent || $cell.text() ) || '' ); } else { // overall extractor function if ( $.isFunction(extractor) ) { return $.trim( override || extractor(cellIndex, $cell) ); } else if ( typeof extractor === 'object' && $.isFunction( extractor[cellIndex] ) ) { return $.trim( override || extractor[cellIndex](cellIndex, $cell) ); } } // fallback return $.trim( override || ( opts.allowHTML ? $cell.html() : cell.textContent || $cell.text() ) || '' ); }; var rowValues = function(row, isHeader) { var result = []; var includeRowId = opts.includeRowId; var useRowId = (typeof includeRowId === 'boolean') ? includeRowId : (typeof includeRowId === 'string') ? true : false; var rowIdName = (typeof includeRowId === 'string') === true ? includeRowId : 'rowId'; if (useRowId) { if (typeof $(row).attr('id') === 'undefined') { result.push(rowIdName); } } $(row).children('td,th').each(function(cellIndex, cell) { result.push( cellValues(cellIndex, cell, isHeader) ); }); return result; }; var getHeadings = function(table) { var firstRow = table.find('tr:first').first(); return notNull(opts.headings) ? opts.headings : rowValues(firstRow, true); }; var construct = function(table, headings) { var i, j, len, len2, txt, $row, $cell, tmpArray = [], cellIndex = 0, result = []; table.children('tbody,*').children('tr').each(function(rowIndex, row) { if( rowIndex > 0 || notNull(opts.headings) ) {
var includeRowId = opts.includeRowId;
var useRowId = (typeof includeRowId === 'boolean') ? includeRowId : (typeof includeRowId === 'string') ? true : false;
$row = $(row);
var isEmpty = ($row.find('td').length === $row.find('td:empty').length) ? true : false;
if( ( $row.is(':visible') || !opts.ignoreHiddenRows ) && ( !isEmpty || !opts.ignoreEmptyRows ) && ( !$row.data('ignore') || $row.data('ignore') === 'false' ) ) {
cellIndex = 0;
if (!tmpArray[rowIndex]) {
tmpArray[rowIndex] = [];
}
if (useRowId) {
cellIndex = cellIndex + 1;
if (typeof $row.attr('id') !== 'undefined') {
tmpArray[rowIndex].push($row.attr('id'));
} else {
tmpArray[rowIndex].push('');
}
}
$row.children().each(function(){
$cell = $(this);
// skip column if already defined
while (tmpArray[rowIndex][cellIndex]) { cellIndex++; }
// process rowspans
if ($cell.filter('[rowspan]').length) {
len = parseInt( $cell.attr('rowspan'), 10) - 1;
txt = cellValues(cellIndex, $cell);
for (i = 1; i <= len; i++) {
if (!tmpArray[rowIndex + i]) { tmpArray[rowIndex + i] = []; }
tmpArray[rowIndex + i][cellIndex] = txt;
}
}
// process colspans
if ($cell.filter('[colspan]').length) {
len = parseInt( $cell.attr('colspan'), 10) - 1;
txt = cellValues(cellIndex, $cell);
for (i = 1; i <= len; i++) {
// cell has both col and row spans
if ($cell.filter('[rowspan]').length) {
len2 = parseInt( $cell.attr('rowspan'), 10);
for (j = 0; j < len2; j++) {
tmpArray[rowIndex + j][cellIndex + i] = txt;
}
} else {
tmpArray[rowIndex][cellIndex + i] = txt;
}
}
}
txt = tmpArray[rowIndex][cellIndex] || cellValues(cellIndex, $cell);
if (notNull(txt)) {
tmpArray[rowIndex][cellIndex] = txt;
}
cellIndex++;
});
}
}
});
$.each(tmpArray, function( i, row ){
if (notNull(row)) {
// remove ignoredColumns / add onlyColumns
var newRow = notNull(opts.onlyColumns) || opts.ignoreColumns.length ?
$.grep(row, function(v, index){ return !ignoredColumn(index); }) : row,
// remove ignoredColumns / add onlyColumns if headings is not defined
newHeadings = notNull(opts.headings) ? headings :
$.grep(headings, function(v, index){ return !ignoredColumn(index); });
txt = arraysToHash(newHeadings, newRow);
result[result.length] = txt;
}
});
return result;
};
// Run
var headings = getHeadings(this);
return construct(this, headings);
};
})( jQuery );
You spend weeks building a project.
Your client pays you.
Then the income stops.
Meanwhile, other developers are turning similar skills into products that generate revenue month after month.
A SaaS, plugin, web app, or digital product can continue bringing in customers long after it's launched.
The real question isn't whether you can build one.
It's how much money you're leaving on the table by not starting.
Learn How To Build Monthly Income →