[PLUGINS] +clavettes et dependances
[lhc/web/clavette_www.git] / www / plugins / gis / lib / leaflet / plugins / KML.js
diff --git a/www/plugins/gis/lib/leaflet/plugins/KML.js b/www/plugins/gis/lib/leaflet/plugins/KML.js
new file mode 100755 (executable)
index 0000000..2a7839d
--- /dev/null
@@ -0,0 +1,350 @@
+L.KML = L.FeatureGroup.extend({
+       options: {
+               async: true
+       },
+
+       initialize: function(kml, options) {
+               L.Util.setOptions(this, options);
+               this._kml = kml;
+               this._layers = {};
+
+               if (kml) {
+                       this.addKML(kml, options, this.options.async);
+               }
+       },
+
+       loadXML: function(url, cb, options, async) {
+               if (async === undefined) async = this.options.async;
+               if (options === undefined) options = this.options;
+
+               var req = new window.XMLHttpRequest();
+               req.open('GET', url, async);
+               try {
+                       req.overrideMimeType('text/xml'); // unsupported by IE
+               } catch(e) {}
+               req.onreadystatechange = function() {
+                       if (req.readyState !== 4) return;
+                       if (req.status === 200) cb(req.responseXML, options);
+               };
+               req.send(null);
+       },
+
+       addKML: function(url, options, async) {
+               var _this = this;
+               var cb = function(gpx, options) { _this._addKML(gpx, options); };
+               this.loadXML(url, cb, options, async);
+       },
+
+       _addKML: function(xml, options) {
+               var layers = L.KML.parseKML(xml);
+               if (!layers || !layers.length) return;
+               for (var i = 0; i < layers.length; i++) {
+                       this.fire('addlayer', {
+                               layer: layers[i]
+                       });
+                       this.addLayer(layers[i]);
+               }
+               this.latLngs = L.KML.getLatLngs(xml);
+               this.fire('loaded');
+       },
+
+       latLngs: []
+});
+
+L.Util.extend(L.KML, {
+
+       parseKML: function (xml) {
+               var style = this.parseStyle(xml);
+               this.parseStyleMap(xml, style);
+               var el = xml.getElementsByTagName('Folder');
+               var layers = [], l;
+               for (var i = 0; i < el.length; i++) {
+                       if (!this._check_folder(el[i])) { continue; }
+                       l = this.parseFolder(el[i], style);
+                       if (l) { layers.push(l); }
+               }
+               el = xml.getElementsByTagName('Placemark');
+               for (var j = 0; j < el.length; j++) {
+                       if (!this._check_folder(el[j])) { continue; }
+                       l = this.parsePlacemark(el[j], xml, style);
+                       if (l) { layers.push(l); }
+               }
+               return layers;
+       },
+
+       // Return false if e's first parent Folder is not [folder]
+       // - returns true if no parent Folders
+       _check_folder: function (e, folder) {
+               e = e.parentElement;
+               while (e && e.tagName !== 'Folder')
+               {
+                       e = e.parentElement;
+               }
+               return !e || e === folder;
+       },
+
+       parseStyle: function (xml) {
+               var style = {};
+               var sl = xml.getElementsByTagName('Style');
+
+               //for (var i = 0; i < sl.length; i++) {
+               var attributes = {color: true, width: true, Icon: true, href: true,
+                                                 hotSpot: true};
+
+               function _parse(xml) {
+                       var options = {};
+                       for (var i = 0; i < xml.childNodes.length; i++) {
+                               var e = xml.childNodes[i];
+                               var key = e.tagName;
+                               if (!attributes[key]) { continue; }
+                               if (key === 'hotSpot')
+                               {
+                                       for (var j = 0; j < e.attributes.length; j++) {
+                                               options[e.attributes[j].name] = e.attributes[j].nodeValue;
+                                       }
+                               } else {
+                                       var value = e.childNodes[0].nodeValue;
+                                       if (key === 'color') {
+                                               options.opacity = parseInt(value.substring(0, 2), 16) / 255.0;
+                                               options.color = '#' + value.substring(6, 8) + value.substring(4, 6) + value.substring(2, 4);
+                                       } else if (key === 'width') {
+                                               options.weight = value;
+                                       } else if (key === 'Icon') {
+                                               ioptions = _parse(e);
+                                               if (ioptions.href) { options.href = ioptions.href; }
+                                       } else if (key === 'href') {
+                                               options.href = value;
+                                       }
+                               }
+                       }
+                       return options;
+               }
+
+               for (var i = 0; i < sl.length; i++) {
+                       var e = sl[i], el;
+                       var options = {}, poptions = {}, ioptions = {};
+                       el = e.getElementsByTagName('LineStyle');
+                       if (el && el[0]) { options = _parse(el[0]); }
+                       el = e.getElementsByTagName('PolyStyle');
+                       if (el && el[0]) { poptions = _parse(el[0]); }
+                       if (poptions.color) { options.fillColor = poptions.color; }
+                       if (poptions.opacity) { options.fillOpacity = poptions.opacity; }
+                       el = e.getElementsByTagName('IconStyle');
+                       if (el && el[0]) { ioptions = _parse(el[0]); }
+                       if (ioptions.href) {
+                               // save anchor info until the image is loaded
+                               options.icon = new L.KMLIcon({
+                                       iconUrl: ioptions.href,
+                                       shadowUrl: null,
+                                       iconAnchorRef: {x: ioptions.x, y: ioptions.y},
+                                       iconAnchorType: {x: ioptions.xunits, y: ioptions.yunits}
+                               });
+                       }
+                       style['#' + e.getAttribute('id')] = options;
+               }
+               return style;
+       },
+       
+       parseStyleMap: function (xml, existingStyles) {
+               var sl = xml.getElementsByTagName('StyleMap');
+               
+               for (var i = 0; i < sl.length; i++) {
+                       var e = sl[i], el;
+                       var smKey, smStyleUrl;
+                       
+                       el = e.getElementsByTagName('key');
+                       if (el && el[0]) { smKey = el[0].textContent; }
+                       el = e.getElementsByTagName('styleUrl');
+                       if (el && el[0]) { smStyleUrl = el[0].textContent; }
+                       
+                       if (smKey === 'normal')
+                       {
+                               existingStyles['#' + e.getAttribute('id')] = existingStyles[smStyleUrl];
+                       }
+               }
+               
+               return;
+       },
+
+       parseFolder: function (xml, style) {
+               var el, layers = [], l;
+               el = xml.getElementsByTagName('Folder');
+               for (var i = 0; i < el.length; i++) {
+                       if (!this._check_folder(el[i], xml)) { continue; }
+                       l = this.parseFolder(el[i], style);
+                       if (l) { layers.push(l); }
+               }
+               el = xml.getElementsByTagName('Placemark');
+               for (var j = 0; j < el.length; j++) {
+                       if (!this._check_folder(el[j], xml)) { continue; }
+                       l = this.parsePlacemark(el[j], xml, style);
+                       if (l) { layers.push(l); }
+               }
+               if (!layers.length) { return; }
+               if (layers.length === 1) { return layers[0]; }
+               return new L.FeatureGroup(layers);
+       },
+
+       parsePlacemark: function (place, xml, style) {
+               var i, j, el, options = {};
+               el = place.getElementsByTagName('styleUrl');
+               for (i = 0; i < el.length; i++) {
+                       var url = el[i].childNodes[0].nodeValue;
+                       for (var a in style[url]) {
+                               options[a] = style[url][a];
+                       }
+               }
+               var layers = [];
+
+               var parse = ['LineString', 'Polygon', 'Point'];
+               for (j in parse) {
+                       // for jshint
+                       if (true)
+                       {
+                               var tag = parse[j];
+                               el = place.getElementsByTagName(tag);
+                               for (i = 0; i < el.length; i++) {
+                                       var l = this['parse' + tag](el[i], xml, options);
+                                       if (l) { layers.push(l); }
+                               }
+                       }
+               }
+
+               if (!layers.length) {
+                       return;
+               }
+               var layer = layers[0];
+               if (layers.length > 1) {
+                       layer = new L.FeatureGroup(layers);
+               }
+
+               var name, descr = '';
+               el = place.getElementsByTagName('name');
+               if (el.length && el[0].childNodes.length) {
+                       name = el[0].childNodes[0].nodeValue;
+               }
+               el = place.getElementsByTagName('description');
+               for (i = 0; i < el.length; i++) {
+                       for (j = 0; j < el[i].childNodes.length; j++) {
+                               descr = descr + el[i].childNodes[j].nodeValue;
+                       }
+               }
+
+               if (name) {
+                       layer.bindPopup('<h2>' + name + '</h2>' + descr);
+               }
+
+               return layer;
+       },
+
+       parseCoords: function (xml) {
+               var el = xml.getElementsByTagName('coordinates');
+               return this._read_coords(el[0]);
+       },
+
+       parseLineString: function (line, xml, options) {
+               var coords = this.parseCoords(line);
+               if (!coords.length) { return; }
+               return new L.Polyline(coords, options);
+       },
+
+       parsePoint: function (line, xml, options) {
+               var el = line.getElementsByTagName('coordinates');
+               if (!el.length) {
+                       return;
+               }
+               var ll = el[0].childNodes[0].nodeValue.split(',');
+               return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options);
+       },
+
+       parsePolygon: function (line, xml, options) {
+               var el, polys = [], inner = [], i, coords;
+               el = line.getElementsByTagName('outerBoundaryIs');
+               for (i = 0; i < el.length; i++) {
+                       coords = this.parseCoords(el[i]);
+                       if (coords) {
+                               polys.push(coords);
+                       }
+               }
+               el = line.getElementsByTagName('innerBoundaryIs');
+               for (i = 0; i < el.length; i++) {
+                       coords = this.parseCoords(el[i]);
+                       if (coords) {
+                               inner.push(coords);
+                       }
+               }
+               if (!polys.length) {
+                       return;
+               }
+               if (options.fillColor) {
+                       options.fill = true;
+               }
+               if (polys.length === 1) {
+                       return new L.Polygon(polys.concat(inner), options);
+               }
+               return new L.MultiPolygon(polys, options);
+       },
+
+       getLatLngs: function (xml) {
+               var el = xml.getElementsByTagName('coordinates');
+               var coords = [];
+               for (var j = 0; j < el.length; j++) {
+                       // text might span many childNodes
+                       coords = coords.concat(this._read_coords(el[j]));
+               }
+               return coords;
+       },
+
+       _read_coords: function (el) {
+               var text = '', coords = [], i;
+               for (i = 0; i < el.childNodes.length; i++) {
+                       text = text + el.childNodes[i].nodeValue;
+               }
+               text = text.split(/[\s\n]+/);
+               for (i = 0; i < text.length; i++) {
+                       var ll = text[i].split(',');
+                       if (ll.length < 2) {
+                               continue;
+                       }
+                       coords.push(new L.LatLng(ll[1], ll[0]));
+               }
+               return coords;
+       }
+
+});
+
+L.KMLIcon = L.Icon.extend({
+
+       createIcon: function () {
+               var img = this._createIcon('icon');
+               img.onload = function () {
+                       var i = img;
+                       this.style.width = i.width + 'px';
+                       this.style.height = i.height + 'px';
+
+                       if (this.anchorType.x === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
+                               img.style.marginLeft = (-this.anchor.x * i.width) + 'px';
+                       }
+                       if (this.anchorType.y === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
+                               img.style.marginTop  = (-(1 - this.anchor.y) * i.height) + 'px';
+                       }
+                       this.style.display = '';
+               };
+               return img;
+       },
+
+       _setIconStyles: function (img, name) {
+               L.Icon.prototype._setIconStyles.apply(this, [img, name]);
+               // save anchor information to the image
+               img.anchor = this.options.iconAnchorRef;
+               img.anchorType = this.options.iconAnchorType;
+       }
+});
+
+
+L.KMLMarker = L.Marker.extend({
+       options: {
+               icon: new L.KMLIcon.Default()
+       }
+});
+