Source: temp/jsdocinputdirs/cercalia.kml.js

/**
 * @class
 * @constructor
 * @param {cercaliax.KMLOptions} options Hash table with extra options to configure the KML layer
 */
cercalia.KML = function(options) {

	/**
	 * Class name
	 * @private
	 * @type {string}
	 */
	this.CLASS_NAME_ = "cercalia.KML";
	
	
	/**
	 * Name
	 * @private
	 * @type {string}
	 */
	this.name_ = options.name ? options.name : "cercalia.KML_" + new Date().getTime() + Math.round((Math.random()*1000));
	
	/**
	 * Map
	 * @private
	 * @type {cercalia.Map|undefined}
	 */
	this.map_ = options.map ? options.map : undefined;

	
	/**
	 * Name
	 * @private
	 * @type {string}
	 */
	this.imgDefault_ = options.imgDefault ? options.imgDefault : "https://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png";
	
	/**
	 * MinResolution
	 * The minimum resolution (inclusive) at which this layer will be visible.
	 * @private
	 * @type {number|undefined}
	 */
	this.minResolution_ = options.minResolution ? options.minResolution : undefined;

	/**
	 * MaxResolution
	 * The maximum resolution (exclusive) below which this layer will be visible.
	 * @private
	 * @type {number|undefined}
	 */
	this.maxResolution_ = options.maxResolution ? options.maxResolution : undefined;
	
	/**
	 * Opacity
	 * Opacity. 0-1. Default is 1
	 * @private
	 * @type {number|undefined}
	 */
	this.opacity_ = options.opacity ? options.opacity : 1;
	
	/**
	 * Projection
	 * @private
	 * @type {string}
	 */
	this.srs_ = options.projection ? options.projection : 'EPSG:3857'; // o 'EPSG:3857' ?
	
	/**
	 * Draggable
	 * Default is false
	 * @private
	 * @type {boolean}
	 */
	this.draggable_ = options.draggable ? options.draggable : false; 
	
	/**
	 * Url
	 * Required.
	 * @private
	 * @type {string}
	 */
	this.url_ = options.url;
	
	/**
	 * Visible
	 * @private
	 * @type {boolean|undefined}
	 */
	this.visible_ = options.visible ? options.visible : true;
	
	/**
	 * KML format
	 * @private
	 * @type {ol.format.KML}
	 */
	this.format_ = new ol.format.KML({
		'maxDepth':10, 
		extractStyles: true, 
		defaultStyle:new ol.style.Style({			   
		    image: new ol.style.Circle({
		      radius: 7,
		      fill: new ol.style.Fill({
		        color: '#ffcc33'
		      })
		    })
		  })
	});
	
	/**
	 * Layer
	 * OL Vector
	 * @private
	 * @type {ol.layer.Vector}
	 * 
	 */
	this.layer_ = null;
	
	/**
	 * Source
	 * @private
	 * @type {ol.source.Vector}
	 * 
	 */
	this.source_ = null;
	
	this.defaultStyle_ = {
		  'Point': [new ol.style.Style({
		    image: new ol.style.Circle({
		      fill: new ol.style.Fill({
		        color: 'rgba(255,255,0,0.5)'
		      }),
		      radius: 5,
		      stroke: new ol.style.Stroke({
		        color: '#ff0',
		        width: 1
		      })
		    })
		  })],
		  'LineString': [new ol.style.Style({
		    stroke: new ol.style.Stroke({
		      color: '#f00',
		      width: 3
		    })
		  })],
		  'Polygon': [new ol.style.Style({
		    fill: new ol.style.Fill({
		      color: 'rgba(0,255,255,0.5)'
		    }),
		    stroke: new ol.style.Stroke({
		      color: '#0ff',
		      width: 1
		    })
		  })],
		  'MultiPoint': [new ol.style.Style({
		    image: new ol.style.Circle({
		      fill: new ol.style.Fill({
		        color: 'rgba(255,0,255,0.5)'
		      }),
		      radius: 5,
		      stroke: new ol.style.Stroke({
		        color: '#f0f',
		        width: 1
		      })
		    })
		  })],
		  'MultiLineString': [new ol.style.Style({
		    stroke: new ol.style.Stroke({
		      color: '#0f0',
		      width: 3
		    })
		  })],
		  'MultiPolygon': [new ol.style.Style({
		    fill: new ol.style.Fill({
		      color: 'rgba(0,0,255,0.5)'
		    }),
		    stroke: new ol.style.Stroke({
		      color: '#00f',
		      width: 1
		    })
		  })]
		};
	
	this.initialize_();
};

/*** INITIALIZE ***/
/**
 * @private
 */
cercalia.KML.prototype.initialize_ = function () {
	var self = this;
	
	//creem el source KML
	this.source_ = new ol.source.Vector({
	    url: this.url_,
	    projection : ol.proj.get('EPSG:3857'),
	    format: this.format_
	});
	
	//creem el vector
	this.layer_ = new ol.layer.Vector({
		  source: this.source_,
		  minResolution : this.minResolution_,
		  maxResolution : this.maxResolution_,
		  opacity : this.opacity_,
		  visible : this.visible_
	});
	
	this.layer_.typeLayer = "cercalia.KML";
	this.source_.typeSource = "cercalia.KML";
	this.layer_.layer  = this;
	this.source_.layer = this;
	
	if(this.map_){
		this.map_.addLayer(this);
	}
	
	// The snap interaction must be added after the Modify and Draw interactions
	// in order for its map browser event handlers to be fired first. Its handlers
	// are responsible of doing the snapping.
	/*var snap = new ol.interaction.Snap({
	  source: this.source_
	});
	this.map_.getMap().addInteraction(snap);*/
	
}

/*** GETTERS AND SETTERS ***/

/**
 * We assign a map to the object. If it's already exist, is deleted in the existing 
 * map and KML layer is painted on the map passed as parameter.
 * If parameter is "null", it's removed from the map.
 * 
 * @param {cercalia.Map|null} map Map.
 * @param {number} position ZIndex position from layers.
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setMap = function(map, position) {

	if(this.map_){
		this.map_.removeLayer(this.layer_);
	}
	
	if(map == null){
		this.map_ = null;
	}else{
		this.map_ = map;
		this.map_.addLayer(this.layer_, position);
	}
	
	//Posem si es dragable
	if(this.map_){
		this.setDraggable(this.draggable_);
	}

	return this;
};

/**
 * return cercalia map
 * @return {cercalia.Map|undefined} map
 */
cercalia.KML.prototype.getMap = function() {
	return this.map_;
}

/**
 * 
 * @param {number} minResolution
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setMinResolution = function(minResolution) {
	this.minResolution_ = minResolution;
	this.layer_.setMinResolution(this.minResolution_)
	return this;
}

/**
 * @return {number} minResolution
 */
cercalia.KML.prototype.getMinResolution = function() {
	return this.minResolution_;
}

/**
 * 
 * @param {number} maxResolution
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setMaxResolution = function(maxResolution) {
	this.maxResolution_ = maxResolution;
	this.layer_.setMaxResolution(this.maxResolution_)
	return this;
}

/**
 * @return {number} maxResolution
 */
cercalia.KML.prototype.getMaxResolution = function() {
	return this.maxResolution_;
}

/**
 * 
 * @param {number} opacity
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setOpacity = function(opacity) {
	this.opacity_ = opacity;
	this.layer_.setOpacity(this.opacity_)
	return this;
}

/**
 * @return {number} opacity
 */
cercalia.KML.prototype.getOpacity = function() {
	return this.opacity_;
}

/**
 * @return {string} url
 */
cercalia.KML.prototype.getUrl = function() {
	return this.url_;
}

/**
 * 
 * @param {number} visible
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setVisible = function(visible) {
	this.visible_ = visible;
	this.layer_.setVisible(this.visible_)
	return this;
}

/**
 * @return {number} visible
 */
cercalia.KML.prototype.getVisible = function() {
	return this.visible_;
}

/**
 * @return {string} ClassName from `cercalia.KML` object.
 */
cercalia.KML.prototype.getClass = function() {
	return this.CLASS_NAME_;
};

/**
 * 
 * @returns {ol.layer.Vector}
 */
cercalia.KML.prototype.getLayer = function() {
	return this.layer_;
};

/**
 * 
 * @returns {ol.source.Vector}
 */
cercalia.KML.prototype.getSource = function() {
	return this.source_;
};

/**
 * @return {string} Projection.
 */
cercalia.KML.prototype.getProjection = function() {
	return this.srs_;
};

/**
 * @return {string} Projection.
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.setProjection = function(projection) {
	this.srs_ = projection;
	this.source_.setProjection(ol.proj.get(this.srs_));
	return this;
};

/**
 * Converts features to `draggable`. You can drag features. 
 * @param {boolean} draggable
 */
cercalia.KML.prototype.setDraggable = function(draggable) {
	this.draggable_ = draggable;
	if(this.draggable_){
		if(this.map_){
			this.map_.getInteractionDrag()
				.addLayer(this);
		}
	}else{
		if(this.map_){
			this.map_.getInteractionDrag()
				.removeLayer(this);
		}
	}
	return this;
};

/**
 * @return {boolean} Returns the drag status. Values: `true` or `false`. 
 */
cercalia.KML.prototype.isDraggable = function() {
	return this.draggable_;
};

/*** METHODS ***/

/**
 * @return {Array} Array of features.
 */
cercalia.KML.prototype.getFeatures = function() {
	return this.source_.getFeatures();
};

/**
 * @param {Array<cercalia.Feature|ol.Feature>} features Array of features.
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.addFeatures = function(features) {
	
	if(Array.isArray(features)){
		
		for(index = 0; index < features.length; index++){
			this.addFeature(features[index]);
		}
		
	}else this.addFeature(features);
	
	return this;
};

/**
 * @param {cercalia.Feature|cercalia.Marker|ol.Feature} feature feature.
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.addFeature = function(feature) {
	
	if(Array.isArray(feature)){
		this.addFeatures(feature);
	}else{
		
		if(feature instanceof cercalia.Feature || feature instanceof cercalia.Marker){
			if(!feature.getMap()){
				feature.setMap(this.map_);
			}
			feature = feature.getFeature();
		}
		
		if(feature instanceof ol.Feature){
			this.source_.addFeature(feature);
		}
	}
	return this;
};

/**
 * @param {string} kml KML string.
 * @param {string} proj Data projection.
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.addFeaturesFromKML = function(kml, proj) {
	if(kml){
		proj = proj ? proj : this.srs_;
		var arr = this.format_.readFeatures(kml
				, {dataProjection: ol.proj.get(proj), featureProjection: ol.proj.get(this.srs_)}
		);
		
		var arrFeatures = [ ];
		if(this.srs_ != 'EPSG:3857') {			
			for(var i = 0 ; i < arr.length ; i++){
				arr[ i ].getGeometry().transform(this.srs_, 'EPSG:3857');//Per defecte EPSG:3857
			}
		}else arrFeatures = arr;
		
		if(arrFeatures){
			this.addFeatures(arrFeatures);
		}
	}
	
	return this;
};

/**
 * Remove a single feature from the source. If you want to remove all features at once, use the `clear()` method instead
 * @param {cercalia.Feature|cercalia.Marker|ol.Feature} feature
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.removeFeature = function(feature) {
	
	if(feature instanceof cercalia.Feature || feature instanceof cercalia.Marker){
		feature = feature.getFeature();
	}
	
	this.source_.removeFeature(feature);
	return this;
};

/**
 * 
 * @return {string} kml of features added
 */
cercalia.KML.prototype.getKML = function() {
	
	var arr = this.getFeatures();
	for(var i = 0; i < arr.length ; i++){
		var feature = arr[i];
		var style = feature.getStyle();
		if(typeof(style)==="function"){
			//style = feature.getProperties().Style[0];
		}
		
		if(style instanceof Array && style.length > 0){
			style = style[0];
		}
		if(style !== undefined && style.getImage !== undefined){
		
			var image = style.getImage();
			if(image.getSrc === undefined){
				var img = this.imgDefault_;
				image.getSrc = function(){return img;};
			}
		}
	}
	
	return this.format_.writeFeatures(arr, {dataProjection: ol.proj.get('EPSG:4326'), featureProjection: ol.proj.get('EPSG:3857')});
};

/**
 * clear all features
 * @return {cercalia.KML} this
 */
cercalia.KML.prototype.clear = function() {
	this.source_.clear();	
	return this;
};