diff --git a/js/angular/service/delegateService.js b/js/angular/service/delegateService.js index ff61d2c31d..f79ead9f71 100644 --- a/js/angular/service/delegateService.js +++ b/js/angular/service/delegateService.js @@ -7,28 +7,6 @@ function delegateService(methodNames) { function trueFn() { return true; } return ['$log', function($log) { - var delegate = this; - - var instances = this._instances = []; - this._registerInstance = function(instance, handle, filterFn) { - instance.$$delegateHandle = handle; - instance.$$filterFn = filterFn || trueFn; - instances.push(instance); - - return function deregister() { - var index = instances.indexOf(instance); - if (index !== -1) { - instances.splice(index, 1); - } - }; - }; - - this.$getByHandle = function(handle) { - if (!handle) { - return delegate; - } - return new InstanceForHandle(handle); - }; /* * Creates a new object that will have all the methodNames given, @@ -46,67 +24,75 @@ function delegateService(methodNames) { * that will only try to fetch the controller with given handle * once the methods are actually called. */ - function InstanceForHandle(handle) { + function DelegateInstance(instances, handle) { + this._instances = instances; this.handle = handle; } - methodNames.forEach(function(methodName) { - InstanceForHandle.prototype[methodName] = function() { + DelegateInstance.prototype[methodName] = instanceMethodCaller(methodName); + }); + + + /** + * The delegate service (eg $ionicNavBarDelegate) is just an instance + * with a non-defined handle, a couple extra methods for registering + * and narrowing down to a specific handle. + */ + function DelegateService() { + this._instances = []; + } + DelegateService.prototype = DelegateInstance.prototype; + DelegateService.prototype._registerInstance = function(instance, handle, filterFn) { + var instances = this._instances; + instance.$$delegateHandle = handle; + instance.$$filterFn = filterFn || trueFn; + instances.push(instance); + + return function deregister() { + var index = instances.indexOf(instance); + if (index !== -1) { + instances.splice(index, 1); + } + }; + }; + DelegateService.prototype.$getByHandle = function(handle) { + return new DelegateInstance(this._instances, handle); + }; + + return new DelegateService(); + + function instanceMethodCaller(methodName) { + return function caller() { var handle = this.handle; var args = arguments; - var matchingInstancesFound = 0; - var finalResult; - var result; + var foundInstancesCount = 0; + var returnValue; - //This logic is repeated below; we could factor some of it out to a function - //but don't because it lets this method be more performant (one loop versus 2) - instances.forEach(function(instance) { - if (instance.$$delegateHandle === handle && instance.$$filterFn(instance)) { - matchingInstancesFound++; - result = instance[methodName].apply(instance, args); + this._instances.forEach(function(instance) { + if ((!handle || handle == instance.$$delegateHandle) && instance.$$filterFn(instance)) { + foundInstancesCount++; + var ret = instance[methodName].apply(instance, args); //Only return the value from the first call - if (matchingInstancesFound === 1) { - finalResult = result; + if (foundInstancesCount === 1) { + returnValue = ret; } } }); - if (!matchingInstancesFound) { + if (!foundInstancesCount && handle) { return $log.warn( - 'Delegate for handle "' + this.handle + '" could not find a ' + - 'corresponding element with delegate-handle="' + this.handle + '"! ' + + 'Delegate for handle "' + handle + '" could not find a ' + + 'corresponding element with delegate-handle="' + handle + '"! ' + methodName + '() was not called!\n' + 'Possible cause: If you are calling ' + methodName + '() immediately, and ' + - 'your element with delegate-handle="' + this.handle + '" is a child of your ' + + 'your element with delegate-handle="' + handle + '" is a child of your ' + 'controller, then your element may not be compiled yet. Put a $timeout ' + 'around your call to ' + methodName + '() and try again.' ); } - - return finalResult; + return returnValue; }; + } - delegate[methodName] = function() { - var args = arguments; - var matchingInstancesFound = 0; - var finalResult; - var result; - - //This logic is repeated above - instances.forEach(function(instance, index) { - if (instance.$$filterFn(instance)) { - matchingInstancesFound++; - result = instance[methodName].apply(instance, args); - //Only return the value from the first call - if (matchingInstancesFound === 1) { - finalResult = result; - } - } - }); - - return finalResult; - }; - - }); }]; } diff --git a/test/unit/angular/service/delegateService.unit.js b/test/unit/angular/service/delegateService.unit.js index 1061d3a552..6983364986 100644 --- a/test/unit/angular/service/delegateService.unit.js +++ b/test/unit/angular/service/delegateService.unit.js @@ -125,11 +125,6 @@ describe('DelegateFactory', function() { expect(delegate.fn()).toBe('ret1'); }); - it('$getByHandle should return this for blank handle', function() { - var delegate = setup(); - expect(delegate.$getByHandle()).toBe(delegate); - }); - describe('$getByHandle', function() { var delegate, instance1, instance2, instance3; beforeEach(function() {