[PLUGINS] +clavettes et dependances
[lhc/web/clavette_www.git] / www / plugins / gis / lib / leaflet / plugins / KML.js
1 L.KML = L.FeatureGroup.extend({
2 options: {
3 async: true
4 },
5
6 initialize: function(kml, options) {
7 L.Util.setOptions(this, options);
8 this._kml = kml;
9 this._layers = {};
10
11 if (kml) {
12 this.addKML(kml, options, this.options.async);
13 }
14 },
15
16 loadXML: function(url, cb, options, async) {
17 if (async === undefined) async = this.options.async;
18 if (options === undefined) options = this.options;
19
20 var req = new window.XMLHttpRequest();
21 req.open('GET', url, async);
22 try {
23 req.overrideMimeType('text/xml'); // unsupported by IE
24 } catch(e) {}
25 req.onreadystatechange = function() {
26 if (req.readyState !== 4) return;
27 if (req.status === 200) cb(req.responseXML, options);
28 };
29 req.send(null);
30 },
31
32 addKML: function(url, options, async) {
33 var _this = this;
34 var cb = function(gpx, options) { _this._addKML(gpx, options); };
35 this.loadXML(url, cb, options, async);
36 },
37
38 _addKML: function(xml, options) {
39 var layers = L.KML.parseKML(xml);
40 if (!layers || !layers.length) return;
41 for (var i = 0; i < layers.length; i++) {
42 this.fire('addlayer', {
43 layer: layers[i]
44 });
45 this.addLayer(layers[i]);
46 }
47 this.latLngs = L.KML.getLatLngs(xml);
48 this.fire('loaded');
49 },
50
51 latLngs: []
52 });
53
54 L.Util.extend(L.KML, {
55
56 parseKML: function (xml) {
57 var style = this.parseStyle(xml);
58 this.parseStyleMap(xml, style);
59 var el = xml.getElementsByTagName('Folder');
60 var layers = [], l;
61 for (var i = 0; i < el.length; i++) {
62 if (!this._check_folder(el[i])) { continue; }
63 l = this.parseFolder(el[i], style);
64 if (l) { layers.push(l); }
65 }
66 el = xml.getElementsByTagName('Placemark');
67 for (var j = 0; j < el.length; j++) {
68 if (!this._check_folder(el[j])) { continue; }
69 l = this.parsePlacemark(el[j], xml, style);
70 if (l) { layers.push(l); }
71 }
72 return layers;
73 },
74
75 // Return false if e's first parent Folder is not [folder]
76 // - returns true if no parent Folders
77 _check_folder: function (e, folder) {
78 e = e.parentElement;
79 while (e && e.tagName !== 'Folder')
80 {
81 e = e.parentElement;
82 }
83 return !e || e === folder;
84 },
85
86 parseStyle: function (xml) {
87 var style = {};
88 var sl = xml.getElementsByTagName('Style');
89
90 //for (var i = 0; i < sl.length; i++) {
91 var attributes = {color: true, width: true, Icon: true, href: true,
92 hotSpot: true};
93
94 function _parse(xml) {
95 var options = {};
96 for (var i = 0; i < xml.childNodes.length; i++) {
97 var e = xml.childNodes[i];
98 var key = e.tagName;
99 if (!attributes[key]) { continue; }
100 if (key === 'hotSpot')
101 {
102 for (var j = 0; j < e.attributes.length; j++) {
103 options[e.attributes[j].name] = e.attributes[j].nodeValue;
104 }
105 } else {
106 var value = e.childNodes[0].nodeValue;
107 if (key === 'color') {
108 options.opacity = parseInt(value.substring(0, 2), 16) / 255.0;
109 options.color = '#' + value.substring(6, 8) + value.substring(4, 6) + value.substring(2, 4);
110 } else if (key === 'width') {
111 options.weight = value;
112 } else if (key === 'Icon') {
113 ioptions = _parse(e);
114 if (ioptions.href) { options.href = ioptions.href; }
115 } else if (key === 'href') {
116 options.href = value;
117 }
118 }
119 }
120 return options;
121 }
122
123 for (var i = 0; i < sl.length; i++) {
124 var e = sl[i], el;
125 var options = {}, poptions = {}, ioptions = {};
126 el = e.getElementsByTagName('LineStyle');
127 if (el && el[0]) { options = _parse(el[0]); }
128 el = e.getElementsByTagName('PolyStyle');
129 if (el && el[0]) { poptions = _parse(el[0]); }
130 if (poptions.color) { options.fillColor = poptions.color; }
131 if (poptions.opacity) { options.fillOpacity = poptions.opacity; }
132 el = e.getElementsByTagName('IconStyle');
133 if (el && el[0]) { ioptions = _parse(el[0]); }
134 if (ioptions.href) {
135 // save anchor info until the image is loaded
136 options.icon = new L.KMLIcon({
137 iconUrl: ioptions.href,
138 shadowUrl: null,
139 iconAnchorRef: {x: ioptions.x, y: ioptions.y},
140 iconAnchorType: {x: ioptions.xunits, y: ioptions.yunits}
141 });
142 }
143 style['#' + e.getAttribute('id')] = options;
144 }
145 return style;
146 },
147
148 parseStyleMap: function (xml, existingStyles) {
149 var sl = xml.getElementsByTagName('StyleMap');
150
151 for (var i = 0; i < sl.length; i++) {
152 var e = sl[i], el;
153 var smKey, smStyleUrl;
154
155 el = e.getElementsByTagName('key');
156 if (el && el[0]) { smKey = el[0].textContent; }
157 el = e.getElementsByTagName('styleUrl');
158 if (el && el[0]) { smStyleUrl = el[0].textContent; }
159
160 if (smKey === 'normal')
161 {
162 existingStyles['#' + e.getAttribute('id')] = existingStyles[smStyleUrl];
163 }
164 }
165
166 return;
167 },
168
169 parseFolder: function (xml, style) {
170 var el, layers = [], l;
171 el = xml.getElementsByTagName('Folder');
172 for (var i = 0; i < el.length; i++) {
173 if (!this._check_folder(el[i], xml)) { continue; }
174 l = this.parseFolder(el[i], style);
175 if (l) { layers.push(l); }
176 }
177 el = xml.getElementsByTagName('Placemark');
178 for (var j = 0; j < el.length; j++) {
179 if (!this._check_folder(el[j], xml)) { continue; }
180 l = this.parsePlacemark(el[j], xml, style);
181 if (l) { layers.push(l); }
182 }
183 if (!layers.length) { return; }
184 if (layers.length === 1) { return layers[0]; }
185 return new L.FeatureGroup(layers);
186 },
187
188 parsePlacemark: function (place, xml, style) {
189 var i, j, el, options = {};
190 el = place.getElementsByTagName('styleUrl');
191 for (i = 0; i < el.length; i++) {
192 var url = el[i].childNodes[0].nodeValue;
193 for (var a in style[url]) {
194 options[a] = style[url][a];
195 }
196 }
197 var layers = [];
198
199 var parse = ['LineString', 'Polygon', 'Point'];
200 for (j in parse) {
201 // for jshint
202 if (true)
203 {
204 var tag = parse[j];
205 el = place.getElementsByTagName(tag);
206 for (i = 0; i < el.length; i++) {
207 var l = this['parse' + tag](el[i], xml, options);
208 if (l) { layers.push(l); }
209 }
210 }
211 }
212
213 if (!layers.length) {
214 return;
215 }
216 var layer = layers[0];
217 if (layers.length > 1) {
218 layer = new L.FeatureGroup(layers);
219 }
220
221 var name, descr = '';
222 el = place.getElementsByTagName('name');
223 if (el.length && el[0].childNodes.length) {
224 name = el[0].childNodes[0].nodeValue;
225 }
226 el = place.getElementsByTagName('description');
227 for (i = 0; i < el.length; i++) {
228 for (j = 0; j < el[i].childNodes.length; j++) {
229 descr = descr + el[i].childNodes[j].nodeValue;
230 }
231 }
232
233 if (name) {
234 layer.bindPopup('<h2>' + name + '</h2>' + descr);
235 }
236
237 return layer;
238 },
239
240 parseCoords: function (xml) {
241 var el = xml.getElementsByTagName('coordinates');
242 return this._read_coords(el[0]);
243 },
244
245 parseLineString: function (line, xml, options) {
246 var coords = this.parseCoords(line);
247 if (!coords.length) { return; }
248 return new L.Polyline(coords, options);
249 },
250
251 parsePoint: function (line, xml, options) {
252 var el = line.getElementsByTagName('coordinates');
253 if (!el.length) {
254 return;
255 }
256 var ll = el[0].childNodes[0].nodeValue.split(',');
257 return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options);
258 },
259
260 parsePolygon: function (line, xml, options) {
261 var el, polys = [], inner = [], i, coords;
262 el = line.getElementsByTagName('outerBoundaryIs');
263 for (i = 0; i < el.length; i++) {
264 coords = this.parseCoords(el[i]);
265 if (coords) {
266 polys.push(coords);
267 }
268 }
269 el = line.getElementsByTagName('innerBoundaryIs');
270 for (i = 0; i < el.length; i++) {
271 coords = this.parseCoords(el[i]);
272 if (coords) {
273 inner.push(coords);
274 }
275 }
276 if (!polys.length) {
277 return;
278 }
279 if (options.fillColor) {
280 options.fill = true;
281 }
282 if (polys.length === 1) {
283 return new L.Polygon(polys.concat(inner), options);
284 }
285 return new L.MultiPolygon(polys, options);
286 },
287
288 getLatLngs: function (xml) {
289 var el = xml.getElementsByTagName('coordinates');
290 var coords = [];
291 for (var j = 0; j < el.length; j++) {
292 // text might span many childNodes
293 coords = coords.concat(this._read_coords(el[j]));
294 }
295 return coords;
296 },
297
298 _read_coords: function (el) {
299 var text = '', coords = [], i;
300 for (i = 0; i < el.childNodes.length; i++) {
301 text = text + el.childNodes[i].nodeValue;
302 }
303 text = text.split(/[\s\n]+/);
304 for (i = 0; i < text.length; i++) {
305 var ll = text[i].split(',');
306 if (ll.length < 2) {
307 continue;
308 }
309 coords.push(new L.LatLng(ll[1], ll[0]));
310 }
311 return coords;
312 }
313
314 });
315
316 L.KMLIcon = L.Icon.extend({
317
318 createIcon: function () {
319 var img = this._createIcon('icon');
320 img.onload = function () {
321 var i = img;
322 this.style.width = i.width + 'px';
323 this.style.height = i.height + 'px';
324
325 if (this.anchorType.x === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
326 img.style.marginLeft = (-this.anchor.x * i.width) + 'px';
327 }
328 if (this.anchorType.y === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
329 img.style.marginTop = (-(1 - this.anchor.y) * i.height) + 'px';
330 }
331 this.style.display = '';
332 };
333 return img;
334 },
335
336 _setIconStyles: function (img, name) {
337 L.Icon.prototype._setIconStyles.apply(this, [img, name]);
338 // save anchor information to the image
339 img.anchor = this.options.iconAnchorRef;
340 img.anchorType = this.options.iconAnchorType;
341 }
342 });
343
344
345 L.KMLMarker = L.Marker.extend({
346 options: {
347 icon: new L.KMLIcon.Default()
348 }
349 });
350