Editable: Fix selectAll & change tbody mouseleave to thead mouseenter. Fixes #848

This commit is contained in:
Mottie 2015-04-26 09:35:06 -05:00
parent 7e5dcf9a7d
commit 45cb86ed57
3 changed files with 32 additions and 12 deletions

View File

@ -1,2 +1,2 @@
/*! Widget: editable - updated 2/9/2015 (v2.19.1) */ /*! Widget: editable - updated 2/9/2015 (v2.19.1) */
!function(a){"use strict";var b=a.tablesorter.editable={editComplete:function(a,b,c,d){c.removeClass("tseditable-last-edited-cell").trigger(b.editable_editComplete,[a]),d&&setTimeout(function(){c.focus()},50)},selectAll:function(a){setTimeout(function(){var b,c=document.createRange();c.selectNodeContents(a),b=window.getSelection(),b.removeAllRanges(),b.addRange(c)},100)},update:function(b,c){var d,e,f,g=[],h=[];if(!c.editable_columnsArray&&"string"===a.type(c.editable_columns)&&c.editable_columns.indexOf("-")>=0)for(e=c.editable_columns.split(/\s*-\s*/),d=parseInt(e[0],10)||0,e=parseInt(e[1],10)||b.columns-1,e>b.columns&&(e=b.columns-1);e>=d;d++)g.push(d),h.push("td:nth-child("+(d+1)+")");else a.isArray(c.editable_columns)&&a.each(c.editable_columnsArray||c.editable_columns,function(a,c){c<b.columns&&(g.push(c),h.push("td:nth-child("+(c+1)+")"))});c.editable_columnsArray||(c.editable_columnsArray=g,c.editable_columnsArray.sort(function(a,b){return a-b})),e=a("<div>").wrapInner(c.editable_wrapContent).children().length||a.isFunction(c.editable_wrapContent),b.$tbodies.find(h.join(",")).not("."+c.editable_noEdit).each(function(){f=a(this),e&&0===f.children().length&&f.wrapInner(c.editable_wrapContent),f.children().length?f.children().not("."+c.editable_noEdit).each(function(){var b=a(this);c.editable_trimContent&&b.html(function(b,c){return a.trim(c)}),b.prop("contenteditable",!0)}):(c.editable_trimContent&&f.html(function(b,c){return a.trim(c)}),f.prop("contenteditable",!0))})},bindEvents:function(c,d){c.$table.off("updateComplete pagerComplete ".split(" ").join(".tseditable ").replace(/\s+/g," ")).on("updateComplete pagerComplete ".split(" ").join(".tseditable "),function(){b.update(c,c.widgetOptions)}),c.$tbodies.off("mouseleave focus blur focusout keydown ".split(" ").join(".tseditable ").replace(/\s+/g," ")).on("mouseleave.tseditable",function(){c.$table.data("contentFocused")&&(c.$table.data("contentFocused",!0),a(":focus").trigger("focusout"))}).on("focus.tseditable","[contenteditable]",function(e){clearTimeout(a(this).data("timer")),c.$table.data("contentFocused",e.target);var f=a(this),g=d.editable_selectAll,h=f.closest("td").index(),i=f.html();d.editable_trimContent&&(i=a.trim(i)),f.off("keydown.tseditable").on("keydown.tseditable",function(a){d.editable_enterToAccept&&13===a.which&&a.preventDefault()}),f.data({before:i,original:i}),"function"==typeof d.editable_focused&&d.editable_focused(i,h,f),g&&("function"==typeof g?g(i,h,f)&&b.selectAll(f[0]):b.selectAll(f[0]))}).on("blur focusout keydown ".split(" ").join(".tseditable "),"[contenteditable]",function(e){if(c.$table.data("contentFocused")){var f,g,h=!1,i=a(e.target),j=i.html(),k=i.closest("td").index();if(d.editable_trimContent&&(j=a.trim(j)),27===e.which)return i.html(i.data("original")).trigger("blur.tseditable"),c.$table.data("contentFocused",!1),!1;if(f=13===e.which&&(d.editable_enterToAccept||e.altKey)||d.editable_autoAccept&&"keydown"!==e.type,f&&i.data("before")!==j){if(g=d.editable_validate,h=j,"function"==typeof g?h=g(j,i.data("original"),k,i):"function"==typeof(g=a.tablesorter.getColumnData(c.table,g,k))&&(h=g(j,i.data("original"),k,i)),f&&h!==!1)return c.$table.find(".tseditable-last-edited-cell").removeClass("tseditable-last-edited-cell"),i.addClass("tseditable-last-edited-cell").html(h).data("before",h).data("original",h).trigger("change"),c.$table.trigger("updateCell",[i.closest("td"),!1,function(){d.editable_autoResort?setTimeout(function(){c.$table.trigger("sorton",[c.sortList,function(){b.editComplete(c,d,c.$table.find(".tseditable-last-edited-cell"),!0)},!0])},10):b.editComplete(c,d,c.$table.find(".tseditable-last-edited-cell"))}]),!1}else h||"keydown"===e.type||(clearTimeout(i.data("timer")),i.data("timer",setTimeout(function(){a.isFunction(d.editable_blur)&&(j=i.html(),d.editable_blur(d.editable_trimContent?a.trim(j):j,k,i))},100)),i.html(i.data("original")))}})}};a.tablesorter.addWidget({id:"editable",options:{editable_columns:[],editable_enterToAccept:!0,editable_autoAccept:!0,editable_autoResort:!1,editable_wrapContent:"<div>",editable_trimContent:!0,editable_validate:null,editable_focused:null,editable_blur:null,editable_selectAll:!1,editable_noEdit:"no-edit",editable_editComplete:"editComplete"},init:function(a,c,d,e){e.editable_columns.length&&(b.update(d,e),b.bindEvents(d,e))}})}(jQuery); !function(a){"use strict";var b=a.tablesorter.editable={editComplete:function(a,b,c,d){c.removeClass("tseditable-last-edited-cell").trigger(b.editable_editComplete,[a]),d&&setTimeout(function(){c.focus()},50)},selectAll:function(a){setTimeout(function(){var b,c;document.body.createTextRange?(b=document.body.createTextRange(),b.moveToElementText(a),b.select()):window.getSelection&&(c=window.getSelection(),b=document.createRange(),b.selectNodeContents(a),c.removeAllRanges(),c.addRange(b))},100)},update:function(b,c){var d,e,f,g=[],h=[];if(!c.editable_columnsArray&&"string"===a.type(c.editable_columns)&&c.editable_columns.indexOf("-")>=0)for(e=c.editable_columns.split(/\s*-\s*/),d=parseInt(e[0],10)||0,e=parseInt(e[1],10)||b.columns-1,e>b.columns&&(e=b.columns-1);e>=d;d++)g.push(d),h.push("td:nth-child("+(d+1)+")");else a.isArray(c.editable_columns)&&a.each(c.editable_columnsArray||c.editable_columns,function(a,c){c<b.columns&&(g.push(c),h.push("td:nth-child("+(c+1)+")"))});c.editable_columnsArray||(c.editable_columnsArray=g,c.editable_columnsArray.sort(function(a,b){return a-b})),e=a("<div>").wrapInner(c.editable_wrapContent).children().length||a.isFunction(c.editable_wrapContent),b.$tbodies.find(h.join(",")).not("."+c.editable_noEdit).each(function(){f=a(this),e&&0===f.children().length&&f.wrapInner(c.editable_wrapContent),f.children().length?f.children().not("."+c.editable_noEdit).each(function(){var b=a(this);c.editable_trimContent&&b.html(function(b,c){return a.trim(c)}),b.prop("contenteditable",!0)}):(c.editable_trimContent&&f.html(function(b,c){return a.trim(c)}),f.prop("contenteditable",!0))})},bindEvents:function(c,d){c.$table.off("updateComplete pagerComplete ".split(" ").join(".tseditable ").replace(/\s+/g," ")).on("updateComplete pagerComplete ".split(" ").join(".tseditable "),function(){b.update(c,c.widgetOptions)}).children("thead").add(a(c.namespace+"_extra_table").children("thead")).off("mouseenter.tseditable").on("mouseenter.tseditable",function(){c.$table.data("contentFocused")&&(c.$table.data("contentFocused",!0),a(":focus").trigger("focusout"))}),c.$tbodies.off("focus blur focusout keydown ".split(" ").join(".tseditable ").replace(/\s+/g," ")).on("focus.tseditable","[contenteditable]",function(e){clearTimeout(a(this).data("timer")),c.$table.data("contentFocused",e.target);var f=a(this),g=d.editable_selectAll,h=f.closest("td").index(),i=f.html();d.editable_trimContent&&(i=a.trim(i)),f.off("keydown.tseditable").on("keydown.tseditable",function(a){d.editable_enterToAccept&&13===a.which&&a.preventDefault()}),f.data({before:i,original:i}),"function"==typeof d.editable_focused&&d.editable_focused(i,h,f),g&&("function"==typeof g?g(i,h,f)&&b.selectAll(f[0]):b.selectAll(f[0]))}).on("blur focusout keydown ".split(" ").join(".tseditable "),"[contenteditable]",function(e){if(c.$table.data("contentFocused")){var f,g,h=!1,i=a(e.target),j=i.html(),k=i.closest("td").index();if(d.editable_trimContent&&(j=a.trim(j)),27===e.which)return i.html(i.data("original")).trigger("blur.tseditable"),c.$table.data("contentFocused",!1),!1;if(f=13===e.which&&(d.editable_enterToAccept||e.altKey)||d.editable_autoAccept&&"keydown"!==e.type,f&&i.data("before")!==j){if(g=d.editable_validate,h=j,"function"==typeof g?h=g(j,i.data("original"),k,i):"function"==typeof(g=a.tablesorter.getColumnData(c.table,g,k))&&(h=g(j,i.data("original"),k,i)),f&&h!==!1)return c.$table.find(".tseditable-last-edited-cell").removeClass("tseditable-last-edited-cell"),i.addClass("tseditable-last-edited-cell").html(h).data("before",h).data("original",h).trigger("change"),c.$table.trigger("updateCell",[i.closest("td"),!1,function(){d.editable_autoResort?setTimeout(function(){c.$table.trigger("sorton",[c.sortList,function(){b.editComplete(c,d,c.$table.find(".tseditable-last-edited-cell"),!0)},!0])},10):b.editComplete(c,d,c.$table.find(".tseditable-last-edited-cell"))}]),!1}else h||"keydown"===e.type||(clearTimeout(i.data("timer")),i.data("timer",setTimeout(function(){a.isFunction(d.editable_blur)&&(j=i.html(),d.editable_blur(d.editable_trimContent?a.trim(j):j,k,i))},100)),i.html(i.data("original")))}})}};a.tablesorter.addWidget({id:"editable",options:{editable_columns:[],editable_enterToAccept:!0,editable_autoAccept:!0,editable_autoResort:!1,editable_wrapContent:"<div>",editable_trimContent:!0,editable_validate:null,editable_focused:null,editable_blur:null,editable_selectAll:!1,editable_noEdit:"no-edit",editable_editComplete:"editComplete"},init:function(a,c,d,e){e.editable_columns.length&&(b.update(d,e),b.bindEvents(d,e))}})}(jQuery);

View File

@ -113,6 +113,14 @@ td.no-edit, span.no-edit {
<ul> <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>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><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.21.6</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>
</ul>
<li>Updated <span class="version">v2.17.6</span>, <li>Updated <span class="version">v2.17.6</span>,
<ul> <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>Fixed the <code>editable_enterToAccept</code> option to do what it was meant to do, accept when the user presses enter.</li>

View File

@ -25,11 +25,18 @@ var tse = $.tablesorter.editable = {
setTimeout( function() { setTimeout( function() {
// select all text in contenteditable // select all text in contenteditable
// see http://stackoverflow.com/a/6150060/145346 // see http://stackoverflow.com/a/6150060/145346
var sel, range = document.createRange(); var range, selection;
range.selectNodeContents( cell ); if ( document.body.createTextRange ) {
sel = window.getSelection(); range = document.body.createTextRange();
sel.removeAllRanges(); range.moveToElementText( cell );
sel.addRange( range ); range.select();
} else if ( window.getSelection ) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents( cell );
selection.removeAllRanges();
selection.addRange( range );
}
}, 100 ); }, 100 );
}, },
@ -98,17 +105,22 @@ var tse = $.tablesorter.editable = {
.off( ( 'updateComplete pagerComplete '.split( ' ' ).join( '.tseditable ' ) ).replace( /\s+/g, ' ' ) ) .off( ( 'updateComplete pagerComplete '.split( ' ' ).join( '.tseditable ' ) ).replace( /\s+/g, ' ' ) )
.on( 'updateComplete pagerComplete '.split( ' ' ).join( '.tseditable ' ), function() { .on( 'updateComplete pagerComplete '.split( ' ' ).join( '.tseditable ' ), function() {
tse.update( c, c.widgetOptions ); tse.update( c, c.widgetOptions );
}); })
// prevent sort initialized by user click on the header from changing the row indexing before
c.$tbodies // updateCell can finish processing the change
.off( ( 'mouseleave focus blur focusout keydown '.split( ' ' ).join( '.tseditable ' ) ).replace( /\s+/g, ' ' ) ) .children( 'thead' )
.on( 'mouseleave.tseditable', function() { .add( $( c.namespace + '_extra_table' ).children( 'thead' ) )
.off( 'mouseenter.tseditable' )
.on( 'mouseenter.tseditable', function() {
if ( c.$table.data( 'contentFocused' ) ) { if ( c.$table.data( 'contentFocused' ) ) {
// change to 'true' instead of element to allow focusout to process // change to 'true' instead of element to allow focusout to process
c.$table.data( 'contentFocused', true ); c.$table.data( 'contentFocused', true );
$( ':focus' ).trigger( 'focusout' ); $( ':focus' ).trigger( 'focusout' );
} }
}) });
c.$tbodies
.off( ( 'focus blur focusout keydown '.split( ' ' ).join( '.tseditable ' ) ).replace( /\s+/g, ' ' ) )
.on( 'focus.tseditable', '[contenteditable]', function( e ) { .on( 'focus.tseditable', '[contenteditable]', function( e ) {
clearTimeout( $( this ).data( 'timer' ) ); clearTimeout( $( this ).data( 'timer' ) );
c.$table.data( 'contentFocused', e.target ); c.$table.data( 'contentFocused', e.target );