(function() {
'use strict';
angular.module('ml.search')
.service('MLRemoteInputService', MLRemoteInputService);
MLRemoteInputService.$inject = ['$injector'];
/**
* @class MLRemoteInputService
* @classdesc angular service for working with {@link ml-remote-input}
*
* @param {Object} $injector - angular dependency resolution service
*/
function MLRemoteInputService($injector) {
var service = this,
$route = null;
this.routeAvailable = true;
try {
$route = $injector.get('$route');
} catch (ex) {
this.routeAvailable = false;
}
service.input = '';
service.mlSearch = null;
service.callbacks = [];
function unsubscribe(idx) {
service.callbacks.splice(idx);
}
/**
* sets the service.input instance property and invokes the registered callbacks
* @method MLRemoteInputService#setInput
*
* @param {string} input
*/
service.setInput = function setInput(input) {
service.input = input;
// TODO: Object.observe service.input?
_.each(service.callbacks, function(callback) {
callback(service.input);
});
};
/**
* registers a callback, returning a de-registration function
* @method MLRemoteInputService#subscribe
*
* @param {function} callback - a callback to be invoked when `this.input` is changed
* @return {function} callback de-registration function
*/
service.subscribe = function subscribe(callback) {
var idx = service.callbacks.length;
service.callbacks.push(callback);
return function() {
unsubscribe(idx);
};
};
/**
* helper function for mlRemoteInput directive
* registers and de-registers a callback that
* - updates the $scope parameter
* - updates the mlSearch parameter with the mlSearch instance property
* (if it exists)
* @method MLRemoteInputService#initInput
*
* @param {object} $scope - search controller scope
* @param {MLSearchContext} mlSearch - controller mlSearch instance
*/
service.initInput = function initInput($scope, mlSearch) {
var unsubscribe = service.subscribe(function(input) {
$scope.qtext = input;
mlSearch = service.mlSearch || mlSearch;
});
$scope.$on('destroy', unsubscribe);
};
/**
* helper function for Search controller
*
* - registers and de-registers a callback that
* - updates the qtext property of the model parameter
* - invokes the searchCallback
* - sets the mlSearch instance property
* - initializes the qtext property of the model parameter
* (unless it's already set and the instance input property is not)
*
* @method MLRemoteInputService#initCtrl
* @deprecated
*
* @param {object} $scope - search controller scope
* @param {object} model - search controller model
* @param {MLSearchContext} mlSearch - controller mlSearch instance
* @param {function} searchCallback - search callback function
*/
service.initCtrl = function initCtrl($scope, model, mlSearch, searchCallback) {
var unsubscribe = service.subscribe(function(input) {
if (model.qtext !== input) {
model.qtext = input;
searchCallback();
}
});
$scope.$on('$destroy', unsubscribe);
service.mlSearch = mlSearch;
if ( model.qtext.length && !service.input.length ) {
service.setInput( model.qtext );
} else {
model.qtext = service.input;
}
};
/**
* gets the path for a specified controller from the `$route` service (if available)
* @method MLRemoteInputService#getPath
*
* @param {string} searchCtrl - search controller name
* @return {?string} search controller path
*/
service.getPath = function getPath(searchCtrl) {
var route = { originalPath: '/' },
matches = null;
if ($route === null) {
return null;
}
matches = _.where($route.routes, { controller: searchCtrl });
if ( matches.length === 0 ) {
// TODO: get route from attr, or throw Error('can\t find Search controller') ?
console.error('can\'t find Search controller: ' + searchCtrl);
} else {
route = matches[0];
if ( matches.length > 1 ) {
console.log('multiple Search controller routes; choosing \'' +
route.originalPath + '\'');
}
}
return route.originalPath;
};
}
}());