]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Layer/Text.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Layer / Text.js
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. */
4
5
6 /**
7  * @requires OpenLayers/Layer/Markers.js
8  * @requires OpenLayers/Request/XMLHttpRequest.js
9  */
10
11 /**
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.
17  *
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.
32  *
33  * Example text file:
34  * (code)
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
37  * (end)
38  *
39  * Inherits from:
40  *  - <OpenLayers.Layer.Markers>
41  */
42 OpenLayers.Layer.Text = OpenLayers.Class(OpenLayers.Layer.Markers, {
43
44     /**
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. 
48      */
49     location:null,
50
51     /** 
52      * Property: features
53      * {Array(<OpenLayers.Feature>)} 
54      */
55     features: null,
56     
57     /**
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.
61      */
62     formatOptions: null, 
63
64     /** 
65      * Property: selectedFeature
66      * {<OpenLayers.Feature>}
67      */
68     selectedFeature: null,
69
70     /**
71      * Constructor: OpenLayers.Layer.Text
72      * Create a text layer.
73      * 
74      * Parameters:
75      * name - {String} 
76      * options - {Object} Object with properties to be set on the layer.
77      *     Must include <location> property.
78      */
79     initialize: function(name, options) {
80         OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
81         this.features = new Array();
82     },
83
84     /**
85      * APIMethod: destroy 
86      */
87     destroy: function() {
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);
94         this.clearFeatures();
95         this.features = null;
96     },
97     
98     /**
99      * Method: loadText
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.
102      */
103     loadText: function() {
104         if (!this.loaded) {
105             if (this.location != null) {
106
107                 var onFail = function(e) {
108                     this.events.triggerEvent("loadend");
109                 };
110
111                 this.events.triggerEvent("loadstart");
112                 OpenLayers.Request.GET({
113                     url: this.location,
114                     success: this.parseData,
115                     failure: onFail,
116                     scope: this
117                 });
118                 this.loaded = true;
119             }
120         }    
121     },    
122     
123     /**
124      * Method: moveTo
125      * If layer is visible and Text has not been loaded, load Text. 
126      * 
127      * Parameters:
128      * bounds - {Object} 
129      * zoomChanged - {Object} 
130      * minor - {Object} 
131      */
132     moveTo:function(bounds, zoomChanged, minor) {
133         OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
134         if(this.visibility && !this.loaded){
135             this.loadText();
136         }
137     },
138     
139     /**
140      * Method: parseData
141      *
142      * Parameters:
143      * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>} 
144      */
145     parseData: function(ajaxRequest) {
146         var text = ajaxRequest.responseText;
147         
148         var options = {};
149         
150         OpenLayers.Util.extend(options, this.formatOptions);
151         
152         if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
153             options.externalProjection = this.projection;
154             options.internalProjection = this.map.getProjectionObject();
155         }    
156         
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++) {
160             var data = {};
161             var feature = features[i];
162             var location;
163             var iconSize, iconOffset;
164             
165             location = new OpenLayers.LonLat(feature.geometry.x, 
166                                              feature.geometry.y);
167             
168             if (feature.style.graphicWidth 
169                 && feature.style.graphicHeight) {
170                 iconSize = new OpenLayers.Size(
171                     feature.style.graphicWidth,
172                     feature.style.graphicHeight);
173             }        
174             
175             // FIXME: At the moment, we only use this if we have an 
176             // externalGraphic, because icon has no setOffset API Method.
177             /**
178              * FIXME FIRST!!
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).
186              */
187             if (feature.style.graphicXOffset !== undefined
188                 && feature.style.graphicYOffset !== undefined) {
189                 iconOffset = new OpenLayers.Pixel(
190                     feature.style.graphicXOffset, 
191                     feature.style.graphicYOffset);
192             }
193             
194             if (feature.style.externalGraphic != null) {
195                 data.icon = new OpenLayers.Icon(feature.style.externalGraphic, 
196                                                 iconSize, 
197                                                 iconOffset);
198             } else {
199                 data.icon = OpenLayers.Marker.defaultIcon();
200
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);
206                 }
207             }
208             
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>';
214             }
215             
216             data['overflow'] = feature.attributes.overflow || "auto"; 
217             
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);
224             }
225             this.addMarker(marker);
226         }
227         this.events.triggerEvent("loadend");
228     },
229     
230     /**
231      * Property: markerClick
232      * 
233      * Parameters:
234      * evt - {Event} 
235      */
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]);
241         }
242         if (!sameMarkerClicked) {
243             this.layer.map.addPopup(this.createPopup()); 
244         }
245         OpenLayers.Event.stop(evt);
246     },
247
248     /**
249      * Method: clearFeatures
250      */
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);
256                 feature.destroy();
257             }
258         }        
259     },
260
261     CLASS_NAME: "OpenLayers.Layer.Text"
262 });