1/*! 2 * jQuery Searchable Plugin v1.0.0 3 * https://github.com/stidges/jquery-searchable 4 * 5 * Copyright 2014 Stidges 6 * Released under the MIT license 7 */ 8;(function( $, window, document, undefined ) { 9 10 var pluginName = 'searchable', 11 defaults = { 12 selector: 'tbody tr', 13 childSelector: 'td', 14 searchField: '#search', 15 striped: false, 16 oddRow: { }, 17 evenRow: { }, 18 hide: function( elem ) { elem.hide(); }, 19 show: function( elem ) { elem.show(); }, 20 searchType: 'default', 21 onSearchActive: false, 22 onSearchEmpty: false, 23 onSearchFocus: false, 24 onSearchBlur: false, 25 clearOnLoad: false 26 }, 27 searchActiveCallback = false, 28 searchEmptyCallback = false, 29 searchFocusCallback = false, 30 searchBlurCallback = false; 31 32 function isFunction(value) { 33 return typeof value === 'function'; 34 } 35 36 function Plugin( element, options ) { 37 this.$element = $( element ); 38 this.settings = $.extend( {}, defaults, options ); 39 40 this.init(); 41 } 42 43 Plugin.prototype = { 44 init: function() { 45 this.$searchElems = $( this.settings.selector, this.$element ); 46 this.$search = $( this.settings.searchField ); 47 this.matcherFunc = this.getMatcherFunction( this.settings.searchType ); 48 49 this.determineCallbacks(); 50 this.bindEvents(); 51 this.updateStriping(); 52 }, 53 54 determineCallbacks: function() { 55 searchActiveCallback = isFunction( this.settings.onSearchActive ); 56 searchEmptyCallback = isFunction( this.settings.onSearchEmpty ); 57 searchFocusCallback = isFunction( this.settings.onSearchFocus ); 58 searchBlurCallback = isFunction( this.settings.onSearchBlur ); 59 }, 60 61 bindEvents: function() { 62 var that = this; 63 64 this.$search.on( 'change keyup', function() { 65 that.search( $( this ).val() ); 66 67 that.updateStriping(); 68 }); 69 70 if ( searchFocusCallback ) { 71 this.$search.on( 'focus', this.settings.onSearchFocus ); 72 } 73 74 if ( searchBlurCallback ) { 75 this.$search.on( 'blur', this.settings.onSearchBlur ); 76 } 77 78 if ( this.settings.clearOnLoad === true ) { 79 this.$search.val( '' ); 80 this.$search.trigger( 'change' ); 81 } 82 83 if ( this.$search.val() !== '' ) { 84 this.$search.trigger( 'change' ); 85 } 86 }, 87 88 updateStriping: function() { 89 var that = this, 90 styles = [ 'oddRow', 'evenRow' ], 91 selector = this.settings.selector + ':visible'; 92 93 if ( !this.settings.striped ) { 94 return; 95 } 96 97 $( selector, this.$element ).each( function( i, row ) { 98 $( row ).css( that.settings[ styles[ i % 2 ] ] ); 99 }); 100 }, 101 102 search: function( term ) { 103 var matcher, elemCount, children, childCount, hide, $elem, i, x; 104 105 if ( $.trim( term ).length === 0 ) { 106 this.$searchElems.css( 'display', '' ); 107 this.updateStriping(); 108 109 if ( searchEmptyCallback ) { 110 this.settings.onSearchEmpty( this.$element ); 111 } 112 113 return; 114 } else if ( searchActiveCallback ) { 115 this.settings.onSearchActive( this.$element, term ); 116 } 117 118 elemCount = this.$searchElems.length; 119 matcher = this.matcherFunc( term ); 120 121 for ( i = 0; i < elemCount; i++ ) { 122 $elem = $( this.$searchElems[ i ] ); 123 children = $elem.find( this.settings.childSelector ); 124 childCount = children.length; 125 hide = true; 126 127 for ( x = 0; x < childCount; x++ ) { 128 if ( matcher( $( children[ x ] ).text() ) ) { 129 hide = false; 130 break; 131 } 132 } 133 134 if ( hide === true ) { 135 this.settings.hide( $elem ); 136 } else { 137 this.settings.show( $elem ); 138 } 139 } 140 }, 141 142 getMatcherFunction: function( type ) { 143 if ( type === 'fuzzy' ) { 144 return this.getFuzzyMatcher; 145 } else if ( type === 'strict' ) {
146 return this.getStrictMatcher; 147 } 148 149 return this.getDefaultMatcher; 150 }, 151 152 getFuzzyMatcher: function( term ) { 153 var regexMatcher, 154 pattern = term.split( '' ).reduce( function( a, b ) { 155 return a + '[^' + b + ']*' + b; 156 }); 157 158 regexMatcher = new RegExp( pattern, 'gi' ); 159 160 return function( s ) { 161 return regexMatcher.test( s ); 162 }; 163 }, 164 165 getStrictMatcher: function( term ) { 166 term = $.trim( term ); 167 168 return function( s ) { 169 return ( s.indexOf( term ) !== -1 ); 170 }; 171 }, 172 173 getDefaultMatcher: function( term ) { 174 term = $.trim( term ).toLowerCase(); 175 176 return function( s ) { 177 return ( s.toLowerCase().indexOf( term ) !== -1 ); 178 }; 179 } 180 }; 181 182 $.fn[ pluginName ] = function( options ) { 183 return this.each( function() { 184 if ( !$.data( this, 'plugin_' + pluginName ) ) { 185 $.data( this, 'plugin_' + pluginName, new Plugin(this, options) ); 186 } 187 }); 188 }; 189 190})( jQuery, window, document );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.