Source: temp/jsdocinputdirs/cercalia.service.autocomplete.js

/**
 * @classdesc
 *
 * This class lets you convert a `<input type="text">` HTML element, into a suggest address search.
 *
 *
 * @constructor
 * @param {cercaliax.service.AutocompleteOptions} options
 */
cercalia.service.Autocomplete = function(options) {

	/**
	 * @private
	 * @type {string}
	 */
	this.cercaliaKey_ = cercaliaGlobals.key;	//Esta variable siempre se pasara al descargar la API

	/**
	 * @constant
	 * @private
	 * @type {string}
	 */
	this.URL_SERVLET_SOLR = servers.solr;

	/**
	 * @constant
	 * @private
	 * @type {string}
	 */
	this.server_ = servers.servlet;

	/**
	 * @private
	 * @type {string}
	 */
	this.responseType_ = "json";

	/**
	 * @private
	 * @type {inputId}
	 */
	this.inputId_ = options.inputId ? options.inputId : null;

	/**
	 * @private
	 * @type {Object}
	 */
	this.jqElement_ = cercalia.jQuery('#' + this.inputId_);

	/**
	 * @private
	 * @type {Object}
	 */
	this.jqListResponse_ = null;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchInsideCountry_ = options.searchInsideCountry ? options.searchInsideCountry : undefined ;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchInsideRegion_ = options.searchInsideRegion ? options.searchInsideRegion : undefined ;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchInsideProvince_ = options.searchInsideProvince ? options.searchInsideProvince : undefined ;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchInsideMunicipality_ = options.searchInsideMunicipality ? options.searchInsideMunicipality : undefined ;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchInsideLocality_ = options.searchInsideLocality ? options.searchInsideLocality : undefined ;

	/**
	 * @private
	 * @type {boolean}
	 */
	this.searchClosestHouseNumber_ = options.searchClosestHouseNumber ? options.searchClosestHouseNumber : false;

	/**
	 * @private
	 * @type {string}
	 */
	this.searchFilterEntity_ = options.searchFilterEntity ? options.searchFilterEntity : undefined;

	/**
	 * @private
	 * @type {string|Array.<string>}
	 */
	this.searchPriorityEntity_ = options.searchPriorityEntity ? options.searchPriorityEntity : undefined;

	/**
	 * @private
	 * @type {string|Array.<string>}
	 */
	this.searchPreferredEntity_ = options.searchPreferredEntity ? options.searchPreferredEntity : undefined;

	/**
	 * @private
	 * @type {boolean|undefined}
	 */
	this.hnrt_ = options.hnrt ? options.hnrt : false;

	/**
	 * @private
	 * @type {Function}
	 */
	this.callbackfunction_ = options.callbackfunction ? options.callbackfunction : (options.callbackFunction ? options.callbackFunction : null);

	/**
	 * @private
	 * @type {Function|undefined}
	 */
	this.onInputFunction_ = options.onInputFunction ? options.onInputFunction : false;

	/**
	 * @private
	 * @type {Object}
	 */
	this.response_ = null;

	/**
	 * @private
	 * @type {Array<string>}
	 */
	this.arrAutocompleteClasses_ = [];


	/**
	 * Class name
	 * @private
	 * @type {string}
	 */
	this.CLASS_NAME_ = "cercalia.service.Autocomplete";

	this.initialize_();
};


/**
 * Assign a callback function after selecting a candidate from the suggest list
 * @param {Function} callbackfunction
 */
cercalia.service.Autocomplete.prototype.setCallbackfunction = function(callbackfunction){
	if(typeof(callbackfunction)=="function"){
		this.callbackfunction_ = callbackfunction;
	} else {
		alert('El parámetro no es una Funcion callback!');
	}
};


/**
 * @return {Object} Return a JSON object with the last information.
 */
cercalia.service.Autocomplete.prototype.getGeocoding = function() {
	return this.response_;
};


/**
 * Search inside a country. For example: `'ESP,FRA,GBR'` or `['ESP','FRA','GBR']`
 * @param {string|Array.<string>|null} countriesId
 */
cercalia.service.Autocomplete.prototype.setSearchInsideCountry = function(countriesId) {
	if(countriesId instanceof Array) {
		countriesId = countriesId.join(",");
	}
	this.searchInsideCountry_ = countriesId ? countriesId.replace(/ +(?= )/g,'') : undefined;
};


/**
 * Search inside a region. For example: `ESPMAD` (Comunidad de Madrid), `ESPCAT` (Catalunya), etc..
 * @param {string|Array.<string>|null} regionsId
 */
cercalia.service.Autocomplete.prototype.setSearchInsideRegion = function(regionsId) {
	if(regionsId instanceof Array) {
		regionsId = regionsId.join(",");
	}
	this.searchInsideRegion_ = regionsId!=null ? regionsId.replace(/ +(?= )/g,'') : undefined;
};

/**
 * Search inside a region. For example: `ESP17` (Girona), `ESP08` (Barcelona) etc..
 * @param {string|Array.<string>|null} provinceId
 */
cercalia.service.Autocomplete.prototype.setSearchInsideProvince = function(provinceId) {
	if(provinceId instanceof Array) {
		provinceId = provinceId.join(",");
	}
	this.searchInsideProvince_ = provinceId != null ? provinceId.replace(/ +(?= )/g,'') : undefined;
};

/**
 * Search inside a municipality. For example: `ESP280796` (Madrid), `ESP080193` (Barcelona), etc..
 * @param {string|Array.<string>|null} municipalityId
 */
cercalia.service.Autocomplete.prototype.setSearchInsideMunicipality = function(municipalityId) {
	if(municipalityId instanceof Array) {
		municipalityId = municipalityId.join(",");
	}
	this.searchInsideMunicipality_ = municipalityId!=null ? municipalityId.replace(/ +(?= )/g,'') : undefined;
};

/**
 * Search inside a locality. For example: `ESP17240205544993` (Vallecas), `ESP17240205545872` (La Barceloneta), etc..
 * @param {string|Array.<string>|null} localityId
 */
cercalia.service.Autocomplete.prototype.setSearchInsideLocality = function(localityId) {
	if(localityId instanceof Array) {
		localityId = localityId.join(",");
	}
	this.searchInsideLocality_ = localityId != null ? localityId.replace(/ +(?= )/g,'') : undefined;
};


/**
 * Set filter by municipality / region / subregion (by entity code). You can mix that entities.
 * Parameter examples: <br/>
 * `ESP170792,ESPCAT,ES08` or * `[ESP170792, ESPCAT, ES08`]<br/>
 * `ESP,ESP08,ESP17,PRT,AND`.<br/>
 */
cercalia.service.Autocomplete.prototype.setSearchFilterEntity = function(entityId) {
	if(entityId instanceof Array) {
		entityId = entityId.join(",");
	}
	this.searchFilterEntity_ = entityId != null ? entityId.replace(/ +(?= )/g,'') : undefined;
};


/**
 * Set preferred municipality / region / subregion (by entity code). This filter, prioritizes the results that are in the
 * specified regions above the other candidates, but does not eliminate the results from other regions or countries.
 * This filter can be combined with the `rsc` filter for maximum results filter beyond the preferred. Example: `ESPVAL`.
 * In case you need to prioritize candidates in the list of preferred regions, the regions may be separated
 * by parameters according to priority level: first element: maximum priority, second element: second level priority, etc <br/>
 * Parameter examples: <br/>
 *	`['ESP170792', 'AND', 'ESP,FRA']`.<br/>
 *	`['ESPCAT', 'ESPMAD', 'PRT,AND,FRA']`.<br/>
 * @param {string|Array.<string>|null} entities Entities.
 */
cercalia.service.Autocomplete.prototype.setSearchPriorityEntity = function(entities) {
	this.searchPriorityEntity_ = entities;
};

/**
 * Set preferred municipality / region / subregion / country (by entity code). Not compatible with "searchPriorityEntity". This filter,
 * use a soft prioritizaton of the results that are in the specified regions above the other candidates, but does not eliminate the results
 * from other regions or countries. This filter can be combined with the `rsc` filter for maximum results filter beyond the preferred.
 * Example: `ESPVAL`. In case you need to prioritize candidates in the list of preferred regions, the regions may be separated by parameters
 * according to priority level: first element: maximum priority, second element: second level priority, etc.
 *	`['ESP170792', 'AND', 'ESP,FRA']`.<br/>
 *	`['ESPCAT', 'ESPMAD', 'PRT,AND,FRA']`.<br/>
 * @param {string|Array.<string>|null} entities Entities.
 */
cercalia.service.Autocomplete.prototype.setSearchPreferredEntity = function(entities) {
	this.searchPreferredEntity_ = entities;
};

/**
 * Search within type specified. Possible values are: `st` (streets), `ct` (locality), `p` (pois), `all|null`. It is possible specify more than one value. Example : `st,ct`
 * @param {string|Array.<string>|null} type
 */
cercalia.service.Autocomplete.prototype.setSearchFilterType = function(type) {
	if(type instanceof Array) {
		type = type.join(",");
	}
	this.searchFiltertype_ = type!=null ? type.replace(/ +(?= )/g,'') : undefined;
};



/**
 * Initializes the element
 * @private
 */
cercalia.service.Autocomplete.prototype.initialize_ = function() {

	var self = this;

	if( ! this.inputId_ ){
		alert('No inputId specified');
	}

	var listId = 'suggest_response_list_' + this.inputId_;

	this.jqListResponse_ = cercalia.jQuery('<div />')
		.attr('id',listId)
		.appendTo("body");

	this.jqElement_.autocomplete({
		appendTo: "#" + listId,
		source: function( request, response ) {
			self.querySolr_(request, response, "AND", 0);
		},
		minLength: 3,
		select: function( event, ui ) {
			var params = {
					key: self.cercaliaKey_,
					cmd: 'autocompletegeocoding',
					response_type: self.responseType_,
					is_poi: ui.item.categoria_id!=null,
					street_id: ui.item.calle_id,
					city_id: ui.item.localidad_id,
					municipality_id: ui.item.municipio_id,
					street_num: ui.item.portal
			};


			cercalia.jQuery.ajax({
				url: self.server_,
				data: params,
				type: 'POST',
				method: "POST",
				dataType: cercalia.Util.isIEUnderTen() ? "jsonp" : "json",
				//contentType: 'application/json; charset=utf-8',
				async:true,
				crossDomain: true,
				timeout: 5000,
				success: function(data){

					if( !ui.item.categoria_id ){ //city or street

						if(data.cercalia.candidates.candidate.length>1 && ui.item.portal) {
							//buscamos el portal más cercano pasado por parámetro si hay más de un candidato.
							self.response_ = self.searchClosestPortal_(data.cercalia.candidates.candidate, ui.item.portal);
						} else {
							self.response_ = data.cercalia.candidates.candidate[0].ge;
						}

						if( ! ui.item.intersection ) { //normal street (no intersection)
							var candidates = data.cercalia.candidates;
							if(candidates.urlcandidates!=null && candidates.urlcandidates.param!=null) {
								self.response_.param = candidates.urlcandidates.param;
								if(ui.item.portal && candidates.urlcommon && candidates.urlcommon.param && candidates.urlcommon.param.name && candidates.urlcommon.param.name == "stnum") {
									self.response_.param[self.response_.param.length] = candidates.urlcommon.param;
								}
							}
						} else { //has intersection
							var coord;
							if( (!ui.item.intersection.portal && !ui.item.portal) || (ui.item.intersection.portal && !ui.item.portal) ){ //si se cumple evitamos utilizar los valors de la geocodificacion
								coord = ui.item.intersection.coord.split(",");
								self.response_.coord.x = coord[1];
								self.response_.coord.y = coord[0];
							}
						}

					} else {
						//type POI (has category)
						var coord = ui.item.coord.split(",");
						var candidates = data.cercalia.candidates;
						self.response_ = candidates.candidate[0].ge;
						self.response_.type = 'p';
						self.response_.category_id = ui.item.categoria_id;
						self.response_.coord.x = coord[1];
						self.response_.coord.y = coord[0];
						self.response_.name.value =  ui.item.calle_descripcion;
					}

					self.response_.formatted_address = ui.item.label;

					if(self.callbackfunction_){
						self.callbackfunction_(self.response_);
					} else {
						console.error("No callbackfunction defined");
					}

				},
				error: cercalia.AJAXException
			});

		},
		open: function(event,ui) {
			//Afegim la classe segons el tipus que sigui (localitat|carrer|poi)
			for(var i = 0; i < self.arrAutocompleteClasses_.length; i++){
				self.jqListResponse_.find('.ui-autocomplete li a span').get(i).className += " " + self.arrAutocompleteClasses_[i];
			}

			//cercalia.jQuery(this).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
			self.jqListResponse_.find('ul').css('width','auto');
		},
		close: function() {
			//cercalia.jQuery(this).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
		}
	}).data("ui-autocomplete")._renderItem = function (ul, item) {
        var li = cercalia.jQuery("<li>").addClass('cercalia-suggest-item').attr( "data-value", item.value ).appendTo( ul );
        cercalia.jQuery("<a>").append(cercalia.jQuery("<span>")).append(item.label).appendTo(li);
        return li;
    };


	if(this.onInputFunction_) {
		this.jqElement_.on('input', this.onInputFunction_);
	}

};

/**
 * Close autocomplete div.
 */
cercalia.service.Autocomplete.prototype.close = function () {
	this.jqElement_.autocomplete("close");
};


/**
 * @private
 * @param {Object} candidates
 * @param {number} portal
 * @return {Object} ge
 */
cercalia.service.Autocomplete.prototype.searchClosestPortal_ = function(geList, portal) {

	var minHouseNumberDistance = 999999;
	var geMinDistance = null;
	for(var i = 0 ; i<geList.length; i++){
		var ge = geList[i].ge;
		if(ge.housenumber){
			var houseNumberDistanceAct = Math.abs(portal - ge.housenumber.value)
			if( houseNumberDistanceAct < minHouseNumberDistance ){
				geMinDistance = ge;
				minHouseNumberDistance = houseNumberDistanceAct;
			}
		}
	}
	return geMinDistance;
};



/**
 * @private
 * @param {string} request
 * @param {string} response
 * @param {string} operand
 * @param {string} attempt
 */
cercalia.service.Autocomplete.prototype.querySolr_ = function(request, response, operand, attempt){

	if(typeof attempt !== "undefined" && attempt > 1){
		return;//no iterar más
	} else {

		var textToSearch = request.term.trim();
		var self = this;
		var dataObj = {
				't' : textToSearch,
				'key' : self.cercaliaKey_
		};

		if (this.searchFiltertype_) dataObj.getype = this.searchFiltertype_;//ct,st,all,p
		if (this.searchInsideCountry_) dataObj.ctryc = this.searchInsideCountry_;
		if (this.searchInsideProvince_) dataObj.subregc = this.searchInsideProvince_;
		if (this.searchInsideRegion_) dataObj.regc = this.searchInsideRegion_;
		if (this.searchInsideMunicipality_) dataObj.munc = this.searchInsideMunicipality_;
		if (this.searchInsideLocality_) dataObj.ctc = this.searchInsideLocality_;
		if (this.hnrt_) dataObj.hnrt = 1;
		if (this.searchFilterEntity_) dataObj.rsc = this.searchFilterEntity_;
		if (this.searchPriorityEntity_) {
			if (!Array.isArray(this.searchPriorityEntity_)) {
				dataObj.rscp = this.searchPriorityEntity_;
			} else {
				for(var i = 0 ; i < this.searchPriorityEntity_.length; i++) {
					dataObj['rscp' + (i + 1)] = this.searchPriorityEntity_[i];
				}
			}
		}
		if (this.searchPreferredEntity_) {
			if (!Array.isArray(this.searchPreferredEntity_)) {
				dataObj.rsclp = this.searchPreferredEntity_;
			} else {
				for(var i = 0; i < this.searchPreferredEntity_.length; i++) {
					dataObj['rsclp' + (i + 1)] = this.searchPreferredEntity_[i];
				}
			}
		}

		cercalia.jQuery.ajax({
			url: self.URL_SERVLET_SOLR,
			dataType: cercalia.Util.isIEUnderTen() ? "jsonp" : "json",
			crossDomain: true,
			jsonp: 'json.wrf',
			data: dataObj,
			success: function( data ) {
				if(data.response.docs.length > 0 ){

					self.arrAutocompleteClasses_ = [];

					response(
						cercalia.jQuery.map( data.response.docs, function(item , numElem) {
							var localidad_norm = null;
							var provincia_norm = null;
							/* Funcionava aixi fins 20170227
							var localidad_norm;
							if(item.localidad_nombre!=null){
								localidad_norm = item.localidad_nombre!=null && item.localidad_nombre==item.municipio_nombre?item.localidad_nombre:item.localidad_nombre + ", " + item.municipio_nombre;
							} else {
								localidad_norm = item.municipio_nombre;
							}

							var provincia_norm = null;

							if(item.provincia_nombre!=null) {
								provincia_norm = item.provincia_nombre==item.comunidad_nombre?item.provincia_nombre:item.provincia_nombre + (item.comunidad_nombre!=null?", " + item.comunidad_nombre:"");
							} else if( item.comunidad_nombre!=null ) {
								provincia_norm = item.comunidad_nombre;
							}*/

							//Apliquem mateix comportament que api nova.
			        //20170227 => Eliminar el municipi, si hi ha localitat. Si només retorna municipi, ho mantenim
			        if (item.localidad_nombre) {
			          localidad_norm = item.localidad_nombre;
			        } else {
			          localidad_norm = item.municipio_nombre;
			        }

			        //20170227 => Eliminar el municipi, si hi ha localitat. Si només retorna municipi, ho mantenim
			        if (['ESP', 'GBR', 'NZL'].indexOf(item.pais_id) !== -1) {
			          provincia_norm = item.provincia_nombre;
			        } else {
			          //20170227 => Per la resta del món: eliminem la província si tenim CCAA. Si no tenim CCAA, mostrem la provincia
			          if (item.comunidad_nombre && item.provincia_nombre) {
			            provincia_norm = item.comunidad_nombre;
			          } else if (item.comunidad_nombre && !item.provincia_nombre) {
			            provincia_norm = item.comunidad_nombre;
			          } else {
			            provincia_norm = item.provincia_nombre;
			          }
			        }

							//Si hay codigo_postal...
							if (item.codigo_postal) {
								localidad_norm = item.codigo_postal + ' ' + localidad_norm;
							}

							if( item.categoria_id ){ //POI
								self.arrAutocompleteClasses_.push('cercalia-suggest poi-' + item.categoria_id.toUpperCase() );

								var obj = {
									label: item.calle_descripcion +", " + localidad_norm + ", " + (provincia_norm!=null? provincia_norm + ", " : "") + item.pais_nombre,
									calle_id: item.calle_id,
									calle_descripcion: item.calle_descripcion,
									localidad_id: item.localidad_id,
									localidad_nombre: item.localidad_nombre,
									municipio_id: item.municipio_id,
									municipio_nombre: item.municipio_nombre,
									provincia_id: item.provincia_id,
									provincia_nombre: item.provincia_nombre,
									comunidad_id: item.comunidad_id,
									comunidad_nombre: item.comunidad_nombre,
									pais_id: item.pais_id,
									pais_nombre: item.pais_nombre,
									coord: item.coord,
									categoria_id: item.categoria_id
								};

								return obj;

							} else if( typeof(item.calle_id) == "undefined" ){ 	//Localidad
								self.arrAutocompleteClasses_.push('cercalia-suggest locality');

								return {
									label: localidad_norm + ", " + (provincia_norm!=null? provincia_norm + ", " : "") + item.pais_nombre,
									localidad_id: item.localidad_id,
									localidad_nombre: item.localidad_nombre,
									municipio_id: item.municipio_id,
									municipio_nombre: item.municipio_nombre,
									provincia_id: item.provincia_id,
									provincia_nombre: item.provincia_nombre,
									comunidad_id: item.comunidad_id,
									comunidad_nombre: item.comunidad_nombre,
									pais_id: item.pais_id,
									pais_nombre: item.pais_nombre,
									coord: item.coord
								};

							} else { //Carrer
								self.arrAutocompleteClasses_.push('cercalia-suggest address');

								var label;
								var portal = self.searchClosestHouseNumber_ ? item.portal_disponible : item.portal;

								//Paises que tienen el número de portal antes del nombre de la calle.
								if( ["ARE","AUS","CAN","EGY","GBR","IND","IRL", "ISR", "KWT","NZL","OMN","QAT","SAU","THA","USA","ZAF"].indexOf(item.pais_id)!=-1 ){
									label = (portal!=null?portal + " ":"") + item.calle_descripcion  +", " + localidad_norm + ", " + (provincia_norm!=null? provincia_norm + ", " : "") + item.pais_nombre;
								} else {
									label = item.calle_descripcion + (portal!=null?" "+portal:"") +", " + localidad_norm + ", " + (provincia_norm!=null? provincia_norm + ", " : "") + item.pais_nombre;
								}

								return {
									label: label,
									calle_id: item.calle_id,
									calle_descripcion: item.calle_descripcion,
									calle_nombre: item.calle_nombre,
									calle_tipo: item.calle_tipo,
									calle_articulo: item.calle_articulo,
									intersection: item.intersection,
									localidad_id: item.localidad_id,
									localidad_nombre: item.localidad_nombre,
									municipio_id: item.municipio_id,
									municipio_nombre: item.municipio_nombre,
									provincia_id: item.provincia_id,
									provincia_nombre: item.provincia_nombre,
									comunidad_id: item.comunidad_id,
									comunidad_nombre: item.comunidad_nombre,
									pais_id: item.pais_id,
									pais_nombre: item.pais_nombre,
									portal: portal,
									portal_min: item.portal_min,
									portal_max: item.portal_max,
									coord: item.coord
								};

							}
						})
					);

				} else {
					self.querySolr_(request, response, "OR", attempt+1);
					response(null);
				}
			},
			error: function(a,b,c){
			}
		});
	}
};


/**
* @return {string} ClassName. Value `cercalia.service.Autocomplete`
*/
cercalia.service.Autocomplete.prototype.getClass = function(){
	return this.CLASS_NAME_;
};