tablesorter/docs/example-widget-editable.html

581 lines
23 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery plugin: Tablesorter 2.0 - Content Editable</title>
<!-- jQuery -->
<script src="js/jquery-latest.min.js"></script>
<!-- Demo stuff -->
<link class="ui-theme" rel="stylesheet" href="css/jquery-ui.min.css">
<script src="js/jquery-ui.min.js"></script>
<link rel="stylesheet" href="css/jq.css">
<link href="css/prettify.css" rel="stylesheet">
<script src="js/prettify.js"></script>
<script src="js/docs.js"></script>
<!-- Tablesorter: required -->
<link rel="stylesheet" href="../css/theme.blue.css">
<link rel="stylesheet" href="../css/theme.ice.css">
<script src="../js/jquery.tablesorter.js"></script>
<script src="../js/widgets/widget-editable.js"></script>
<style>
table.info2.tablesorter-ice { table-layout: auto; }
.options th.option { width: 150px; }
.info2 th { vertical-align: middle; text-align: center; }
.info2 th.col { width: 42%; }
.color1 { color: purple; }
.color2 { color: blue; }
.color3 { color: green; }
</style>
<style id="css">.tablesorter tbody > tr > td[contenteditable=true]:focus {
outline: #08f 1px solid;
background: #eee;
resize: none;
}
td.no-edit, span.no-edit {
background-color: rgba(230,191,153,0.5);
}
.focused {
color: blue;
}</style>
<script id="js">$(function() {
$("#table")
.tablesorter({
theme : 'blue',
widgets: ['editable'],
widgetOptions: {
editable_columns : [0,1,2], // or "0-2" (v2.14.2); point to the columns to make editable (zero-based index)
editable_enterToAccept : true, // press enter to accept content, or click outside if false
editable_autoAccept : true, // accepts any changes made to the table cell automatically (v2.17.6)
editable_autoResort : false, // auto resort after the content has changed.
editable_validate : null, // return a valid string: function(text, original, columnIndex){ return text; }
editable_focused : function(txt, columnIndex, $element) {
// $element is the div, not the td
// to get the td, use $element.closest('td')
$element.addClass('focused');
},
editable_blur : function(txt, columnIndex, $element) {
// $element is the div, not the td
// to get the td, use $element.closest('td')
$element.removeClass('focused');
},
editable_selectAll : function(txt, columnIndex, $element){
// note $element is the div inside of the table cell, so use $element.closest('td') to get the cell
// only select everthing within the element when the content starts with the letter "B"
return /^b/i.test(txt) && columnIndex === 0;
},
editable_wrapContent : '<div>', // wrap all editable cell content... makes this widget work in IE, and with autocomplete
editable_trimContent : true, // trim content ( removes outer tabs & carriage returns )
editable_noEdit : 'no-edit', // class name of cell that is not editable
editable_editComplete : 'editComplete' // event fired after the table content has been edited
}
})
// config event variable new in v2.17.6
.children('tbody').on('editComplete', 'td', function(event, config){
var $this = $(this),
newContent = $this.text(),
cellIndex = this.cellIndex, // there shouldn't be any colspans in the tbody
rowIndex = $this.closest('tr').attr('id'); // data-row-index stored in row id
/*
$.post("mysite.php", {
"row" : rowIndex,
"cell" : cellIndex,
"content" : newContent
});
*/
});
});</script>
</head>
<body>
<div id="banner">
<h1>table<em>sorter</em></h1>
<h2>Content Editable</h2>
<h3>Flexible client-side table sorting</h3>
<a href="index.html">Back to documentation</a>
</div>
<div id="main">
<p></p>
<br>
<div id="root" class="accordion">
<h3><a href="#">Notes</a></h3>
<div>
<ul>
<li>This widget can not be applied to the original plugin and requires jQuery 1.7+ and a browser that supports <a href="http://caniuse.com/#feat=contenteditable"><code>contenteditable</code> attributes</a> (almost all modern browsers).</li>
<li><span class="label warning">Important</span>: In Internet Explorer, please wrap the cell content with a DIV or SPAN as <a href="http://msdn.microsoft.com/en-us/library/ie/ms533690(v=vs.85).aspx">it is not possible to make table cells directly contenteditable</a>. Wrapping the content in the markup is much more efficient than using javascript to do it for you (especially in IE).<br><br></li>
<li>In <span class="version">v2.22.2</span>, <kbd>Shift</kbd>+<kbd>Enter</kbd> can now be used to start a new line even if <code>editable_enterToAccept</code> is <code>true</code>.</li>
<li>In <span class="version">v2.22.0</span>,
<ul>
<li>The cell content now only <em>automatically updates</em> when the user hovers over the table header. Prior to this version, the automatic update would occur when the mouse left the tbody of the table. The reason this is necessary is because initiating a sort would change the row indexing set prior to the cell content being updated, so the cache would end up not matching the table content.</li>
<li>Modified the <code>editable_trimContent</code> option to only trim content when set.</li>
<li>The widget now works with the contenteditable html (using jQuery's <code>.html()</code>); previously, the widget would only manipulate the text (using jQuery <code>.text()</code>), so any HTML would get stripped out.<br>
<span class="label label-info">*Note*</span> Because of this change, if the user presses <kbd>Enter</kbd>, a <code>&lt;div&gt;</code> will be automatically inserted by the browser (not the widget) and any content entered will be added inside this "new line" div. If this is undesirable, use the <code>editable_blur</code> callback to modify the content.</li>
<li>If the cell content is already wrapped in a div or span, that element will be made contenteditable. Otherwise any direct children of the table cell will be made contenteditable; prior to this update, all direct child elements (including <code>&lt;br&gt;</code>s were made contenteditable by mistake).</li>
</ul>
</li>
<li>Updated <span class="version">v2.17.6</span>,
<ul>
<li>Fixed the <code>editable_enterToAccept</code> option to do what it was meant to do, accept when the user presses enter.</li>
<li>Added <code>editable_autoAccept</code> option, so that when it is <code>true</code> the original behavior of accepting content changes will be maintained.</li>
<li>Added <code>editable_validate</code> option, to allow validating the edited content.</li>
<li>Focus is now maintained within the contenteditable element after updating. This makes it easier to tab through the table while editing. This change also fixes <a href="http://stackoverflow.com/q/24947995/145346">this Stackoverflow issue</a>.</li>
<li>The <code>editComplete</code> event now passes the table <code>config</code> variable to make it easier to access tablesorter variables.</li>
</ul>
</li>
<li>Updated <span class="version updated">v2.13.2</span>, because of the limitation in IE, if a table cell contains any DIV or SPAN immediately inside the cell, it will be targeted instead of the table cell itself and made content editable. So, if you don't care about IE support, there is no need to include the extra markup.</li>
<li>In some browsers, additional CSS is needed to highlight a focused editable table cell. See the CSS block below.</li>
<li>Pressing escape while editing will cancel any changes.</li>
<li>In the demo below, click in any of the first three columns to edit the content, except for the cell containing <span class="no-edit">"Peter"</span>.</li>
<li>To prevent a table cell from becoming editable, add the class name <code>"no-edit"</code> to the cell. Set by the <code>editable_noEdit</code> option.</li>
</ul>
</div>
<h3><a href="#">When Content Changes are Accepted</a></h3>
<div>
<table class="info2 tablesorter-ice">
<thead>
<tr><th style="width:250px" colspan="2" rowspan="2"></th><th colspan="2">editable_enterToAccept</th></tr>
<tr><th class="col">true</th><th class="col">false</th></tr>
</thead>
<tbody>
<tr>
<th stlye="width:200px" rowspan="2">editable_autoAccept</th>
<th style="width:50px">true</th>
<td>
<ul>
<li class="color1">Pressing alt-enter</li>
<li class="color2">Pressing enter</li>
<li class="color3">Clicking outside of the current editable content.</li>
<li class="color3">Moving the mouse outside of the current tbody (this is done because if the content editable is still active when the user clicks on the header to sort the column, all sorts of bad things happen).</li>
</ul>
</td>
<td>
<ul>
<li class="color1">Pressing alt-enter</li>
<li class="color3">Clicking outside of the current editable content.</li>
<li class="color3">Moving the mouse outside of the current tbody.</li>
</ul>
</td>
</tr>
<tr>
<th>false</th>
<td>
<ul>
<li class="color1">Pressing alt-enter</li>
<li class="color2">Pressing enter</li>
</ul>
</td>
<td>
<ul>
<li class="color1">Pressing alt-enter</li>
</ul>
</td>
</tr>
</tbody>
</table>
* <span class="label label-info">Note</span> The content is only accepted when the <code>editable_validation</code> function <em>does not</em> return <code>false</code>.
</div>
<h3><a href="#">Options</a></h3>
<div>
<h4>Editable widget default options (added inside of tablesorter <code>widgetOptions</code>)</h4>
<div>
<span class="label label-info">TIP!</span> Click on the link in the function column to reveal full details (or <a href="#" class="toggleAll">toggle</a>|<a href="#" class="showAll">show</a>|<a href="#" class="hideAll">hide</a> all) or double click to update the browser location.
</div>
<table class="options tablesorter-blue" data-sortlist="[[0,0]]">
<thead>
<tr><th class="option">Option</th><th class="sorter-false">Description</th></tr>
</thead>
<tbody>
<tr id="editable-auto-accept">
<td><a href="#" class="permalink">editable_autoAccept</a></td>
<td>Accepts any changes made to the table cell automatically <span class="version">v2.17.6</span>
<div class="collapsible">
<br>
If the user clicks outside or tabs out of the edited cell, or moves the mouse out of the current tbody, any changes to the cell will be accepted<br>
<br>
The only time the content is not accepted is if the user presses the escape key.<br>
<br>
if <code>false</code>, the acceptance behavior follows the <code>editable_enterToAccept</code> setting.<br>
<br>
Default value: <code>true</code>
</div>
</td>
</tr>
<tr id="editable-columns">
<td><a href="#" class="permalink">editable_columns</a></td>
<td>Contains an array (or range string) of columns numbers you want to have editable content (zero-based index).
<div class="collapsible">
<ul>
<li>In tablesorter core <span class="version">v2.14.2</span>, this widget was updated to allow passing a range string in this option, i.e. <code>"0-2"</code> instead of <code>[0,1,2]</code>.</li>
<li><code>contenteditable="true"</code> is added to cells within these columns.</li>
</ul>
Default value: <code>[]</code> (empty array)
</div>
</td>
</tr>
<tr id="editable-enter-to-accept">
<td><a href="#" class="permalink">editable_enterToAccept</a></td>
<td>Makes the user press enter to accept the content within the editable table cell
<div class="collapsible">
<br>
if <code>false</code>, clicking outside the cell will accept the content.<br>
<br>
Default value: <code>true</code>
</div>
</td>
</tr>
<tr id="editable-auto-resort">
<td><a href="#" class="permalink">editable_autoResort</a></td>
<td>If <code>true</code>, the column will resort (only if already sorted) after the content has been changed.
<div class="collapsible">
<br>
Default value: <code>false</code>
</div>
</td>
</tr>
<tr id="editable-no-edit">
<td><a href="#" class="permalink">editable_noEdit</a></td>
<td>Class name on table cells to search for that are not to become editable.
<div class="collapsible">
<br>
The search is only done within the columns set by the <code>editable_columns</code> option.<br>
<br>
Default value: <code>'no-edit'</code>
</div>
</td>
</tr>
<tr id="editable-edit-complete">
<td><a href="#" class="permalink">editable_editComplete</a></td>
<td>Event fired after the table content has been edited
<div class="collapsible">
<br>
<pre class="prettyprint lang-js">$(function(){
$('#table')
.tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_editComplete : 'giterdone'
}
})
// use delegated event binding
.on('giterdone', 'td', function(event, config){
// this = td; the event bubble up
console.log( 'new content = ' + $(this).text() );
});
});</pre>
Default value: <code>'editComplete'</code>
</div>
</td>
</tr>
<tr id="editable-focused">
<td><a href="#" class="permalink">editable_focused</a></td>
<td>Callback function that is executeed when the contenteditable cell is focused (<span class="version">v2.17.8</span>)
<div class="collapsible">
<br>
Set this function to manipulate or adjust the content when the content editable is focused
<pre class="prettyprint lang-js">$(function(){
$('#table').tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_focused : function(txt, columnIndex, $element){
// note $element is the div inside of the table cell, so use $element.closest('td') to get the cell
$element.closest('td').addClass('focused');
},
editable_blur : function(txt, columnIndex, $element){
$element.closest('td').removeClass('focused');
}
}
});
});</pre>
Default value: <code>null</code>
</div>
</td>
</tr>
<tr id="editable-blur">
<td><a href="#" class="permalink">editable_blur</a></td>
<td>Callback function that is executeed when the contenteditable cell is no longer focused (<span class="version">v2.17.8</span>)
<div class="collapsible">
<br>
Set this function to manipulate or adjust the content when the content editable is blurred
<pre class="prettyprint lang-js">$(function(){
$('#table').tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_focused : function(txt, columnIndex, $element){
// note $element is the div inside of the table cell, so use $element.closest('td') to get the cell
$element.closest('td').addClass('focused');
},
editable_blur : function(txt, columnIndex, $element){
$element.closest('td').removeClass('focused');
}
}
});
});</pre>
Default value: <code>null</code>
</div>
</td>
</tr>
<tr id="editable-selectall">
<td><a href="#" class="permalink">editable_selectAll</a></td>
<td>Set to automatically select all content when the contenteditable cell is focused (<span class="version">v2.17.8</span>)
<div class="collapsible">
<br>
Set this option to a boolean, or a function that returns a boolean:
<ul>
<li>When <code>true</code>, all of the text within the current contenteditable element will be selected.</li>
<li>When <code>false</code>, no selection is made.</li>
<li>When this option contains a function, return either <code>true</code> to select all of the text within the element, or <code>false</code> to not select any text.</li>
</ul>
<pre class="prettyprint lang-js">$(function(){
$('#table').tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_selectAll : function(txt, columnIndex, $element){
// note $element is the div inside of the table cell, so use $element.closest('td') to get the cell
// only select everthing within the element when the content starts with the letter "B"
return /^b/i.test(txt) && columnIndex === 0;
}
}
});
});</pre>
Default value: <code>null</code>
</div>
</td>
</tr>
<tr id="editable-validate">
<td><a href="#" class="permalink">editable_validate</a></td>
<td>Validate the content change (<span class="version updated">v2.17.8</span>)
<div class="collapsible">
<br>
Use this function to validate and/or modify the content before it is accepted.<br>
<br>
In <span class="version updated">v2.17.8</span>:
<ul>
<li>Set this option to be a global function, or an object containing a column index, or class name of the desired column</li>
<li>A <code>columnIndex</code> is now included in the function parameters</li>
<li>A <code>$element</code> parameter has been included which contains the contenteditable element. To get the table cell, use <code>$element.closest('td');</code></li>
</ul>
This function must return either a string containing the modified content or <code>false</code> to revert the content back to it's original value. Example:
<pre class="prettyprint lang-js">$(function(){
$('#table1').tablesorter({
widgets : ['editable'],
widgetOptions : {
// global validate function
editable_validate : function(txt, orig, columnIndex, $element){
// only allow one word
var t = /\s/.test(txt) ? txt.split(/\s/)[0] : txt;
return t || false;
}
}
});
$('#table2').tablesorter({
widgets : ['editable'],
widgetOptions : {
// validate function per column
editable_validate : {
0 : function(txt, orig, columnIndex, $element){
// allow up to two words
var t = txt.split(' ');
return t.length > 2 ? t[0] + (t[1] ? ' ' + t[1] : '') : txt;
},
'.price' : function(txt, orig, columnIndex, $element) {
// make sure the price column(s) are using a number
return isNaN( txt.replace(/[$,\s]/g, '') ) ? false : txt;
}
}
}
});
});</pre>
Default value: <code>null</code>
</div>
</td>
</tr>
<tr id="editable-trimcontent">
<td><a href="#" class="permalink">editable_trimContent</a></td>
<td>Trim the content within the editable cell (<span class="version">v2.17.8</span>)
<div class="collapsible">
<br>
When a table cell is formatted as follows:
<pre class="prettyprint lang-html">&lt;td&gt;
John
&lt;/td&gt;</pre>Carriage returns and tab(s) at the beginning &amp; end of the contenteditable table cells will be removed initially and after editing.<br>
<br>
If this option is <code>true</code>, this widget will trim content <em>upon initialization</em>; this is necessary if you need cleaned it up content before editing, like with an autocomplete script.<br>
<br>
Use this option as follows:
<pre class="prettyprint lang-js">$(function(){
$('#table').tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_trimContent : true
}
});
});</pre>
Default value: <code>true</code>
</div>
</td>
</tr>
<tr id="editable-wrapcontent">
<td><a href="#" class="permalink">editable_wrapContent</a></td>
<td>Wrap the editable cell content with this element (<span class="version">v2.17.8</span>)
<div class="collapsible">
<br>
Internally, the widget uses jQuery's <code>wrapInner</code> to wrap the cell contents, using the following rules:
<ul>
<li>If this option is set to <code>false</code> or an empty string (<code>''</code>), then no wrapping will occur. The "contenteditable" attribute will be applied to the table cell.</li>
<li>If the table cell has no children, then the content is wrapped using this option, and the wrapping element will have the "contentediable" attribute enabled.</li>
<li>If the cell already has children (one or more) immediately inside of the table cell, no wrapping occurs and the child element(s) that don't have the class name set in <code>editable_noEdit</code>, will have the "contenteditable" attribute enabled.</li>
</ul>
Note: that this option uses jQuery's <code>wrapInner</code>, so this option can be set to a html string or selector, jQuery object, DOM element, or a function (jQuery 1.4+)
<pre class="prettyprint lang-js">$(function(){
$('#table').tablesorter({
widgets : ['editable'],
widgetOptions : {
editable_wrap : '&lt;div&gt;'
}
});
});</pre>
Default value: <code>'&lt;div&gt;'</code>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p></p>
<h1>Demo</h1>
<button class="auto">Toggle</button> <code>editable_autoAccept&nbsp;&nbsp;&nbsp;&nbsp;: <span>true</span></code><br>
<button class="enter">Toggle</button> <code>editable_enterToAccept : <span>true</span></code>
<br>
<div id="demo"><table id="table" class="tablesorter">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
<th>Total</th>
<th>Discount</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr id="db-row-344">
<td class="no-edit">Peter</td>
<td>Parker</td>
<td>28</td>
<td>$9.99</td>
<td>20%</td>
<td>Jul 6, 2006 8:14 AM</td>
</tr>
<tr id="db-row-884">
<td>John</td>
<td>Hood</td>
<td>33</td>
<td>$19.99</td>
<td>25%</td>
<td>Dec 10, 2002 5:14 AM</td>
</tr>
<tr id="db-row-234">
<td>Clark</td>
<td>Kent</td>
<td>18</td>
<td>$15.89</td>
<td>44%</td>
<td>Jan 12, 2003 11:14 AM</td>
</tr>
<tr id="db-row-756">
<td>Bruce</td>
<td>Almighty</td>
<td>45</td>
<td>$153.19</td>
<td>44%</td>
<td>Jan 18, 2001 9:12 AM</td>
</tr>
<tr id="db-row-232">
<td>Bruce</td>
<td>Evans</td>
<td>22</td>
<td>$13.19</td>
<td>11%</td>
<td>Jan 18, 2007 9:12 AM</td>
</tr>
</tbody>
</table></div>
<h1>Javascript</h1>
<div id="javascript">
<pre class="prettyprint lang-javascript"></pre>
</div>
<h1>CSS</h1>
<div id="css">
<pre class="prettyprint lang-css"></pre>
</div>
<h1>HTML</h1>
<div id="html">
<pre class="prettyprint lang-html"></pre>
</div>
</div>
<script>
$(function() {
var wo = $('#table')[0].config.widgetOptions;
$('.enter').click(function(){
var t = wo.editable_enterToAccept = !wo.editable_enterToAccept;
$(this).next().find('span').html('' + t);
});
$('.auto').click(function(){
var t = wo.editable_autoAccept = !wo.editable_autoAccept;
$(this).next().find('span').html('' + t);
});
});
</script>
</body>
</html>