Mark: Add mark_tsIgnore option. See #1243

This commit is contained in:
Rob Garrison 2016-08-30 16:52:07 -05:00
parent d9a4597aee
commit a1f4ca14df
No known key found for this signature in database
GPG Key ID: A6B138ABD8A3FF4A
3 changed files with 108 additions and 38 deletions

View File

@ -1,2 +1,2 @@
/*! Widget: mark.js - updated 8/1/2016 (v2.27.2) */
!function(a){"use strict";var b=a.tablesorter;b.mark={init:function(c){if("function"==typeof a.fn.mark){var d,e=c.widgetOptions.mark_tsUpdate;c.$table.on("filterEnd.tsmark"+(e?" "+e:""),function(a,d){b.mark.update(c,"filterEnd"===a.type?"":d)}),d="(?:<|=|>|\\||\"|\\'|\\s+(?:&&|-|"+(b.language.and||"and")+"|"+(b.language.or||"or")+"|"+(b.language.to||"to")+")\\s+)",b.mark.regex.filter=new RegExp(d,"gim")}else console.warn('Widget-mark not initialized: missing "jquery.mark.js"')},regex:{mark:/^mark_(.+)$/,pure:/^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/},checkRegex:function(a){if(a instanceof RegExp){var b="".match(a);return null===b||b.length<5}return!1},cleanMatches:function(a){for(var b=[],c=a&&a.length||0;c--;)""!==a[c]&&(b[b.length]=a[c]);return b},update:function(c,d){var e={},f=c.widgetOptions,g="undefined"==typeof f.filter_ignoreCase||f.filter_ignoreCase,h=b.mark.regex,i=c.$table.find("tbody tr").unmark().not("."+(c.widgetOptions.filter_filteredRow||"filtered"));d=d||a.tablesorter.getFilters(c.$table),a.each(c.widgetOptions,function(a,b){var c=a.match(h.mark);c&&"undefined"!=typeof c[1]&&(e[c[1]]=b)}),a.each(d,function(a,d){if(d){var f=null,j=d,k=!1,l=a===c.columns?"":":nth-child("+(a+1)+")";if(h.pure.test(d)){j=h.pure.exec(d),".*"===j[1]&&(j[1]="");try{f=new RegExp(j[1],"gim"),j=new RegExp(j[1],j[2])}catch(a){j=null}return void(b.mark.checkRegex(f)&&i.children(l).markRegExp(j,e))}0===d.indexOf("~")?(k=!0,j=d.replace(/~/g,"").split("")):(d.indexOf("?")>-1&&(k=!0,d=d.replace(/\?/g,"\\S{1}")),d.indexOf("*")>-1&&(k=!0,d=d.replace(/\*/g,"\\S*")),j=d.split(h.filter)),k&&j&&j.length?(j=new RegExp(b.mark.cleanMatches(j).join(".*"),"gm"+(g?"i":"")),b.mark.checkRegex(j)&&i.children(l).markRegExp(j,e)):i.children(l).mark(b.mark.cleanMatches(j),e)}})}},b.addWidget({id:"mark",options:{mark_tsUpdate:"markUpdate"},init:function(a,c,d,e){b.mark.init(d,e)},remove:function(a,b){var c=b.widgetOptions.mark_tsUpdate;b.$table.off("filterEnd.tsmark"+(c?" "+c:""))}})}(jQuery);
!function(a){"use strict";var b=a.tablesorter;b.mark={init:function(c){if("function"==typeof a.fn.mark){var d,e=c.widgetOptions.mark_tsUpdate;c.$table.on("filterEnd.tsmark pagerComplete.tsmark"+(e?" "+e:""),function(a,d){b.mark.update(c,a.type===e?d:"")}),d="(?:<|=|>|\\||\"|\\'|\\s+(?:&&|-|"+(b.language.and||"and")+"|"+(b.language.or||"or")+"|"+(b.language.to||"to")+")\\s+)",b.mark.regex.filter=new RegExp(d,"gim")}else console.warn('Widget-mark not initialized: missing "jquery.mark.js"')},regex:{mark:/^mark_(.+)$/,pure:/^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/},checkRegex:function(a){if(a instanceof RegExp){var b="".match(a);return null===b||b.length<5}return!1},cleanMatches:function(a){for(var b=[],c=a&&a.length||0;c--;)""!==a[c]&&(b[b.length]=a[c]);return b},ignoreColumns:function(b){for(var c=b.widgetOptions,d=b.columns,e=[];d--;)(c.mark_tsIgnore[d]||a(b.$headerIndexed[d]).hasClass("mark-ignore"))&&(e[e.length]=":nth-child("+(d+1)+")");return e.length?":not("+e.join(",")+")":""},update:function(c,d){var e={},f=c.widgetOptions,g="undefined"==typeof f.filter_ignoreCase||f.filter_ignoreCase,h=b.mark.regex,i=c.$table.find("tbody tr").unmark().not("."+(c.widgetOptions.filter_filteredRow||"filtered"));d=d||a.tablesorter.getFilters(c.$table),a.each(c.widgetOptions,function(a,b){var c=a.match(h.mark);c&&"undefined"!=typeof c[1]&&(e[c[1]]=b)}),a.each(d,function(d,j){if(j&&!a(c.$headerIndexed[d]).hasClass("mark-ignore")&&!f.mark_tsIgnore[d]){var k=null,l=j,m=!1,n=d===c.columns?b.mark.ignoreColumns(c):":nth-child("+(d+1)+")";if(h.pure.test(j)){l=h.pure.exec(j),".*"===l[1]&&(l[1]="");try{k=new RegExp(l[1],"gim"),l=new RegExp(l[1],l[2])}catch(a){l=null}return void(b.mark.checkRegex(k)&&i.children(n).markRegExp(l,e))}0===j.indexOf("~")?(m=!0,l=j.replace(/~/g,"").split("")):(j.indexOf("?")>-1&&(m=!0,j=j.replace(/\?/g,"\\S{1}")),j.indexOf("*")>-1&&(m=!0,j=j.replace(/\*/g,"\\S*")),l=j.split(h.filter)),m&&l&&l.length?(l=new RegExp(b.mark.cleanMatches(l).join(".*"),"gm"+(g?"i":"")),b.mark.checkRegex(l)&&i.children(n).markRegExp(l,e)):i.children(n).mark(b.mark.cleanMatches(l),e)}})}},b.addWidget({id:"mark",options:{mark_tsUpdate:"markUpdate",mark_tsIgnore:{}},init:function(a,c,d,e){b.mark.init(d,e)},remove:function(a,b){var c=b.widgetOptions.mark_tsUpdate;b.$table.off("filterEnd.tsmark pagerComplete.tsmark"+(c?" "+c:""))}})}(jQuery);

View File

@ -21,14 +21,18 @@
tr td:nth-child(1) mark { background: #aa0000; color: #fff; }
tr td:nth-child(2) mark { background: #00aa00; color: #fff; }
tr td:nth-child(3) mark { background: #0000aa; color: #fff; }
tr td:nth-child(4) mark { background: #aaaa00; color: #fff; }
/* tr td:nth-child(4) mark { background: #aaaa00; color: #fff; } Age column not highlighted */
tr td:nth-child(5) mark { background: #00aaaa; color: #fff; }
tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
/* column will not be highlighted */
th.tablesorter-header.mark-ignore,
th.tablesorter-header.ignore { background-color: #e6bf99; }
</style>
<script src="../js/jquery.tablesorter.js"></script>
<script src="../js/widgets/widget-filter.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/7.0.2/jquery.mark.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.0.0/jquery.mark.js"></script>
<script src="../js/widgets/widget-mark.js"></script>
<script id="js">$(function() {
@ -46,22 +50,33 @@ tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
filter_external: 'input[name="keyword"]',
filter_reset: 'button.reset',
// default settings
// *** mark widget only settings
mark_tsUpdate : 'markUpdate',
mark_tsIgnore : {
// don't highlight the age column
3: true
},
// *** default settings for non-regular expression searches only
mark_accuracy: 'partially',
mark_diacritics: true,
mark_separateWordSearch: true,
mark_synonyms: {},
// *** settings that apply to regex & non-regular expression searches
mark_acrossElements: false,
mark_className: '',
mark_debug: false,
mark_diacritics: true,
mark_element: 'mark',
mark_exclude: [],
mark_iframes: false,
mark_log: console,
mark_separateWordSearch: true,
mark_synonyms: {},
// callback functions
mark_done: function(totalMatches) {},
mark_each: function(element) {},
mark_filter: function(node, term, counter, totalCounter) { return true; },
mark_noMatch: function(keyword) {}
mark_filter: function(node, term, totalMatches, matches) {
// "matches" parameter is not defined for regular expression searches
return true;
},
mark_noMatch: function(termNotFound) {}
}
});
@ -86,22 +101,11 @@ tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
sortLocaleCompare: true,
widgets: ['zebra', 'mark'],
widgetOptions : {
// default settings
mark_accuracy: 'partially',
mark_className: '',
mark_debug: false,
mark_diacritics: true,
mark_element: 'mark',
mark_exclude: [],
mark_iframes: false,
mark_log: console,
mark_separateWordSearch: true,
mark_synonyms: {},
// callback functions
mark_done: function(totalMatches) {},
mark_each: function(element) {},
mark_filter: function(node, term, counter, totalCounter) { return true; },
mark_noMatch: function(keyword) {}
// using mark.js default settings
mark_tsIgnore : {
// don't highlight the age column
// 3: true // done by adding "mark-ignore" class to header
}
}
});
@ -144,6 +148,12 @@ tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
<h3 id="notes"><a href="#">Notes</a></h3>
<div>
<ul>
<li>Updated <span class="verison">v2.27.6</span>
<ul>
<li>The mark widget properly applies after a pager change has occured.</li>
<li>Added <code>mark_tsIgnore</code> option as well as support of adding a "mark-ignore" class to the header. These columns will not be highlighted.</li>
<li>Included mark.js v8.0.0's new option as <code>mark_acrossElements</code>. This widget does not however apply the search across table cells.</li>
</ul>
<li>Added <span class="verison">v2.27.0</span> for use with the <a href="https://markjs.io/">mark.js</a> plugin.</li>
<li>Notable Issues:
<ul>
@ -159,7 +169,7 @@ tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
<li>The <a href="https://markjs.io/#mark"><code>mark</code> function</a> is used for the following filter queries:
<ul>
<li>Plain text</li>
<li>Logical AND (<code>&nbsp;and&nbsp;</code> or <code>&nbsp;&&&nbsp;</code>) &amp; logical OR (<code>&nbsp;or&nbsp;</code> or <code>|</code>) searches.</li>
<li>Logical AND (<code>&nbsp;and&nbsp;</code> or <code>&nbsp;&amp;&amp;&nbsp;</code>) &amp; logical OR (<code>&nbsp;or&nbsp;</code> or <code>|</code>) searches.</li>
<li>Invalid regex (e.g. <code>/(|)/</code>).</li>
<li>Operator, range, exact and not searches.</li>
</ul>
@ -210,6 +220,28 @@ $('button.update').click(function(){
</div>
</td>
</tr>
<tr id="mark-tsignore">
<td><a href="#" class="permalink">mark_tsIgnore</a></td>
<td>{}</td>
<td>This option sets which columns in the table to ignore when searching.
<div class="collapsible">
<br>
Use it as follows:
<pre class="prettyprint lang-js">$('table').tablesorter({
widgets: ['mark'],
widgetOptions: {
mark_tsIgnore: {
// ignore second column (zero-based index)
1: true
}
}
});</pre>
You can also add a <code>"mark-ignore"</code> class name to the table header to accomplish the same thing.
</div>
</td>
</tr>
</tbody>
<tbody class="tablesorter-infoOnly">
<tr>
@ -218,6 +250,15 @@ $('button.update').click(function(){
</tbody>
<tbody>
<tr id="mark-acrossElements">
<td><span class="permalink">mark_acrossElements</span></td>
<td>false</td>
<td>
Set to <code>true</code> to search for matches across elements (added in mark.js v8.0.0).<br>
This option does not apply to content across table cells as this widget targets individual cells while
performing an "any" match.
</td>
</tr>
<tr id="mark-element">
<td><span class="permalink">mark_element</span></td>
<td>"mark"</td>
@ -321,14 +362,14 @@ $('button.update').click(function(){
<button type="button" data-filter-column="all">br?n</button>
<button type="button" data-filter-column="all">br*n</button>
<button type="button" data-filter-column="all">aaron|bruce</button>
<button type="button" data-filter-column="all">aaron && 2</button>
<button type="button" data-filter-column="all">aaron &amp;&amp; 2</button>
<table id="table" class="tablesorter">
<thead>
<tr>
<th>Rank</th>
<th class="filter-match">First Name</th>
<th>Last Name</th>
<th>Age</th>
<th class="ignore" title="no highlighting">Age</th>
<th>Total</th>
<th>Discount</th>
<th>Date</th>
@ -360,7 +401,7 @@ $('button.update').click(function(){
<button class="table2" type="button">br?n</button>
<button class="table2" type="button">br*n</button>
<button class="table2" type="button">aaron|bruce</button>
<button class="table2" type="button">aaron && 2</button>
<button class="table2" type="button">aaron &amp;&amp; 2</button>
<table id="table2" class="tablesorter">
<thead>
@ -368,7 +409,7 @@ $('button.update').click(function(){
<th>Rank</th>
<th class="filter-match">First Name</th>
<th>Last Name</th>
<th>Age</th>
<th class="mark-ignore" title="no highlighting">Age</th>
<th>Total</th>
<th>Discount</th>
<th>Date</th>

View File

@ -11,7 +11,8 @@
if ( typeof $.fn.mark === 'function' ) {
var tmp,
update = c.widgetOptions.mark_tsUpdate;
c.$table.on( 'filterEnd.tsmark pagerComplete.tsmark' + ( update ? ' ' + update : '' ), function( e, filters ) {
c.$table.on( 'filterEnd.tsmark pagerComplete.tsmark' +
( update ? ' ' + update : '' ), function( e, filters ) {
// filterEnd passes "config" as the param
ts.mark.update( c, e.type === update ? filters : '' );
});
@ -33,7 +34,8 @@
},
checkRegex : function( regex ) {
if ( regex instanceof RegExp ) {
// prevent lock up of mark.js (see https://github.com/julmot/mark.js/issues/55)
// prevent lock up of mark.js
// (see https://github.com/julmot/mark.js/issues/55)
var result = '\u0001\u0002\u0003\u0004\u0005'.match( regex );
return result === null || result.length < 5;
}
@ -49,10 +51,27 @@
}
return results;
},
// used when "any" match is performed
ignoreColumns : function( c ) {
var wo = c.widgetOptions,
len = c.columns,
cols = [];
while (len--) {
if (wo.mark_tsIgnore[len] ||
$( c.$headerIndexed[len] ).hasClass( 'mark-ignore' ) ) {
cols[cols.length] = ':nth-child(' + (len + 1) + ')';
}
}
if (cols.length) {
return ':not(' + cols.join(',') + ')';
}
return '';
},
update : function( c, filters ) {
var options = {},
wo = c.widgetOptions,
setIgnoreCase = typeof wo.filter_ignoreCase === 'undefined' ? true : wo.filter_ignoreCase,
setIgnoreCase = typeof wo.filter_ignoreCase === 'undefined' ? true :
wo.filter_ignoreCase,
regex = ts.mark.regex,
$rows = c.$table
.find( 'tbody tr' )
@ -68,11 +87,16 @@
}
});
$.each( filters, function( indx, filter ) {
if ( filter ) {
if ( filter &&
!( $(c.$headerIndexed[indx]).hasClass('mark-ignore') ||
wo.mark_tsIgnore[indx]
) ) {
var testRegex = null,
matches = filter,
useRegex = false,
col = indx === c.columns ? '' : ':nth-child(' + ( indx + 1 ) + ')';
col = indx === c.columns ?
ts.mark.ignoreColumns( c ) :
':nth-child(' + ( indx + 1 ) + ')';
// regular expression entered
if ( regex.pure.test( filter ) ) {
matches = regex.pure.exec( filter );
@ -122,7 +146,10 @@
}
} else {
// pass an array of matches
$rows.children( col ).mark( ts.mark.cleanMatches( matches ), options );
$rows.children( col ).mark(
ts.mark.cleanMatches( matches ),
options
);
}
}
});
@ -132,14 +159,16 @@
ts.addWidget({
id: 'mark',
options: {
mark_tsUpdate : 'markUpdate'
mark_tsUpdate : 'markUpdate',
mark_tsIgnore : {}
},
init : function( table, thisWidget, c, wo ) {
ts.mark.init( c, wo );
},
remove : function( table, c ) {
var update = c.widgetOptions.mark_tsUpdate;
c.$table.off( 'filterEnd.tsmark pagerComplete.tsmark' + ( update ? ' ' + update : '' ) );
c.$table.off( 'filterEnd.tsmark pagerComplete.tsmark' +
( update ? ' ' + update : '' ) );
}
});