| | 1 | /* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license. |
|---|
| | 2 | * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt |
|---|
| | 3 | * for the full text of the license. */ |
|---|
| | 4 | |
|---|
| | 5 | /** |
|---|
| | 6 | * @requires OpenLayers/Format.js |
|---|
| | 7 | * |
|---|
| | 8 | * Class: OpenLayers.Format.APP |
|---|
| | 9 | * Write-only APP. Create a new instance with the |
|---|
| | 10 | * <OpenLayers.Format.APP> constructor. |
|---|
| | 11 | * |
|---|
| | 12 | * Inherits from: |
|---|
| | 13 | * - <OpenLayers.Format> |
|---|
| | 14 | */ |
|---|
| | 15 | OpenLayers.Format.APP = OpenLayers.Class(OpenLayers.Format.XML, { |
|---|
| | 16 | |
|---|
| | 17 | /** |
|---|
| | 18 | * APIProperty: rssns |
|---|
| | 19 | * RSS namespace to use. |
|---|
| | 20 | */ |
|---|
| | 21 | rssns: "http://backend.userland.com/rss2", |
|---|
| | 22 | |
|---|
| | 23 | /** |
|---|
| | 24 | * APIProperty: featurens |
|---|
| | 25 | * Feature Attributes namespace |
|---|
| | 26 | */ |
|---|
| | 27 | featureNS: "http://mapserver.gis.umn.edu/mapserver", |
|---|
| | 28 | |
|---|
| | 29 | /** |
|---|
| | 30 | * APIProperty: georssns |
|---|
| | 31 | * APP namespace to use. |
|---|
| | 32 | */ |
|---|
| | 33 | georssns: "http://www.georss.org/georss", |
|---|
| | 34 | |
|---|
| | 35 | |
|---|
| | 36 | /** |
|---|
| | 37 | * Constructor: OpenLayers.Format.APP |
|---|
| | 38 | * Create a new parser for APP |
|---|
| | 39 | * |
|---|
| | 40 | * Parameters: |
|---|
| | 41 | * options - {Object} An optional object whose properties will be set on |
|---|
| | 42 | * this instance. |
|---|
| | 43 | */ |
|---|
| | 44 | initialize: function(options) { |
|---|
| | 45 | OpenLayers.Format.prototype.initialize.apply(this, [options]); |
|---|
| | 46 | }, |
|---|
| | 47 | |
|---|
| | 48 | /** |
|---|
| | 49 | * APIMethod: read |
|---|
| | 50 | * Return a list of features from a APP doc |
|---|
| | 51 | |
|---|
| | 52 | * Parameters: |
|---|
| | 53 | * data - {Element} |
|---|
| | 54 | * |
|---|
| | 55 | * Returns: |
|---|
| | 56 | * An Array of <OpenLayers.Feature.Vector>s |
|---|
| | 57 | */ |
|---|
| | 58 | read: function(doc) { |
|---|
| | 59 | if (typeof doc == "string") { |
|---|
| | 60 | doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]); |
|---|
| | 61 | } |
|---|
| | 62 | |
|---|
| | 63 | /* Try RSS items first, then Atom entries */ |
|---|
| | 64 | var itemlist = null; |
|---|
| | 65 | itemlist = this.getElementsByTagNameNS(doc, '*', 'item'); |
|---|
| | 66 | if (itemlist.length == 0) { |
|---|
| | 67 | itemlist = this.getElementsByTagNameNS(doc, '*', 'entry'); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | var features = []; |
|---|
| | 71 | for(var i=0; i<itemlist.length; i++) { |
|---|
| | 72 | // this is horrendous - please change this |
|---|
| | 73 | var point = OpenLayers.Util.getNodes(itemlist[i], 'georss:point'); |
|---|
| | 74 | var lat = OpenLayers.Util.getNodes(itemlist[i], 'geo:lat'); |
|---|
| | 75 | var lon = OpenLayers.Util.getNodes(itemlist[i], 'geo:long'); |
|---|
| | 76 | if (point.length > 0) { |
|---|
| | 77 | var location = point[0].firstChild.nodeValue.trim().split(/\s+/); |
|---|
| | 78 | |
|---|
| | 79 | if (location.length !=2) { |
|---|
| | 80 | var location = point[0].firstChild.nodeValue.trim().split(/\s*,\s*/); |
|---|
| | 81 | } |
|---|
| | 82 | } else if (lat.length > 0 && lon.length > 0) { |
|---|
| | 83 | var location = [parseFloat(lat[0].firstChild.nodeValue), parseFloat(lon[0].firstChild.nodeValue)]; |
|---|
| | 84 | } else { |
|---|
| | 85 | continue; |
|---|
| | 86 | } |
|---|
| | 87 | var geometry = new OpenLayers.Geometry.Point(parseFloat(location[1]), |
|---|
| | 88 | parseFloat(location[0])); |
|---|
| | 89 | |
|---|
| | 90 | /* Provide defaults for title and description */ |
|---|
| | 91 | var title = "Untitled"; |
|---|
| | 92 | try { |
|---|
| | 93 | title = OpenLayers.Util.getNodes(itemlist[i], |
|---|
| | 94 | "title")[0].firstChild.nodeValue; |
|---|
| | 95 | } |
|---|
| | 96 | catch (e) { title="Untitled"; } |
|---|
| | 97 | |
|---|
| | 98 | /* First try RSS descriptions, then Atom summaries */ |
|---|
| | 99 | var descr_nodes = this.getElementsByTagNameNS(itemlist[i], |
|---|
| | 100 | "*", |
|---|
| | 101 | "description"); |
|---|
| | 102 | if (descr_nodes.length == 0) { |
|---|
| | 103 | descr_nodes = this.getElementsByTagNameNS(itemlist[i], |
|---|
| | 104 | "*", |
|---|
| | 105 | "summary"); |
|---|
| | 106 | } |
|---|
| | 107 | var description = "No description."; |
|---|
| | 108 | try { |
|---|
| | 109 | description = descr_nodes[0].firstChild.nodeValue; |
|---|
| | 110 | } |
|---|
| | 111 | catch (e) { description="No description."; } |
|---|
| | 112 | |
|---|
| | 113 | /* If no link URL is found in the first child node, try the |
|---|
| | 114 | href attribute */ |
|---|
| | 115 | var link = null; |
|---|
| | 116 | var edit_link = null; |
|---|
| | 117 | try { |
|---|
| | 118 | var link = OpenLayers.Util.getNodes(itemlist[i], "link")[0].firstChild.nodeValue; |
|---|
| | 119 | } |
|---|
| | 120 | catch (e) { |
|---|
| | 121 | var link_list = OpenLayers.Util.getNodes(itemlist[i], "link"); |
|---|
| | 122 | for (var i = 0; i < link_list.length; i++) { |
|---|
| | 123 | var this_link = link_list[i]; |
|---|
| | 124 | if (this_link.getAttribute("href") && this_link.getAttribute("rel") == "edit") { |
|---|
| | 125 | edit_link = this_link.getAttribute("href"); |
|---|
| | 126 | } else { |
|---|
| | 127 | link = this_link.getAttribute("href"); |
|---|
| | 128 | } |
|---|
| | 129 | } |
|---|
| | 130 | } |
|---|
| | 131 | |
|---|
| | 132 | var data = { |
|---|
| | 133 | "title": title, |
|---|
| | 134 | "description": description, |
|---|
| | 135 | "link": link, |
|---|
| | 136 | "edit_link": edit_link |
|---|
| | 137 | }; |
|---|
| | 138 | features.push(new OpenLayers.Feature.Vector(geometry, data)); |
|---|
| | 139 | } |
|---|
| | 140 | return features; |
|---|
| | 141 | }, |
|---|
| | 142 | |
|---|
| | 143 | |
|---|
| | 144 | /** |
|---|
| | 145 | * APIMethod: write |
|---|
| | 146 | * Accept Feature Collection, and return a string. |
|---|
| | 147 | * |
|---|
| | 148 | * Parameters: |
|---|
| | 149 | * features - Array({<OpenLayers.Feature.Vector>}) List of features to serialize into a string. |
|---|
| | 150 | */ |
|---|
| | 151 | write: function(features) { |
|---|
| | 152 | var georss; |
|---|
| | 153 | if(features instanceof Array) { |
|---|
| | 154 | georss = this.createElementNS(this.rssns, "rss"); |
|---|
| | 155 | for(var i=0; i < features.length; i++) { |
|---|
| | 156 | georss.appendChild(this.createFeatureXML(features[i])); |
|---|
| | 157 | } |
|---|
| | 158 | } else { |
|---|
| | 159 | georss = this.createFeatureXML(features); |
|---|
| | 160 | } |
|---|
| | 161 | return OpenLayers.Format.XML.prototype.write.apply(this, [georss]); |
|---|
| | 162 | }, |
|---|
| | 163 | |
|---|
| | 164 | /** |
|---|
| | 165 | * Method: createFeatureXML |
|---|
| | 166 | * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it. |
|---|
| | 167 | * |
|---|
| | 168 | * Parameters: |
|---|
| | 169 | * feature - {<OpenLayers.Feature.Vector>} |
|---|
| | 170 | * |
|---|
| | 171 | * Returns: |
|---|
| | 172 | * {DOMElement} |
|---|
| | 173 | */ |
|---|
| | 174 | createFeatureXML: function(feature) { |
|---|
| | 175 | var geometryNode = this.buildGeometryNode(feature.geometry); |
|---|
| | 176 | var featureNode = this.createElementNS(this.rssns, "item"); |
|---|
| | 177 | var titleNode = this.createElementNS(this.rssns, "title"); |
|---|
| | 178 | titleNode.appendChild(this.createTextNode(feature.attributes.title ? feature.attributes.title : "")); |
|---|
| | 179 | var descNode = this.createElementNS(this.rssns, "description"); |
|---|
| | 180 | descNode.appendChild(this.createTextNode(feature.attributes.description ? feature.attributes.description : "")); |
|---|
| | 181 | featureNode.appendChild(titleNode); |
|---|
| | 182 | featureNode.appendChild(descNode); |
|---|
| | 183 | for(var attr in feature.attributes) { |
|---|
| | 184 | if (attr == "edit_link" || attr == "title" || attr == "description" ) { continue; } |
|---|
| | 185 | var attrText = this.createTextNode(feature.attributes[attr]); |
|---|
| | 186 | var nodename = attr; |
|---|
| | 187 | if (attr.search(":") != -1) { |
|---|
| | 188 | nodename = attr.split(":")[1]; |
|---|
| | 189 | } |
|---|
| | 190 | var attrContainer = this.createElementNS(this.featureNS, "feature:"+nodename); |
|---|
| | 191 | attrContainer.appendChild(attrText); |
|---|
| | 192 | featureNode.appendChild(attrContainer); |
|---|
| | 193 | } |
|---|
| | 194 | featureNode.appendChild(geometryNode); |
|---|
| | 195 | return featureNode; |
|---|
| | 196 | }, |
|---|
| | 197 | |
|---|
| | 198 | /** |
|---|
| | 199 | * Method: buildGeometryNode |
|---|
| | 200 | * builds a APP node with a given geometry |
|---|
| | 201 | * |
|---|
| | 202 | * Parameters: |
|---|
| | 203 | * geometry - {<OpenLayers.Geometry>} |
|---|
| | 204 | */ |
|---|
| | 205 | buildGeometryNode: function(geometry) { |
|---|
| | 206 | var gml = ""; |
|---|
| | 207 | // match MultiPolygon or Polygon |
|---|
| | 208 | if (geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { |
|---|
| | 209 | gml = this.createElementNS(this.georssns, 'georss:polygon'); |
|---|
| | 210 | |
|---|
| | 211 | gml.appendChild(this.buildCoordinatesNode(geometry.components[0])); |
|---|
| | 212 | } |
|---|
| | 213 | // match MultiLineString or LineString |
|---|
| | 214 | else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { |
|---|
| | 215 | gml = this.createElementNS(this.georssns, 'georss:line'); |
|---|
| | 216 | |
|---|
| | 217 | gml.appendChild(this.buildCoordinatesNode(geometry)); |
|---|
| | 218 | } |
|---|
| | 219 | // match MultiPoint or Point |
|---|
| | 220 | else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { |
|---|
| | 221 | gml = this.createElementNS(this.georssns, 'georss:point'); |
|---|
| | 222 | gml.appendChild(this.buildCoordinatesNode(geometry)); |
|---|
| | 223 | } else { |
|---|
| | 224 | alert("Couldn't parse " + geometry.CLASS_NAME); |
|---|
| | 225 | } |
|---|
| | 226 | return gml; |
|---|
| | 227 | }, |
|---|
| | 228 | |
|---|
| | 229 | /** |
|---|
| | 230 | * Method: buildCoordinatesNode |
|---|
| | 231 | * |
|---|
| | 232 | * Parameters: |
|---|
| | 233 | * geometry - {<OpenLayers.Geometry>} |
|---|
| | 234 | */ |
|---|
| | 235 | buildCoordinatesNode: function(geometry) { |
|---|
| | 236 | var points = null; |
|---|
| | 237 | |
|---|
| | 238 | if (geometry.components) { |
|---|
| | 239 | points = geometry.components; |
|---|
| | 240 | } |
|---|
| | 241 | |
|---|
| | 242 | var path = ""; |
|---|
| | 243 | if (points) { |
|---|
| | 244 | for (var i = 0; i < points.length; i++) { |
|---|
| | 245 | path += points[i].y + " " + points[i].x + " "; |
|---|
| | 246 | } |
|---|
| | 247 | } else { |
|---|
| | 248 | path += geometry.y + " " + geometry.x + " "; |
|---|
| | 249 | } |
|---|
| | 250 | return this.createTextNode(path); |
|---|
| | 251 | }, |
|---|
| | 252 | |
|---|
| | 253 | CLASS_NAME: "OpenLayers.Format.APP" |
|---|
| | 254 | }); |