// var table = field_table(
// class => TableClass,
// id => ID (for wrapper)
//
// fetch => URL_FOR_ITEMS,
//
// place_row => function(row_html, item, table) { return bool } // true means function placed row, false means append row
// modify_row_hook => function(row_html, item) { return null },
//
// row_redraw_check => function(item) { return bool },
// row_redraw_fetch => function(item) { return uri },
// row_redraw_interval => integer,
//
// dynamic_field_attribute => FIELD_NAME,
// dynamic_field_fetch => function(field_data) { return uri },
// dynamic_field_builder => function(data) { return data },
//
// columns => [
// { field: '', label: '', class: '', builder => function(item, col, field_spec) { ... }},
// ...
// ],
//
// postfix_columns => [
// ...
// ],
// )
function FieldTable(spec) {
var me = this;
me.spec = spec;
me.rows = [];
me.columns = [];
me.postfix_columns = [];
me.dynamic_columns = [];
me.dynamic_column_lookup = {};
me.redraw = {};
me.redraw_id = 1;
me.row_state = {};
me.hidden_columns = {};
me.render = function() {
me.table = $('<table class="field-table ' + spec.class + '"></table>');
me.header = me.render_header();
var hwrap = $('<thead></thead>');
hwrap.append(me.header);
me.table.append(hwrap);
me.body = $('<tbody></tbody>');
me.table.append(me.body);
me.row_state.body = me.body;
me.row_state.header = me.header;
if (me.spec.row_redraw_interval) {
setInterval(function() {
Object.keys(me.redraw).forEach(function (redraw_id) {
var old = me.redraw[redraw_id];
delete me.redraw[redraw_id];
var uri = me.spec.row_redraw_fetch(old.item);
$.ajax(uri, {
'data': { 'content-type': 'application/json' },
'error': function(a, b, c) { me.redraw[redraw_id] = old },
'success': function(item) {
var row = me.render_row(item);
row.index = old.index;
if (me.spec.modify_row_hook) {
me.spec.modify_row_hook(row.html, item);
}
if (me.spec.row_redraw_check(item)) {
me.redraw[row.redraw_id] = row;
}
me.rows[old.index] = row;
old.html.replaceWith(row.html);
old.html.remove();
},
});
});
}, me.spec.row_redraw_interval);
}
if (typeof(me.spec.fetch) === 'string') {
t2hui.fetch(me.spec.fetch, {done: me.make_sortable}, me.render_item);
}
else if (typeof(me.spec.fetch) === 'object') {
me.spec.fetch.forEach(me.render_item);
if (me.spec.fetch.length > 1) {
me.make_sortable();
}
}
var wrapper = $('<div id="' + spec.id + '" class="field-table-wrapper ' + spec.class + '"></div>');
wrapper.append(me.table);
return wrapper;
}
me.make_sortable = function() {
if (!me.spec.sortable) { return }
me.table.DataTable({
paging: false,
searching: false,
info: false,
orderCellsTop: true,
});
// var them = me.table.children('thead').children('tr').first().children('th');
// them.click(function() {
// $(this).addClass('sorting');
// });
//
// var x = me.table.tablesort({
// 'compare': function(a, b) {
// var an = parseFloat(a);
// var bn = parseFloat(b);
//
// if (!isNaN(an) && !isNaN(bn)) {
// if (an > bn) {
// return 1;
// } else if (an < bn) {
// return -1;
// } else {
// return 0;
// }
// }
// if (!isNaN(an)) {
// return 1;
// }
// if (!isNaN(bn)) {
// return -1;
// }
//
// if (a > b) {
// return 1;
// } else if (a < b) {
// return -1;
// } else {
// return 0;
// }
// }
// });
//
// me.table.on('tablesort:complete', function() {
// them.removeClass('sorting');
// })
}
me.render_item = function(item) {
if (me.spec.expand_item) {
var list = me.spec.expand_item(item);
list.forEach(me._render_item);
}
else {
me._render_item(item);
}
}
me._render_item = function(item) {
var row = me.render_row(item);
if (me.spec.modify_row_hook) {
me.spec.modify_row_hook(row.html, item);
}
if (me.spec.place_row) {
if (!me.spec.place_row(row.html, item, me.table, me.row_state)) {
me.body.append(row.html);
}
}
else {
me.body.append(row.html);
}
if (me.spec.row_redraw_check) {
if (me.spec.row_redraw_check(item)) {
row.redraw_id = me.redraw_id++;
me.redraw[row.redraw_id] = row;
}
}
row.index = me.rows.length;
me.rows.push(row);
}
me.render_row = function(item) {
var row = {
'html': $('<tr></tr>'),
'columns': [],
'dynamic_columns': [],
'postfix_columns': [],
'item': item,
};
row.html.hover(
function() { row.html.addClass('hover') },
function() { row.html.removeClass('hover') },
);
if (me.spec.columns) {
me.spec.columns.forEach(function(data) {
var col = me.render_row_col(data, item);
row.html.append(col);
row.columns.push(col);
});
}
me.dynamic_columns.forEach(function(header) {
var name = header.attr('data-dynamic-name');
var col = $('<td class="col-' + name + '"></td>');
row.html.append(col);
row.dynamic_columns.push(col);
if (me.hidden_columns[name]) {
col.hide();
}
});
if (me.spec.postfix_columns) {
me.spec.postfix_columns.forEach(function(data) {
var col = me.render_row_col(data, item);
row.html.append(col);
row.postfix_columns.push(col);
});
}
var attr = me.spec.dynamic_field_attribute;
if (attr && item[attr]) {
item[attr].forEach(function(field) {
var col = me.render_dynamic_col(field, field.name);
if (me.hidden_columns[field.name]) {
col.hide();
}
var idx = me.find_dynamic_column(field.name);
if (idx === null) {
idx = me.inject_dynamic_column({"name": field.name});
if (row.dynamic_columns.length) {
row.dynamic_columns[row.dynamic_columns.length - 1].after(col);
}
else if (row.columns.length) {
row.columns[row.columns.length - 1].after(col);
}
else {
row.prepend(col);
}
row.dynamic_columns.push(col);
}
else {
row.dynamic_columns[idx].replaceWith(col);
row.dynamic_columns[idx] = col;
}
})
}
return row;
}
me.render_dynamic_col = function(field, name) {
var tooltable = $('<table class="tool_table"></table>');
var toolrow = $('<tr></tr>');
tooltable.append(toolrow);
var col = $('<td class="col-' + name + '"></td>');
col.append(tooltable);
toolrow.append('<td>' + field.details + '</td>');
if (field.raw) {
col.attr('data-order', field.raw);
var tt = t2hui.build_tooltip(col.parent(), field.raw);
var td = $('<td></td>');
td.append(tt);
toolrow.prepend(td);
}
if (field.data) {
var viewer = $('<div class="tool etoggle" title="Extended Data"><img src="/img/data.png" /></div>');
var td = $('<td></td>');
td.append(viewer);
toolrow.prepend(td);
viewer.click(function() {
$('#modal_body').empty();
$('#modal_body').text("loading...");
$('#free_modal').slideDown();
var uri = me.spec.dynamic_field_fetch(field);
$.ajax(uri, {
'data': { 'content-type': 'application/json' },
'success': function(field) {
var data = me.spec.dynamic_field_builder ? me.spec.dynamic_field_builder(field, name) : field;
$('#modal_body').empty();
$('#modal_body').jsonView(data, {collapsed: true});
},
});
});
}
if (field.link) {
var link = $('<td><a class="tool etoggle" title="Link" href="' + field.link + '"><img src="/img/link.png" /></a></td>');
toolrow.prepend(link);
}
return col;
}
me.render_row_col = function(data, item) {
var col = $('<td class="' + data.class + '"></td>');
if (data.builder) {
data.builder(item, col, data);
}
else {
col.text(item[data.name]);
}
return col;
}
me.render_header = function() {
var header = $('<tr class="field-table-header"></tr>');
if (me.spec.columns) {
me.spec.columns.forEach(function(data) {
var col = me.render_header_col(data);
header.append(col);
me.columns.push(col);
});
}
if (me.spec.postfix_columns) {
me.spec.postfix_columns.forEach(function(data) {
var col = me.render_header_col(data);
header.append(col);
me.postfix_columns.push(col);
});
}
return header;
}
me.column_class = function(data) {
return "col-" + (data.class || data.name);
}
me.render_header_col = function(data) {
var label = data.label ? data.label : data.name;
var inner = $('<div class="field-table-header-col-inner">' + label + '</div>');
var col = $('<th class="field-table-header-col ' + me.column_class(data) + '"></th>');
col.append(inner);
inner.click(function() { col.trigger('click'); });
return col;
}
me.find_dynamic_column = function(field) {
if (me.dynamic_column_lookup[field] !== null && me.dynamic_column_lookup[field] !== undefined) {
return me.dynamic_column_lookup[field];
}
return null;
}
me.inject_dynamic_column = function(data) {
var col = me.render_header_col(data);
col.addClass('dynamic');
col.attr('data-dynamic-name', data.name);
var cclass = me.column_class(data);
var tools = col.children('div').first();
var close_icon = $('<img src="/img/close.png" />');
var close = $('<div class="etoggle" title="hide column"></div>');
close.append(close_icon);
close.hover(
function() { close_icon.attr('src', '/img/close_red.png') },
function() { close_icon.attr('src', '/img/close.png') },
);
close.click(function() {
col.hide();
me.table.find('td.' + cclass).hide();
me.hidden_columns[data.name] = 1;
return false;
});
tools.append(close);
if (me.dynamic_columns.length) {
me.dynamic_columns[me.dynamic_columns.length - 1].after(col);
me.rows.forEach(function(row) {
var td = $('<td class="' + cclass + '"></td>');
row.dynamic_columns[row.dynamic_columns.length - 1].after(td);
row.dynamic_columns.push(td);
});
}
else if (me.columns.length) {
me.columns[me.columns.length - 1].after(col);
me.rows.forEach(function(row) {
var td = $('<td class="' + cclass + '"></td>');
row.columns[row.columns.length - 1].after(td);
row.dynamic_columns.push(td);
});
}
else {
me.header.prepend(col);
var row;
me.rows.forEach(function(row) {
var td = $('<td class="' + cclass + '"></td>');
row.append(td);
row.dynamic_columns.push(td);
});
}
me.dynamic_column_lookup[data.name] = me.dynamic_columns.length;
me.dynamic_columns.push(col);
return me.dynamic_column_lookup[data.name];
}
return me;
}