204 lines
6.9 KiB
JavaScript
204 lines
6.9 KiB
JavaScript
|
/*
|
||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @fileOverview
|
||
|
* GeoRSS Loader
|
||
|
*
|
||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||
|
*/
|
||
|
|
||
|
/*globals GXml, TimeMap, TimeMapDataset */
|
||
|
|
||
|
/**
|
||
|
* @class
|
||
|
* GeoRSS loader factory - inherits from remote loader.
|
||
|
*
|
||
|
* <p>This is a loader class for GeoRSS feeds. Parsing is complicated by the
|
||
|
* diversity of GeoRSS formats; this parser handles:</p>
|
||
|
* <ul>
|
||
|
* <li>RSS feeds</li>
|
||
|
* <li>Atom feeds</li>
|
||
|
* </ul>
|
||
|
* <p>and looks for geographic information in the following formats:</p>
|
||
|
* <ul>
|
||
|
* <li>GeoRSS-Simple</li>
|
||
|
* <li>GML </li>
|
||
|
* <li>W3C Geo</li>
|
||
|
* </ul>
|
||
|
* <p>At the moment, this only supports points; polygons, polylines, and boxes
|
||
|
* will be added at some later point.</p>
|
||
|
*
|
||
|
* @example Usage in TimeMap.init():
|
||
|
|
||
|
datasets: [
|
||
|
{
|
||
|
title: "GeoRSS Dataset",
|
||
|
type: "georss", // Data to be loaded in GeoRSS
|
||
|
options: {
|
||
|
url: "mydata.rss" // GeoRSS file to load - must be a local URL
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
*
|
||
|
* @param {Object} options All options for the loader:<pre>
|
||
|
* {Array} url URL of GeoRSS file to load (NB: must be local address)
|
||
|
* {Function} preloadFunction Function to call on data before loading
|
||
|
* {Function} transformFunction Function to call on individual items before loading
|
||
|
* </pre>
|
||
|
* @return {TimeMap.loaders.remote} Remote loader configured for GeoRSS
|
||
|
*/
|
||
|
TimeMap.loaders.georss = function(options) {
|
||
|
var loader = new TimeMap.loaders.remote(options);
|
||
|
loader.parse = TimeMap.loaders.georss.parse;
|
||
|
return loader;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Static function to parse GeoRSS
|
||
|
*
|
||
|
* @param {XML text} rss GeoRSS to be parsed
|
||
|
* @return {TimeMapItem Array} Array of TimeMapItems
|
||
|
*/
|
||
|
TimeMap.loaders.georss.parse = function(rss) {
|
||
|
var items = [], data, node, placemarks, pm;
|
||
|
node = GXml.parse(rss);
|
||
|
|
||
|
// get TimeMap utilty functions
|
||
|
// assigning to variables should compress better
|
||
|
var util = TimeMap.util;
|
||
|
var getTagValue = util.getTagValue,
|
||
|
getNodeList = util.getNodeList,
|
||
|
makePoint = util.makePoint,
|
||
|
makePoly = util.makePoly,
|
||
|
formatDate = util.formatDate,
|
||
|
nsMap = util.nsMap;
|
||
|
|
||
|
// define namespaces
|
||
|
nsMap.georss = 'http://www.georss.org/georss';
|
||
|
nsMap.gml = 'http://www.opengis.net/gml';
|
||
|
nsMap.geo = 'http://www.w3.org/2003/01/geo/wgs84_pos#';
|
||
|
nsMap.kml = 'http://www.opengis.net/kml/2.2';
|
||
|
|
||
|
// determine whether this is an Atom feed or an RSS feed
|
||
|
var feedType = (node.firstChild.tagName == 'rss') ? 'rss' : 'atom';
|
||
|
|
||
|
// look for placemarks
|
||
|
var tName = (feedType == 'rss' ? "item" : "entry");
|
||
|
placemarks = getNodeList(node, tName);
|
||
|
for (var i=0; i<placemarks.length; i++) {
|
||
|
pm = placemarks[i];
|
||
|
data = { options: {} };
|
||
|
// get title & description
|
||
|
data.title = getTagValue(pm, "title");
|
||
|
tName = (feedType == 'rss' ? "description" : "summary");
|
||
|
data.options.description = getTagValue(pm, tName);
|
||
|
// get time information, allowing KML-namespaced time elements
|
||
|
var nList = getNodeList(pm, "TimeStamp", "kml");
|
||
|
if (nList.length > 0) {
|
||
|
data.start = getTagValue(nList[0], "when", "kml");
|
||
|
}
|
||
|
// look for timespan
|
||
|
if (!data.start) {
|
||
|
nList = getNodeList(pm, "TimeSpan", "kml");
|
||
|
if (nList.length > 0) {
|
||
|
data.start = getTagValue(nList[0], "begin", "kml");
|
||
|
data.end = getTagValue(nList[0], "end", "kml") ||
|
||
|
// unbounded spans end at the present time
|
||
|
formatDate(new Date());
|
||
|
}
|
||
|
}
|
||
|
// otherwise, use pubDate/updated elements
|
||
|
if (!data.start) {
|
||
|
if (feedType == 'rss') {
|
||
|
// RSS needs date conversion
|
||
|
var d = new Date(Date.parse(getTagValue(pm, "pubDate")));
|
||
|
// reformat
|
||
|
data.start = formatDate(d);
|
||
|
} else {
|
||
|
// atom uses ISO 8601
|
||
|
data.start = getTagValue(pm, "updated");
|
||
|
}
|
||
|
}
|
||
|
// find placemark - single geometry only for the moment
|
||
|
PLACEMARK: {
|
||
|
var coords, geom;
|
||
|
// look for point, GeoRSS-Simple
|
||
|
coords = getTagValue(pm, "point", 'georss');
|
||
|
if (coords) {
|
||
|
data.point = makePoint(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
// look for point, GML
|
||
|
nList = getNodeList(pm, "Point", 'gml');
|
||
|
if (nList.length > 0) {
|
||
|
// GML <pos>
|
||
|
coords = getTagValue(nList[0], "pos", 'gml');
|
||
|
// GML <coordinates>
|
||
|
if (!coords) {
|
||
|
coords = getTagValue(nList[0], "coordinates", 'gml');
|
||
|
}
|
||
|
if (coords) {
|
||
|
data.point = makePoint(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
}
|
||
|
// look for point, W3C Geo
|
||
|
if (getTagValue(pm, "lat", 'geo')) {
|
||
|
coords = [
|
||
|
getTagValue(pm, "lat", 'geo'),
|
||
|
getTagValue(pm, "long", 'geo')
|
||
|
];
|
||
|
data.point = makePoint(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
// look for polyline, GeoRSS-Simple
|
||
|
coords = getTagValue(pm, "line", 'georss');
|
||
|
if (coords) {
|
||
|
data.polyline = makePoly(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
// look for polygon, GeoRSS-Simple
|
||
|
coords = getTagValue(pm, "polygon", 'georss');
|
||
|
if (coords) {
|
||
|
data.polygon = makePoly(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
// look for polyline, GML
|
||
|
nList = getNodeList(pm, "LineString", 'gml');
|
||
|
if (nList.length > 0) {
|
||
|
geom = "polyline";
|
||
|
} else {
|
||
|
nList = getNodeList(pm, "Polygon", 'gml');
|
||
|
if (nList.length > 0) {
|
||
|
geom = "polygon";
|
||
|
}
|
||
|
}
|
||
|
if (nList.length > 0) {
|
||
|
// GML <posList>
|
||
|
coords = getTagValue(nList[0], "posList", 'gml');
|
||
|
// GML <coordinates>
|
||
|
if (!coords) {
|
||
|
coords = getTagValue(nList[0], "coordinates", 'gml');
|
||
|
}
|
||
|
if (coords) {
|
||
|
data[geom] = makePoly(coords);
|
||
|
break PLACEMARK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// XXX: deal with boxes
|
||
|
}
|
||
|
items.push(data);
|
||
|
}
|
||
|
|
||
|
// clean up
|
||
|
node = null;
|
||
|
placemarks = null;
|
||
|
pm = null;
|
||
|
nList = null;
|
||
|
return items;
|
||
|
};
|