基于timemap 1.5,实现时空浏览
This commit is contained in:
parent
c3edc3f083
commit
6dc1248cfa
|
@ -273,7 +273,7 @@ class DataController extends Zend_Controller_Action
|
||||||
$dateformat="D M j Y G:i:s O";
|
$dateformat="D M j Y G:i:s O";
|
||||||
$md = new MetadataTable();
|
$md = new MetadataTable();
|
||||||
$db=$md->getAdapter();
|
$db=$md->getAdapter();
|
||||||
$state=$db->query('select id,uuid,title,description,timebegin,timeend from metadata where timebegin is not null');
|
$state=$db->query('select id,uuid,title,timebegin,timeend from metadata where timebegin is not null');
|
||||||
$rows=$state->fetchAll();
|
$rows=$state->fetchAll();
|
||||||
$timexml='<data>';
|
$timexml='<data>';
|
||||||
foreach($rows as $row) {
|
foreach($rows as $row) {
|
||||||
|
@ -331,6 +331,14 @@ class DataController extends Zend_Controller_Action
|
||||||
$this->_helper->json($geomd);
|
$this->_helper->json($geomd);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
* 时空动态浏览
|
||||||
|
*/
|
||||||
|
function timemapAction()
|
||||||
|
{
|
||||||
|
$sql='select id,uuid,west,south,north,east,title,timebegin,timeend,description from metadata where timebegin is not null';
|
||||||
|
$this->view->rows=$this->db->fetchAll($sql);
|
||||||
|
}
|
||||||
|
/*
|
||||||
* 返回XML源文件
|
* 返回XML源文件
|
||||||
*/
|
*/
|
||||||
function xmlAction()
|
function xmlAction()
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
$this->headTitle($this->config->title->site);
|
||||||
|
$this->headTitle($this->config->title->data);
|
||||||
|
$this->headTitle('时空导航');
|
||||||
|
$this->headTitle()->setSeparator(' - ');
|
||||||
|
$this->headLink()->appendStylesheet('/css/metadata.css');
|
||||||
|
$this->breadcrumb('<a href="/">首页</a>');
|
||||||
|
$this->breadcrumb('<a href="/data">'.$this->config->title->data.'</a>');
|
||||||
|
$this->breadcrumb('<a href="/data/timeline">时空导航</a>');
|
||||||
|
$this->breadcrumb()->setSeparator(' > ');
|
||||||
|
$this->headScript()->appendFile('http://maps.google.com/maps?file=api&v=2&key=ABQIAAAACD-MqkkoOm60o_dvwdcKVhThiRESR0xRCe9JKd36EL3glTk0OxTsRzifkUWmTTrYWaE7dY1lYUlGxA');
|
||||||
|
$this->headScript()->appendFile('/js/timeline_var.js');
|
||||||
|
$this->headScript()->appendFile('/js/timeline_js/timeline-api.js');
|
||||||
|
$this->headScript()->appendFile('/js/timemap/timemap.js');
|
||||||
|
$this->headScript()->captureStart();
|
||||||
|
?>
|
||||||
|
var tm;
|
||||||
|
window.onload=function() {
|
||||||
|
tm = TimeMap.init({
|
||||||
|
mapId: "map", // Id of map div element (required)
|
||||||
|
timelineId: "timeline", // Id of timeline div element (required)
|
||||||
|
options: {
|
||||||
|
eventIconPath: "../images/"
|
||||||
|
},
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
id: "artists",
|
||||||
|
title: "Artists",
|
||||||
|
theme: "orange",
|
||||||
|
// note that the lines below are now the preferred syntax
|
||||||
|
type: "basic",
|
||||||
|
options: {
|
||||||
|
items: [
|
||||||
|
<?php
|
||||||
|
foreach($this->rows as $row) : ?>
|
||||||
|
{
|
||||||
|
"start" : "<?php echo $row['timebegin']; ?>",
|
||||||
|
<?php if ($row['timeend']!='') : ?>
|
||||||
|
"end" : "<?php echo $row['timeend']; ?>",
|
||||||
|
<?php endif; ?>
|
||||||
|
"polygon" : [
|
||||||
|
{
|
||||||
|
"lat" : <?php echo $row['south']; ?>,
|
||||||
|
"lon" : <?php echo $row['west']; ?>
|
||||||
|
},{
|
||||||
|
"lat" : <?php echo $row['north']; ?>,
|
||||||
|
"lon" : <?php echo $row['west']; ?>
|
||||||
|
},{
|
||||||
|
"lat" : <?php echo $row['north']; ?>,
|
||||||
|
"lon" : <?php echo $row['east']; ?>
|
||||||
|
},{
|
||||||
|
"lat" : <?php echo $row['south']; ?>,
|
||||||
|
"lon" : <?php echo $row['east']; ?>
|
||||||
|
},{
|
||||||
|
"lat" : <?php echo $row['south']; ?>,
|
||||||
|
"lon" : <?php echo $row['west']; ?>
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title" : "<?php echo $row['title']; ?>",
|
||||||
|
"options" : {
|
||||||
|
// set the full HTML for the info window
|
||||||
|
"infoHtml": "<a href=/data/<?php echo $row['uuid']; ?>><?php echo $row['title']; ?></a><hr /><img src=/data/thumb/id/<?php echo $row['id']; ?> />"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
<?php endforeach; ?>
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
bandIntervals: [
|
||||||
|
Timeline.DateTime.MONTH,
|
||||||
|
Timeline.DateTime.DECADE
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// manipulate the timemap further here if you like
|
||||||
|
}
|
||||||
|
window.onunload=GUnload();
|
||||||
|
<?php $this->headScript()->captureEnd(); ?>
|
||||||
|
<div id='tools'><?= $this->partial('data/tools.phtml'); ?></div>
|
||||||
|
<div id="timemap" style="clear:both;">
|
||||||
|
<div id="timeline" style="height:300px;width:100%;"></div>
|
||||||
|
<div id="map" style="height:300px;"></div>
|
||||||
|
</div>
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* Flickr Loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* Flickr loader factory - inherits from jsonp loader
|
||||||
|
*
|
||||||
|
* <p>This is a loader for data from Flickr. You probably want to use it with a
|
||||||
|
* URL for the Flickr Geo Feed API: <a href="http://www.flickr.com/services/feeds/geo/">http://www.flickr.com/services/feeds/geo/</a></p>
|
||||||
|
*
|
||||||
|
* <p>The loader takes a full URL, minus the JSONP callback function.</p>
|
||||||
|
*
|
||||||
|
* <p>Depends on:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>loaders/jsonp.js</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "Flickr Dataset",
|
||||||
|
type: "flickr",
|
||||||
|
options: {
|
||||||
|
// This is just the latest geotagged photo stream - try adding
|
||||||
|
// an "id" or "tag" or "photoset" parameter to get what you want
|
||||||
|
url: "http://www.flickr.com/services/feeds/geo/?format=json&jsoncallback="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {String} url Full JSONP url of Flickr feed to load
|
||||||
|
* {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 Flickr
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.flickr = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.jsonp(options);
|
||||||
|
|
||||||
|
// preload function for Flickr feeds
|
||||||
|
loader.preload = function(data) {
|
||||||
|
return data["items"];
|
||||||
|
};
|
||||||
|
|
||||||
|
// transform function for Flickr feeds
|
||||||
|
loader.transform = function(data) {
|
||||||
|
var item = {
|
||||||
|
title: data["title"],
|
||||||
|
start: data["date_taken"],
|
||||||
|
point: {
|
||||||
|
lat: data["latitude"],
|
||||||
|
lon: data["longitude"]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
description: data["description"]
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (options.transformFunction)
|
||||||
|
item = options.transformFunction(item);
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
};
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* Google Spreadsheet Loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* Google spreadsheet loader factory - inherits from jsonp loader.
|
||||||
|
*
|
||||||
|
* <p>This is a loader for data from Google Spreadsheets. Takes an optional map
|
||||||
|
* to indicate which columns contain which data elements; the default column
|
||||||
|
* names (case-insensitive) are: title, description, start, end, lat, lon</p>
|
||||||
|
*
|
||||||
|
* <p>See <a href="http://code.google.com/apis/spreadsheets/docs/2.0/reference.html#gsx_reference">http://code.google.com/apis/spreadsheets/docs/2.0/reference.html#gsx_reference</a>
|
||||||
|
* for details on how spreadsheet column ids are derived. Note that date fields
|
||||||
|
* must be in yyyy-mm-dd format - you may need to set the cell format as "plain text"
|
||||||
|
* in the spreadsheet (Google's automatic date formatting won't work).</p>
|
||||||
|
*
|
||||||
|
* <p>The loader takes either a full URL, minus the JSONP callback function, or
|
||||||
|
* just the spreadsheet key. Note that the spreadsheet must be published.</p>
|
||||||
|
*
|
||||||
|
* <p>Depends on:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>loaders/jsonp.js</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "Google Spreadsheet by key",
|
||||||
|
type: "gss",
|
||||||
|
options: {
|
||||||
|
key: "pjUcDAp-oNIOjmx3LCxT4XA" // Spreadsheet key
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Google Spreadsheet by url",
|
||||||
|
type: "gss",
|
||||||
|
options: {
|
||||||
|
url: "http://spreadsheets.google.com/feeds/list/pjUcDAp-oNIOjmx3LCxT4XA/1/public/values?alt=json-in-script&callback="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {String} key Key of spreadsheet to load, or
|
||||||
|
* {String} url Full JSONP url of spreadsheet to load
|
||||||
|
* {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 Google Spreadsheets
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.gss = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.jsonp(options);
|
||||||
|
|
||||||
|
// use key if no URL was supplied
|
||||||
|
if (!loader.url) {
|
||||||
|
loader.url = "http://spreadsheets.google.com/feeds/list/" +
|
||||||
|
options.key + "/1/public/values?alt=json-in-script&callback=";
|
||||||
|
}
|
||||||
|
|
||||||
|
// column map
|
||||||
|
loader.map = options.map;
|
||||||
|
|
||||||
|
// preload function for spreadsheet data
|
||||||
|
loader.preload = function(data) {
|
||||||
|
return data["feed"]["entry"];
|
||||||
|
};
|
||||||
|
|
||||||
|
// transform function for spreadsheet data
|
||||||
|
loader.transform = function(data) {
|
||||||
|
// map spreadsheet column ids to corresponding TimeMap elements
|
||||||
|
var fieldMap = loader.map || TimeMap.loaders.gss.map;
|
||||||
|
var getField = function(f) {
|
||||||
|
if (f in fieldMap && fieldMap[f]) {
|
||||||
|
return data['gsx$' + fieldMap[f]]['$t'];
|
||||||
|
} else return false;
|
||||||
|
};
|
||||||
|
var item = {
|
||||||
|
title: getField("title"),
|
||||||
|
start: getField("start"),
|
||||||
|
point: {
|
||||||
|
lat: getField("lat"),
|
||||||
|
lon: getField("lon")
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
description: getField("description")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// hook for further transformation
|
||||||
|
if (options.transformFunction)
|
||||||
|
item = options.transformFunction(item);
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1:1 map of expected spreadsheet column ids.
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.gss.map = {
|
||||||
|
'title':'title',
|
||||||
|
'description':'description',
|
||||||
|
'start':'start',
|
||||||
|
'end':'end',
|
||||||
|
'lat':'lat',
|
||||||
|
'lon':'lon'
|
||||||
|
};
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* JSON Loaders (JSONP, JSON String)
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* JSONP loader class - expects a service that takes a callback function name as
|
||||||
|
* the last URL parameter.
|
||||||
|
*
|
||||||
|
* <p>The jsonp loader assumes that the JSON can be loaded from a url to which a
|
||||||
|
* callback function name can be appended, e.g. "http://www.test.com/getsomejson.php?callback="
|
||||||
|
* The loader then appends a nonce function name which the JSON should include.
|
||||||
|
* This works for services like Google Spreadsheets, etc., and accepts remote URLs.</p>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "JSONP Dataset",
|
||||||
|
type: "jsonp",
|
||||||
|
options: {
|
||||||
|
url: "http://www.test.com/getsomejson.php?callback="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {Array} url URL of JSON service to load, callback name left off
|
||||||
|
* {Function} preloadFunction Function to call on data before loading
|
||||||
|
* {Function} transformFunction Function to call on individual items before loading
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.jsonp = function(options) {
|
||||||
|
// get standard functions
|
||||||
|
TimeMap.loaders.mixin(this, options);
|
||||||
|
// get URL to load
|
||||||
|
this.url = options.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSONP load function.
|
||||||
|
*
|
||||||
|
* @param {TimeMapDataset} dataset Dataset to load data into
|
||||||
|
* @param {Function} callback Function to call once data is loaded
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.jsonp.prototype.load = function(dataset, callback) {
|
||||||
|
var loader = this;
|
||||||
|
// get items
|
||||||
|
TimeMap.loaders.jsonp.read(this.url, function(result) {
|
||||||
|
// load
|
||||||
|
items = loader.preload(result);
|
||||||
|
dataset.loadItems(items, loader.transform);
|
||||||
|
// callback
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static - for naming anonymous callback functions
|
||||||
|
* @type int
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.jsonp.counter = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static - reads JSON from a URL, assuming that the service is set up to apply
|
||||||
|
* a callback function specified in the URL parameters.
|
||||||
|
*
|
||||||
|
* @param {String} jsonUrl URL to load, missing the callback function name
|
||||||
|
* @param {function} f Callback function to apply to returned data
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.jsonp.read = function(url, f) {
|
||||||
|
// Define a unique function name
|
||||||
|
var callbackName = "_" + TimeMap.loaders.jsonp.counter++;
|
||||||
|
|
||||||
|
TimeMap.loaders.jsonp[callbackName] = function(result) {
|
||||||
|
// Pass result to user function
|
||||||
|
f(result);
|
||||||
|
// Delete the callback function
|
||||||
|
delete TimeMap.loaders.jsonp[callbackName];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a script tag, set its src attribute and add it to the document
|
||||||
|
// This triggers the HTTP request and submits the query
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.src = url + "TimeMap.loaders.jsonp." + callbackName;
|
||||||
|
document.body.appendChild(script);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* JSON string loader factory - expects a plain JSON array.
|
||||||
|
* Inherits from remote loader.
|
||||||
|
*
|
||||||
|
* <p>The json_string loader assumes an array of items in plain JSON, with no
|
||||||
|
* callback function - this will require a local URL.</p>
|
||||||
|
*
|
||||||
|
* <p>Depends on:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>lib/json2.pack.js</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "JSON String Dataset",
|
||||||
|
type: "json_string",
|
||||||
|
options: {
|
||||||
|
url: "mydata.json" // Must be a local URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {Array} url URL of JSON service to load, callback name left off
|
||||||
|
* {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 JSON strings
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.json_string = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.remote(options);
|
||||||
|
loader.parse = JSON.parse;
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probably the default json loader should be json_string, not
|
||||||
|
// jsonp. I may change this in the future, so I'd encourage you to use
|
||||||
|
// the specific one you want.
|
||||||
|
TimeMap.loaders.json = TimeMap.loaders.jsonp;
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* KML Loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*globals GXml, TimeMap */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* KML loader factory - inherits from remote loader
|
||||||
|
*
|
||||||
|
* <p>This is a loader class for KML files. Currently supports all geometry
|
||||||
|
* types (point, polyline, polygon, and overlay) and multiple geometries.</p>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "KML Dataset",
|
||||||
|
type: "kml",
|
||||||
|
options: {
|
||||||
|
url: "mydata.kml" // Must be local
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {Array} url URL of KML 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 KML
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.kml = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.remote(options);
|
||||||
|
loader.parse = TimeMap.loaders.kml.parse;
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static function to parse KML with time data.
|
||||||
|
*
|
||||||
|
* @param {XML string} kml KML to be parsed
|
||||||
|
* @return {TimeMapItem Array} Array of TimeMapItems
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.kml.parse = function(kml) {
|
||||||
|
var items = [], data, kmlnode, placemarks, pm, i, j;
|
||||||
|
kmlnode = GXml.parse(kml);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// recursive time data search
|
||||||
|
var findNodeTime = function(n, data) {
|
||||||
|
var check = false;
|
||||||
|
// look for instant timestamp
|
||||||
|
var nList = getNodeList(n, "TimeStamp");
|
||||||
|
if (nList.length > 0) {
|
||||||
|
data.start = getTagValue(nList[0], "when");
|
||||||
|
check = true;
|
||||||
|
}
|
||||||
|
// otherwise look for span
|
||||||
|
else {
|
||||||
|
nList = getNodeList(n, "TimeSpan");
|
||||||
|
if (nList.length > 0) {
|
||||||
|
data.start = getTagValue(nList[0], "begin");
|
||||||
|
data.end = getTagValue(nList[0], "end") ||
|
||||||
|
// unbounded spans end at the present time
|
||||||
|
formatDate(new Date());
|
||||||
|
check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// try looking recursively at parent nodes
|
||||||
|
if (!check) {
|
||||||
|
var pn = n.parentNode;
|
||||||
|
if (pn.nodeName == "Folder" || pn.nodeName=="Document") {
|
||||||
|
findNodeTime(pn, data);
|
||||||
|
}
|
||||||
|
pn = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// look for placemarks
|
||||||
|
placemarks = getNodeList(kmlnode, "Placemark");
|
||||||
|
for (i=0; i<placemarks.length; i++) {
|
||||||
|
pm = placemarks[i];
|
||||||
|
data = { options: {} };
|
||||||
|
// get title & description
|
||||||
|
data.title = getTagValue(pm, "name");
|
||||||
|
data.options.description = getTagValue(pm, "description");
|
||||||
|
// get time information
|
||||||
|
findNodeTime(pm, data);
|
||||||
|
// find placemark(s)
|
||||||
|
var nList, coords, pmobj;
|
||||||
|
data.placemarks = [];
|
||||||
|
// look for marker
|
||||||
|
nList = getNodeList(pm, "Point");
|
||||||
|
for (j=0; j<nList.length; j++) {
|
||||||
|
pmobj = { point: {} };
|
||||||
|
// get lat/lon
|
||||||
|
coords = getTagValue(nList[j], "coordinates");
|
||||||
|
pmobj.point = makePoint(coords, 1);
|
||||||
|
data.placemarks.push(pmobj);
|
||||||
|
}
|
||||||
|
// look for polylines
|
||||||
|
nList = getNodeList(pm, "LineString");
|
||||||
|
for (j=0; j<nList.length; j++) {
|
||||||
|
pmobj = { polyline: [] };
|
||||||
|
// get lat/lon
|
||||||
|
coords = getTagValue(nList[j], "coordinates");
|
||||||
|
pmobj.polyline = makePoly(coords, 1);
|
||||||
|
data.placemarks.push(pmobj);
|
||||||
|
}
|
||||||
|
// look for polygons
|
||||||
|
nList = getNodeList(pm, "Polygon");
|
||||||
|
for (j=0; j<nList.length; j++) {
|
||||||
|
pmobj = { polygon: [] };
|
||||||
|
// get lat/lon
|
||||||
|
coords = getTagValue(nList[j], "coordinates");
|
||||||
|
pmobj.polygon = makePoly(coords, 1);
|
||||||
|
// XXX: worth closing unclosed polygons?
|
||||||
|
data.placemarks.push(pmobj);
|
||||||
|
}
|
||||||
|
items.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for ground overlays
|
||||||
|
placemarks = getNodeList(kmlnode, "GroundOverlay");
|
||||||
|
for (i=0; i<placemarks.length; i++) {
|
||||||
|
pm = placemarks[i];
|
||||||
|
data = { options: {}, overlay: {} };
|
||||||
|
// get title & description
|
||||||
|
data.title = getTagValue(pm, "name");
|
||||||
|
data.options.description = getTagValue(pm, "description");
|
||||||
|
// get time information
|
||||||
|
findNodeTime(pm, data);
|
||||||
|
// get image
|
||||||
|
nList = getNodeList(pm, "Icon");
|
||||||
|
data.overlay.image = getTagValue(nList[0], "href");
|
||||||
|
// get coordinates
|
||||||
|
nList = getNodeList(pm, "LatLonBox");
|
||||||
|
data.overlay.north = getTagValue(nList[0], "north");
|
||||||
|
data.overlay.south = getTagValue(nList[0], "south");
|
||||||
|
data.overlay.east = getTagValue(nList[0], "east");
|
||||||
|
data.overlay.west = getTagValue(nList[0], "west");
|
||||||
|
items.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
kmlnode = null;
|
||||||
|
placemarks = null;
|
||||||
|
pm = null;
|
||||||
|
nList = null;
|
||||||
|
return items;
|
||||||
|
};
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* Metaweb Loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Loader
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* Metaweb loader factory - inherits from jsonp loader
|
||||||
|
*
|
||||||
|
* <p>This is a loader for data from the Metaweb service at freebase.com. See
|
||||||
|
* the API documentation at <a href="http://www.freebase.com/view/en/documentation">http://www.freebase.com/view/en/documentation</a> for
|
||||||
|
* a description of how to write MQL queries. This code is based on code from
|
||||||
|
* the API site.</p>
|
||||||
|
*
|
||||||
|
* <p>Depends on:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>lib/json2.pack.js</li>
|
||||||
|
* <li>loaders/jsonp.js</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @example Usage in TimeMap.init():
|
||||||
|
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "Freebase Dataset",
|
||||||
|
type: "metaweb",
|
||||||
|
options: {
|
||||||
|
query: [
|
||||||
|
{
|
||||||
|
// query here - see Metaweb API
|
||||||
|
}
|
||||||
|
],
|
||||||
|
transformFunction: function(data) {
|
||||||
|
// map returned data to the expected format - see
|
||||||
|
// http://code.google.com/p/timemap/wiki/JsonFormat
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader:<pre>
|
||||||
|
* {Object} query MQL query to load
|
||||||
|
* {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 MetaWeb
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.metaweb = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.jsonp(options);
|
||||||
|
|
||||||
|
// Host and service - default to freebase.com
|
||||||
|
loader.HOST = options.host || "http://www.freebase.com";
|
||||||
|
loader.QUERY_SERVICE = options.service || "/api/service/mqlread";
|
||||||
|
|
||||||
|
// Metaweb preload functon
|
||||||
|
loader.preload = function(data) {
|
||||||
|
// Open outer envelope
|
||||||
|
var innerEnvelope = data.qname;
|
||||||
|
// Make sure the query was successful
|
||||||
|
if (innerEnvelope.code.indexOf("/api/status/ok") != 0) {
|
||||||
|
// uncomment for debugging
|
||||||
|
/*
|
||||||
|
// If error, get error message and throw
|
||||||
|
var error = innerEnvelope.messages[0];
|
||||||
|
throw error.code + ": " + error.message;
|
||||||
|
*/
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// Get result from inner envelope
|
||||||
|
var result = innerEnvelope.result;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// format the query URL for Metaweb
|
||||||
|
var q = options.query || {};
|
||||||
|
var querytext = encodeURIComponent(JSON.stringify({qname: {query: q}}));
|
||||||
|
|
||||||
|
// Build the URL using encoded query text and the callback name
|
||||||
|
loader.url = loader.HOST + loader.QUERY_SERVICE + "?queries=" + querytext + "&callback=";
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue