/**
* @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,
postalcode: ui.item.codigo_postal
};
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,
codigo_postal: item.codigo_postal,
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,
codigo_postal: item.codigo_postal,
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,
codigo_postal: item.codigo_postal,
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_;
};