1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
7 * @requires OpenLayers/Layer/Markers.js
8 * @requires OpenLayers/Request/XMLHttpRequest.js
12 * Class: OpenLayers.Layer.Text
13 * This layer creates markers given data in a text file. The <location>
14 * property of the layer (specified as a property of the options argument
15 * in the <OpenLayers.Layer.Text> constructor) points to a tab delimited
16 * file with data used to create markers.
18 * The first row of the data file should be a header line with the column names
19 * of the data. Each column should be delimited by a tab space. The
20 * possible columns are:
21 * - *point* lat,lon of the point where a marker is to be placed
22 * - *lat* Latitude of the point where a marker is to be placed
23 * - *lon* Longitude of the point where a marker is to be placed
24 * - *icon* or *image* URL of marker icon to use.
25 * - *iconSize* Size of Icon to use.
26 * - *iconOffset* Where the top-left corner of the icon is to be placed
27 * relative to the latitude and longitude of the point.
28 * - *title* The text of the 'title' is placed inside an 'h2' marker
29 * inside a popup, which opens when the marker is clicked.
30 * - *description* The text of the 'description' is placed below the h2
31 * in the popup. this can be plain text or HTML.
35 * lat lon title description iconSize iconOffset icon
36 * 10 20 title description 21,25 -10,-25 http://www.openlayers.org/dev/img/marker.png
40 * - <OpenLayers.Layer.Markers>
42 OpenLayers.Layer.Text = OpenLayers.Class(OpenLayers.Layer.Markers, {
45 * APIProperty: location
46 * {String} URL of text file. Must be specified in the "options" argument
47 * of the constructor. Can not be changed once passed in.
53 * {Array(<OpenLayers.Feature>)}
58 * APIProperty: formatOptions
59 * {Object} Hash of options which should be passed to the format when it is
60 * created. Must be passed in the constructor.
65 * Property: selectedFeature
66 * {<OpenLayers.Feature>}
68 selectedFeature: null,
71 * Constructor: OpenLayers.Layer.Text
72 * Create a text layer.
76 * options - {Object} Object with properties to be set on the layer.
77 * Must include <location> property.
79 initialize: function(name, options) {
80 OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
81 this.features = new Array();
88 // Warning: Layer.Markers.destroy() must be called prior to calling
89 // clearFeatures() here, otherwise we leak memory. Indeed, if
90 // Layer.Markers.destroy() is called after clearFeatures(), it won't be
91 // able to remove the marker image elements from the layer's div since
92 // the markers will have been destroyed by clearFeatures().
93 OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
100 * Start the load of the Text data. Don't do this when we first add the layer,
101 * since we may not be visible at any point, and it would therefore be a waste.
103 loadText: function() {
105 if (this.location != null) {
107 var onFail = function(e) {
108 this.events.triggerEvent("loadend");
111 this.events.triggerEvent("loadstart");
112 OpenLayers.Request.GET({
114 success: this.parseData,
125 * If layer is visible and Text has not been loaded, load Text.
129 * zoomChanged - {Object}
132 moveTo:function(bounds, zoomChanged, minor) {
133 OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
134 if(this.visibility && !this.loaded){
143 * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>}
145 parseData: function(ajaxRequest) {
146 var text = ajaxRequest.responseText;
150 OpenLayers.Util.extend(options, this.formatOptions);
152 if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
153 options.externalProjection = this.projection;
154 options.internalProjection = this.map.getProjectionObject();
157 var parser = new OpenLayers.Format.Text(options);
158 var features = parser.read(text);
159 for (var i=0, len=features.length; i<len; i++) {
161 var feature = features[i];
163 var iconSize, iconOffset;
165 location = new OpenLayers.LonLat(feature.geometry.x,
168 if (feature.style.graphicWidth
169 && feature.style.graphicHeight) {
170 iconSize = new OpenLayers.Size(
171 feature.style.graphicWidth,
172 feature.style.graphicHeight);
175 // FIXME: At the moment, we only use this if we have an
176 // externalGraphic, because icon has no setOffset API Method.
179 * The Text format does all sorts of parseFloating
180 * The result of a parseFloat for a bogus string is NaN. That
181 * means the three possible values here are undefined, NaN, or a
182 * number. The previous check was an identity check for null. This
183 * means it was failing for all undefined or NaN. A slightly better
184 * check is for undefined. An even better check is to see if the
185 * value is a number (see #1441).
187 if (feature.style.graphicXOffset !== undefined
188 && feature.style.graphicYOffset !== undefined) {
189 iconOffset = new OpenLayers.Pixel(
190 feature.style.graphicXOffset,
191 feature.style.graphicYOffset);
194 if (feature.style.externalGraphic != null) {
195 data.icon = new OpenLayers.Icon(feature.style.externalGraphic,
199 data.icon = OpenLayers.Marker.defaultIcon();
201 //allows for the case where the image url is not
202 // specified but the size is. use a default icon
203 // but change the size
204 if (iconSize != null) {
205 data.icon.setSize(iconSize);
209 if ((feature.attributes.title != null)
210 && (feature.attributes.description != null)) {
211 data['popupContentHTML'] =
212 '<h2>'+feature.attributes.title+'</h2>' +
213 '<p>'+feature.attributes.description+'</p>';
216 data['overflow'] = feature.attributes.overflow || "auto";
218 var markerFeature = new OpenLayers.Feature(this, location, data);
219 this.features.push(markerFeature);
220 var marker = markerFeature.createMarker();
221 if ((feature.attributes.title != null)
222 && (feature.attributes.description != null)) {
223 marker.events.register('click', markerFeature, this.markerClick);
225 this.addMarker(marker);
227 this.events.triggerEvent("loadend");
231 * Property: markerClick
236 markerClick: function(evt) {
237 var sameMarkerClicked = (this == this.layer.selectedFeature);
238 this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
239 for(var i=0, len=this.layer.map.popups.length; i<len; i++) {
240 this.layer.map.removePopup(this.layer.map.popups[i]);
242 if (!sameMarkerClicked) {
243 this.layer.map.addPopup(this.createPopup());
245 OpenLayers.Event.stop(evt);
249 * Method: clearFeatures
251 clearFeatures: function() {
252 if (this.features != null) {
253 while(this.features.length > 0) {
254 var feature = this.features[0];
255 OpenLayers.Util.removeItem(this.features, feature);
261 CLASS_NAME: "OpenLayers.Layer.Text"