update timemap to version 1.6
This commit is contained in:
parent
8acf29a8c3
commit
fc689a66f2
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,23 +9,24 @@
|
||||||
*
|
*
|
||||||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// for JSLint
|
||||||
|
/*global TimeMap */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* Flickr loader factory - inherits from jsonp loader
|
* Flickr loader: Load JSONP data from Flickr.
|
||||||
*
|
*
|
||||||
* <p>This is a loader for data from Flickr. You probably want to use it with a
|
* <p>This is a loader for Flickr data. 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>
|
* 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>The loader takes a full URL, minus the JSONP callback function.</p>
|
||||||
|
*
|
||||||
|
* @augments TimeMap.loaders.jsonp
|
||||||
|
* @requires loaders/json.js
|
||||||
*
|
*
|
||||||
* <p>Depends on:</p>
|
* @example
|
||||||
* <ul>
|
TimeMap.init({
|
||||||
* <li>loaders/jsonp.js</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @example Usage in TimeMap.init():
|
|
||||||
|
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "Flickr Dataset",
|
title: "Flickr Dataset",
|
||||||
|
@ -36,43 +37,56 @@
|
||||||
url: "http://www.flickr.com/services/feeds/geo/?format=json&jsoncallback="
|
url: "http://www.flickr.com/services/feeds/geo/?format=json&jsoncallback="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/pathlines.html">Flickr Pathlines Example</a>
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader
|
||||||
* {String} url Full JSONP url of Flickr feed to load
|
* @param {String} options.url Full JSONP url of Flickr feed to load
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.jsonp})
|
||||||
* {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) {
|
TimeMap.loaders.flickr = function(options) {
|
||||||
var loader = new TimeMap.loaders.jsonp(options);
|
var loader = new TimeMap.loaders.jsonp(options);
|
||||||
|
|
||||||
// preload function for Flickr feeds
|
/**
|
||||||
|
* Preload function for Flickr feeds
|
||||||
|
* @name TimeMap.loaders.flickr#preload
|
||||||
|
* @function
|
||||||
|
* @parameter {Object} data Data to preload
|
||||||
|
* @return {Array} data Array of item data
|
||||||
|
*/
|
||||||
loader.preload = function(data) {
|
loader.preload = function(data) {
|
||||||
return data["items"];
|
return data["items"];
|
||||||
};
|
};
|
||||||
|
|
||||||
// transform function for Flickr feeds
|
/**
|
||||||
|
* Transform function for Flickr feeds
|
||||||
|
* @name TimeMap.loaders.flickr#transform
|
||||||
|
* @function
|
||||||
|
* @parameter {Object} data Data to transform
|
||||||
|
* @return {Object} data Transformed data for one item
|
||||||
|
*/
|
||||||
loader.transform = function(data) {
|
loader.transform = function(data) {
|
||||||
var item = {
|
var item = {
|
||||||
title: data["title"],
|
title: data.title,
|
||||||
start: data["date_taken"],
|
start: data.date_taken,
|
||||||
point: {
|
point: {
|
||||||
lat: data["latitude"],
|
lat: data.latitude,
|
||||||
lon: data["longitude"]
|
lon: data.longitude
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
description: data["description"]
|
description: data.description
|
||||||
.replace(/>/g, ">")
|
.replace(/>/g, ">")
|
||||||
.replace(/</g, "<")
|
.replace(/</g, "<")
|
||||||
.replace(/"/g, '"')
|
.replace(/"/g, '"')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (options.transformFunction)
|
if (options.transformFunction) {
|
||||||
item = options.transformFunction(item);
|
item = options.transformFunction(item);
|
||||||
|
}
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
|
||||||
return loader;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* GeoRSS loader factory - inherits from remote loader.
|
* GeoRSS loader: Load GeoRSS feeds.
|
||||||
*
|
*
|
||||||
* <p>This is a loader class for GeoRSS feeds. Parsing is complicated by the
|
* <p> Parsing is complicated by the
|
||||||
* diversity of GeoRSS formats; this parser handles:</p>
|
* diversity of GeoRSS formats; this parser handles:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>RSS feeds</li>
|
* <li>RSS feeds</li>
|
||||||
|
@ -28,11 +28,16 @@
|
||||||
* <li>GML </li>
|
* <li>GML </li>
|
||||||
* <li>W3C Geo</li>
|
* <li>W3C Geo</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>At the moment, this only supports points; polygons, polylines, and boxes
|
* <p>At the moment, this only supports points, polygons, polylines; boxes
|
||||||
* will be added at some later point.</p>
|
* may be added at some later point.</p>
|
||||||
*
|
*
|
||||||
* @example Usage in TimeMap.init():
|
* @augments TimeMap.loaders.xml
|
||||||
|
* @requires loaders/xml.js
|
||||||
|
* @requires param.js
|
||||||
|
* @borrows TimeMap.loaders.georss.parse as #parse
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "GeoRSS Dataset",
|
title: "GeoRSS Dataset",
|
||||||
|
@ -41,35 +46,35 @@
|
||||||
url: "mydata.rss" // GeoRSS file to load - must be a local URL
|
url: "mydata.rss" // GeoRSS file to load - must be a local URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/earthquake_georss.html">GeoRSS Example</a>
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader:
|
||||||
* {Array} url URL of GeoRSS file to load (NB: must be local address)
|
* @param {String} options.url URL of GeoRSS file to load (NB: must be local address)
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.xml})
|
||||||
* {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) {
|
TimeMap.loaders.georss = function(options) {
|
||||||
var loader = new TimeMap.loaders.remote(options);
|
var loader = new TimeMap.loaders.xml(options);
|
||||||
loader.parse = TimeMap.loaders.georss.parse;
|
loader.parse = TimeMap.loaders.georss.parse;
|
||||||
return loader;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static function to parse GeoRSS
|
* Static function to parse GeoRSS
|
||||||
*
|
*
|
||||||
* @param {XML text} rss GeoRSS to be parsed
|
* @param {String} rss GeoRSS string to be parsed
|
||||||
* @return {TimeMapItem Array} Array of TimeMapItems
|
* @return {TimeMapItem[]} Array of TimeMapItems
|
||||||
*/
|
*/
|
||||||
TimeMap.loaders.georss.parse = function(rss) {
|
TimeMap.loaders.georss.parse = function(rss) {
|
||||||
var items = [], data, node, placemarks, pm;
|
var items = [], data, node, placemarks, pm, i;
|
||||||
node = GXml.parse(rss);
|
node = GXml.parse(rss);
|
||||||
|
|
||||||
// get TimeMap utilty functions
|
// get TimeMap utilty functions
|
||||||
// assigning to variables should compress better
|
// assigning to variables should compress better
|
||||||
var util = TimeMap.util;
|
var util = TimeMap.util,
|
||||||
var getTagValue = util.getTagValue,
|
getTagValue = util.getTagValue,
|
||||||
getNodeList = util.getNodeList,
|
getNodeList = util.getNodeList,
|
||||||
makePoint = util.makePoint,
|
makePoint = util.makePoint,
|
||||||
makePoly = util.makePoly,
|
makePoly = util.makePoly,
|
||||||
|
@ -88,7 +93,7 @@ TimeMap.loaders.georss.parse = function(rss) {
|
||||||
// look for placemarks
|
// look for placemarks
|
||||||
var tName = (feedType == 'rss' ? "item" : "entry");
|
var tName = (feedType == 'rss' ? "item" : "entry");
|
||||||
placemarks = getNodeList(node, tName);
|
placemarks = getNodeList(node, tName);
|
||||||
for (var i=0; i<placemarks.length; i++) {
|
for (i=0; i<placemarks.length; i++) {
|
||||||
pm = placemarks[i];
|
pm = placemarks[i];
|
||||||
data = { options: {} };
|
data = { options: {} };
|
||||||
// get title & description
|
// get title & description
|
||||||
|
@ -122,8 +127,9 @@ TimeMap.loaders.georss.parse = function(rss) {
|
||||||
data.start = getTagValue(pm, "updated");
|
data.start = getTagValue(pm, "updated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// find placemark - single geometry only for the moment
|
// find placemark - single geometry only for the moment
|
||||||
PLACEMARK: {
|
var done = false;
|
||||||
|
PLACEMARK: while (!done) {
|
||||||
var coords, geom;
|
var coords, geom;
|
||||||
// look for point, GeoRSS-Simple
|
// look for point, GeoRSS-Simple
|
||||||
coords = getTagValue(pm, "point", 'georss');
|
coords = getTagValue(pm, "point", 'georss');
|
||||||
|
@ -189,15 +195,16 @@ TimeMap.loaders.georss.parse = function(rss) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: deal with boxes
|
// XXX: deal with boxes
|
||||||
|
|
||||||
|
done = true;
|
||||||
}
|
}
|
||||||
|
// look for any extra tags specified
|
||||||
|
this.parseExtra(data, pm);
|
||||||
items.push(data);
|
items.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
node = null;
|
node = placemarks = pm = nList = null;
|
||||||
placemarks = null;
|
|
||||||
pm = null;
|
|
||||||
nList = null;
|
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,12 +9,15 @@
|
||||||
*
|
*
|
||||||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// for JSLint
|
||||||
|
/*global TimeMap, TimeMapItem */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* Google spreadsheet loader factory - inherits from jsonp loader.
|
* Google Spreadsheet loader.
|
||||||
*
|
*
|
||||||
* <p>This is a loader for data from Google Spreadsheets. Takes an optional map
|
* <p>This is a loader for data from Google Spreadsheets. The constructor takes an optional map
|
||||||
* to indicate which columns contain which data elements; the default column
|
* to indicate which columns contain which data elements; the default column
|
||||||
* names (case-insensitive) are: title, description, start, end, lat, lon</p>
|
* names (case-insensitive) are: title, description, start, end, lat, lon</p>
|
||||||
*
|
*
|
||||||
|
@ -24,15 +27,14 @@
|
||||||
* in the spreadsheet (Google's automatic date formatting won't work).</p>
|
* 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
|
* <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>
|
* just the spreadsheet key. Note that the spreadsheet must be published.</p>
|
||||||
|
*
|
||||||
|
* @augments TimeMap.loaders.jsonp
|
||||||
|
* @requires param.js
|
||||||
|
* @requires loaders/json.js
|
||||||
*
|
*
|
||||||
* <p>Depends on:</p>
|
* @example
|
||||||
* <ul>
|
TimeMap.init({
|
||||||
* <li>loaders/jsonp.js</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @example Usage in TimeMap.init():
|
|
||||||
|
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "Google Spreadsheet by key",
|
title: "Google Spreadsheet by key",
|
||||||
|
@ -48,70 +50,104 @@
|
||||||
url: "http://spreadsheets.google.com/feeds/list/pjUcDAp-oNIOjmx3LCxT4XA/1/public/values?alt=json-in-script&callback="
|
url: "http://spreadsheets.google.com/feeds/list/pjUcDAp-oNIOjmx3LCxT4XA/1/public/values?alt=json-in-script&callback="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/google_spreadsheet.html">Google Spreadsheet Example</a>
|
||||||
|
* @see <a href="../../examples/google_spreadsheet_columns.html">Google Spreadsheet Example, Arbitrary Columns</a>
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader:
|
||||||
* {String} key Key of spreadsheet to load, or
|
* @param {String} options.key Key of spreadsheet to load, or
|
||||||
* {String} url Full JSONP url of spreadsheet to load
|
* @param {String} options.url Full JSONP url of spreadsheet to load
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {Object} [options.paramMap] Map of paramName:columnName pairs for core parameters,
|
||||||
* {Function} transformFunction Function to call on individual items before loading
|
* if using non-standard column names; see keys in
|
||||||
* </pre>
|
* {@link TimeMap.loaders.base#params} for the standard param names
|
||||||
* @return {TimeMap.loaders.remote} Remote loader configured for Google Spreadsheets
|
* @param {String[]} [options.extraColumns] Array of additional columns to load; all named columns will be
|
||||||
|
* loaded into the item.opts object.
|
||||||
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.jsonp})
|
||||||
*/
|
*/
|
||||||
TimeMap.loaders.gss = function(options) {
|
TimeMap.loaders.gss = function(options) {
|
||||||
var loader = new TimeMap.loaders.jsonp(options);
|
var loader = new TimeMap.loaders.jsonp(options),
|
||||||
|
params = loader.params, paramName, x,
|
||||||
|
setParamField = TimeMap.loaders.gss.setParamField,
|
||||||
|
paramMap = options.paramMap || {},
|
||||||
|
extraColumns = options.extraColumns || [];
|
||||||
|
|
||||||
// use key if no URL was supplied
|
// use key if no URL was supplied
|
||||||
if (!loader.url) {
|
if (!loader.url) {
|
||||||
loader.url = "http://spreadsheets.google.com/feeds/list/" +
|
loader.url = "http://spreadsheets.google.com/feeds/list/" +
|
||||||
options.key + "/1/public/values?alt=json-in-script&callback=";
|
options.key + "/1/public/values?alt=json-in-script&callback=";
|
||||||
}
|
}
|
||||||
|
|
||||||
// column map
|
|
||||||
loader.map = options.map;
|
|
||||||
|
|
||||||
// preload function for spreadsheet data
|
// Set up additional columns
|
||||||
|
for (x=0; x < extraColumns.length; x++) {
|
||||||
|
paramName = extraColumns[x];
|
||||||
|
params[paramName] = new TimeMap.params.OptionParam(paramName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up parameters to work with Google Spreadsheets
|
||||||
|
for (paramName in params) {
|
||||||
|
if (params.hasOwnProperty(paramName)) {
|
||||||
|
fieldName = paramMap[paramName] || paramName;
|
||||||
|
setParamField(params[paramName], fieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preload function for spreadsheet data
|
||||||
|
* @name TimeMap.loaders.gss#preload
|
||||||
|
* @function
|
||||||
|
* @parameter {Object} data Data to preload
|
||||||
|
* @return {Array} data Array of item data
|
||||||
|
*/
|
||||||
loader.preload = function(data) {
|
loader.preload = function(data) {
|
||||||
return data["feed"]["entry"];
|
return data.feed.entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
// transform function for spreadsheet data
|
/**
|
||||||
|
* Transform function for spreadsheet data
|
||||||
|
* @name TimeMap.loaders.gss#transform
|
||||||
|
* @function
|
||||||
|
* @parameter {Object} data Data to transform
|
||||||
|
* @return {Object} data Transformed data for one item
|
||||||
|
*/
|
||||||
loader.transform = function(data) {
|
loader.transform = function(data) {
|
||||||
// map spreadsheet column ids to corresponding TimeMap elements
|
var item = {}, params = loader.params, paramName,
|
||||||
var fieldMap = loader.map || TimeMap.loaders.gss.map;
|
transform = options.transformFunction;
|
||||||
var getField = function(f) {
|
// run through parameters, loading each
|
||||||
if (f in fieldMap && fieldMap[f]) {
|
for (paramName in params) {
|
||||||
return data['gsx$' + fieldMap[f]]['$t'];
|
if (params.hasOwnProperty(paramName)) {
|
||||||
} else return false;
|
params[paramName].setConfigGSS(item, data);
|
||||||
};
|
|
||||||
var item = {
|
|
||||||
title: getField("title"),
|
|
||||||
start: getField("start"),
|
|
||||||
point: {
|
|
||||||
lat: getField("lat"),
|
|
||||||
lon: getField("lon")
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
description: getField("description")
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// hook for further transformation
|
// hook for further transformation
|
||||||
if (options.transformFunction)
|
if (transform) {
|
||||||
item = options.transformFunction(item);
|
item = transform(item);
|
||||||
|
}
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
|
||||||
return loader;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1:1 map of expected spreadsheet column ids.
|
* Set a parameter to get its value from a given Google Spreadsheet field.
|
||||||
*/
|
*
|
||||||
TimeMap.loaders.gss.map = {
|
* @param {TimeMap.Param} param Param object
|
||||||
'title':'title',
|
* @param {String} fieldName Name of the field
|
||||||
'description':'description',
|
*/
|
||||||
'start':'start',
|
TimeMap.loaders.gss.setParamField = function(param, fieldName) {
|
||||||
'end':'end',
|
// internal function: Get the value of a Google Spreadsheet field
|
||||||
'lat':'lat',
|
var getField = function(data, fieldName) {
|
||||||
'lon':'lon'
|
// get element, converting field name to GSS format
|
||||||
|
var el = data['gsx$' + fieldName.toLowerCase().replace(" ", "")];
|
||||||
|
if (el) {
|
||||||
|
return el.$t;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
// set the method on the parameter
|
||||||
|
param.setConfigGSS = function(config, data) {
|
||||||
|
this.setConfig(config, getField(data, fieldName));
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,107 +9,80 @@
|
||||||
*
|
*
|
||||||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// for JSLint
|
||||||
|
/*global TimeMap */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* JSONP loader class - expects a service that takes a callback function name as
|
* JSONP loader - expects a service that takes a callback function name as
|
||||||
* the last URL parameter.
|
* the last URL parameter.
|
||||||
*
|
*
|
||||||
* <p>The jsonp loader assumes that the JSON can be loaded from a url to which a
|
* <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="
|
* 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.
|
* 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>
|
* This works for services like Google Spreadsheets, etc., and accepts remote URLs.</p>
|
||||||
|
*
|
||||||
|
* @augments TimeMap.loaders.remote
|
||||||
*
|
*
|
||||||
* @example Usage in TimeMap.init():
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "JSONP Dataset",
|
title: "JSONP Dataset",
|
||||||
type: "jsonp",
|
type: "jsonp",
|
||||||
options: {
|
options: {
|
||||||
url: "http://www.test.com/getsomejson.php?callback="
|
url: "http://www.example.com/getsomejson.php?callback="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader:
|
||||||
* {Array} url URL of JSON service to load, callback name left off
|
* @param {String} options.url URL of JSON service to load, callback name left off
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.remote})
|
||||||
* {Function} transformFunction Function to call on individual items before loading
|
|
||||||
* </pre>
|
|
||||||
*/
|
*/
|
||||||
TimeMap.loaders.jsonp = function(options) {
|
TimeMap.loaders.jsonp = function(options) {
|
||||||
// get standard functions
|
var loader = new TimeMap.loaders.remote(options);
|
||||||
TimeMap.loaders.mixin(this, options);
|
|
||||||
// get URL to load
|
/**
|
||||||
this.url = options.url;
|
* JSONP load function. Creates a callback function and adds a script tag
|
||||||
}
|
* with the appropriate URL to the document, triggering the HTTP request.
|
||||||
|
* @name TimeMap.loaders.jsonp#load
|
||||||
/**
|
* @function
|
||||||
* JSONP load function.
|
*
|
||||||
*
|
* @param {TimeMapDataset} dataset Dataset to load data into
|
||||||
* @param {TimeMapDataset} dataset Dataset to load data into
|
* @param {Function} callback Function to call once data is loaded
|
||||||
* @param {Function} callback Function to call once data is loaded
|
*/
|
||||||
*/
|
loader.load = function(dataset, callback) {
|
||||||
TimeMap.loaders.jsonp.prototype.load = function(dataset, callback) {
|
// get loader callback name
|
||||||
var loader = this;
|
var callbackName = this.getCallbackName(dataset, callback),
|
||||||
// get items
|
// create a script tag
|
||||||
TimeMap.loaders.jsonp.read(this.url, function(result) {
|
script = document.createElement("script");
|
||||||
// load
|
// set the src attribute and add to the document
|
||||||
items = loader.preload(result);
|
script.src = this.url + "TimeMap.loaders.cb." + callbackName;
|
||||||
dataset.loadItems(items, loader.transform);
|
document.body.appendChild(script);
|
||||||
// callback
|
};
|
||||||
callback();
|
|
||||||
});
|
return loader;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* @class
|
||||||
* JSON string loader factory - expects a plain JSON array.
|
* 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
|
* <p>The json_string loader assumes an array of items in plain JSON, with no
|
||||||
* callback function - this will require a local URL.</p>
|
* callback function - this will require a local URL.</p>
|
||||||
|
* <p>Note that this loader requires lib/json2.pack.js.</p>
|
||||||
*
|
*
|
||||||
* <p>Depends on:</p>
|
* @augments TimeMap.loaders.remote
|
||||||
* <ul>
|
*
|
||||||
* <li>lib/json2.pack.js</li>
|
* @requires lib/json2.pack.js
|
||||||
* </ul>
|
|
||||||
*
|
*
|
||||||
* @example Usage in TimeMap.init():
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "JSON String Dataset",
|
title: "JSON String Dataset",
|
||||||
|
@ -118,20 +91,28 @@ TimeMap.loaders.jsonp.read = function(url, f) {
|
||||||
url: "mydata.json" // Must be a local URL
|
url: "mydata.json" // Must be a local URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader
|
||||||
* {Array} url URL of JSON service to load, callback name left off
|
* @param {String} options.url URL of JSON file to load
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.remote})
|
||||||
* {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) {
|
TimeMap.loaders.json_string = function(options) {
|
||||||
var loader = new TimeMap.loaders.remote(options);
|
var loader = new TimeMap.loaders.remote(options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a JSON string into a JavaScript object, using the json2.js library.
|
||||||
|
* @name TimeMap.loaders.json_string#parse
|
||||||
|
* @function
|
||||||
|
* @param {String} json JSON string to parse
|
||||||
|
* @returns {Object} Parsed JavaScript object
|
||||||
|
*/
|
||||||
loader.parse = JSON.parse;
|
loader.parse = JSON.parse;
|
||||||
|
|
||||||
return loader;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Probably the default json loader should be json_string, not
|
// 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
|
// jsonp. I may change this in the future, so I'd encourage you to use
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,13 +14,21 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* KML loader factory - inherits from remote loader
|
* KML loader: load KML files.
|
||||||
*
|
*
|
||||||
* <p>This is a loader class for KML files. Currently supports all geometry
|
* <p>This is a loader class for KML files. Currently supports all geometry
|
||||||
* types (point, polyline, polygon, and overlay) and multiple geometries.</p>
|
* types (point, polyline, polygon, and overlay) and multiple geometries. Supports loading
|
||||||
|
* <a href="http://code.google.com/apis/kml/documentation/extendeddata.html">ExtendedData</a>
|
||||||
|
* through the extendedData parameter.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @augments TimeMap.loaders.xml
|
||||||
|
* @requires loaders/xml.js
|
||||||
|
* @requires param.js
|
||||||
|
* @borrows TimeMap.loaders.kml.parse as #parse
|
||||||
*
|
*
|
||||||
* @example Usage in TimeMap.init():
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "KML Dataset",
|
title: "KML Dataset",
|
||||||
|
@ -29,20 +37,36 @@
|
||||||
url: "mydata.kml" // Must be local
|
url: "mydata.kml" // Must be local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/kenya.html">KML Example</a>
|
||||||
|
* @see <a href="../../examples/kml_extendeddata.html">KML ExtendedData Example</a>
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader
|
||||||
* {Array} url URL of KML file to load (NB: must be local address)
|
* @param {String} options.url URL of KML file to load (NB: must be local address)
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {String[]} [options.extendedData] Array of names for ExtendedData data elements
|
||||||
* {Function} transformFunction Function to call on individual items before loading
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.xml})
|
||||||
* </pre>
|
* @return {TimeMap.loaders.xml} Loader configured for KML
|
||||||
* @return {TimeMap.loaders.remote} Remote loader configured for KML
|
|
||||||
*/
|
*/
|
||||||
TimeMap.loaders.kml = function(options) {
|
TimeMap.loaders.kml = function(options) {
|
||||||
var loader = new TimeMap.loaders.remote(options);
|
var loader = new TimeMap.loaders.xml(options),
|
||||||
|
tagMap = options.tagMap || {},
|
||||||
|
extendedData = options.extendedData || [],
|
||||||
|
tagName, x;
|
||||||
|
|
||||||
|
// Add ExtendedData parameters to extra params
|
||||||
|
for (x=0; x < extendedData.length; x++) {
|
||||||
|
tagName = extendedData[x];
|
||||||
|
loader.extraParams.push(
|
||||||
|
new TimeMap.params.ExtendedDataParam(tagMap[tagName] || tagName, tagName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set custom parser
|
||||||
loader.parse = TimeMap.loaders.kml.parse;
|
loader.parse = TimeMap.loaders.kml.parse;
|
||||||
return loader;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static function to parse KML with time data.
|
* Static function to parse KML with time data.
|
||||||
|
@ -56,8 +80,8 @@ TimeMap.loaders.kml.parse = function(kml) {
|
||||||
|
|
||||||
// get TimeMap utilty functions
|
// get TimeMap utilty functions
|
||||||
// assigning to variables should compress better
|
// assigning to variables should compress better
|
||||||
var util = TimeMap.util;
|
var util = TimeMap.util,
|
||||||
var getTagValue = util.getTagValue,
|
getTagValue = util.getTagValue,
|
||||||
getNodeList = util.getNodeList,
|
getNodeList = util.getNodeList,
|
||||||
makePoint = util.makePoint,
|
makePoint = util.makePoint,
|
||||||
makePoly = util.makePoly,
|
makePoly = util.makePoly,
|
||||||
|
@ -134,6 +158,9 @@ TimeMap.loaders.kml.parse = function(kml) {
|
||||||
// XXX: worth closing unclosed polygons?
|
// XXX: worth closing unclosed polygons?
|
||||||
data.placemarks.push(pmobj);
|
data.placemarks.push(pmobj);
|
||||||
}
|
}
|
||||||
|
// look for any extra tags and/or ExtendedData specified
|
||||||
|
this.parseExtra(data, pm);
|
||||||
|
|
||||||
items.push(data);
|
items.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,13 +183,51 @@ TimeMap.loaders.kml.parse = function(kml) {
|
||||||
data.overlay.south = getTagValue(nList[0], "south");
|
data.overlay.south = getTagValue(nList[0], "south");
|
||||||
data.overlay.east = getTagValue(nList[0], "east");
|
data.overlay.east = getTagValue(nList[0], "east");
|
||||||
data.overlay.west = getTagValue(nList[0], "west");
|
data.overlay.west = getTagValue(nList[0], "west");
|
||||||
|
// look for any extra tags and/or ExtendedData specified
|
||||||
|
this.parseExtra(data, pm);
|
||||||
items.push(data);
|
items.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
kmlnode = null;
|
kmlnode = placemarks = pm = nList = null;
|
||||||
placemarks = null;
|
|
||||||
pm = null;
|
|
||||||
nList = null;
|
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* Class for parameters loaded from KML ExtendedData elements
|
||||||
|
*
|
||||||
|
* @augments TimeMap.params.OptionParam
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} paramName String name of the parameter
|
||||||
|
* @param {String} [tagName] Tag name, if different
|
||||||
|
*/
|
||||||
|
TimeMap.params.ExtendedDataParam = function(paramName, tagName) {
|
||||||
|
return new TimeMap.params.OptionParam(paramName, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a config object based on an ExtendedData element
|
||||||
|
* @name TimeMap.params.ExtendedDataParam#setConfigKML
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object to modify
|
||||||
|
* @param {XML NodeList} node Parent node to look for tags in
|
||||||
|
*/
|
||||||
|
setConfigXML: function(config, node) {
|
||||||
|
var util = TimeMap.util,
|
||||||
|
nList = util.getNodeList(node, "Data"),
|
||||||
|
i;
|
||||||
|
for (i=0; i<nList.length; i++) {
|
||||||
|
if (nList[i].getAttribute("name") == tagName) {
|
||||||
|
this.setConfig(config, util.getTagValue(nList[i], "value"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = nList = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
sourceName: tagName
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
* Licensed under the MIT License (see LICENSE.txt)
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -8,30 +8,26 @@
|
||||||
* Metaweb Loader
|
* Metaweb Loader
|
||||||
*
|
*
|
||||||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
*/
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
|
||||||
* Loader
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// for JSLint
|
||||||
|
/*global TimeMap */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* Metaweb loader factory - inherits from jsonp loader
|
* Metaweb loader: Load data from freebase.com.
|
||||||
*
|
*
|
||||||
* <p>This is a loader for data from the Metaweb service at freebase.com. See
|
* <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
|
* the API documentation at <a href="http://www.freebase.com/docs/mql/ch01.html">http://www.freebase.com/docs/mql/ch01.html</a> for
|
||||||
* a description of how to write MQL queries. This code is based on code from
|
* a description of how to write MQL queries. This code is based on code from
|
||||||
* the API site.</p>
|
* the API site.</p>
|
||||||
*
|
*
|
||||||
* <p>Depends on:</p>
|
* @augments TimeMap.loaders.jsonp
|
||||||
* <ul>
|
* @requires lib/json2.pack.js
|
||||||
* <li>lib/json2.pack.js</li>
|
* @requires loaders/jsonp.js
|
||||||
* <li>loaders/jsonp.js</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
*
|
||||||
* @example Usage in TimeMap.init():
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
title: "Freebase Dataset",
|
title: "Freebase Dataset",
|
||||||
|
@ -49,28 +45,56 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/artists.html">Metaweb Example</a>
|
||||||
*
|
*
|
||||||
* @param {Object} options All options for the loader:<pre>
|
* @param {Object} options All options for the loader
|
||||||
* {Object} query MQL query to load
|
* @param {Object} options.query MQL query to load
|
||||||
* {Function} preloadFunction Function to call on data before loading
|
* @param {Function} options.transformFunction Function to call on individual items before loading
|
||||||
* {Function} transformFunction Function to call on individual items before loading
|
* @param {String} [options.host=http://www.freebase.com] Host url of web service
|
||||||
* </pre>
|
* @param {String} [options.service=/api/service/mqlread] Path to web service on host
|
||||||
* @return {TimeMap.loaders.remote} Remote loader configured for MetaWeb
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.jsonp})
|
||||||
*/
|
*/
|
||||||
TimeMap.loaders.metaweb = function(options) {
|
TimeMap.loaders.metaweb = function(options) {
|
||||||
var loader = new TimeMap.loaders.jsonp(options);
|
var loader = new TimeMap.loaders.jsonp(options),
|
||||||
|
q = options.query || {},
|
||||||
|
// format the query URL for Metaweb
|
||||||
|
querytext = encodeURIComponent(JSON.stringify({qname: {query: q}}));
|
||||||
|
|
||||||
// Host and service - default to freebase.com
|
/**
|
||||||
|
* Host url - default to freebase.com
|
||||||
|
* @name TimeMap.loaders.metaweb#HOST
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
loader.HOST = options.host || "http://www.freebase.com";
|
loader.HOST = options.host || "http://www.freebase.com";
|
||||||
loader.QUERY_SERVICE = options.service || "/api/service/mqlread";
|
/**
|
||||||
|
* Service path - default to freebase.com default
|
||||||
|
* @name TimeMap.loaders.metaweb#QUERY_SERVICE
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
loader.QUERY_SERVICE = options.service || "/api/service/mqlread";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL built using encoded query text and the callback name
|
||||||
|
* @name TimeMap.loaders.metaweb#url
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
loader.url = loader.HOST + loader.QUERY_SERVICE + "?queries=" + querytext + "&callback=";
|
||||||
|
|
||||||
// Metaweb preload functon
|
/**
|
||||||
|
* Preload function for Metaweb
|
||||||
|
* @name TimeMap.loaders.metaweb#preload
|
||||||
|
* @function
|
||||||
|
* @parameter {Object} data Data to preload
|
||||||
|
* @return {Array} data Array of item data
|
||||||
|
*/
|
||||||
loader.preload = function(data) {
|
loader.preload = function(data) {
|
||||||
// Open outer envelope
|
// Open outer envelope
|
||||||
var innerEnvelope = data.qname;
|
var innerEnvelope = data.qname;
|
||||||
// Make sure the query was successful
|
// Make sure the query was successful
|
||||||
if (innerEnvelope.code.indexOf("/api/status/ok") != 0) {
|
if (innerEnvelope.code.indexOf("/api/status/ok") !== 0) {
|
||||||
// uncomment for debugging
|
// uncomment for debugging
|
||||||
/*
|
/*
|
||||||
// If error, get error message and throw
|
// If error, get error message and throw
|
||||||
|
@ -80,16 +104,8 @@ TimeMap.loaders.metaweb = function(options) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
// Get result from inner envelope
|
// Get result from inner envelope
|
||||||
var result = innerEnvelope.result;
|
return 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;
|
return loader;
|
||||||
}
|
};
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* Progressive loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// for JSLint
|
||||||
|
/*global TimeMap */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* Progressive loader class - basically a wrapper for another remote loader that can
|
||||||
|
* load data progressively by date range, depending on timeline position.
|
||||||
|
*
|
||||||
|
* <p>The progressive loader can take either another loader or parameters for
|
||||||
|
* another loader. It expects a loader with a "url" attribute including placeholder
|
||||||
|
* strings [start] and [end] for the start and end dates to retrieve. The assumption
|
||||||
|
* is that the data service can take start and end parameters and return the data for
|
||||||
|
* that date range.</p>
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "Progressive JSONP Dataset",
|
||||||
|
type: "progressive",
|
||||||
|
options: {
|
||||||
|
type: "jsonp",
|
||||||
|
url: "http://www.test.com/getsomejson.php?start=[start]&end=[end]callback="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
TimeMap.init({
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
title: "Progressive KML Dataset",
|
||||||
|
type: "progressive",
|
||||||
|
options: {
|
||||||
|
loader: new TimeMap.loaders.kml({
|
||||||
|
url: "/mydata.kml?start=[start]&end=[end]"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// etc...
|
||||||
|
});
|
||||||
|
* @see <a href="../../examples/progressive.html">Progressive Loader Example</a>
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options All options for the loader
|
||||||
|
* @param {TimeMap.loaders.remote} [options.loader] Instantiated loader class (overrides "type")
|
||||||
|
* @param {String} [options.type] Name of loader class to use
|
||||||
|
* @param {String|Date} options.start Start of initial date range, as date or string
|
||||||
|
* @param {Number} options.interval Size in milliseconds of date ranges to load at a time
|
||||||
|
* @param {String|Date} [options.dataMinDate] Minimum date available in data (optional, will avoid
|
||||||
|
* unnecessary service requests if supplied)
|
||||||
|
* @param {String|Date} [options.dataMaxDate] Maximum date available in data (optional, will avoid
|
||||||
|
* unnecessary service requests if supplied)
|
||||||
|
* @param {Function} [options.formatUrl] Function taking (urlTemplate, start, end) and returning
|
||||||
|
* a URL formatted as needed by the service
|
||||||
|
* @param {Function} [options.formatDate={@link TimeMap.util.formatDate}]
|
||||||
|
* Function to turn a date into a string formatted
|
||||||
|
* as needed by the service
|
||||||
|
* @param {mixed} [options[...]] Other options needed by the "type" loader
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.progressive = function(options) {
|
||||||
|
// get loader
|
||||||
|
var loader = options.loader,
|
||||||
|
type = options.type;
|
||||||
|
if (!loader) {
|
||||||
|
// get loader class
|
||||||
|
var loaderClass = (typeof(type) == 'string') ? TimeMap.loaders[type] : type;
|
||||||
|
loader = new loaderClass(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// quick string/date check
|
||||||
|
function cleanDate(d) {
|
||||||
|
if (typeof(d) == "string") {
|
||||||
|
d = TimeMapDataset.hybridParser(d);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save loader attributes
|
||||||
|
var baseUrl = loader.url,
|
||||||
|
baseLoadFunction = loader.load,
|
||||||
|
interval = options.interval,
|
||||||
|
formatDate = options.formatDate || TimeMap.util.formatDate,
|
||||||
|
formatUrl = options.formatUrl,
|
||||||
|
zeroDate = cleanDate(options.start),
|
||||||
|
dataMinDate = cleanDate(options.dataMinDate),
|
||||||
|
dataMaxDate = cleanDate(options.dataMaxDate),
|
||||||
|
loaded = {};
|
||||||
|
|
||||||
|
if (!formatUrl) {
|
||||||
|
formatUrl = function(url, start, end) {
|
||||||
|
return url
|
||||||
|
.replace('[start]', formatDate(start))
|
||||||
|
.replace('[end]', formatDate(end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't start with a TimeMap reference, so we need
|
||||||
|
// to stick the listener in on the first load() call
|
||||||
|
var addListener = function(dataset) {
|
||||||
|
var band = dataset.timemap.timeline.getBand(0);
|
||||||
|
// add listener
|
||||||
|
band.addOnScrollListener(function() {
|
||||||
|
// determine relevant blocks
|
||||||
|
var now = band.getCenterVisibleDate(),
|
||||||
|
currBlock = Math.floor((now.getTime() - zeroDate.getTime()) / interval),
|
||||||
|
currBlockTime = zeroDate.getTime() + (interval * currBlock)
|
||||||
|
nextBlockTime = currBlockTime + interval,
|
||||||
|
prevBlockTime = currBlockTime - interval,
|
||||||
|
// no callback necessary?
|
||||||
|
callback = function() {
|
||||||
|
dataset.timemap.timeline.layout();
|
||||||
|
};
|
||||||
|
|
||||||
|
// is the current block loaded?
|
||||||
|
if ((!dataMaxDate || currBlockTime < dataMaxDate.getTime()) &&
|
||||||
|
(!dataMinDate || currBlockTime > dataMinDate.getTime()) &&
|
||||||
|
!loaded[currBlock]) {
|
||||||
|
// load it
|
||||||
|
// console.log("loading current block (" + currBlock + ")");
|
||||||
|
loader.load(dataset, callback, new Date(currBlockTime), currBlock);
|
||||||
|
}
|
||||||
|
// are we close enough to load the next block, and is it loaded?
|
||||||
|
if (nextBlockTime < band.getMaxDate().getTime() &&
|
||||||
|
(!dataMaxDate || nextBlockTime < dataMaxDate.getTime()) &&
|
||||||
|
!loaded[currBlock + 1]) {
|
||||||
|
// load next block
|
||||||
|
// console.log("loading next block (" + (currBlock + 1) + ")");
|
||||||
|
loader.load(dataset, callback, new Date(nextBlockTime), currBlock + 1);
|
||||||
|
}
|
||||||
|
// are we close enough to load the previous block, and is it loaded?
|
||||||
|
if (prevBlockTime > band.getMinDate().getTime() &&
|
||||||
|
(!dataMinDate || prevBlockTime > dataMinDate.getTime()) &&
|
||||||
|
!loaded[currBlock - 1]) {
|
||||||
|
// load previous block
|
||||||
|
// console.log("loading prev block (" + (currBlock - 1) + ")");
|
||||||
|
loader.load(dataset, callback, new Date(prevBlockTime), currBlock - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// kill this function so that listener is only added once
|
||||||
|
addListener = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data based on current time
|
||||||
|
* @name TimeMap.loaders.progressive#load
|
||||||
|
* @function
|
||||||
|
* @param {TimeMapDataset} dataset Dataset to load data into
|
||||||
|
* @param {Function} callback Callback to execute when data is loaded
|
||||||
|
* @param {Date} start Start date to load data from
|
||||||
|
* @param {Number} currBlock Index of the current time block
|
||||||
|
*/
|
||||||
|
loader.load = function(dataset, callback, start, currBlock) {
|
||||||
|
// set start date, defaulting to zero date
|
||||||
|
start = cleanDate(start) || zeroDate;
|
||||||
|
// set current block, defaulting to 0
|
||||||
|
currBlock = currBlock || 0;
|
||||||
|
// set end by interval
|
||||||
|
var end = new Date(start.getTime() + interval);
|
||||||
|
|
||||||
|
// set current block as loaded
|
||||||
|
// XXX: Failed loads will give a false positive here...
|
||||||
|
// but I'm not sure how else to avoid multiple loads :(
|
||||||
|
loaded[currBlock] = true;
|
||||||
|
|
||||||
|
// put dates into URL
|
||||||
|
loader.url = formatUrl(baseUrl, start, end);
|
||||||
|
// console.log(loader.url);
|
||||||
|
|
||||||
|
// load data
|
||||||
|
baseLoadFunction.call(loader, dataset, function() {
|
||||||
|
// add onscroll listener if not yet done
|
||||||
|
if (addListener) {
|
||||||
|
addListener(dataset);
|
||||||
|
}
|
||||||
|
// run callback
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
};
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* XML Loader
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*globals TimeMap */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* This is a base loader class for XML files.
|
||||||
|
*
|
||||||
|
* @augments TimeMap.loaders.remote
|
||||||
|
* @requires param.js
|
||||||
|
*
|
||||||
|
* @param {Object} options All options for the loader
|
||||||
|
* @param {String} options.url URL of XML file to load (NB: must be local address)
|
||||||
|
* @parem {String[]} [options.extraTags] Array of names for extra tag elements to load
|
||||||
|
* @param {Object} [options.tagMap] Map of tagName:paramName pairs, if you want to load
|
||||||
|
* data into a differently-named elements
|
||||||
|
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.remote})
|
||||||
|
* @return {TimeMap.loaders.remote} Remote loader configured for XML
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.xml = function(options) {
|
||||||
|
var loader = new TimeMap.loaders.remote(options),
|
||||||
|
tagMap = options.tagMap || {},
|
||||||
|
extraTags = options.extraTags || [],
|
||||||
|
params = loader.params,
|
||||||
|
paramName, tagName, x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional parameters to load
|
||||||
|
* @name TimeMap.loaders.xml#extraParams
|
||||||
|
* @type TimeMap.params.OptionParam[]
|
||||||
|
*/
|
||||||
|
loader.extraParams = [];
|
||||||
|
|
||||||
|
// set up extra params
|
||||||
|
for (x=0; x < extraTags.length; x++) {
|
||||||
|
tagName = extraTags[x];
|
||||||
|
loader.extraParams.push(
|
||||||
|
new TimeMap.params.OptionParam(tagMap[tagName] || tagName, {
|
||||||
|
sourceName: tagName
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse any extra tags that have been specified into the config object
|
||||||
|
* @name TimeMap.loaders.xml#parseExtra
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object to modify
|
||||||
|
* @param {XML NodeList} node Parent node to look for tags in
|
||||||
|
*/
|
||||||
|
loader.parseExtra = function(config, node) {
|
||||||
|
var extraParams = loader.extraParams, x;
|
||||||
|
for (x=0; x<extraParams.length; x++) {
|
||||||
|
extraParams[x].setConfigXML(config, node);
|
||||||
|
}
|
||||||
|
node = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
};
|
|
@ -0,0 +1,274 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* This file defines the Param class, which is used to get, set, and serialize
|
||||||
|
* different fields on TimeMap and TimeMapItem objects.
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// save a few bytes
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name TimeMap.params
|
||||||
|
* @namespace Namespace for parameter classes
|
||||||
|
*/
|
||||||
|
var params = TimeMap.params = {
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* A parameter, with methods to get, set, and serialize the current value.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} paramName String name of the parameter
|
||||||
|
* @param {Object} options Container for named arguments
|
||||||
|
* @param {String} [sourceName] String name of the source element, if different
|
||||||
|
* @param {Function} [options.get] Function to get the current param value
|
||||||
|
* @param {Function} [options.set] Function to set the param to a new value
|
||||||
|
* @param {Function} [options.setConfig] Function to set a new value in a config object
|
||||||
|
* @param {Function} [options.fromStr] Function to parse the value from a string
|
||||||
|
* @param {Function} [options.toStr] Function to serialize the current value to a string
|
||||||
|
* @param {Function} [options.setConfigXML] Function to parse the value from an XML node and set to config
|
||||||
|
*/
|
||||||
|
Param: function(paramName, options) {
|
||||||
|
var param = this,
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String name of this param
|
||||||
|
* @name TimeMap.params.Param#paramName
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
param.paramName = paramName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String name of the source element, if different
|
||||||
|
* @name TimeMap.params.Param#sourceName
|
||||||
|
*/
|
||||||
|
param.sourceName = options.sourceName || paramName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current state value from a TimeMap or TimeMapItem object
|
||||||
|
* @name TimeMap.params.Param#get
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to inspect
|
||||||
|
* @return {mixed} Current state value
|
||||||
|
*/
|
||||||
|
param.get = options.get;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current state value on a TimeMap or TimeMapItem object
|
||||||
|
* @name TimeMap.params.Param#set
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to modify
|
||||||
|
* @param {mixed} value Value to set
|
||||||
|
*/
|
||||||
|
param.set = options.set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new value on a config object for TimeMap.init()
|
||||||
|
* @name TimeMap.params.Param#setConfig
|
||||||
|
* @function
|
||||||
|
* @see TimeMap.init
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object to modify
|
||||||
|
* @param {mixed} value Value to set
|
||||||
|
*/
|
||||||
|
param.setConfig = options.setConfig || function(config, value) {
|
||||||
|
// default: set at top level
|
||||||
|
config[paramName] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a state value from a string
|
||||||
|
* @name TimeMap.params.Param#fromString
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {String} s String to parse
|
||||||
|
* @return {mixed} Current state value
|
||||||
|
*/
|
||||||
|
param.fromString = options.fromStr || function(s) {
|
||||||
|
// default: param is a string
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize a state value as a string
|
||||||
|
* @name TimeMap.params.Param#toString
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {mixed} value Value to serialize
|
||||||
|
* @return {String} Serialized string
|
||||||
|
*/
|
||||||
|
param.toString = options.toStr || function(value) {
|
||||||
|
// default: use the built-in string method
|
||||||
|
return value.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current value as a string
|
||||||
|
* @name TimeMap.params.Param#getString
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to inspect
|
||||||
|
*/
|
||||||
|
param.getString = function(o) {
|
||||||
|
param.toString(param.get(o));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current state value from a string
|
||||||
|
* @name TimeMap.params.Param#setString
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to modify
|
||||||
|
* @param {String} s String version of value to set
|
||||||
|
*/
|
||||||
|
param.setString = function(o, s) {
|
||||||
|
param.set(o, param.fromString(s));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a config object based on an XML tag
|
||||||
|
* @name TimeMap.params.Param#setConfigXML
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object to modify
|
||||||
|
* @param {XML NodeList} node Parent node of the desired tag
|
||||||
|
*/
|
||||||
|
param.setConfigXML = options.setConfigXML || function(config, node) {
|
||||||
|
var tagName = param.sourceName,
|
||||||
|
nameParts = tagName.split(':'),
|
||||||
|
ns;
|
||||||
|
// deal with namespaced tags
|
||||||
|
if (nameParts.length > 1) {
|
||||||
|
tagName = nameParts[1];
|
||||||
|
ns = nameParts[0];
|
||||||
|
}
|
||||||
|
// set to config
|
||||||
|
param.setConfig(config, TimeMap.util.getTagValue(node, tagName, ns));
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* A convenience class for those parameters which deal with a value
|
||||||
|
* in the options of a TimeMap or TimeMapItem object, setting some
|
||||||
|
* additional default functions.
|
||||||
|
*
|
||||||
|
* @augments TimeMap.params.Param
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} paramName String name of the option parameter
|
||||||
|
* @param {Object} [options] Container for named arguments (see {@link TimeMap.params.Param})
|
||||||
|
*/
|
||||||
|
OptionParam: function(paramName, options) {
|
||||||
|
options = options || {};
|
||||||
|
var defaults = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current state value from the opts object of a TimeMap or TimeMapItem
|
||||||
|
* @name TimeMap.params.OptionParam#get
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to inspect
|
||||||
|
* @return {mixed} Current state value
|
||||||
|
*/
|
||||||
|
get: function(o) {
|
||||||
|
return o.opts[paramName];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the state value in the opts object of a TimeMap or TimeMapItem
|
||||||
|
* @name TimeMap.params.OptionParam#set
|
||||||
|
*
|
||||||
|
* @param {TimeMap|TimeMapItem} o Object to modify
|
||||||
|
* @param {mixed} value Value to set
|
||||||
|
*/
|
||||||
|
set: function(o, value) {
|
||||||
|
o.opts[paramName] = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new value on a config object for TimeMap.init() or a particular item
|
||||||
|
* @name TimeMap.params.OptionParam#setConfig
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object to modify
|
||||||
|
* @param {mixed} value Value to set
|
||||||
|
*/
|
||||||
|
setConfig: function(config, value) {
|
||||||
|
config.options = config.options || {};
|
||||||
|
config.options[paramName] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
options = TimeMap.util.merge(options, defaults);
|
||||||
|
return new params.Param(paramName, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* TimeMapItem params
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace Namespace for parameters used for loading data into a TimeMapItem
|
||||||
|
* object. Because these are intended for loading, only setConfig is defined.
|
||||||
|
*/
|
||||||
|
TimeMap.loaders.base.prototype.params = {
|
||||||
|
/**
|
||||||
|
* Item title
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
title: new params.Param("title"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item start date
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
start: new params.Param("start"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item end date
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
end: new params.Param("end"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item description
|
||||||
|
* @type TimeMap.params.OptionParam
|
||||||
|
*/
|
||||||
|
description: new params.OptionParam("description"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item latitude
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
lat: new params.Param("lat", {
|
||||||
|
setConfig: function(config, value) {
|
||||||
|
config.point = config.point || {};
|
||||||
|
config.point.lat = value;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item longitude
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
lon: new params.Param("lon", {
|
||||||
|
setConfig: function(config, value) {
|
||||||
|
config.point = config.point || {};
|
||||||
|
config.point.lon = value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,314 @@
|
||||||
|
/*
|
||||||
|
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||||
|
* Licensed under the MIT License (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileOverview
|
||||||
|
* Functions in this file are used to set the timemap state programmatically,
|
||||||
|
* either in a script or from the url hash.
|
||||||
|
*
|
||||||
|
* @requires param.js
|
||||||
|
*
|
||||||
|
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// save a few bytes
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* State namespace, with setters, serializers, and url functions
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var paramNS = TimeMap.params,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name TimeMap.state
|
||||||
|
* @namespace Namespace for static state functions used to
|
||||||
|
* set the timemap state programmatically, either in a script or
|
||||||
|
* from the url hash.
|
||||||
|
* @see <a href="../../examples/state.html#zoom=8¢er=44.04811573082351,13.29345703125&date=1500-01-21T12:17:37Z&selected=0">State Example</a>
|
||||||
|
*/
|
||||||
|
stateNS = TimeMap.state = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state parameters from the URL, returning as a config object
|
||||||
|
*
|
||||||
|
* @return {Object} Object with state config settings
|
||||||
|
*/
|
||||||
|
fromUrl: function() {
|
||||||
|
var pairs = location.hash.substring(1).split('&'),
|
||||||
|
params = stateNS.params,
|
||||||
|
state = {}, x, pair, key;
|
||||||
|
for (x=0; x < pairs.length; x++) {
|
||||||
|
if (pairs[x] != "") {
|
||||||
|
pair = pairs[x].split('=');
|
||||||
|
key = pair[0];
|
||||||
|
if (key && key in params) {
|
||||||
|
state[key] = params[key].fromString(decodeURI(pair[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a parameter string from a state object
|
||||||
|
*
|
||||||
|
* @param {Object} state Object with state config settings
|
||||||
|
* @return {String} Parameter string in URL param format
|
||||||
|
*/
|
||||||
|
toParamString: function(state) {
|
||||||
|
var params = stateNS.params,
|
||||||
|
paramArray = [],
|
||||||
|
key;
|
||||||
|
// go through each key in state
|
||||||
|
for (key in state) {
|
||||||
|
if (state.hasOwnProperty(key)) {
|
||||||
|
if (key in params) {
|
||||||
|
paramArray.push(key + "=" + encodeURI(params[key].toString(state[key])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paramArray.join("&");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a full URL from a state object
|
||||||
|
*
|
||||||
|
* @param {Object} state Object with state config settings
|
||||||
|
* @return {String} Full URL with parameters
|
||||||
|
*/
|
||||||
|
toUrl: function(state) {
|
||||||
|
var paramString = stateNS.toParamString(state),
|
||||||
|
url = location.href.split("#")[0];
|
||||||
|
return url + "#" + paramString;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set state settings on a config object for TimeMap.init()
|
||||||
|
* @see TimeMap.init
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object for TimeMap.init(), modified in place
|
||||||
|
* @param {Object} state Object with state config settings
|
||||||
|
*/
|
||||||
|
setConfig: function(config, state) {
|
||||||
|
var params = stateNS.params,
|
||||||
|
key;
|
||||||
|
for (key in state) {
|
||||||
|
if (state.hasOwnProperty(key)) {
|
||||||
|
if (key in params) {
|
||||||
|
params[key].setConfig(config, state[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set state settings on a config object for TimeMap.init() using
|
||||||
|
* parameters in the URL. Note that as of Timemap.js v.1.6, this
|
||||||
|
* will run automatically if state functions are present.
|
||||||
|
* @see TimeMap.init
|
||||||
|
* @example
|
||||||
|
// set up the config object
|
||||||
|
var config = {
|
||||||
|
// various settings, as usual for TimeMap.init()
|
||||||
|
};
|
||||||
|
|
||||||
|
// get state settings from the URL, e.g.:
|
||||||
|
// http://www.example.com/mytimemap.html#zoom=4&selected=1
|
||||||
|
TimeMap.state.setConfigFromUrl(config);
|
||||||
|
|
||||||
|
// initialize TimeMap object
|
||||||
|
var tm = TimeMap.init(config);
|
||||||
|
*
|
||||||
|
* @param {Object} config Config object for TimeMap.init()
|
||||||
|
*/
|
||||||
|
setConfigFromUrl: function(config) {
|
||||||
|
stateNS.setConfig(config, stateNS.fromUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* TimeMap object methods
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the timemap state with a set of configuration options.
|
||||||
|
*
|
||||||
|
* @param {Object} state Object with state config settings
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.setState = function(state) {
|
||||||
|
var params = stateNS.params,
|
||||||
|
key;
|
||||||
|
// go through each key in state
|
||||||
|
for (key in state) {
|
||||||
|
if (state.hasOwnProperty(key)) {
|
||||||
|
if (key in params) {
|
||||||
|
// run setter function with config value
|
||||||
|
params[key].set(this, state[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a configuration object of state variables
|
||||||
|
*
|
||||||
|
* @return {Object} Object with state config settings
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.getState = function() {
|
||||||
|
var state = {},
|
||||||
|
params = stateNS.params,
|
||||||
|
key;
|
||||||
|
// run through params, adding values to state
|
||||||
|
for (key in params) {
|
||||||
|
if (params.hasOwnProperty(key)) {
|
||||||
|
// get state value
|
||||||
|
state[key] = params[key].get(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize state tracking based on URL.
|
||||||
|
* Note: continuous tracking will only work
|
||||||
|
* on browsers that support the "onhashchange" event.
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.initState = function() {
|
||||||
|
var tm = this;
|
||||||
|
tm.setStateFromUrl();
|
||||||
|
window.onhashchange = function() {
|
||||||
|
tm.setStateFromUrl();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the timemap state with parameters in the URL
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.setStateFromUrl = function() {
|
||||||
|
this.setState(stateNS.fromUrl());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current state parameters serialized as a hash string
|
||||||
|
*
|
||||||
|
* @return {String} State parameters serialized as a hash string
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.getStateParamString = function() {
|
||||||
|
return stateNS.toParamString(this.getState());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get URL with current state parameters in hash
|
||||||
|
*
|
||||||
|
* @return {String} URL with state parameters
|
||||||
|
*/
|
||||||
|
TimeMap.prototype.getStateUrl = function() {
|
||||||
|
return stateNS.toUrl(this.getState());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* State parameters
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace
|
||||||
|
* Namespace for state parameters, each with a set of functions to set and serialize values.
|
||||||
|
* Add your own Param objects to this namespace to get and set additional state variables.
|
||||||
|
*/
|
||||||
|
TimeMap.state.params = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map zoom level
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
zoom: new paramNS.OptionParam("mapZoom", {
|
||||||
|
get: function(tm) {
|
||||||
|
return tm.map.getZoom();
|
||||||
|
},
|
||||||
|
set: function(tm, value) {
|
||||||
|
tm.map.setZoom(value);
|
||||||
|
},
|
||||||
|
fromStr: function(s) {
|
||||||
|
return parseInt(s);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map center
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
center: new paramNS.OptionParam("mapCenter", {
|
||||||
|
get: function(tm) {
|
||||||
|
return tm.map.getCenter();
|
||||||
|
},
|
||||||
|
set: function(tm, value) {
|
||||||
|
tm.map.setCenter(value);
|
||||||
|
},
|
||||||
|
fromStr: function(s) {
|
||||||
|
var params = s.split(",");
|
||||||
|
if (params.length < 2) {
|
||||||
|
// give up
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new GLatLng(
|
||||||
|
parseFloat(params[0]),
|
||||||
|
parseFloat(params[1])
|
||||||
|
);
|
||||||
|
},
|
||||||
|
toStr: function(value) {
|
||||||
|
return value.lat() + "," + value.lng();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeline center date
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
date: new paramNS.Param("scrollTo", {
|
||||||
|
get: function(tm) {
|
||||||
|
return tm.timeline.getBand(0).getCenterVisibleDate();
|
||||||
|
},
|
||||||
|
set: function(tm, value) {
|
||||||
|
tm.scrollToDate(value);
|
||||||
|
},
|
||||||
|
fromStr: function(s) {
|
||||||
|
return TimeMapDataset.hybridParser(s);
|
||||||
|
},
|
||||||
|
toStr: function(value) {
|
||||||
|
return TimeMap.util.formatDate(value);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of selected/open item, if any
|
||||||
|
* @type TimeMap.params.Param
|
||||||
|
*/
|
||||||
|
selected: new paramNS.Param("selected", {
|
||||||
|
get: function(tm) {
|
||||||
|
var items = tm.getItems(),
|
||||||
|
i = items.length-1;
|
||||||
|
while (i >= 0 && i--) {
|
||||||
|
if (items[i].selected) break;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
},
|
||||||
|
set: function(tm, value) {
|
||||||
|
if (value >= 0) {
|
||||||
|
var item = tm.getItems()[value];
|
||||||
|
if (item) {
|
||||||
|
item.openInfoWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fromStr: function(s) {
|
||||||
|
return parseInt(s);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue