Editable on Steroids
by Herst
HTML
<link rel="stylesheet" href="http://mottie.github.io/tablesorter/dist/css/theme.default.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://rawgit.com/Mottie/tablesorter/master/js/jquery.tablesorter.js"></script>
<script src="https://rawgit.com/Mottie/tablesorter/master/js/widgets/widget-editable.js"></script>
<div class="container-fluid">
<table id="table" class="table table-bordered">
<thead>
<tr>http://jsfiddle.net/Herst/3ckksgbh/#fork
<th>Name (One-Line)</th>
<th>Descr. (Multi-Line)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="cell-name">foo</td>
<td class="cell-descr">bar</td>
</tr>
</tbody>
</table>Results:
<textarea id="results"></textarea>
</div>
CSS
#table div.form-control {
height: 100% !important;
}
JavaScript
function appendToLineArr(arr, texts) {
if (arr.length) arr[arr.length - 1] += texts.splice(0, 1); // take first element and append to last line
$.merge(arr, texts);
}
function getLinesFromHTML($el) {
var $contents = $el.contents(),
lines = [];
if (!$contents.length) return '';
$contents.each(function (i, subEl) {
if (subEl.nodeType === 3) // text node
appendToLineArr(lines, subEl.data.split(/\n/g));
else if (subEl.nodeType === 1) { // element node
// alt idea: use .css('display')
switch (subEl.tagName.toLowerCase()) { // or .nodeName?
// common block elements
case 'blockquote':
case 'div':
case 'p':
$.merge(lines, getLinesFromHTML($(subEl))); // TODO trim?
break;
case 'br':
lines.push('');
break;
default:
// assume inline elements for the rest, assume no block element inside (standard-compliant)
appendToLineArr(lines, $(subEl).text().split(/\n/g));
}
}
});
return lines;
}
function trimArray(arr) {
if (!arr.length) return [];
var firstNonEmpty = -1,
lastNonEmpty = -1;
for (var i = 0; i < arr.length; ++i)
if (arr[i]) {
firstNonEmpty = i
break;
}
if (firstNonEmpty < 0) return [];
for (var j = arr.length - 1; j >= 0; --j)
if (arr[j]) {
lastNonEmpty = j;
break;
}
return arr.slice(firstNonEmpty, lastNonEmpty + 1);
}
function getTextFromHTML($el, withNewLines) {
if (!withNewLines) return $.trim($el.text()); // .trim necessary? JQuery doc unclear
return $.trim($.map($el.contents(), function (el) {
if (el.nodeType === 3 && el.data) // text node
return el.data;
else if (el.nodeType === 1 && el.tagName.toLowerCase() == 'br')...