mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
This change makes the DelegateService available on the ionic namespace. It is useful so external directives can follow the delegate pattern set by the framework itself.
103 lines
3.7 KiB
JavaScript
103 lines
3.7 KiB
JavaScript
(function (ionic) {
|
|
|
|
ionic.DelegateService = function(methodNames) {
|
|
|
|
if (methodNames.indexOf('$getByHandle') > -1) {
|
|
throw new Error("Method '$getByHandle' is implicitly added to each delegate service. Do not list it as a method.");
|
|
}
|
|
|
|
function trueFn() { return true; }
|
|
|
|
return ['$log', function($log) {
|
|
|
|
/*
|
|
* Creates a new object that will have all the methodNames given,
|
|
* and call them on the given the controller instance matching given
|
|
* handle.
|
|
* The reason we don't just let $getByHandle return the controller instance
|
|
* itself is that the controller instance might not exist yet.
|
|
*
|
|
* We want people to be able to do
|
|
* `var instance = $ionicScrollDelegate.$getByHandle('foo')` on controller
|
|
* instantiation, but on controller instantiation a child directive
|
|
* may not have been compiled yet!
|
|
*
|
|
* So this is our way of solving this problem: we create an object
|
|
* that will only try to fetch the controller with given handle
|
|
* once the methods are actually called.
|
|
*/
|
|
function DelegateInstance(instances, handle) {
|
|
this._instances = instances;
|
|
this.handle = handle;
|
|
}
|
|
methodNames.forEach(function(methodName) {
|
|
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 foundInstancesCount = 0;
|
|
var returnValue;
|
|
|
|
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 (foundInstancesCount === 1) {
|
|
returnValue = ret;
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!foundInstancesCount && handle) {
|
|
return $log.warn(
|
|
'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="' + 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 returnValue;
|
|
};
|
|
}
|
|
|
|
}];
|
|
};
|
|
|
|
})(window.ionic);
|