/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
A Table builder class.
*/
/**
* The Table builder class.
* @param {Array|undefined} heading An array of column titles or don't supply this if you want a
* table of rows containing a key heading cell and a value normal table cell.
* @constructor
*/
CKCatalog.Table = function(heading) {
this.el = document.createElement('div');
this.el.className = 'table-wrapper';
this._numberOfColumns = 2;
var table = document.createElement('table');
if(heading && Array.isArray(heading)) {
this._numberOfColumns = heading.length;
var head = table.appendChild(document.createElement('thead'));
var tr = head.appendChild(document.createElement('tr'));
heading.forEach(function(name) {
var th = document.createElement('th');
th.textContent = name;
tr.appendChild(th);
});
this.body = table.appendChild(document.createElement('tbody'));
} else {
this.body = table;
}
this.el.appendChild(table);
};
/**
* Display an object of key-value pairs in a table
* @param {object} object Key-value pairs to display in a table
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.renderObject = function(object) {
for(var k in object) {
if(object.hasOwnProperty(k)) {
this.appendRow(k,object[k]);
}
}
return this;
};
/**
* Sets the text for a cell with an undefined value.
* @param {string} text
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.setTextForUndefinedValue = function(text) {
this._textForUndefinedValue = text;
return this;
};
/**
* Sets the text for an empty row.
* @param {string} text
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.setTextForEmptyRow = function(text) {
this._textForEmptyRow = text;
return this;
};
CKCatalog.Table.prototype._textForUndefinedValue = '-';
CKCatalog.Table.prototype._textForEmptyRow = 'No Content';
CKCatalog.Table.prototype._createRowWithKey = function(key) {
var tr = document.createElement('tr');
var th = document.createElement('th');
th.textContent = key;
tr.appendChild(th);
return tr;
};
CKCatalog.Table.prototype._createRowWithValues = function(values,boolArray) {
var tr = document.createElement('tr');
var that = this;
values.forEach(function(value,index) {
var td;
if(value === null || value === undefined) {
td = that._createEmptyValueCell();
} else {
td = document.createElement('td');
if(boolArray && !boolArray[index]) {
if(typeof value === 'object' && !(value instanceof Date)) {
td.appendChild(that._createPrettyObject(value));
} else {
td.textContent = that._prettyPrintValue(value);
}
} else {
td.innerHTML = value;
}
}
tr.appendChild(td);
});
return tr;
};
CKCatalog.Table.prototype._createEmptyRow = function() {
var tr = document.createElement('tr');
tr.innerHTML = '
' + this._textForEmptyRow + ' | ';
tr.className = 'empty';
return tr;
};
CKCatalog.Table.prototype._createEmptyValueCell = function() {
var td = document.createElement('td');
var span = document.createElement('span');
span.className = 'light';
span.textContent = this._textForUndefinedValue;
td.appendChild(span);
return td;
};
CKCatalog.Table.prototype._createRowWithHtmlValues = function(keyOrValues,html) {
var tr;
if(Array.isArray(keyOrValues)) {
tr = this._createRowWithValues(keyOrValues,html);
} else {
tr = this._createRowWithKey(keyOrValues);
var td = document.createElement('td');
td.innerHTML = html;
tr.appendChild(td);
}
return tr;
};
CKCatalog.Table.prototype._prettyPrintValue = function(value) {
if(value instanceof Date) {
return value.toLocaleString();
} else if(typeof value === 'object') {
return JSON.stringify(value,null,' ');
} else {
return value;
}
};
CKCatalog.Table.prototype._createPrettyObject = function(object) {
var el = document.createElement('div');
el.className = 'object';
if(Array.isArray(object)) {
el.textContent = object.join(', ');
} else {
for (var k in object) {
if (object.hasOwnProperty(k)) {
var key = document.createElement('span');
key.className = 'object-key';
key.textContent = k + ':';
var val;
if(typeof object[k] === 'object' && !(object[k] instanceof Date)) {
val = document.createElement('pre');
} else {
val = document.createElement('span');
}
val.className = 'object-value';
val.textContent = this._prettyPrintValue(object[k]);
var wrapper = document.createElement('div');
wrapper.appendChild(key);
wrapper.appendChild(val);
el.appendChild(wrapper);
}
}
}
return el;
};
CKCatalog.Table.prototype._createRow = function(keyOrValues,value) {
var tr;
if(Array.isArray(keyOrValues)) {
if(keyOrValues.length === 0) {
tr = this._createEmptyRow();
} else {
tr = this._createRowWithValues(keyOrValues, []);
}
} else {
tr = this._createRowWithKey(keyOrValues);
var td;
if(value === null || value === undefined) {
td = this._createEmptyValueCell();
} else {
td = document.createElement('td');
if(typeof value === 'object' && !(value instanceof Date)) {
td.appendChild(this._createPrettyObject(value));
} else {
td.textContent = this._prettyPrintValue(value);
}
}
tr.appendChild(td);
}
return tr;
};
CKCatalog.Table.prototype.appendRow = function(keyOrValues,value) {
var tr = this._createRow(keyOrValues,value);
this.body.appendChild(tr);
return this;
};
CKCatalog.Table.prototype.prependRow = function(keyOrValues,value) {
var tr = this._createRow(keyOrValues,value);
this.body.insertBefore(tr,this.body.firstChild);
return this;
};
/**
* Adds a row to the Table with HTML value(s).
* @param keyOrValues if this is an Array then 'html' will be interpreted as an array of booleans indicating which values
* are to be treated as HTML or if undefined then all values will be treated as html
* @param html
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.appendRowWithHtmlValues = function(keyOrValues,html) {
var tr = this._createRowWithHtmlValues(keyOrValues,html);
this.body.appendChild(tr);
return this;
};
/**
* Prepends a row with HTML value(s) to the Table.
* @param keyOrValues
* @param html
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.prependRowWithHtmlValues = function(keyOrValues,html) {
var tr = this._createRowWithHtmlValues(keyOrValues,html);
this.body.insertBefore(tr,this.body.firstChild);
return this;
};
/**
* Appends a row with a download link to a url.
* @param {string} name
* @param {string} url
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.appendRowWithDownloadLink = function(name,url) {
if(!url) {
return this.appendRow(name);
}
return this.appendRowWithHtmlValues(name,'Download');
};
/**
* Prepends a row with a download link to a url.
* @param {string} name
* @param {string} url
* @returns {CKCatalog.Table}
*/
CKCatalog.Table.prototype.prependRowWithDownloadLink = function(name,url) {
if(!url) {
return this.prependRow(name);
}
return this.prependRowWithHtmlValues(name,'Download');
};