diff --git a/README.md b/README.md index aa58377..70aba46 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,9 @@ This plugin provides the following configuration options: | onSearchEmpty | `false` | Allows you to define a function to be called when the search input is empty. This function will be called once when the search input is empty or cleared. The searchable element will be passed to the function. | | onSearchFocus | `false` | Allows you to define a function to be called when the search input is focussed. The `this` context of this function will be the search input element. | | onSearchBlur | `false` | Allows you to define a function to be called when the search input is blurred. The `this` context of this function will be the search input element. | +| onAfterSearch | `false` | Allows you to define a function to be called after searchable has hidden/shown the elements. This can be used to count the number of elements being hidden/shown. | | clearOnLoad | `false` | Determines whether the search input should be cleared on page load (either `true` or `false`). | +| ignoreDiacritics | `false` | Determines if diacritic letters should be ignore. For example, when searching for `u` -> `ú` and `ü` will also be found. | ### Example usage @@ -89,7 +91,11 @@ $( '#element' ).searchable({ onSearchBlur: function() { $( '#feedback' ).hide(); }, - clearOnLoad: true + onAfterSearch: function() { + // i.e. count number of items shown + }, + clearOnLoad: true, + ignoreDiacritics: true }); ``` @@ -104,6 +110,11 @@ $( '#element' ).searchable({ - Added some events that allow you to call custom functions during the search lifecycle: onSearchActive, onSearchEmpty, onSearchFocus, onSearchBlur (view the [configuration](#configuration) for more information). - Added the `clearOnLoad` setting which allows you to clear the search input on page load / refresh. +**Version 1.1.1:** + +- Added onAfterSearch callback. +- Added ignoreDiacritics option. Default is false so it should be backwards compatible. + ## Contributing & Issues Please feel free to submit any issues or pull requests, they are more then welcome. When submitting an issue, please specify the version number and describe the issue in detail so that it can be solved as soon as possible! diff --git a/dist/jquery.searchable-1.1.1.min.js b/dist/jquery.searchable-1.1.1.min.js new file mode 100644 index 0000000..d26edf1 --- /dev/null +++ b/dist/jquery.searchable-1.1.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery Searchable v1.1.1 by Stidges (http://twitter.com/stidges) | MIT */ +!function(a,b,c,d){function e(a){return"function"==typeof a}function f(b,c){this.$element=a(b),this.settings=a.extend({},h,c),this.init()}var g="searchable",h={selector:"tbody tr",childSelector:"td",searchField:"#search",striped:!1,oddRow:{},evenRow:{},hide:function(a){a.hide()},show:function(a){a.show()},searchType:"default",onSearchActive:!1,onSearchEmpty:!1,onSearchFocus:!1,onSearchBlur:!1,clearOnLoad:!1,onAfterSearch:!1,ignoreDiacritics:!1},i=!1,j=!1,k=!1,l=!1,m=!1;f.prototype={init:function(){this.$searchElems=a(this.settings.selector,this.$element),this.$search=a(this.settings.searchField),this.matcherFunc=this.getMatcherFunction(this.settings.searchType),this.determineCallbacks(),this.bindEvents(),this.updateStriping()},determineCallbacks:function(){i=e(this.settings.onSearchActive),j=e(this.settings.onSearchEmpty),k=e(this.settings.onSearchFocus),l=e(this.settings.onSearchBlur),m=e(this.settings.onAfterSearch)},removeDiacritics:function(a){return this.settings.ignoreDiacritics&&(a=a.replace(/[ÀÁÂÃÄÅ]/g,"A").replace(/[àáâãäå]/g,"a").replace(/[ÈÉÊË]/g,"E").replace(/[èéêë]/g,"e").replace(/[Í]/g,"I").replace(/[í]/g,"i").replace(/[ÓÖ]/g,"O").replace(/[óö]/g,"o").replace(/[ÚÜ]/g,"U").replace(/[úü]/g,"u").replace(/[Ñ]/g,"N").replace(/[ñ]/g,"n").replace(/[ß]/g,"s")),a},bindEvents:function(){var b=this;this.$search.on("change keyup",function(){b.search(a(this).val()),b.updateStriping(),m&&b.settings.onAfterSearch()}),k&&this.$search.on("focus",this.settings.onSearchFocus),l&&this.$search.on("blur",this.settings.onSearchBlur),this.settings.clearOnLoad===!0&&(this.$search.val(""),this.$search.trigger("change")),""!==this.$search.val()&&this.$search.trigger("change")},updateStriping:function(){var b=this,c=["oddRow","evenRow"],d=this.settings.selector+":visible";this.settings.striped&&a(d,this.$element).each(function(d,e){a(e).css(b.settings[c[d%2]])})},search:function(b){var c,d,e,f,g,h,k,l,m;if(0===a.trim(b).length)return this.$searchElems.css("display",""),this.updateStriping(),void(j&&this.settings.onSearchEmpty(this.$element));for(i&&this.settings.onSearchActive(this.$element,b),d=this.$searchElems.length,b=this.removeDiacritics(b),c=this.matcherFunc(b),k=0;d>k;k++){for(h=a(this.$searchElems[k]),e=h.find(this.settings.childSelector),f=e.length,g=!0,l=0;f>l;l++)if(m=a(e[l]).text(),m=this.removeDiacritics(m),c(m)){g=!1;break}g===!0?this.settings.hide(h):this.settings.show(h)}},getMatcherFunction:function(a){return"fuzzy"===a?this.getFuzzyMatcher:"strict"===a?this.getStrictMatcher:this.getDefaultMatcher},getFuzzyMatcher:function(a){var b,c=a.split("").reduce(function(a,b){return a+"[^"+b+"]*"+b});return b=new RegExp(c,"gi"),function(a){return b.test(a)}},getStrictMatcher:function(b){return b=a.trim(b),function(a){return-1!==a.indexOf(b)}},getDefaultMatcher:function(b){return b=a.trim(b).toLowerCase(),function(a){return-1!==a.toLowerCase().indexOf(b)}}},a.fn[g]=function(b){return this.each(function(){a.data(this,"plugin_"+g)||a.data(this,"plugin_"+g,new f(this,b))})}}(jQuery,window,document); \ No newline at end of file diff --git a/dist/jquery.searchable-ie-1.1.1.min.js b/dist/jquery.searchable-ie-1.1.1.min.js new file mode 100644 index 0000000..1d83f3a --- /dev/null +++ b/dist/jquery.searchable-ie-1.1.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery Searchable v1.1.1 by Stidges (http://twitter.com/stidges) | MIT */ +!function(a,b,c,d){function e(a){return"function"==typeof a}function f(b,c){this.$element=a(b),this.settings=a.extend({},h,c),this.init()}var g="searchable",h={selector:"tbody tr",childSelector:"td",searchField:"#search",striped:!1,oddRow:{},evenRow:{},hide:function(a){a.hide()},show:function(a){a.show()},searchType:"default",onSearchActive:!1,onSearchEmpty:!1,onSearchFocus:!1,onSearchBlur:!1,clearOnLoad:!1,onAfterSearch:!1,ignoreDiacritics:!1},i=!1,j=!1,k=!1,l=!1,m=!1;"function"!=typeof Array.prototype.reduce&&(Array.prototype.reduce=function(a,b){"use strict";if(null===this||"undefined"==typeof this)throw new TypeError("Array.prototype.reduce called on null or undefined");if("function"!=typeof a)throw new TypeError(a+" is not a function");var c,d,e=this.length>>>0,f=!1;for(1c;++c)this.hasOwnProperty(c)&&(f?d=a(d,this[c],c,this):(d=this[c],f=!0));if(!f)throw new TypeError("Reduce of empty array with no initial value");return d}),f.prototype={init:function(){this.$searchElems=a(this.settings.selector,this.$element),this.$search=a(this.settings.searchField),this.matcherFunc=this.getMatcherFunction(this.settings.searchType),this.determineCallbacks(),this.bindEvents(),this.updateStriping()},determineCallbacks:function(){i=e(this.settings.onSearchActive),j=e(this.settings.onSearchEmpty),k=e(this.settings.onSearchFocus),l=e(this.settings.onSearchBlur),m=e(this.settings.onAfterSearch)},removeDiacritics:function(a){return this.settings.ignoreDiacritics&&(a=a.replace(/[ÀÁÂÃÄÅ]/g,"A").replace(/[àáâãäå]/g,"a").replace(/[ÈÉÊË]/g,"E").replace(/[èéêë]/g,"e").replace(/[Í]/g,"I").replace(/[í]/g,"i").replace(/[ÓÖ]/g,"O").replace(/[óö]/g,"o").replace(/[ÚÜ]/g,"U").replace(/[úü]/g,"u").replace(/[Ñ]/g,"N").replace(/[ñ]/g,"n").replace(/[ß]/g,"s")),a},bindEvents:function(){var b=this;this.$search.on("change keyup",function(){b.search(a(this).val()),b.updateStriping(),m&&b.settings.onAfterSearch()}),k&&this.$search.on("focus",this.settings.onSearchFocus),l&&this.$search.on("blur",this.settings.onSearchBlur),this.settings.clearOnLoad===!0&&(this.$search.val(""),this.$search.trigger("change")),""!==this.$search.val()&&this.$search.trigger("change")},updateStriping:function(){var b=this,c=["oddRow","evenRow"],d=this.settings.selector+":visible";this.settings.striped&&a(d,this.$element).each(function(d,e){a(e).css(b.settings[c[d%2]])})},search:function(b){var c,d,e,f,g,h,k,l,m;if(0===a.trim(b).length)return this.$searchElems.css("display",""),this.updateStriping(),void(j&&this.settings.onSearchEmpty(this.$element));for(i&&this.settings.onSearchActive(this.$element,b),d=this.$searchElems.length,b=this.removeDiacritics(b),c=this.matcherFunc(b),k=0;d>k;k++){for(h=a(this.$searchElems[k]),e=h.find(this.settings.childSelector),f=e.length,g=!0,l=0;f>l;l++)if(m=a(e[l]).text(),m=this.removeDiacritics(m),c(m)){g=!1;break}g===!0?this.settings.hide(h):this.settings.show(h)}},getMatcherFunction:function(a){return"fuzzy"===a?this.getFuzzyMatcher:"strict"===a?this.getStrictMatcher:this.getDefaultMatcher},getFuzzyMatcher:function(a){var b,c=a.split("").reduce(function(a,b){return a+"[^"+b+"]*"+b});return b=new RegExp(c,"gi"),function(a){return b.test(a)}},getStrictMatcher:function(b){return b=a.trim(b),function(a){return-1!==a.indexOf(b)}},getDefaultMatcher:function(b){return b=a.trim(b).toLowerCase(),function(a){return-1!==a.toLowerCase().indexOf(b)}}},a.fn[g]=function(b){return this.each(function(){a.data(this,"plugin_"+g)||a.data(this,"plugin_"+g,new f(this,b))})}}(jQuery,window,document); \ No newline at end of file diff --git a/jquery.searchable-ie.js b/jquery.searchable-ie.js index 60aee45..1a33cc5 100644 --- a/jquery.searchable-ie.js +++ b/jquery.searchable-ie.js @@ -1,4 +1,4 @@ -/*! +/*! * jQuery Searchable Plugin v1.0.0 * https://github.com/stidges/jquery-searchable * @@ -22,12 +22,15 @@ onSearchEmpty: false, onSearchFocus: false, onSearchBlur: false, - clearOnLoad: false + clearOnLoad: false, + onAfterSearch: false, + ignoreDiacritics: false }, searchActiveCallback = false, searchEmptyCallback = false, searchFocusCallback = false, - searchBlurCallback = false; + searchBlurCallback = false, + afterSearchCallback = false; function isFunction(value) { return typeof value === 'function'; @@ -98,6 +101,28 @@ searchEmptyCallback = isFunction( this.settings.onSearchEmpty ); searchFocusCallback = isFunction( this.settings.onSearchFocus ); searchBlurCallback = isFunction( this.settings.onSearchBlur ); + afterSearchCallback = isFunction( this.settings.onAfterSearch ); + }, + + removeDiacritics : function (text) { + if (this.settings.ignoreDiacritics) { + text = text + .replace(/[ÀÁÂÃÄÅ]/g, 'A') + .replace(/[àáâãäå]/g, 'a') + .replace(/[ÈÉÊË]/g, 'E') + .replace(/[èéêë]/g, 'e') + .replace(/[Í]/g, 'I') + .replace(/[í]/g, 'i') + .replace(/[ÓÖ]/g, 'O') + .replace(/[óö]/g, 'o') + .replace(/[ÚÜ]/g, 'U') + .replace(/[úü]/g, 'u') + .replace(/[Ñ]/g, 'N') + .replace(/[ñ]/g, 'n') + .replace(/[ß]/g, 's') + ; + } + return text; }, bindEvents: function() { @@ -107,6 +132,10 @@ that.search( $( this ).val() ); that.updateStriping(); + + if ( afterSearchCallback ) { + that.settings.onAfterSearch(); + } }); if ( searchFocusCallback ) { @@ -142,7 +171,7 @@ }, search: function( term ) { - var matcher, elemCount, children, childCount, hide, $elem, i, x; + var matcher, elemCount, children, childCount, hide, $elem, i, x, contentText; if ( $.trim( term ).length === 0 ) { this.$searchElems.css( 'display', '' ); @@ -158,6 +187,7 @@ } elemCount = this.$searchElems.length; + term = this.removeDiacritics(term); matcher = this.matcherFunc( term ); for ( i = 0; i < elemCount; i++ ) { @@ -167,7 +197,9 @@ hide = true; for ( x = 0; x < childCount; x++ ) { - if ( matcher( $( children[ x ] ).text() ) ) { + contentText = $( children[ x ] ).text(); + contentText = this.removeDiacritics(contentText); + if ( matcher( contentText ) ) { hide = false; break; } diff --git a/jquery.searchable.js b/jquery.searchable.js index c0d243a..3f54aa0 100644 --- a/jquery.searchable.js +++ b/jquery.searchable.js @@ -1,4 +1,4 @@ -/*! +/*! * jQuery Searchable Plugin v1.0.0 * https://github.com/stidges/jquery-searchable * @@ -22,12 +22,15 @@ onSearchEmpty: false, onSearchFocus: false, onSearchBlur: false, - clearOnLoad: false + clearOnLoad: false, + onAfterSearch: false, + ignoreDiacritics: false }, searchActiveCallback = false, searchEmptyCallback = false, searchFocusCallback = false, - searchBlurCallback = false; + searchBlurCallback = false, + afterSearchCallback = false; function isFunction(value) { return typeof value === 'function'; @@ -56,6 +59,28 @@ searchEmptyCallback = isFunction( this.settings.onSearchEmpty ); searchFocusCallback = isFunction( this.settings.onSearchFocus ); searchBlurCallback = isFunction( this.settings.onSearchBlur ); + afterSearchCallback = isFunction( this.settings.onAfterSearch ); + }, + + removeDiacritics : function (text) { + if (this.settings.ignoreDiacritics) { + text = text + .replace(/[ÀÁÂÃÄÅ]/g, 'A') + .replace(/[àáâãäå]/g, 'a') + .replace(/[ÈÉÊË]/g, 'E') + .replace(/[èéêë]/g, 'e') + .replace(/[Í]/g, 'I') + .replace(/[í]/g, 'i') + .replace(/[ÓÖ]/g, 'O') + .replace(/[óö]/g, 'o') + .replace(/[ÚÜ]/g, 'U') + .replace(/[úü]/g, 'u') + .replace(/[Ñ]/g, 'N') + .replace(/[ñ]/g, 'n') + .replace(/[ß]/g, 's') + ; + } + return text; }, bindEvents: function() { @@ -65,6 +90,10 @@ that.search( $( this ).val() ); that.updateStriping(); + + if ( afterSearchCallback ) { + that.settings.onAfterSearch(); + } }); if ( searchFocusCallback ) { @@ -100,7 +129,7 @@ }, search: function( term ) { - var matcher, elemCount, children, childCount, hide, $elem, i, x; + var matcher, elemCount, children, childCount, hide, $elem, i, x, contentText; if ( $.trim( term ).length === 0 ) { this.$searchElems.css( 'display', '' ); @@ -116,6 +145,7 @@ } elemCount = this.$searchElems.length; + term = this.removeDiacritics(term); matcher = this.matcherFunc( term ); for ( i = 0; i < elemCount; i++ ) { @@ -125,7 +155,9 @@ hide = true; for ( x = 0; x < childCount; x++ ) { - if ( matcher( $( children[ x ] ).text() ) ) { + contentText = $( children[ x ] ).text(); + contentText = this.removeDiacritics(contentText); + if ( matcher( contentText ) ) { hide = false; break; } diff --git a/package.json b/package.json index c42b99f..b9d0c19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jquery.searchable", "title": "jQuery Searchable", - "version": "1.1.0", + "version": "1.1.1", "description": "Tiny, fast jQuery plugin to search through elements as you type.", "main": "jquery.searchable.js", "scripts": {},