tablesorter/js/widgets/widget-mark.js
2016-09-23 11:45:10 -05:00

174 lines
5.0 KiB
JavaScript

/*! Widget: mark.js - updated 9/23/2016 (v2.27.7) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison
*/
;( function( $ ) {
'use strict';
var ts = $.tablesorter;
ts.mark = {
init : function( c ) {
if ( typeof $.fn.mark === 'function' ) {
var tmp,
update = c.widgetOptions.mark_tsUpdate;
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 : '' );
});
// Regex to split up a query
tmp = '(?:<|=|>|\\||\"|' + "\\'|" +
'\\s+(?:&&|-|' +
( ts.language.and || 'and' ) + '|' +
( ts.language.or || 'or' ) + '|' +
( ts.language.to || 'to' ) + ')\\s+)';
ts.mark.regex.filter = new RegExp(tmp, 'gim');
} else {
console.warn('Widget-mark not initialized: missing "jquery.mark.js"');
}
},
regex : {
mark : /^mark_(.+)$/,
// test for regex (e.g. "/(lorem|ipsum)/gi")
pure : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/
},
checkRegex : function( regex ) {
if ( regex instanceof RegExp ) {
// 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;
}
return false;
},
cleanMatches : function( matches ) {
var results = [],
indx = matches && matches.length || 0;
while ( indx-- ) {
if ( matches[indx] !== '' ) {
results[ results.length ] = matches[ indx ];
}
}
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,
regex = ts.mark.regex,
$rows = c.$table
.find( 'tbody tr' )
.unmark()
.not( '.' + ( c.widgetOptions.filter_filteredRow || 'filtered' ) );
filters = filters || $.tablesorter.getFilters( c.$table );
// extract & save mark options from widgetOptions (prefixed with "mark_")
// update dynamically
$.each( c.widgetOptions, function( key, val ) {
var matches = key.match( regex.mark );
if ( matches && typeof matches[1] !== 'undefined' ) {
options[ matches[1] ] = val;
}
});
$.each( filters, function( indx, filter ) {
if ( filter &&
!( $(c.$headerIndexed[indx]).hasClass('mark-ignore') ||
wo.mark_tsIgnore[indx]
) ) {
var testRegex = null,
matches = filter,
useRegex = false,
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 );
// ignore "all" matches (i.e. /.*/)
if (matches[1] === '.*') {
matches[1] = '';
}
try {
// make sure to include global flag when testing regex
testRegex = new RegExp( matches[ 1 ], 'gim' );
matches = new RegExp( matches[ 1 ], matches[ 2 ] );
} catch (err) {
matches = null;
}
if ( ts.mark.checkRegex( testRegex ) ) {
$rows.children( col ).markRegExp( matches, options );
}
// matches is either null, invalid, or done my markRegExp
return;
}
// all special querys (or, and, wild cards & fuzzy)
// regex seems to not be consistent here; so use string indexOf
// fuzzy or wild card matches
if ( filter.indexOf( '~' ) === 0 ) {
useRegex = true;
// fuzzy search separate each letter
matches = filter.replace( /~/g, '' ).split( '' );
} else {
// wild card matching
if ( filter.indexOf( '?' ) > -1 ) {
useRegex = true;
filter = filter.replace( /\?/g, '\\S{1}' );
}
if ( filter.indexOf( '*' ) > -1 ) {
useRegex = true;
filter = filter.replace( /\*/g, '\\S*' );
}
matches = filter.split( regex.filter );
}
if ( useRegex && matches && matches.length ) {
matches = new RegExp(
ts.mark.cleanMatches( matches ).join( '.*' ),
'gm'
);
if ( ts.mark.checkRegex( matches ) ) {
$rows.children( col ).markRegExp( matches, options );
}
} else {
// pass an array of matches
$rows.children( col ).mark(
ts.mark.cleanMatches( matches ),
options
);
}
}
});
}
};
ts.addWidget({
id: 'mark',
options: {
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 : '' ) );
}
});
})( jQuery );