Sorting two similar tables simultaneously - javascript

I've two tables which has exactly same columns. These tables are placed besides each other. Currently they are sorted separately. I want them to be sorted together. i.e. when I click on first column header of table 1 both tables should be sorted as if both are a single table.
This is the .js which I am using
function SortableTable (tableEl) {
this.tbody = tableEl.getElementsByTagName('tbody');
this.thead = tableEl.getElementsByTagName('thead');
this.tfoot = tableEl.getElementsByTagName('tfoot');
this.getInnerText = function (el) {
if (typeof(el.textContent) != 'undefined') return el.textContent;
if (typeof(el.innerText) != 'undefined') return el.innerText;
if (typeof(el.innerHTML) == 'string') return el.innerHTML.replace(/<[^<>]+>/g,'');
}
this.getParent = function (el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
return el;
else
return this.getParent(el.parentNode, pTagName);
}
this.sort = function (cell) {
var column = cell.cellIndex;
var itm = this.getInnerText(this.tbody[0].rows[1].cells[column]);
var sortfn = this.sortCaseInsensitive;
if (itm.match(/\d\d[-]+\d\d[-]+\d\d\d\d/)) sortfn = this.sortDate; // date format mm-dd-yyyy
if (itm.replace(/^\s+|\s+$/g,"").match(/^[\d\.]+$/)) sortfn = this.sortNumeric;
this.sortColumnIndex = column;
var newRows = new Array();
for (j = 0; j < this.tbody[0].rows.length; j++) {
newRows[j] = this.tbody[0].rows[j];
}
newRows.sort(sortfn);
if (cell.getAttribute("sortdir") == 'down') {
newRows.reverse();
cell.setAttribute('sortdir','up');
} else {
cell.setAttribute('sortdir','down');
}
for (i=0;i<newRows.length;i++) {
this.tbody[0].appendChild(newRows[i]);
}
}
this.sortCaseInsensitive = function(a,b) {
aa = thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]).toLowerCase();
bb = thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]).toLowerCase();
if (aa==bb) return 0;
if (aa<bb) return -1;
return 1;
}
this.sortDate = function(a,b) {
aa = thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]);
bb = thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]);
date1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
date2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
if (date1==date2) return 0;
if (date1<date2) return -1;
return 1;
}
this.sortNumeric = function(a,b) {
aa = parseFloat(thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]));
if (isNaN(aa)) aa = 0;
bb = parseFloat(thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]));
if (isNaN(bb)) bb = 0;
return aa-bb;
}
// define variables
var thisObject = this;
var sortSection = this.thead;
// constructor actions
if (!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length > 0)) return;
if (sortSection && sortSection[0].rows && sortSection[0].rows.length > 0) {
var sortRow = sortSection[0].rows[0];
} else {
return;
}
for (var i=0; i<sortRow.cells.length; i++) {
sortRow.cells[i].sTable = this;
sortRow.cells[i].onclick = function () {
this.sTable.sort(this);
return false;
}
}
}
There are just two columns and are likely to remain the same. Some ideas would be really appreciated.

I don't quite follow the HTML you have (since you didn't include any HTML), so I created a simple version myself here and implemented a sort across tables. The basic idea is that it collects all the data out of the tables into a single javascript data structure, sorts the javascript data structure and then puts all the data back into the tables.
This makes the sorting much simpler and the only places you have to deal with the complexities of multiple tables is when retrieving the data and then putting it back into the tables. You can see it work here: http://jsfiddle.net/jfriend00/Z5ywA/. Just click on a column header to see both tables sorted by that column.
The code is this:
function sortTables(colNum) {
var t1 = document.getElementById("table1");
var t2 = document.getElementById("table2");
var data = [], sortFn;
function sortAlpha(a, b) {
// deal with empty strings
var aa = a[colNum].data, bb = b[colNum].data;
if (!aa) {
return(!bb ? 0 : -1);
} else if (!bb){
return(1);
} else {
return(aa.localeCompare(bb));
}
}
function sortNumeric(a, b) {
// deal with possibly empty strings
var aa = a[colNum].data, bb = b[colNum].data;
if (typeof aa == "string" || typeof bb == "string") {
return(sortAlpha(a, b));
} else {
return(aa - bb);
}
}
// get the data
function getData(table) {
var cells, rowData, matches, item, cellData;
var rows = table.getElementsByTagName("tbody")[0].getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
rowData = [];
cells = rows[i].getElementsByTagName("td");
for (var j = 0; j < cells.length; j++) {
// add each cell in the row to the rowData data structure
item = {};
item.origStr = cells[j].textContent || cells[j].innerText;
cellData = item.origStr.replace(/^\s*|\s*$/g, "").toLowerCase();
if (cellData.match(/^[\d\.]+$/)) {
cellData= parseFloat(cellData);
} else if (matches = cellData.match(/^(\d+)-(\d+)-(\d+)$/)) {
cellData= new Date(
parseInt(matches[3], 10),
parseInt(matches[1], 10) - 1,
parseInt(matches[2], 10)
);
}
item.data = cellData;
// determine the type of sort based on the first cell we find
// with data in the column that we're sorting
if (!sortFn && item.data !== "" && j == colNum) {
if (typeof item.data == "number" || typeof item.data == "object") {
sortFn = sortNumeric;
} else {
sortFn = sortAlpha;
}
}
rowData.push(item);
}
// add each row to the overall data structure
data.push(rowData);
}
}
// put data back into the tables
function putData(table) {
var cells, rowData, item;
var rows = table.getElementsByTagName("tbody")[0].getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
cells = rows[i].getElementsByTagName("td");
for (var j = 0; j < cells.length; j++) {
// add each cell in the row to the rowData data structure
cells[j].innerHTML = data[0][j].origStr;
}
// remove this row
data.shift();
}
}
getData(t1);
getData(t2);
data.sort(sortFn);
putData(t1);
putData(t2);
return(false);
}
​ ​

Related

Last Key in JavaScript array appearing as Length?

Bit of a weird one. Am using the following code build an array from a json object to make it easier to reference later in the code. However it would appear that when the last item of each array is created, rather than adding a new item, the Key of the item appears as the length of the array.
perfsJson = $.parseJSON(result);
var extras = new Array();
for (var i = perfsJson.length - 1; i >= 0; i--) {
var obj = perfsJson[i];
if (obj != null) {
if (obj.Extras != null) {
for (var perf_no in obj.Extras) {
if (extras[perf_no] == undefined) {
var arr = new Array();
for (var extra in obj.Extras[perf_no]) {
if (arr[extra] == undefined) {
arr[extra] = obj.Extras[perf_no][extra];
}
}
extras[perf_no] = arr;
}
}
break;
}
}
}
The resulting array appears as below:
Any ideas what's going on here?
Edit:
Sample of Json below
{"Extras":{"32516":{"24186":"Example text"},"32515":{"24186":"Example text"},"32514":{"24186":"Example text"},"32512":{"24186":"Example text"},"32513":{"24186":"Example text"},"32511":{"24186":"Example text"},"32510":{"24186":"Example text"},"32509":{"24186":"Example text"},"32507":{"24186":"Example text"},"32503":{"24186":"Example text"},"32506":{"24186":"Example text"},"32505":{"24186":"Example text"},"32508":{"24186":"Example text"},"32502":{},"32497":{}}}
What's going on hear is that you are using for..in to iterate over an array, which is a no-no because it iterates properties that are not the array elements (such as the .length property). Instead, use Array#forEach:
perfsJson = $.parseJSON(result);
var extras = new Array();
for (var i = perfsJson.length - 1; i >= 0; i--) {
var obj = perfsJson[i];
if (obj != null) {
if (obj.Extras != null) {
obj.Extras.forEach(function (item, idx) {
if (typeof extras[idx] === 'undefined') {
var arr = new Array();
item.forEach(function (item2, idx2) {
if (typeof arr[idx2] === 'undefined') {
arr[idx2] = item2;
}
});
extras[idx] = arr;
}
});
break;
}
}
}
The innermost loop is pretty pointless and can be replaced with Array#slice:
perfsJson = $.parseJSON(result);
var extras = new Array();
for (var i = perfsJson.length - 1; i >= 0; i--) {
var obj = perfsJson[i];
if (obj != null) {
if (obj.Extras != null) {
obj.Extras.forEach(function (item, idx) {
if (typeof extras[idx] === 'undefined') {
extras[idx] = item.slice();
}
});
break;
}
}
}
The next inner loop can be replaced with Array#map and two if statements can be combined:
perfsJson = $.parseJSON(result);
var extras = new Array();
for (var i = perfsJson.length - 1; i >= 0; i--) {
var obj = perfsJson[i];
if (obj != null&& obj.Extras != null) {
extras = obj.Extras.map(function (item) {
return item.slice();
});
break;
}
}
In fact, most of this code can be simplified:
function findLastElement(arr) {
for (var i = arr.length - 1; i >= 0; i -= 1) {
if (arr[i] != null && arr[i].Extras != null) { return arr[i]; }
}
}
perfsJson = $.parseJSON(result);
var lastElement = findLastElement(perfsJson);
var extras = lastElement
? lastElement.Extras.map(function (item) { return item.slice(); })
: [];

Angular 1.5 custom filter return data issue

module.filter('myCustomFilter', function ($filter) {
return function(items, searchedTxt, headers) {
if (headers.choice === "option1") {
return resultByDates(items, searchedTxt);
} else if (headers.choice === "option2") {
return resultByName(items, searchedTxt, headers);
}
else if (headers.choice === "option3") {
return resultSimple(items, searchedTxt);
}
return items;
};
function resultByDates(items, search) {
if (search === undefined || search === null)
return items;
var k = Object.keys(search)[0];
var i;
for (i = 0; i < items.length; i++) {
items[i][k] = $filter('date')(items[i][k], "MM/dd/yyyy");
}
var filteredData = $filter('filter')(items, search);
var indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(items.indexOf(filteredData[i]));
}
var output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
}
function resultByName(items, search, headers) {
if (search === undefined || search === null)
return items;
if (headers !== undefined) {
var k = Object.keys(search)[0];
var i;
var componentVals = headers.componentVals;
var itemsCopy = angular.copy(items);
for (i = 0; i < items.length; i++) {
for (var obj in componentVals) {
if (componentVals[obj].ID === itemsCopy[i][k]) {
itemsCopy[i][k] = componentVals[obj].Name;
break;
}
}
}
var filteredData = $filter('filter')(itemsCopy, search);
var indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(itemsCopy.indexOf(filteredData[i]));
}
var output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
}
return items;
}
function resultSimple(items, search) {
if (search === undefined || search === null)
return items;
return $filter('filter')(items, search);
}
});
Guys, I have above filter which works - partially, Option1 and Option3 returns correct filtered data, but there is some problem with Option2.
When I filter data with Option1 it returns correctly filtered data, then I can additionally filter with Option3 and it filters incorrectly returned previously data. When I use Option2 it seems like the data is being returned is not binded with the previous return, it's returning separate data.It seems like it is a separate collection... Is there something wrong with the way I return data in Option2?
Hope I have explained problem sufficiently. Thanks.
Below version with some fixes suggested by Himmel.
module.filter('myCustomFilter', function ($filter) {
return function (items, searchedTxt, headers) {
var key;
var i;
var indexes;
var filteredData;
var output;
if (headers.choice === "option1") {
key = Object.keys(searchedTxt)[0];
for (i = 0; i < items.length; i++) {
items[i][key] = $filter('date')(items[i][key], "MM/dd/yyyy");
}
filteredData = $filter('filter')(items, searchedTxt);
indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(items.indexOf(filteredData[i]));
}
output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
} else if (headers.choice === "option2") {
key = Object.keys(searchedTxt)[0];
var componentVals = headers.componentVals;
var itemsCopy = angular.copy(items);
for (i = 0; i < items.length; i++) {
for (var obj in componentVals) {
if (componentVals[obj].ID === itemsCopy[i][key]) {
itemsCopy[i][key] = componentVals[obj].Name;
break;
}
}
}
filteredData = $filter('filter')(itemsCopy, searchedTxt);
indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(itemsCopy.indexOf(filteredData[i]));
}
output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
} else if (headers.choice === "option3") {
return $filter('filter')(items, searchedTxt);
}
return items;
};
});
I have finally figured out the problem… So when I filtered with Option3 there was no issue because I didn’t modify collection before filtering, after when I filtered with Option1 I did mods to the collection because I wanted to filter based on displayed formatted date. Finally when I used Option3 I was only modifying collection for needs of current Option3 filter – without considering that before filtering I should consider mods that I have done during Option2 filtering. To confirm/test I have created a global array which holds my modified collection, so every time I’m filtering with any of the options I’m using that global array. It’s very dirty temporary solution but it works. Hope I clarified this problem enough. Is there a better solution?
It seems like you're trying to combine learning JavaScript and Angular at the same time, tough times!
module.filter('myCustomFilter', function ($filter) {
// You probably aren't trying to return "function", here
return function(items, searchedTxt, headers) {
if (headers.choice === "option1") {
return resultByDates(items, searchedTxt);
} else if (headers.choice === "option2") {
return resultByName(items, searchedTxt, headers);
}
else if (headers.choice === "option3") {
return resultSimple(items, searchedTxt);
}
return items;
};
// are you declaring another function after you've returned?
function resultByDates(items, search) {
if (search === undefined || search === null)
return items;
var k = Object.keys(search)[0];
var i;
for (i = 0; i < items.length; i++) {
items[i][k] = $filter('date')(items[i][k], "MM/dd/yyyy");
}
var filteredData = $filter('filter')(items, search);
var indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(items.indexOf(filteredData[i]));
}
var output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
}
// another??
function resultByName(items, search, headers) {
if (search === undefined || search === null)
return items;
if (headers !== undefined) {
var k = Object.keys(search)[0];
var i;
var componentVals = headers.componentVals;
var itemsCopy = angular.copy(items);
for (i = 0; i < items.length; i++) {
for (var obj in componentVals) {
if (componentVals[obj].ID === itemsCopy[i][k]) {
itemsCopy[i][k] = componentVals[obj].Name;
break;
}
}
}
var filteredData = $filter('filter')(itemsCopy, search);
var indexes = [];
for (i = 0; i < filteredData.length; i++) {
indexes.push(itemsCopy.indexOf(filteredData[i]));
}
var output = [];
for (i = 0; i < indexes.length; i++) {
output.push(items[indexes[i]]);
}
return output;
}
return items;
}
// christ!!
function resultSimple(items, search) {
if (search === undefined || search === null)
return items;
return $filter('filter')(items, search);
}
});
So, the first line, function($filter) {... is the function that is "invoked" when the list filter is triggered. The value that it returns will be the values that constitute the new list.
So if you "return" [1, 2, 3, 4] you will see those in the list in the browser. But if your function immediately returns a "function" instead of a "list" ([]), well then the browser will probably do something weird with it...
Oh wait, you're calling a bunch of functions that are outside of the current function you're in. Probably remove resultByDates from the current function call, as well as resultByName..., put them as siblings to module.filter.
This question is very hard to fix with so many issues, can you isolate a simpler problem? Maybe a small piece of unexpected behavior?

Push to an array in a nested loop is repeating the last value

I am trying to push elements to an array in a nested loop, but only the last item is getting repeated in the final array, where am I going wrong, very new to javascript asynchronous concept.Below is the function in which I push the items to an array.
$scope.showBeList = function(feed) {
if (feed[srcServ.KEY_CONTENT_TEXT]) {
var content = JSON.parse(feed[srcServ.KEY_CONTENT_TEXT])
if (content) {
$scope.beList = {};
for (var key in content) {
var decorationVal;
//reading value from a lokijs collection
var decoration = dataServ[srcServ.CONST_COLLECTION_DECORATION].find({
'name': key
});
if (decoration && decoration.length) {
decorationVal = decoration[0];
if (decorationVal != null) {
var tempObj = JSON.parse(decorationVal.value);
if (tempObj) {
var header = tempObj[key][key + '_HEADER'];
if (header) {
var counter = content[key].length;
var tempItems = [];
for (var j = 0; j < content[key].length; j++) {
(function(j) {
var obj = {};
obj[srcServ.KEY_MAIN_HEADER] = tempObj[key][srcServ.KEY_DESC];
obj[srcServ.KEY_SUB_HEADER] = header[srcServ.KEY_DESC];
obj.id = j;
var itemVal = content[key][j][key + '_HEADER'];
var details = [];
var notes = [];
for (var item in itemVal) {
var val = null;
var found = false;
for (var i = 0; i < header.field.length; i++) {
if (header.field[i].name == item) {
val = header.field[i];
found = true;
break;
}
}
if (found && val != null) {
val[srcServ.KEY_DESC_VALUE] = itemVal[item];
details.push(val);
}
}
obj.details = details;
counter--;
if (counter == 0) {
$scope.showMoreDetails = true;
$scope.beList.beItems = tempItems;
console.log(JSON.stringify($scope.beList));
}
tempItems.push(obj)
})(j);
// $scope.beList.beItems.push(obj);
}
}
}
}
}
}
}
}
}

Why is the fnSettings() saying it is not a function in the following code and is there a way around it?

I am trying to take data from a table and show/hide rows depending on the id.
var txnfilterbox = function(table, tabID)
{
if (table)
{
var filtervalue = $('#filterText').val();
if((filtervalue != undefined)&&(filtervalue.length > 0))
{
var tableData = table.fnSettings().aoData;
for (var index = 0; index < tableData.length; index++)
{
var rowData = tableData[index]._aData;
if (filtervalue === rowData.id)
{
rowData.show();
}
else
{
rowData.hide();
}
}
}
}
};

Tables to JSON -> Adding additional object identifiers from <tr> ids

I am using tableToJson, which you may or may not be familiar with, to convert a table to JSON (Ive included the code for it here if you don't know it). Simple enough. The output is entirely as expected and looks like:
{"data":[
{"Time":"6:30am - 8:30am","Monday":"","Tuesday":"Maths","Wednesday":"","Thursday":"","Friday":""},
{"Time":"11:15am - 12:45pm","Monday":"Maths","Tuesday":"","Wednesday":"English","Thursday":"","Friday":""},
{"Time":"3:00pm - 5:00pm","Monday":"","Tuesday":"","Wednesday":"English","Thursday":"","Friday":""},
{"Time":"5:00pm - 7:00pm","Monday":"","Tuesday":"Science","Wednesday":"","Thursday":"","Friday":""},
{"Time":"7:00pm - 9:00pm","Monday":"","Tuesday":"Science","Wednesday":"","Thursday":"","Friday":""}]
}
However, I need to expand on it to take the #ids of each <tr> so the JSON looks like: (Assuming the table HTML is <tr id="session 1"></tr> etc.)
{
"data":{
"session 1":{"Time":"6:30am - 8:30am","Monday":"","Tuesday":"sdfsdf","Wednesday":"","Thursday":"","Friday":""},
"session 2":{"Time":"11:15am - 12:45pm","Monday":"sdfsdfsdf","Tuesday":"","Wednesday":"","Thursday":"","Friday":""},
"session 3":{"Time":"3:00pm - 5:00pm","Monday":"","Tuesday":"","Wednesday":"","Thursday":"","Friday":""},
"session 4":{"Time":"5:00pm - 7:00pm","Monday":"","Tuesday":"","Wednesday":"","Thursday":"","Friday":""},
"session 5":{"Time":"7:00pm - 9:00pm","Monday":"","Tuesday":"","Wednesday":"","Thursday":"","Friday":""}
}
}
For reference The code for tableToJson looks like:
(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, name = 'test';
$.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 );
I'm probably missing something really simple, but honestly cannot see how to do this. Any help would be super appreciated. Thank you all in advance!
Please rethink why you'd need to change it. This already provides valid ordered content in a JSON array (accessible via foo.data[0], foo.data[1] etc, or iterable with for(var i; i<foo.data.length;i++){}).
What you want will give you something with no guaranteed order (properties order in an object is irrelevant in JSON) and goes against the flow).
Edit: Stupid API.
If you must conform to some obscure and evil standard, edit the data after it was created. You can't expect $.fn.tableToJSON not to conform to JSON & javascript standards...
var foo = // output from $.fn.tableToJSON
var out = {data:{}}; //declare an *object* instead of an array
for(var i = 0; i < foo.data.length; i++){
out.data['Session ' + (i + 1)] = foo.data[i];
}
//debug output
console.log(JSON.stringify(out))

Categories