Source: temp/jsdocinputdirs/cercalia.control.traffic.js

/**
 * @classdesc
 * Traffic control. <br/>
 * This control shows the following traffic elements: <br/>
 * - `cercalia.MapControls.TrafficOptions.LIVE` Live traffic.<br/>
 * - `cercalia.MapControls.TrafficOptions.PREDICTED`  Predicted traffic.<br/>
 * - `cercalia.MapControls.TrafficOptions.CAMERAS` Live traffic cams (only Spain).<br/>
 * - `cercalia.MapControls.TrafficOptions.PKS` Highway location marker.<br/>
 * - `cercalia.MapControls.TrafficOptions.WORKS` Road works (only Spain).<br/>
 * @constructor
 * @extends {ol.control.Control}
 */

cercalia.Control.Traffic =  function() {

	/**
	 * @private
	 * @type {string}
	 */
	this.name_ = cercalia.MapControls.Traffic;

	/**
	 * @private
	 * @type {string}
	 */
	this.topBarId_ = null;

	/**
	 * Class name
	 * @private
	 * @type {string}
	 */
	this.CLASS_NAME_ = 'cercalia.Control.Traffic';

	/**
	 * @private
	 * @type {cercalia.WMS}
	 */
	this.layerPredictedTraffic_ = null;

	/**
	 * @private
	 * @type {cercalia.WMS}
	 */
	this.layerPksTraffic_ = null;

	/**
	 * @private
	 * @type {cercalia.WMS}
	 */
	this.layerLiveTraffic_ = null;

  /**
   * @private
   * @type {cercalia.WMS}
   */
  this.layerRoadWorks_ = null;

  /**
   * @private
   * @type {ol.layer.Vector}
   */
  this.layerFeatures_ = null;

	/**
	 * @private
	 * @type {cercalia.service.Pois}
	 */
	this.servicePoisCameras_ = new cercalia.service.Pois({
			categories : ['D00CAM'],
			searchByScale : true
	});


	/**
	 * @private
	 * @type {boolean}
	 */
	this.trafficHDFlowEnabled_ = false;

	/**
	 * @private
	 * @type {boolean}
	 */
	this.trafficPredictedEnabled_ = false;

	/**
	 * @private
	 * @type {boolean}
	 */
	this.camerasEnabled_ = false;

	/**
	 * @private
	 * @type {boolean}
	 */
	this.pksEnabled_ = false;

	/**
	 * @private
	 * @type {boolean}
	 */
	this.worksEnabled_ = false;

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

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

	/**
	 * @private
	 * @type {number}
	 */
	this.intervalTimeId_ = null;

	/**
	 * @private
	 * @type {Element|null}
	 */
	this.dialogLiveTraffic_ = null

  /**
   * @private
   * @type {number}
   */
  this.minZoomMarkers_ = 12;

  /**
   * @private
   * @type {number}
   */
  this.minZoomWMS_ = 9;

  /**
   * @private
   * @type {Array.<ol.Feature>|null}
   */
  this.featuresTmp_ = null;

  /**
   * @private
   * @type {ol.Overlay}
   */
  this.popupAffectations_ = null;

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

  /**
   * @private
   * @type {string}
   */
  this.listFeatureTypesEnabled_ = [];

  /**
   * @private
   * @type {boolean}
   */
   this.zoomEndHandlerEnabled_ = false;


	this.element_ = document.createElement('button');
	this.element_.className = 'trafficswitcher';
	this.element_.innerHTML = cercalia.i18n._('Traffic');

	cercalia.jQuery(this.element_).button({ icons: { primary: 'cercalia-big-icon-car	cercalia-big-icon', secondary: 'ui-icon-triangle-1-s'} });
	cercalia.jQuery(this.element_).removeClass('ui-button-text-icons').addClass('ui-button-text-icon-secondary cercalia-tool-button');

  this.initializeJSONAffectations_();

};
ol.inherits(cercalia.Control.Traffic, ol.control.Control);



/**
 * Create the button in the tools topbar
 * @param {string} idTopBar Div element ID where the control will be embedded
 */
cercalia.Control.Traffic.prototype.setTopBar = function(idTopBar) {
	var self = this;

	//Asignamos evento click al botón para abrir la lista
	this.element_.addEventListener('click', function(event) {

		if(cercalia.jQuery(self.element_).hasClass('cercalia-tool-button-open')) {
			cercalia.jQuery(self.element_).removeClass('cercalia-tool-button-open');
			cercalia.jQuery('.cercalia-tool-button-open').click().removeClass('cercalia-tool-button-open').button('refresh');
		} else {
			cercalia.jQuery('.cercalia-tool-button-open').click().removeClass('cercalia-tool-button-open').button('refresh');
			cercalia.jQuery(self.element_).addClass('cercalia-tool-button-open');
		}

		//Obrim o tanquem segons com es trobi
		cercalia.jQuery(self.elementList_).is(':visible') ? self.closeList_() : self.openList_();
	}, false);

	this.topBarId_ = idTopBar;
	var target = document.getElementById(idTopBar);

	ol.control.Control.call(this, {
	    element: self.element_,
	    target: target
	});

	//Creamos la lista
	var trafficswitcherList = document.createElement('div');
	trafficswitcherList.className = 'trafficswitcherList';

	var ulTrafficswitcherList = document.createElement('ul');
	ulTrafficswitcherList.className = 'ui-corner-all ui-widget ui-state-default';

	trafficswitcherList.appendChild(ulTrafficswitcherList);

	target.appendChild(trafficswitcherList);

	this.elementList_ = trafficswitcherList;

	this.createTrafficMenuList_(idTopBar);
};



/**
 * @private
 */
cercalia.Control.Traffic.prototype.openList_ = function() {
	//Siempre que abramos ajustamos la posición del list respecto el botón

	var width = cercalia.jQuery(this.element_).width();
	var rightPosition = cercalia.jQuery(this.element_).parent().width() - cercalia.jQuery(this.element_).position().left - width + 8;
	cercalia.jQuery(this.elementList_).css('right', rightPosition);

	cercalia.jQuery(this.elementList_).fadeIn();
	cercalia.jQuery(this.element_).find('.ui-button-icon-secondary')
			.addClass('ui-icon-triangle-1-n')
			.removeClass('ui-icon-triangle-1-s');
};

/**
 * @private
 */
cercalia.Control.Traffic.prototype.closeList_ = function() {
	cercalia.jQuery(this.elementList_).fadeOut();
	cercalia.jQuery(this.element_).find('.ui-button-icon-secondary')
			.addClass('ui-icon-triangle-1-s')
			.removeClass('ui-icon-triangle-1-n');
};


/**
 * Creates the list
 * @private
 * @param {string} idTopBar
 */
cercalia.Control.Traffic.prototype.createTrafficMenuList_ = function(idTopBar){

	var self = this;

	//Trafico en tiempo real
	cercalia.jQuery('<li />')
		.addClass('radioElem ui-corner-top ui-no-corner-bottom cercalia-box-sizing ' + cercalia.MapControls.TrafficOptions.LIVE)
		.data('trafficOption', cercalia.MapControls.TrafficOptions.LIVE)
		.html( cercalia.i18n._('Real-time traffic') )
		.click(function(){
			self.toggleTrafficHDFlow_(this, !self.trafficHDFlowEnabled_);
		})
	.appendTo( cercalia.jQuery(this.elementList_).find('ul') )
	.button({icons: {primary:'', secondary: 'cercalia-icon cercalia-icon-traffic-radio-disabled'}});

	//Trafico previsto
	cercalia.jQuery('<li />')
		.addClass('radioElem ui-no-corner-all cercalia-box-sizing ' + cercalia.MapControls.TrafficOptions.PREDICTED)
		.data('trafficOption', cercalia.MapControls.TrafficOptions.PREDICTED)
		.html( cercalia.i18n._('Traffic planned') )
		.click(function(){
			self.toggleTrafficPredicted_(this, !self.trafficPredictedEnabled_);
		})
	.appendTo( cercalia.jQuery(this.elementList_).find('ul') )
	.button({icons: {primary:'', secondary: 'cercalia-icon cercalia-icon-traffic-radio-disabled'}});


	//Camaras trafico
	cercalia.jQuery('<li />')
		.addClass('checkElem ui-no-corner-all cercalia-box-sizing ' + cercalia.MapControls.TrafficOptions.CAMERAS)
		.data('trafficOption', cercalia.MapControls.TrafficOptions.CAMERAS)
		.html( cercalia.i18n._('Traffic cameras') )
		.click(function(){
			self.toggleCameras_(this, !self.camerasEnabled_);
		})
	.appendTo( cercalia.jQuery(this.elementList_).find('ul') )
	.button({icons: {primary:'', secondary: 'cercalia-icon cercalia-icon-traffic-check-disabled'}});


	//Puntos kilométricos
	cercalia.jQuery('<li />')
		.addClass('checkElem ui-no-corner-all cercalia-box-sizing ' + cercalia.MapControls.TrafficOptions.PKS)
		.data('trafficOption', cercalia.MapControls.TrafficOptions.PKS)
		.html( cercalia.i18n._('Kilometer points') )
		.click(function(){
			self.togglePks_(this, !self.pksEnabled_);
		})
	.appendTo( cercalia.jQuery(this.elementList_).find('ul') )
	.button({icons: {primary:'', secondary: 'cercalia-icon cercalia-icon-traffic-check-disabled'}});


	//Obras
	cercalia.jQuery('<li />')
		.addClass('checkElem ui-corner-bottom ui-no-corner-top cercalia-box-sizing ' +  cercalia.MapControls.TrafficOptions.WORKS)
		.data('trafficOption', cercalia.MapControls.TrafficOptions.WORKS)
		.data('enabled',false)
		.html( cercalia.i18n._('Works') )
		.click(function(){
			self.toggleWorks_(this, !self.worksEnabled_);
		})
	.appendTo( cercalia.jQuery(this.elementList_).find('ul') )
	.button({icons: {primary:'', secondary: 'cercalia-icon cercalia-icon-traffic-check-disabled'}});

};

/**
 * Enables the traffic layer option selected by parameter<br/>
 * Options:<br/>
 * 	`cercalia.MapControls.TrafficOptions.LIVE` Live traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.PREDICTED` Predicted traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.CAMERAS` Live traffic cams (only Spain)<br/>
 * 	`cercalia.MapControls.TrafficOptions.PKS` Highway location marker<br/>
 *  `cercalia.MapControls.TrafficOptions.WORKS`	Road works (only Spain)<br/>
 * @param {string} option
 */
cercalia.Control.Traffic.prototype.enable = function(option) {
	this.toggleOption_(option, true);
};


/**
 * Disables the traffic layer option selected by parameter<br/>
 * Options:<br/>
 * 	`cercalia.MapControls.TrafficOptions.LIVE` Live traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.PREDICTED` Predicted traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.CAMERAS` Live traffic cams (only Spain)<br/>
 * 	`cercalia.MapControls.TrafficOptions.PKS` Highway location marker<br/>
 *  `cercalia.MapControls.TrafficOptions.WORKS`	Road works (only Spain)<br/>
 *  @param {string} option
 */
cercalia.Control.Traffic.prototype.disable = function(option) {
	this.toggleOption_(option, false);
};


/**
 * Return boolean if parameter traffic option is enabled or not.
 * Options:
 * 	`cercalia.MapControls.TrafficOptions.LIVE` Live traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.PREDICTED` Predicted traffic<br/>
 * 	`cercalia.MapControls.TrafficOptions.CAMERAS` Live traffic cams (only Spain)<br/>
 * 	`cercalia.MapControls.TrafficOptions.PKS` Highway location marker<br/>
 *  `cercalia.MapControls.TrafficOptions.WORKS`	Road works (only Spain)<br/>
 *  @param {string} option
 *  @return {boolean}
 */
cercalia.Control.Traffic.prototype.isTrafficOptionEnabled = function(option) {

	switch(option) {
		case cercalia.MapControls.TrafficOptions.LIVE:
			return this.layerLiveTraffic_!=null;
		case cercalia.MapControls.TrafficOptions.PREDICTED:
			return this.layerPredictedTraffic_!=null;
		case cercalia.MapControls.TrafficOptions.CAMERAS:
			return this.camerasEnabled_;
		case cercalia.MapControls.TrafficOptions.PKS:
			return this.layerPksTraffic_!=null;
		case cercalia.MapControls.TrafficOptions.WORKS:
			return this.worksEnabled_;
		default:
			alert('Opción de tráfico desconocida: ' + option);
			return false;
	}

};

/**
 * @private
 * @param {string} option
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.toggleOption_ = function(option, enable){

	switch(option){
		case cercalia.MapControls.TrafficOptions.LIVE:
			var objDom = cercalia.jQuery('#' + this.topBarId_ + ' .' + cercalia.MapControls.TrafficOptions.LIVE);
			this.toggleTrafficHDFlow_(objDom, enable);
			break;
		case cercalia.MapControls.TrafficOptions.PREDICTED:
			var objDom = cercalia.jQuery('#' + this.topBarId_ + ' .' + cercalia.MapControls.TrafficOptions.PREDICTED);
			this.toggleTrafficPredicted_(objDom, enable);
			break;
		case cercalia.MapControls.TrafficOptions.CAMERAS:
			var objDom = cercalia.jQuery('#' + this.topBarId_ + ' .' + cercalia.MapControls.TrafficOptions.CAMERAS);
			this.toggleCameras_(objDom, enable);
			break;
		case cercalia.MapControls.TrafficOptions.PKS:
			var objDom = cercalia.jQuery('#' + this.topBarId_ + ' .' + cercalia.MapControls.TrafficOptions.PKS);
			this.togglePks_(objDom, enable);
			break;
		case cercalia.MapControls.TrafficOptions.WORKS:
			var objDom = cercalia.jQuery('#' + this.topBarId_ + ' .' + cercalia.MapControls.TrafficOptions.WORKS);
			this.toggleWorks_(objDom, enable);
			break;
	}
};

/**
 * @private
 */
cercalia.Control.Traffic.prototype.disableTraffic_ = function() {

  var olMap = this.getMap();
	var cercaliaMap = olMap.getCercalia();

  if (this.layerFeatures_) {
    cercaliaMap.removeLayer(this.layerFeatures_);
    this.layerFeatures_ = null;
  }

	//Disable real traffic
	if(this.layerLiveTraffic_){
		cercaliaMap.removeWMSLayer(this.layerLiveTraffic_);
		this.layerLiveTraffic_ = null;
		this.trafficHDFlowEnabled_ = false;
	}

	//Disable predicted traffic (both must not active at same time)
	if(this.layerPredictedTraffic_){
		this.layerPredictedTraffic_.dialog.dialog('close');
		cercaliaMap.removeWMSLayer(this.layerPredictedTraffic_);
		if(this.layerPredictedTraffic_.dialog){
			this.layerPredictedTraffic_.dialog.dialog('destroy').remove();
		}
		this.layerPredictedTraffic_ = null;
		this.trafficPredictedEnabled_ = false;
	}

};



/**
 * @private
 * @param {Object} obj
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.toggleTrafficHDFlow_ = function (obj, enable) {

  var olMap = this.getMap();
	var cercaliaMap = olMap.getCercalia();
  var view = olMap.getView();
	var jqElemSelected = cercalia.jQuery(obj);

	this.disableTraffic_();

	jqElemSelected.parent().find('li.radioElem .ui-button-icon-secondary').removeClass('cercalia-icon-traffic-radio-enabled');

	//Capa desactivada
	if( enable ){
    this.trafficHDFlowEnabled_ = true;
		var params = {
				  LAYERS: 'TTHDFLOW',
				  FORMAT: 'image/png',
				  TRANSPARENT: 'TRUE',
				  VERSION: '1.1.1',
				  authkey: servers.authkey,
				  projection: cercaliaMap.getProjectionCode(),
				  _: Date.now()
		};

		var options = {};

		this.layerLiveTraffic_ = new cercalia.WMS(cercalia.LayerEnumeration.CercaliaTrafficReal, servers.hdflow, params, {
			tileLoadFunction: function(imageTile, src) {
				imageTile.getImage().src = src + '&time=' + Date.now();
				imageTile.getImage().src = src + '&time=' + Date.now();
			}
		});

		cercaliaMap.addWMSLayer(this.layerLiveTraffic_, 1);

		jqElemSelected.find('.ui-button-icon-secondary').addClass('cercalia-icon-traffic-radio-enabled');

    this.getGeojsonFeatures_();
    if (!this.zoomEndHandlerEnabled_) {
      view.on('change:resolution', this.zoomEndFunctionAffectations_.bind(this));
      this.zoomEndHandlerEnabled_ = true
    }

	} else {

    this.closePopups();

    if (this.worksEnabled_) {
      this.getGeojsonFeatures_();
    } else {
      view.un('change:resolution', this.zoomEndFunctionAffectations_.bind(this));
      this.zoomEndHandlerEnabled_ = false;
    }

  }

	this.setRefreshingTrafficData_(enable);
	this.showLegendLiveTraffic_(enable, 'hdflow');
};


/**
 * @private
 * @param {Object} obj
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.toggleTrafficPredicted_ = function (obj, enable) {

	var self = this;
	var mapOl = this.getMap();
	var cercaliaMap = mapOl.getCercalia();
	var jqElemSelected = cercalia.jQuery(obj);

	this.disableTraffic_();

	jqElemSelected.parent().find('li.radioElem .ui-button-icon-secondary').removeClass('cercalia-icon-traffic-radio-enabled');

	//Layer disabled
	if (enable) {

    if (this.worksEnabled_) {
      this.toggleOption_(cercalia.MapControls.TrafficOptions.WORKS, false);
    }

		var date = new Date();
		var daySelected = date.getDay()+1;//Dia actual de la setmana
		var strHour = date.getHours()+1 + ':00';
		var secondsSelected =  (date.getHours()+1)*3600;//Sumamos 1hora a la hora actual
		var paramLayers = 'SERVICE_LEVEL';

		var params = {
		  LAYERS: paramLayers,
		  FORMAT: 'image/png',
		  TRANSPARENT: 'TRUE',
		  VERSION: '1.1.1',
		  SERVICE: 'WMS',
		  authkey: servers.authkey,
		  projection : cercaliaMap.getProjectionCode(),
		  DAY: daySelected,
		  TIME: secondsSelected
		};

		this.layerPredictedTraffic_ = new cercalia.WMS(cercalia.LayerEnumeration.CercaliaPredictedTraffic, servers.sp, params, {});
		cercaliaMap.addWMSLayer(this.layerPredictedTraffic_, 1);

		jqElemSelected.find('.ui-button-icon-secondary').addClass('cercalia-icon-traffic-radio-enabled');

		var idDialog = "TrafficPredicted" + cercaliaMap.getId();

		//Creating dialog prediction
		if (!this.layerPredictedTraffic_.dialog) {

			var idPrevisionLegendDate = 'previsionLegendDate_'+cercaliaMap.getId();
			var idPrevisionLegendColors = 'colors'+cercaliaMap.getId()+'_SERVICE_LEVEL';
			var idPrevisionLegendColors2 = 'colors'+cercaliaMap.getId()+'_SPEED_LEVEL';

			var updateStrDayHour = function(day, hour){
				var str = '';

				switch(parseInt(day)){
					case 1: str = cercalia.i18n._('Sunday') + " " + hour + "h"; break;
					case 2: str =  cercalia.i18n._('Monday') + " " + hour + "h"; break;
					case 3: str =  cercalia.i18n._('Tuesday') + " " + hour + "h"; break;
					case 4: str =  cercalia.i18n._('Wednesday') + " " + hour + "h"; break;
					case 5: str =  cercalia.i18n._('Thursday') + " " + hour + "h"; break;
					case 6: str =  cercalia.i18n._('Friday') + " " + hour + "h"; break;
					case 7: str =  cercalia.i18n._('Saturday') + " " + hour + "h"; break;
				}

				cercalia.jQuery('#'+idPrevisionLegendDate).html(str);

				return str;
			};

			var strDayHourAct = updateStrDayHour(params.DAY, strHour);


			this.layerPredictedTraffic_.dialog =
					cercalia.jQuery('<div />')
						.attr('id',idDialog)
						.append(
							cercalia.jQuery('<div />')
								.append(
									cercalia.jQuery("<div class='selectDay'/>")
										.append(
											cercalia.jQuery("<span />")
											.html(cercalia.i18n._('Day'))
										)
										.append(
											cercalia.jQuery("<select />")
												.change(function(){
													params.DAY = this.value;
													self.layerPredictedTraffic_.updateParams(params);
													updateStrDayHour(params.DAY, strHour);
												})
												.html(
														'<option value="2" '+((daySelected==2)?'selected="true"':'')+'>'+cercalia.i18n._('Monday')+'</option>'+
														'<option value="3" '+((daySelected==3)?'selected="true"':'')+'>'+cercalia.i18n._('Tuesday')+'</option>'+
														'<option value="4" '+((daySelected==4)?'selected="true"':'')+'>'+cercalia.i18n._('Wednesday')+'</option>'+
														'<option value="5" '+((daySelected==5)?'selected="true"':'')+'>'+cercalia.i18n._('Thursday')+'</option>'+
														'<option value="6" '+((daySelected==6)?'selected="true"':'')+'>'+cercalia.i18n._('Friday')+'</option>'+
														'<option value="7" '+((daySelected==7)?'selected="true"':'')+'>'+cercalia.i18n._('Saturday')+'</option>'+
														'<option value="1" '+((daySelected==1)?'selected="true"':'')+'>'+cercalia.i18n._('Sunday')+'</option>'
												)
										)
								)
								.append(
									cercalia.jQuery("<div class='selectLevel'/>")
										.append(
											cercalia.jQuery("<span />")
											.html(cercalia.i18n._('Level'))
										)
										.append(
											cercalia.jQuery("<select />")
												.change(function(){
													params.LAYERS = this.value;
													self.layerPredictedTraffic_.updateParams(params);
													switch(this.value){
														case "SERVICE_LEVEL":
															cercalia.jQuery('#'+idPrevisionLegendColors2).hide();
															cercalia.jQuery('#'+idPrevisionLegendColors).show();
															break;
														case "SPEED_LEVEL":
														case "SPEED_LEVEL_URBAN":
															cercalia.jQuery('#'+idPrevisionLegendColors).hide();
															cercalia.jQuery('#'+idPrevisionLegendColors2).show();
															break;
													}
												})
												.html(
							                        '<option value="SERVICE_LEVEL" >'+cercalia.i18n._('Service level')+'</option>'+
							                        '<option value="SPEED_LEVEL" >'+cercalia.i18n._('Speed')+'</option>'+
							                        '<option value="SPEED_LEVEL_URBAN" >'+cercalia.i18n._('Urban speed')+'</option>'
												)
										)
								)
						)
						.append( cercalia.jQuery('<br style="clear:both"/>') )
						.append(
							cercalia.jQuery('<div class="sliderdiv"/>')
								.append(
									cercalia.jQuery('<div class="sliderlabel"/>').html( cercalia.i18n._('Hour') )
								)
								.append(
									cercalia.jQuery('<div class="slider"/>')
										.slider({
											range: "min",
											value: (secondsSelected/86400) * 96,
											min: 1,
											max: 96,
											stop: function(event, ui ){
												var hour = Math.floor(ui.value/4);
												var minutes = null;
												switch(ui.value%4){
													case 0: minutes = "00"; break;
													case 1: minutes = "15"; break;
													case 2: minutes = "30"; break;
													case 3: minutes = "45"; break;
												}

												strHour = hour +":"+minutes;
												secondsSelected = hour*3600 + minutes*60;

												updateStrDayHour(params.DAY, strHour);

												params.TIME = secondsSelected;

												self.layerPredictedTraffic_.updateParams(params);
											}
									})
								)
						)
						.append(
							cercalia.jQuery('<div/>')
								.append(
									cercalia.jQuery('<div class="sliderscale"/>').html( '<span>|</span>'+ '<span>|</span>'+ '<span>|</span>'+ '<span>|</span>'+ '<span>|</span>'+ '<span>|</span>' )
								)
						)
						.append(
							cercalia.jQuery('<div class="sliderdiv"/>')
								.append(
									cercalia.jQuery('<div class="sliderscale"/>').html('<span>04:00</span>'+ '<span>08:00</span>'+ '<span>12:00</span>'+ '<span>16:00</span>'+ '<span>20:00</span>'+ '<span>24:00</span>' )
								)
						)
						.append( cercalia.jQuery('<br style="clear:both"/>') )
						.append(
							cercalia.jQuery('<div />')
								.html(
									'<div class="previsionLegendDiv"  >'+
										'<div class="previsionLegendDate" id="'+idPrevisionLegendDate+'" >'+strDayHourAct+'</div>'+
										'<div class="previsionLegendColors" id="'+idPrevisionLegendColors+'">'+
											'<div style="float:left">'+cercalia.i18n._('Slow')+'</div>'+
											'<div style="float:right">'+cercalia.i18n._('Fast')+'</div>'+
										'</div>'+
										'<div class="previsionLegendColors2"  style="display:none" id="'+idPrevisionLegendColors2+'">'+
											'<div style="float:left;margin-right:3px">&lt;20</div>'+
											'<div style="float:left;margin-right:3px">20-40</div>'+
											'<div style="float:left;margin-right:3px">40-60</div>'+
											'<div style="float:left;margin-right:3px">60-80</div>'+
											'<div style="float:left;margin-right:3px">&gt;80</div>'+
											'<div style="float:left;margin-right:3px">km/h</div>'+
										'</div>'+
									'</div>'
								)
						)
					.dialog({
						autoOpen: true,
						closeOnEscape: false,
						closeText: "",
						draggable: false,
						resizable: false,
						title: "",
						dialogClass: "menuDialogPredictTraffic cercalia-widget-overlay-dialog",
						position: { my: "right bottom", at: "right-5px bottom-5px", of: "#" + cercaliaMap.getContainerId() },
						appendTo: "#" + cercaliaMap.getContainerId()
					}
			);


			//event when resize window
			cercalia.jQuery(window).bind('resize', function() {
				if(self.layerPredictedTraffic_.dialog && self.trafficPredictedEnabled_) {
					setTimeout(function() {
						self.layerPredictedTraffic_.dialog
							.dialog({})
							.parent()
							.position({
								my: "right bottom",
								at: "right-5px bottom-25px",
								of: "#" + cercaliaMap.getContainerId()
							});
					}, 300);
				}
			});


		}
		//Final creacion Popup prediccion de trafico
		self.trafficPredictedEnabled_ = true;
	}

};


/**
 * Close popups.
 */
cercalia.Control.Traffic.prototype.closePopups = function(){
	this.closePopupCameras_();
  this.closePopupAffectations_();
};


/**
 * @private
 */
cercalia.Control.Traffic.prototype.closePopupCameras_ = function() {
	if(this.servicePoisCameras_ && this.servicePoisCameras_.popupOpened && this.servicePoisCameras_.popupOpened.isOpen() ){
		this.servicePoisCameras_.popupOpened.hide();
		this.servicePoisCameras_.popupOpened.setContent(null); //Borramos el contenido y lo pedimos de nuevo si se vuelve a hacer un mouseOver del marker
		this.servicePoisCameras_.popupOpened = null;
	}
};

/**
 * @private
 */
cercalia.Control.Traffic.prototype.closePopupAffectations_ = function(){
  if(this.popupAffectations_){
    this.popupAffectations_.setElement(null);
    this.popupAffectations_.setMap(null);
    this.popupAffectations_ = null;
  }
};

/**
 * @private
 * @param {Object} obj
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.toggleCameras_ = function(obj, enable){

  var olMap = this.getMap();
	var cercaliaMap = olMap.getCercalia();

	//Capa desactivada
	if(!this.camerasEnabled_ && enable){

		this.getPoisCamerasOnMoveEnd_();//Primera peticion al activarlo
		olMap.on('moveend', this.getPoisCamerasOnMoveEnd_, this);

		cercalia.jQuery(obj).find('.ui-button-icon-secondary').addClass('cercalia-icon-traffic-check-enabled');

		this.camerasEnabled_ = true;

	} else if(this.camerasEnabled_ && !enable) {
		if(this.servicePoisCameras_.listMarkers){
			cercaliaMap.removeApiMarkers(this.servicePoisCameras_.listMarkers);
			for (var i = this.servicePoisCameras_.listMarkers.length - 1; i >= 0; i--) {
				this.servicePoisCameras_.listMarkers[i].destroy();
			}
		}
		this.servicePoisCameras_.listMarkers = null;

		olMap.un('moveend', this.getPoisCamerasOnMoveEnd_, this);
		this.servicePoisCameras_.clearResponse();
		this.camerasEnabled_ = false;

		//Activamos/Desactivamos la imagen de checkbox
		cercalia.jQuery(obj).find('.ui-button-icon-secondary').removeClass('cercalia-icon-traffic-check-enabled');
	} else if (!this.camerasEnabled_ && !enable) {
		this.camerasEnabled_ = false;
	}

};

/**
 * @private
 * @param {Object} obj
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.togglePks_ = function(obj, enable) {
	var cercaliaMap = this.getMap().getCercalia();

	//Capa desactivada
	if(!this.pksEnabled_ && enable ){

    var params = {
      LAYERS: 'cercalia',
      FORMAT: 'image/png',
      TRANSPARENT: 'TRUE',
      VERSION: '1.1.1',
      SERVICE: 'WMS',
      authkey: servers.authkey,
      projection: cercaliaMap.getProjectionCode(),
      HEIGHT: 256,
      WIDTH: 256
    };

		var options = {};

		this.layerPksTraffic_ = new cercalia.WMS(cercalia.LayerEnumeration.CercaliaPKs, servers.pks, params, {});
		cercaliaMap.addWMSLayer(this.layerPksTraffic_, 2);

		//Activamos la imagen de checkbox
		cercalia.jQuery(obj).find('span').addClass('cercalia-icon-traffic-check-enabled');
		this.pksEnabled_ = true;

	} else if( this.pksEnabled_ && !enable ) {

		if(this.layerPksTraffic_){
			cercaliaMap.removeWMSLayer(this.layerPksTraffic_);
		}

		//Desactivamos la imagen de checkbox
		cercalia.jQuery(obj).find('span').removeClass('cercalia-icon-traffic-check-enabled');
		this.pksEnabled_ = false;

	} else if ( !this.pksEnabled_ && !enable ) {
		this.pksEnabled_ = false;
	}
};

/**
 * @private
 * @param {Object} obj
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.toggleWorks_ = function(obj, enable) {

  var olMap = this.getMap();
	var cercaliaMap = olMap.getCercalia();
  var view = olMap.getView();

	if (!this.worksEnabled_) {

    var projectionCode = cercaliaMap.getProjectionCode();

    var params = {
      LAYERS: 'traffic_incidences',
      FORMAT: 'image/png',
      TRANSPARENT: 'TRUE',
      VERSION: '1.1.1',
      SERVICE: 'WMS',
      authkey: servers.authkey,
      projection: projectionCode
    };

    this.layerRoadWorks_ = new cercalia.WMS(cercalia.LayerEnumeration.CercaliaAffectationsLines, servers.live, params,{
      tileLoadFunction: function(imageTile, src) {
        imageTile.getImage().src = src + "&time="+new Date().getTime();
      }
    });
    cercaliaMap.addWMSLayer(this.layerRoadWorks_, 2);

		//Activamos la imagen de checkbox
		cercalia.jQuery(obj).find('.ui-button-icon-secondary').addClass('cercalia-icon-traffic-check-enabled');
		this.worksEnabled_ = true;


    this.getGeojsonFeatures_();
    if (!this.zoomEndHandlerEnabled_) {
      view.on('change:resolution', this.zoomEndFunctionAffectations_.bind(this));
      this.zoomEndHandlerEnabled_ = true
    }

	} else if(this.worksEnabled_ && !enable) {

    cercaliaMap.removeWMSLayer(this.layerRoadWorks_);
    cercaliaMap.removeLayer(this.layerFeatures_);
    this.layerFeatures_ = null;
    this.closePopups();

    this.layerRoadWorks_ = null;

		//Desactivamos la imagen de checkbox
		cercalia.jQuery(obj).find('.ui-button-icon-secondary').removeClass('cercalia-icon-traffic-check-enabled');
		this.worksEnabled_ = false;

    //Si livetraffic active => Forcem a tornarlo a crear
    if (this.layerLiveTraffic_) {
      this.getGeojsonFeatures_();
    } else {
      view.un('change:resolution', this.zoomEndFunctionAffectations_.bind(this));
      this.zoomEndHandlerEnabled_ = false;
    }
	}

};

/**
 * @private
 */
cercalia.Control.Traffic.prototype.getGeojsonFeatures_ = function() {

  var olMap = this.getMap();
  var cercaliaMap = olMap.getCercalia();
  var projectionCode = cercaliaMap.getProjectionCode();

  this.featuresTmp_ = null;

  this.listFeatureTypesEnabled_ = [];
  if (this.worksEnabled_) {
    this.listFeatureTypesEnabled_ = this.listFeatureTypesEnabled_.concat(['MaintenanceWorks']);
  }
  if (this.trafficHDFlowEnabled_) {
    this.listFeatureTypesEnabled_ = this.listFeatureTypesEnabled_.concat(['Accident','EnvironmentalObstruction','GeneralObstruction','VehicleObstruction','NetworkManagement']);
  }

  var vectorSource = new ol.source.Vector({
    loader: this.getGeojsonFeaturesLoader_.bind(this),
    strategy: this.getGeojsonStrategy_.bind(this, vectorSource),
    projection: projectionCode
  });

  if (this.layerFeatures_) {
    cercaliaMap.removeLayer(this.layerFeatures_);
  }

  this.layerFeatures_ = new ol.layer.Vector({
    name: cercalia.LayerEnumeration.OpenlrGeojsonLayer,
    source: vectorSource,
    style: function(feature, resolution) {
    	var type = feature.get('TYPE');
    	var subtype = feature.get('SUBTYPE');
    	var zoom = cercaliaMap.getZoom();

    	if (type === 'NetworkManagement' && zoom < this.minZoomMarkers_ + 2) {
    		return null;
    	} else {
      	var srcIcon = this.affectationsGetIconByType_(type, subtype);
      	return [new ol.style.Style({
	        image: new ol.style.Icon({
          	src: srcIcon
        	})
      	})];
      }
    }.bind(this)
  });

  var indexLayer = cercaliaMap.getLayerIndexByName(cercalia.LayerEnumeration.MarkerApiLayer);
  cercaliaMap.addLayer(this.layerFeatures_, indexLayer - 1);

};

/**
 * @param {Array.<number>} extent
 * @param {number} resolution
 */
cercalia.Control.Traffic.prototype.getGeojsonStrategy_ = function(source, extent, resolution) {
  var olMap = this.getMap();
  var view = olMap.getView();
  var zoom = view.getZoom();

  if (zoom >= this.minZoomMarkers_) {
    return [extent];
  } else {
    if (source) {
      source.clear();
      this.closePopupAffectations_();
      this.featuresTmp_ = null;
    }
    return [];
  }
};


/**
 * @private
 */
cercalia.Control.Traffic.prototype.getGeojsonFeaturesLoader_ = function(extent, resolution, projection) {

  var olMap = this.getMap();
  var cercaliaMap = olMap.getCercalia();
  var vectorSource = this.layerFeatures_.getSource();
  var projectionCode = cercaliaMap.getProjectionCode();
  var numServers = servers.openlrjson.length;
  var randomIndex = Math.floor(Math.random() * numServers);
  var url =
    servers.openlrjson[randomIndex] +
    'layers=retenciones&' +
    'qformat=geojson&' +
    'mode=nquery&' +
    'srsName=EPSG:4326&'+
    'MAPEXT=' + ol.proj.transformExtent(extent, projectionCode, 'EPSG:4326').join(' ') + '&' +
    '_=' + Date.now();

  cercalia.jQuery.getJSON(url, function(response) {

    var format = new ol.format.GeoJSON();
    var features = format.readFeatures(response, {featureProjection: projection});

    //Borrem els anteriors abans de pintar els nous
    if (this.featuresTmp_) {
      for(var i = 0; i < this.featuresTmp_.length; i++) {
        vectorSource.removeFeature(this.featuresTmp_[i]);
      }
    }

    var filteredFeatures = features.filter(function(elem) {
      var type = elem.get('TYPE')
      return this.listFeatureTypesEnabled_.indexOf(type) !== -1;
    }.bind(this));

    this.featuresTmp_ = filteredFeatures;
    vectorSource.addFeatures(filteredFeatures);
  }.bind(this));

};



/**
 * @private
 */
cercalia.Control.Traffic.prototype.zoomEndFunctionAffectations_ = function(){

  if (this.worksEnabled_ || this.layerLiveTraffic_) {
    var olMap = this.getMap();
    var view = olMap.getView();
    var zoom = view.getZoom();
    var layerWMS = this.layerRoadWorks_ ? this.layerRoadWorks_.getLayer() : null;

    if (zoom >= this.minZoomMarkers_) {
      layerWMS && layerWMS.setVisible(true);
      this.layerFeatures_.setVisible(true);
    } else if (zoom >= this.minZoomWMS_) {
      layerWMS && layerWMS.setVisible(true);
      this.layerFeatures_.setVisible(false);
    } else {
      layerWMS && layerWMS.setVisible(false);
      this.layerFeatures_.setVisible(false);
    }
  }
};

/**
 * @private
 * @param {string} type
 * @param {string|null} subtype
 */
cercalia.Control.Traffic.prototype.affectationsGetIconByType_ = function(type, subtype) {

  try {
    var icon = this.jsonAffectations_.type[type][subtype].icon;
    return cercaliaGlobals.img + '/traffic/' + icon;
  } catch(e) {
    console.log('Icon not found. Type=' + type + ', subtype=' + subtype + ', using default.');
    switch (type) {
      case "Accident":
        return cercaliaGlobals.img + '/traffic/accident.png';
      case "MaintenanceWorks":
        return cercaliaGlobals.img + '/traffic/roadworks.png';
      default:
        return cercaliaGlobals.img + '/traffic/obstruction.png';
    }
  }
};

/**
 * @private
 * @param {Event} evt
 */
cercalia.Control.Traffic.prototype.getPoisCamerasOnMoveEnd_ = function(evt) {

	var self = this;
	var cercaliaMap = this.getMap().getCercalia();
  var bounds = cercaliaMap.getBounds();

	//Comprobamos si hace falta recalcular
	//Casos:
	//	1) response==null -> No se ha hecho ninguna peticion des de que se ha construido el objeto
	//  2) Cambio de zoom
	//  3) Los bounds despues del 'moveend' no estan dentro de los ultimos calculados que eran el doble
	if (this.servicePoisCameras_.getResponse() == null ||
      cercaliaMap.getZoom() != this.servicePoisCameras_.lastZoom ||
      !this.servicePoisCameras_.getBounds().containsBounds(bounds)) {

		var size = this.getMap().getSize(); //Obtenemos los pixeles del mapa
		this.servicePoisCameras_.lastZoom = cercaliaMap.getZoom();

		this.servicePoisCameras_.setBounds(bounds.getDouble()); //Doble de extension (sumamos x0.5) por todos los lados
		this.servicePoisCameras_.setWidth(size[0] * 2);
		this.servicePoisCameras_.setHeight(size[1] * 2);

		if (this.servicePoisCameras_.listMarkers && this.servicePoisCameras_.listMarkers.length > 0) {
			cercaliaMap.removeApiMarkers(this.servicePoisCameras_.listMarkers);
			for (var i = 0; i < this.servicePoisCameras_.listMarkers.length; i++) {
				this.servicePoisCameras_.listMarkers[i].destroy();
			}
			this.servicePoisCameras_.listMarkers = [];
		}

		this.servicePoisCameras_.doPoisRequest(function(data) {

			//Como se ejecuta asincronamenente, tenemos que asegurarnos que está vacío
			if (self.servicePoisCameras_.listMarkers && self.servicePoisCameras_.listMarkers.length > 0) {
				cercaliaMap.removeApiMarkers(self.servicePoisCameras_.listMarkers);
				for (var i = 0; i<self.servicePoisCameras_.listMarkers.length; i++) {
					self.servicePoisCameras_.listMarkers[i].destroy();
				}
				self.servicePoisCameras_.listMarkers = [];
			}

			var listPoi = data.cercalia.map.gpoicats.poilist.poi instanceof Array ? data.cercalia.map.gpoicats.poilist.poi : [];
			var listMarkers = [];

			//Recorrido por todos los POIs
			listPoi.forEach(function(elem,index) {

				var arrInfo = elem.info.value.split('|');
				var title = arrInfo[1];
				var font = arrInfo[2];
				var img = cercaliaGlobals.img + '/pois/D00CAM.png';
				var src = arrInfo[3] + (arrInfo[3].indexOf('?') == -1 ? '?time=' : '&time=') + Date.now();

        var content =
          '<div>' +
            '<img style="width:240px;height:176px" src="' + src + '">' +
            '<br/>' +
            '<div>' + cercalia.i18n._('Font') + ': ' + font + '</div>' +
          '</div>';

        var meteoControl = cercaliaMap.getControlsByName(cercalia.MapControls.MeteoControl);
				var marker = new cercalia.Marker({
					position : new cercalia.LonLat(elem.coord.x, elem.coord.y),
					icon : new cercalia.Icon({src:img}),
					popup : new cercalia.Popup({
						title:title,
						content:null
					}),
					onClick: function(){
						return false;
					},
					onMouseOver: function() {
						self.closePopups();
						if (meteoControl) {
							meteoControl.closePopups();
						}

						self.servicePoisCameras_.popupOpened = this.getPopup();
						self.servicePoisCameras_.popupOpened.setContent(this.hiddenContent); //Cambiamos el contenido para solo descargarlo si interesa
						self.servicePoisCameras_.popupOpened.show();
					},
					onMouseOut: function() {
						if (meteoControl) {
							meteoControl.closePopups();
						}
						self.closePopups();
					}
				});

				marker.hiddenContent = content;

				listMarkers.push(marker);
			});

			cercaliaMap.addApiMarkers(listMarkers);
			self.servicePoisCameras_.listMarkers = listMarkers; //Guardamos en este objeto para poder recuperarlo
		});
	}
};



/**
 * Enable or disable automatic refresh for traffic data.
 * @private
 * @param {boolean} enable
 */
cercalia.Control.Traffic.prototype.setRefreshingTrafficData_ = function(enable) {

  var INTERVAL_REFRESH = 60000; //ms
  var mapOl = this.getMap();

	if (this.intervalTimeId_) {
		clearInterval(this.intervalTimeId_);
	}

	if (enable) {
		var self = this;
		this.intervalTimeId_ = setInterval(function(){
			self.refreshTrafficData_();
		}, INTERVAL_REFRESH);
		mapOl.on('moveend',this.refreshTrafficData_);
	} else {
		mapOl.un('moveend',this.refreshTrafficData_);
	}
};


/**
 * Refresh data hdflow and affectations (both tomtom info)
 * @private
 */
cercalia.Control.Traffic.prototype.refreshTrafficData_ = function() {
	if (this.trafficHDFlowEnabled_) {
		var params = this.layerLiveTraffic_.getParams();
		params['_'] = Date.now();
		this.layerLiveTraffic_.updateParams(params);
	}
};

/**
 * @private
 * @param {boolean} show
 */
cercalia.Control.Traffic.prototype.showLegendLiveTraffic_ = function(show) {

	var self = this;
	var cercaliaMap = this.getMap().getCercalia();
	var idDialog = "TrafficLive"+cercaliaMap.getId();

	if (this.dialogLiveTraffic_) {
		this.dialogLiveTraffic_.dialog('close');
		this.dialogLiveTraffic_.remove();
		this.dialogLiveTraffic_ = null;
	}

	if (show || this.trafficHDFlowEnabled_) {

		if (this.dialogLiveTraffic_) {
			this.dialogLiveTraffic_.dialog('open');
		} else {
			//it not exist, so create it
			this.dialogLiveTraffic_ = cercalia.jQuery("<div />")
				.attr('id',idDialog)
				.append(
					cercalia.jQuery(
						"<div class='hdflow'>" +
							"<div class='trafficIcon'>" +
								"<div class='icon'/>" +
								"<div class='label'>" + cercalia.i18n._('Retentions') + "</div>" +
							"</div>" +
							"<br style='clear:both'/>" +
							"<div class='trafficColors'>" +
								"<div class='labelSlow'>" + cercalia.i18n._('Slow') + "</div>" +
								"<div class='" + (this.trafficHDFlowEnabled_ ? "colorsIcon" : "colorsIcon2") + "'/>" +
								"<div class='labelFast'>" + cercalia.i18n._('Fast') + "</div>" +
							"</div>" +
						"</div>" +
						"<div class='affectations'>" +
							"<div style='float:left'>" +
								"<div class='worksIcon'>"+
									"<div class='icon'/>" +
									"<div class='label'>" + cercalia.i18n._('Works') + "</div>" +
								"</div>" +
								"<div class='obstructionIcon'>"+
									"<div class='icon'/>" +
									"<div class='label'>" + cercalia.i18n._('Obstruction') + "</div>" +
								"</div>" +
								"<br style='clear:both'/>" +
							"</div>" +
							"<div style='float:right'>" +
								"<div class='accidentIcon'>"+
									"<div class='icon'/>" +
									"<div class='label'>" + cercalia.i18n._('Accident') + "</div>" +
								"</div>" +
								"<div class='closedIcon'>"+
									"<div class='icon'/>" +
									"<div class='label'>" + cercalia.i18n._('Closed') + "</div>" +
								"</div>" +
								"<br style='clear:both'/>" +
							"</div>" +
							"<br style='clear:both'/>" +
						"</div>"
					)
				)
				.dialog({
					autoOpen: true,
					closeOnEscape: false,
					closeText: '',
					draggable: false,
					resizable: false,
					minHeight: 'auto',
					title: '',
					dialogClass: 'menuDialogLiveTraffic cercalia-widget-overlay-dialog',
					position: {
						my: 'right bottom',
						at: 'right-5px bottom-25px',
						of: '#' + cercaliaMap.getContainerId()
					},
					appendTo: '#' + cercaliaMap.getContainerId()
			});

			//event when resize window
			cercalia.jQuery(window).bind('resize', function() {
				if(self.dialogLiveTraffic_) {
					setTimeout(function() {
						self.dialogLiveTraffic_
							.dialog({})
							.parent()
							.position({
								my: 'right bottom',
								at: 'right-5px bottom-25px',
								of: '#' + cercaliaMap.getContainerId()
							});
					}, 300);
				}
			});
		}
	}
};

/**
 * @private
 */
cercalia.Control.Traffic.prototype.initializeJSONAffectations_ = function() {
  var url = cercaliaGlobals.context + "data/traffic_"  + cercaliaGlobals.lang + ".json";
  var jqXHR = cercalia.jQuery.getJSON(url);
  jqXHR.done(function(data) {
    this.jsonAffectations_ = data;
  }.bind(this));
};


/**
 * @private
 * @param {ol.Feature} feature
 */
cercalia.Control.Traffic.prototype.affectationsGetPopupContent_ = function(feature) {

  var type = feature.get('TYPE');
  var subtype = feature.get('SUBTYPE');
  var eventCode = feature.get('EVENTCODE');

  var innerPopupHTML =  '<b>' + this.jsonAffectations_.type[type][subtype].title + '</b><br/>';
  if (type == 'AbnormalTraffic') {
    var speed = feature.get('AVERAGESPEED');
    var minutes = (feature.get('DELAYTIMEVALUE') / 60).toFixed(2);
    innerPopupHTML +=
      cercalia.i18n._('Average speed:') + ' ' + speed + ' km/h<br/> ' +
      cercalia.i18n._('Delay:') + ' ' + minutes + ' min<br/> ';
  } else {
    if (this.jsonAffectations_.eventCodes[eventCode]) {
      innerPopupHTML += this.jsonAffectations_.eventCodes[eventCode]
    } else {
      innerPopupHTML += this.jsonAffectations_.type[type][subtype].description;
    }
  }

  return innerPopupHTML;
};


/**
 * @param {ol.Feature} feature
 */
cercalia.Control.Traffic.prototype.showAffectationPopup = function(feature) {

  var map = this.getMap();
  var innerPopupHTML = this.affectationsGetPopupContent_(feature);

  var html =
    '<div class="cercalia-popup-openlrInfo"> ' +
      '<div class="cercalia-popup-openlrClose" onclick="this.parentNode.parentNode.remove(this.parentNode)">X</div>' +
      '<div class="cercalia-popup-openlrTop"></div> ' +
      '<div class="cercalia-popup-openlrMiddle" style="width:169px"> ' +
        innerPopupHTML +
      '</div> ' +
      '<div class="cercalia-popup-openlrBottom"></div> ' +
    '</div>';

  var jqElement = cercalia.jQuery(html);

  if (!this.popupAffectations_) {
    map.removeOverlay(this.popupAffectations_);
    this.popupAffectations_ = new ol.Overlay({
      element: cercalia.jQuery(jqElement).get(),
      position: feature.getGeometry().getCoordinates(),
      positioning : 'bottom-left'
    });
  } else {
    this.popupAffectations_.setElement( cercalia.jQuery(jqElement).get() );
    this.popupAffectations_.setPosition(feature.getGeometry().getCoordinates());
  }

  map.addOverlay(this.popupAffectations_);
};