From 4dd753e1b72a95cfc48439f29fd1bd692d8b56bc Mon Sep 17 00:00:00 2001 From: Victor Calvello Date: Wed, 9 Sep 2015 17:13:55 -0300 Subject: [PATCH] added config opts for filterBar instance --- README.md | 33 +++++++++++++--------- dist/ionic.filter.bar.js | 4 +++ dist/ionic.filter.bar.min.js | 2 +- js/ionic.filter.bar.service.js | 4 +++ test/unit/ionic.filter.bar.service.unit.js | 20 +++++++++++++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fa06c0f..0b1a9d6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Run the following ommands: npm install bower install gulp - + ## Setup #### Install @@ -49,7 +49,7 @@ Keyboard in your module's run section. #### JS/CSS Imports (index.html) Include the following JavaScript/CSS file imports in your index.html. Remember to import the ionic libraries first! The example below assumes your 3rd party bower dependencies are located in the default bower_components folder. - + @@ -155,7 +155,7 @@ A service you can inject in your controller to show the filter bar @param {object} options The options for the filterBar. Properties: - + - `[Object]` `items` The array of items to filter. When the filterBar is cancelled or removed, the original list of items will @@ -165,7 +165,7 @@ A service you can inject in your controller to show the filter bar - `{function=}` `update` Called after the items are filtered. The new filtered items will be passed to this function which can be used - to update the items on your controller's scope. The text string that was searched on will be passed as the + to update the items on your controller's scope. The text string that was searched on will be passed as the second argument. @@ -194,32 +194,32 @@ A service you can inject in your controller to show the filter bar - `{function=}` `expression` - The predicate to be used for selecting items from the `items` array. This is similar to the angular filter - `expression` function described [here](https://docs.angularjs.org/api/ng/filter/filter), except that the first + The predicate to be used for selecting items from the `items` array. This is similar to the angular filter + `expression` function described [here](https://docs.angularjs.org/api/ng/filter/filter), except that the first argument will be the filterText as shown below. Default value is `null`. NOTE: This property will take precedence over `filterProperties`. Only one can be defined. - + function (filterText, value, index, array) { return value.propertyName === filterText || value.anotherPropertyName === filterText; } - `{function,true,false,undefined=}` `comparator` - Determines if the expected value (from the filter expression) and actual value (from the object in the array) - should be considered a match. This is the same as the angular filter `comparator` argument described [here](https://docs.angularjs.org/api/ng/filter/filter). + Determines if the expected value (from the filter expression) and actual value (from the object in the array) + should be considered a match. This is the same as the angular filter `comparator` argument described [here](https://docs.angularjs.org/api/ng/filter/filter). Default value is `undefined`. - + - `[String]` `filterProperties` A string or string array of object properties that will be used to create a filterExpression object for - filtering items in the array. All properties will be matched against the input filter text. For example, given + filtering items in the array. All properties will be matched against the input filter text. For example, given the following object in an array of items , and assume the user searches for "fish" - + {name: 'fish', description: 'fish', color: 'blue'} - + filterProperties: ['name', 'description'] ... The object will be matched and passed to the array in `update` filterProperties: ['name', 'color'] ... The object will NOT be matched or passed to the array in `update` - + NOTE: If `expression` is defined, `filterProperties` will have no effect. Only one can be defined. Default value is null. @@ -252,6 +252,11 @@ A service you can inject in your controller to show the filter bar - `.modal` (Appends to a modal) - `.menu-content` (Appends to the content section of a side menu. Useful when the expose-aside-when attr is set.) + - `{object=}` `config` + + A config object to customize the filter bar template instance. + + ## Screenshots diff --git a/dist/ionic.filter.bar.js b/dist/ionic.filter.bar.js index 9d39717..6e34f63 100644 --- a/dist/ionic.filter.bar.js +++ b/dist/ionic.filter.bar.js @@ -371,6 +371,10 @@ angular.module('jett.ionic.filter.bar', ['ionic']); opts.container = angular.element($body[0].querySelector(opts.container)); } + //extend templateConfig with supplied config options + angular.extend(templateConfig, opts.config); + delete opts.config; + //extend scope defaults with supplied options angular.extend(scope, { config: templateConfig, diff --git a/dist/ionic.filter.bar.min.js b/dist/ionic.filter.bar.min.js index 35d79a7..356ad28 100644 --- a/dist/ionic.filter.bar.min.js +++ b/dist/ionic.filter.bar.min.js @@ -1 +1 @@ -angular.module("jett.ionic.filter.bar",["ionic"]),function(e){"use strict";e.module("jett.ionic.filter.bar").directive("ionFilterBar",["$document","$timeout","$ionicGesture","$ionicPlatform",function(t,n,r,i){var o;return o=i.is("android")?'
':'
',{restrict:"E",scope:!0,link:function(i,o){var a,c,l,s,f,u=e.element(o[0].querySelector(".filter-bar-clear")),d=e.element(o[0].querySelector(".filter-bar-cancel")),p=o.find("input");i.filterText="";var b=function(){i.cancelFilterBar()};d.bind("click",b),i.config.backdrop&&(l=e.element('
'),o.append(l),s=function(e){e.target==l[0]&&b()},l.bind("click",s),c=r.on("swipe",s,l));var m=function(){"none"===u.css("display")&&u.css("display","block")},h=function(){"block"===u.css("display")&&u.css("display","none")},g=function(){n(function(){i.filterText="",h(),ionic.requestAnimationFrame(function(){i.showBackdrop(),i.scrollItemsTop(),i.focusInput()})})};u.bind("touchstart mousedown",g),p.bind("touchstart mousedown",function(){i.scrollItemsTop(),i.focusInput()});var v=function(e){27==e.which?b():i.filterText&&i.filterText.length?(m(),i.hideBackdrop()):(h(),i.showBackdrop())};t.bind("keyup",v);var B=function(){i.filterItems(i.filterText)};i.$on("$destroy",function(){o.remove(),t.unbind("keyup",v),l&&r.off(c,"swipe",s),f()}),f=i.$watch("filterText",function(e,t){var r;a&&n.cancel(a),e!==t&&(r=e.length&&i.debounce?i.delay:0,a=n(B,r,!1))})},template:o}}])}(angular),function(e){"use strict";e.module("jett.ionic.filter.bar").provider("$ionicFilterBarConfig",function(){function t(e,t){c.platform[e]=t,o.platform[e]={},n(c,c.platform[e]),r(c.platform[e],o.platform[e],"")}function n(t,r){for(var i in t)i!=a&&t.hasOwnProperty(i)&&(e.isObject(t[i])?(e.isDefined(r[i])||(r[i]={}),n(t[i],r[i])):e.isDefined(r[i])||(r[i]=null))}function r(t,n,o){e.forEach(t,function(l,s){e.isObject(t[s])?(n[s]={},r(t[s],n[s],o+"."+s)):n[s]=function(e){if(arguments.length)return t[s]=e,n;if(t[s]==a){var r=i(c.platform,ionic.Platform.platform()+o+"."+s);return r||r===!1?r:i(c.platform,"default"+o+"."+s)}return t[s]}})}function i(t,n){n=n.split(".");for(var r=0;r')(s),g=h.children().eq(0),v=g.find("input")[0],B=h.children().eq(1),k=s.scrollDelegate.getScrollView(),$=!!k,y=$?e.element(k.__container):null,w=s.cancelOnStateChange?i.$on("$stateChangeSuccess",function(){s.cancelFilterBar()}):e.noop,T=function(){d||(d=!0,v&&v.focus())},F=function(){d&&(d=!1,v&&v.blur())},x=function(){k.__scrollTop>0&&F()};return s.scrollItemsTop=function(){$&&s.scrollDelegate.scrollTop&&s.scrollDelegate.scrollTop()},s.focusInput=function(){d=!1,T()},s.hideBackdrop=function(){B.length&&f&&(f=!1,B.removeClass("active").css("display","none"))},s.showBackdrop=function(){B.length&&!f&&(f=!0,B.css("display","block").addClass("active"))},s.filterItems=function(t){var n,r;t.length?(s.expression?n=e.bind(this,s.expression,t):e.isArray(s.filterProperties)?(n={},e.forEach(s.filterProperties,function(e){n[e]=t})):s.filterProperties?(n={},n[s.filterProperties]=t):n=t,r=s.filter(s.items,n,s.comparator)):r=s.items,a(function(){s.update(r,t),s.scrollItemsTop()})},s.$deregisterBackButton=l.registerBackButtonAction(function(){a(s.cancelFilterBar)},300),s.removeFilterBar=function(n){s.removed||(s.removed=!0,t.requestAnimationFrame(function(){g.removeClass("filter-bar-in"),F(),s.hideBackdrop(),a(function(){s.scrollItemsTop(),s.update(s.items),s.$destroy(),h.remove(),s.cancelFilterBar.$scope=y=k=g=B=v=null,p=!1,(n||e.noop)()},350)}),a(function(){s.container.removeClass("filter-bar-open")},400),s.$deregisterBackButton(),w(),y&&y.off("scroll",x))},s.showFilterBar=function(n){s.removed||(s.container.append(h).addClass("filter-bar-open"),s.scrollItemsTop(),t.requestAnimationFrame(function(){s.removed||a(function(){g.addClass("filter-bar-in"),s.focusInput(),s.showBackdrop(),(n||e.noop)()},20,!1)}),y&&y.on("scroll",x))},s.cancelFilterBar=function(){s.removeFilterBar(s.cancel)},s.showFilterBar(s.done),s.cancelFilterBar.$scope=s,s.cancelFilterBar}}var p=!1,b=e.element(r[0].body),m={theme:s.theme(),transition:s.transition(),back:f.backButton.icon(),clear:s.clear(),search:s.search(),backdrop:s.backdrop(),placeholder:s.placeholder()};return{show:d}}])}(angular,ionic); \ No newline at end of file +angular.module("jett.ionic.filter.bar",["ionic"]),function(e){"use strict";e.module("jett.ionic.filter.bar").directive("ionFilterBar",["$document","$timeout","$ionicGesture","$ionicPlatform",function(t,n,r,i){var o;return o=i.is("android")?'
':'
',{restrict:"E",scope:!0,link:function(i,o){var a,c,l,s,f,u=e.element(o[0].querySelector(".filter-bar-clear")),d=e.element(o[0].querySelector(".filter-bar-cancel")),p=o.find("input");i.filterText="";var b=function(){i.cancelFilterBar()};d.bind("click",b),i.config.backdrop&&(l=e.element('
'),o.append(l),s=function(e){e.target==l[0]&&b()},l.bind("click",s),c=r.on("swipe",s,l));var m=function(){"none"===u.css("display")&&u.css("display","block")},h=function(){"block"===u.css("display")&&u.css("display","none")},g=function(){n(function(){i.filterText="",h(),ionic.requestAnimationFrame(function(){i.showBackdrop(),i.scrollItemsTop(),i.focusInput()})})};u.bind("touchstart mousedown",g),p.bind("touchstart mousedown",function(){i.scrollItemsTop(),i.focusInput()});var v=function(e){27==e.which?b():i.filterText&&i.filterText.length?(m(),i.hideBackdrop()):(h(),i.showBackdrop())};t.bind("keyup",v);var B=function(){i.filterItems(i.filterText)};i.$on("$destroy",function(){o.remove(),t.unbind("keyup",v),l&&r.off(c,"swipe",s),f()}),f=i.$watch("filterText",function(e,t){var r;a&&n.cancel(a),e!==t&&(r=e.length&&i.debounce?i.delay:0,a=n(B,r,!1))})},template:o}}])}(angular),function(e){"use strict";e.module("jett.ionic.filter.bar").provider("$ionicFilterBarConfig",function(){function t(e,t){c.platform[e]=t,o.platform[e]={},n(c,c.platform[e]),r(c.platform[e],o.platform[e],"")}function n(t,r){for(var i in t)i!=a&&t.hasOwnProperty(i)&&(e.isObject(t[i])?(e.isDefined(r[i])||(r[i]={}),n(t[i],r[i])):e.isDefined(r[i])||(r[i]=null))}function r(t,n,o){e.forEach(t,function(l,s){e.isObject(t[s])?(n[s]={},r(t[s],n[s],o+"."+s)):n[s]=function(e){if(arguments.length)return t[s]=e,n;if(t[s]==a){var r=i(c.platform,ionic.Platform.platform()+o+"."+s);return r||r===!1?r:i(c.platform,"default"+o+"."+s)}return t[s]}})}function i(t,n){n=n.split(".");for(var r=0;r')(s),g=h.children().eq(0),v=g.find("input")[0],B=h.children().eq(1),k=s.scrollDelegate.getScrollView(),$=!!k,y=$?e.element(k.__container):null,w=s.cancelOnStateChange?i.$on("$stateChangeSuccess",function(){s.cancelFilterBar()}):e.noop,T=function(){d||(d=!0,v&&v.focus())},F=function(){d&&(d=!1,v&&v.blur())},x=function(){k.__scrollTop>0&&F()};return s.scrollItemsTop=function(){$&&s.scrollDelegate.scrollTop&&s.scrollDelegate.scrollTop()},s.focusInput=function(){d=!1,T()},s.hideBackdrop=function(){B.length&&f&&(f=!1,B.removeClass("active").css("display","none"))},s.showBackdrop=function(){B.length&&!f&&(f=!0,B.css("display","block").addClass("active"))},s.filterItems=function(t){var n,r;t.length?(s.expression?n=e.bind(this,s.expression,t):e.isArray(s.filterProperties)?(n={},e.forEach(s.filterProperties,function(e){n[e]=t})):s.filterProperties?(n={},n[s.filterProperties]=t):n=t,r=s.filter(s.items,n,s.comparator)):r=s.items,a(function(){s.update(r,t),s.scrollItemsTop()})},s.$deregisterBackButton=l.registerBackButtonAction(function(){a(s.cancelFilterBar)},300),s.removeFilterBar=function(n){s.removed||(s.removed=!0,t.requestAnimationFrame(function(){g.removeClass("filter-bar-in"),F(),s.hideBackdrop(),a(function(){s.scrollItemsTop(),s.update(s.items),s.$destroy(),h.remove(),s.cancelFilterBar.$scope=y=k=g=B=v=null,p=!1,(n||e.noop)()},350)}),a(function(){s.container.removeClass("filter-bar-open")},400),s.$deregisterBackButton(),w(),y&&y.off("scroll",x))},s.showFilterBar=function(n){s.removed||(s.container.append(h).addClass("filter-bar-open"),s.scrollItemsTop(),t.requestAnimationFrame(function(){s.removed||a(function(){g.addClass("filter-bar-in"),s.focusInput(),s.showBackdrop(),(n||e.noop)()},20,!1)}),y&&y.on("scroll",x))},s.cancelFilterBar=function(){s.removeFilterBar(s.cancel)},s.showFilterBar(s.done),s.cancelFilterBar.$scope=s,s.cancelFilterBar}}var p=!1,b=e.element(r[0].body),m={theme:s.theme(),transition:s.transition(),back:f.backButton.icon(),clear:s.clear(),search:s.search(),backdrop:s.backdrop(),placeholder:s.placeholder()};return{show:d}}])}(angular,ionic); \ No newline at end of file diff --git a/js/ionic.filter.bar.service.js b/js/ionic.filter.bar.service.js index 3aa33ad..102aaba 100644 --- a/js/ionic.filter.bar.service.js +++ b/js/ionic.filter.bar.service.js @@ -76,6 +76,10 @@ opts.container = angular.element($body[0].querySelector(opts.container)); } + //extend templateConfig with supplied config options + angular.extend(templateConfig, opts.config); + delete opts.config; + //extend scope defaults with supplied options angular.extend(scope, { config: templateConfig, diff --git a/test/unit/ionic.filter.bar.service.unit.js b/test/unit/ionic.filter.bar.service.unit.js index 7dd7b86..c5e52e7 100644 --- a/test/unit/ionic.filter.bar.service.unit.js +++ b/test/unit/ionic.filter.bar.service.unit.js @@ -191,6 +191,26 @@ describe('Ionic FilterBar Service', function() { expect(scope.delay).toBe(0); expect(scope.cancelText).toBe('Done'); })); + + it('should override provider custom options with supplied on show call', inject(function() { + var scope = setup({ + config: { + theme: 'dark', + transition: 'vertical', + clear: 'ion-close-other', + search: 'ion-search-other', + backdrop: true, + placeholder: 'Other Filter' + } + }); + + expect(scope.config.theme).toBe('dark'); + expect(scope.config.transition).toBe('vertical'); + expect(scope.config.clear).toBe('ion-close-other'); + expect(scope.config.search).toBe('ion-search-other'); + expect(scope.config.backdrop).toBe(true); + expect(scope.config.placeholder).toBe('Other Filter'); + })); }); });