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)
|
||||
*/
|
||||
|
||||
|
@ -10,22 +10,23 @@
|
|||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||
*/
|
||||
|
||||
// for JSLint
|
||||
/*global TimeMap */
|
||||
|
||||
/**
|
||||
* @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>
|
||||
*
|
||||
* <p>The loader takes a full URL, minus the JSONP callback function.</p>
|
||||
*
|
||||
* <p>Depends on:</p>
|
||||
* <ul>
|
||||
* <li>loaders/jsonp.js</li>
|
||||
* </ul>
|
||||
* @augments TimeMap.loaders.jsonp
|
||||
* @requires loaders/json.js
|
||||
*
|
||||
* @example Usage in TimeMap.init():
|
||||
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
title: "Flickr Dataset",
|
||||
|
@ -36,43 +37,56 @@
|
|||
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>
|
||||
* {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
|
||||
* @param {Object} options All options for the loader
|
||||
* @param {String} options.url Full JSONP url of Flickr feed to load
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.jsonp})
|
||||
*/
|
||||
TimeMap.loaders.flickr = function(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) {
|
||||
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) {
|
||||
var item = {
|
||||
title: data["title"],
|
||||
start: data["date_taken"],
|
||||
title: data.title,
|
||||
start: data.date_taken,
|
||||
point: {
|
||||
lat: data["latitude"],
|
||||
lon: data["longitude"]
|
||||
lat: data.latitude,
|
||||
lon: data.longitude
|
||||
},
|
||||
options: {
|
||||
description: data["description"]
|
||||
description: data.description
|
||||
.replace(/>/g, ">")
|
||||
.replace(/</g, "<")
|
||||
.replace(/"/g, '"')
|
||||
}
|
||||
};
|
||||
if (options.transformFunction)
|
||||
if (options.transformFunction) {
|
||||
item = options.transformFunction(item);
|
||||
}
|
||||
return item;
|
||||
};
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
|||
|
||||
/**
|
||||
* @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>
|
||||
* <ul>
|
||||
* <li>RSS feeds</li>
|
||||
|
@ -28,11 +28,16 @@
|
|||
* <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>
|
||||
* <p>At the moment, this only supports points, polygons, polylines; boxes
|
||||
* 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: [
|
||||
{
|
||||
title: "GeoRSS Dataset",
|
||||
|
@ -41,35 +46,35 @@
|
|||
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>
|
||||
* {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
|
||||
* @param {Object} options All options for the loader:
|
||||
* @param {String} options.url URL of GeoRSS file to load (NB: must be local address)
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.xml})
|
||||
*/
|
||||
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;
|
||||
return loader;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Static function to parse GeoRSS
|
||||
*
|
||||
* @param {XML text} rss GeoRSS to be parsed
|
||||
* @return {TimeMapItem Array} Array of TimeMapItems
|
||||
* @param {String} rss GeoRSS string to be parsed
|
||||
* @return {TimeMapItem[]} Array of TimeMapItems
|
||||
*/
|
||||
TimeMap.loaders.georss.parse = function(rss) {
|
||||
var items = [], data, node, placemarks, pm;
|
||||
var items = [], data, node, placemarks, pm, i;
|
||||
node = GXml.parse(rss);
|
||||
|
||||
// get TimeMap utilty functions
|
||||
// assigning to variables should compress better
|
||||
var util = TimeMap.util;
|
||||
var getTagValue = util.getTagValue,
|
||||
var util = TimeMap.util,
|
||||
getTagValue = util.getTagValue,
|
||||
getNodeList = util.getNodeList,
|
||||
makePoint = util.makePoint,
|
||||
makePoly = util.makePoly,
|
||||
|
@ -88,7 +93,7 @@ TimeMap.loaders.georss.parse = function(rss) {
|
|||
// look for placemarks
|
||||
var tName = (feedType == 'rss' ? "item" : "entry");
|
||||
placemarks = getNodeList(node, tName);
|
||||
for (var i=0; i<placemarks.length; i++) {
|
||||
for (i=0; i<placemarks.length; i++) {
|
||||
pm = placemarks[i];
|
||||
data = { options: {} };
|
||||
// get title & description
|
||||
|
@ -123,7 +128,8 @@ TimeMap.loaders.georss.parse = function(rss) {
|
|||
}
|
||||
}
|
||||
// find placemark - single geometry only for the moment
|
||||
PLACEMARK: {
|
||||
var done = false;
|
||||
PLACEMARK: while (!done) {
|
||||
var coords, geom;
|
||||
// look for point, GeoRSS-Simple
|
||||
coords = getTagValue(pm, "point", 'georss');
|
||||
|
@ -190,14 +196,15 @@ TimeMap.loaders.georss.parse = function(rss) {
|
|||
}
|
||||
|
||||
// XXX: deal with boxes
|
||||
|
||||
done = true;
|
||||
}
|
||||
// look for any extra tags specified
|
||||
this.parseExtra(data, pm);
|
||||
items.push(data);
|
||||
}
|
||||
|
||||
// clean up
|
||||
node = null;
|
||||
placemarks = null;
|
||||
pm = null;
|
||||
nList = null;
|
||||
node = placemarks = pm = nList = null;
|
||||
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)
|
||||
*/
|
||||
|
||||
|
@ -10,11 +10,14 @@
|
|||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||
*/
|
||||
|
||||
// for JSLint
|
||||
/*global TimeMap, TimeMapItem */
|
||||
|
||||
/**
|
||||
* @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
|
||||
* names (case-insensitive) are: title, description, start, end, lat, lon</p>
|
||||
*
|
||||
|
@ -26,13 +29,12 @@
|
|||
* <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>
|
||||
* @augments TimeMap.loaders.jsonp
|
||||
* @requires param.js
|
||||
* @requires loaders/json.js
|
||||
*
|
||||
* @example Usage in TimeMap.init():
|
||||
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
title: "Google Spreadsheet by key",
|
||||
|
@ -48,18 +50,28 @@
|
|||
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>
|
||||
* {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
|
||||
* @param {Object} options All options for the loader:
|
||||
* @param {String} options.key Key of spreadsheet to load, or
|
||||
* @param {String} options.url Full JSONP url of spreadsheet to load
|
||||
* @param {Object} [options.paramMap] Map of paramName:columnName pairs for core parameters,
|
||||
* if using non-standard column names; see keys in
|
||||
* {@link TimeMap.loaders.base#params} for the standard param names
|
||||
* @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) {
|
||||
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
|
||||
if (!loader.url) {
|
||||
|
@ -67,51 +79,75 @@ TimeMap.loaders.gss = function(options) {
|
|||
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")
|
||||
// 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) {
|
||||
return data.feed.entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var item = {}, params = loader.params, paramName,
|
||||
transform = options.transformFunction;
|
||||
// run through parameters, loading each
|
||||
for (paramName in params) {
|
||||
if (params.hasOwnProperty(paramName)) {
|
||||
params[paramName].setConfigGSS(item, data);
|
||||
}
|
||||
}
|
||||
// hook for further transformation
|
||||
if (options.transformFunction)
|
||||
item = options.transformFunction(item);
|
||||
if (transform) {
|
||||
item = transform(item);
|
||||
}
|
||||
return item;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1:1 map of expected spreadsheet column ids.
|
||||
* Set a parameter to get its value from a given Google Spreadsheet field.
|
||||
*
|
||||
* @param {TimeMap.Param} param Param object
|
||||
* @param {String} fieldName Name of the field
|
||||
*/
|
||||
TimeMap.loaders.gss.map = {
|
||||
'title':'title',
|
||||
'description':'description',
|
||||
'start':'start',
|
||||
'end':'end',
|
||||
'lat':'lat',
|
||||
'lon':'lon'
|
||||
TimeMap.loaders.gss.setParamField = function(param, fieldName) {
|
||||
// internal function: Get the value of a Google Spreadsheet field
|
||||
var getField = function(data, fieldName) {
|
||||
// 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)
|
||||
*/
|
||||
|
||||
|
@ -10,9 +10,12 @@
|
|||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||
*/
|
||||
|
||||
// for JSLint
|
||||
/*global TimeMap */
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* <p>The jsonp loader assumes that the JSON can be loaded from a url to which a
|
||||
|
@ -20,96 +23,66 @@
|
|||
* 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():
|
||||
|
||||
* @augments TimeMap.loaders.remote
|
||||
*
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
title: "JSONP Dataset",
|
||||
type: "jsonp",
|
||||
options: {
|
||||
url: "http://www.test.com/getsomejson.php?callback="
|
||||
url: "http://www.example.com/getsomejson.php?callback="
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
// etc...
|
||||
});
|
||||
*
|
||||
* @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>
|
||||
* @param {Object} options All options for the loader:
|
||||
* @param {String} options.url URL of JSON service to load, callback name left off
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.remote})
|
||||
*/
|
||||
TimeMap.loaders.jsonp = function(options) {
|
||||
// get standard functions
|
||||
TimeMap.loaders.mixin(this, options);
|
||||
// get URL to load
|
||||
this.url = options.url;
|
||||
}
|
||||
var loader = new TimeMap.loaders.remote(options);
|
||||
|
||||
/**
|
||||
* JSONP load function.
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @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];
|
||||
loader.load = function(dataset, callback) {
|
||||
// get loader callback name
|
||||
var callbackName = this.getCallbackName(dataset, callback),
|
||||
// create a script tag
|
||||
script = document.createElement("script");
|
||||
// set the src attribute and add to the document
|
||||
script.src = this.url + "TimeMap.loaders.cb." + callbackName;
|
||||
document.body.appendChild(script);
|
||||
};
|
||||
|
||||
// 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);
|
||||
return loader;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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>Note that this loader requires lib/json2.pack.js.</p>
|
||||
*
|
||||
* <p>Depends on:</p>
|
||||
* <ul>
|
||||
* <li>lib/json2.pack.js</li>
|
||||
* </ul>
|
||||
* @augments TimeMap.loaders.remote
|
||||
*
|
||||
* @example Usage in TimeMap.init():
|
||||
|
||||
* @requires lib/json2.pack.js
|
||||
*
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
title: "JSON String Dataset",
|
||||
|
@ -118,20 +91,28 @@ TimeMap.loaders.jsonp.read = function(url, f) {
|
|||
url: "mydata.json" // Must be a local URL
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
// etc...
|
||||
});
|
||||
*
|
||||
* @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
|
||||
* @param {Object} options All options for the loader
|
||||
* @param {String} options.url URL of JSON file to load
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.remote})
|
||||
*/
|
||||
TimeMap.loaders.json_string = function(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;
|
||||
|
||||
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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Timemap.js Copyright 2008 Nick Rabinowitz.
|
||||
* Timemap.js Copyright 2010 Nick Rabinowitz.
|
||||
* Licensed under the MIT License (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
|
@ -14,13 +14,21 @@
|
|||
|
||||
/**
|
||||
* @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
|
||||
* 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>
|
||||
*
|
||||
* @example Usage in TimeMap.init():
|
||||
|
||||
* @augments TimeMap.loaders.xml
|
||||
* @requires loaders/xml.js
|
||||
* @requires param.js
|
||||
* @borrows TimeMap.loaders.kml.parse as #parse
|
||||
*
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
title: "KML Dataset",
|
||||
|
@ -29,20 +37,36 @@
|
|||
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>
|
||||
* {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
|
||||
* @param {Object} options All options for the loader
|
||||
* @param {String} options.url URL of KML file to load (NB: must be local address)
|
||||
* @param {String[]} [options.extendedData] Array of names for ExtendedData data elements
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.xml})
|
||||
* @return {TimeMap.loaders.xml} Loader configured for KML
|
||||
*/
|
||||
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;
|
||||
return loader;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Static function to parse KML with time data.
|
||||
|
@ -56,8 +80,8 @@ TimeMap.loaders.kml.parse = function(kml) {
|
|||
|
||||
// get TimeMap utilty functions
|
||||
// assigning to variables should compress better
|
||||
var util = TimeMap.util;
|
||||
var getTagValue = util.getTagValue,
|
||||
var util = TimeMap.util,
|
||||
getTagValue = util.getTagValue,
|
||||
getNodeList = util.getNodeList,
|
||||
makePoint = util.makePoint,
|
||||
makePoly = util.makePoly,
|
||||
|
@ -134,6 +158,9 @@ TimeMap.loaders.kml.parse = function(kml) {
|
|||
// XXX: worth closing unclosed polygons?
|
||||
data.placemarks.push(pmobj);
|
||||
}
|
||||
// look for any extra tags and/or ExtendedData specified
|
||||
this.parseExtra(data, pm);
|
||||
|
||||
items.push(data);
|
||||
}
|
||||
|
||||
|
@ -156,13 +183,51 @@ TimeMap.loaders.kml.parse = function(kml) {
|
|||
data.overlay.south = getTagValue(nList[0], "south");
|
||||
data.overlay.east = getTagValue(nList[0], "east");
|
||||
data.overlay.west = getTagValue(nList[0], "west");
|
||||
// look for any extra tags and/or ExtendedData specified
|
||||
this.parseExtra(data, pm);
|
||||
items.push(data);
|
||||
}
|
||||
|
||||
// clean up
|
||||
kmlnode = null;
|
||||
placemarks = null;
|
||||
pm = null;
|
||||
nList = null;
|
||||
kmlnode = placemarks = pm = nList = null;
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
|
@ -10,28 +10,24 @@
|
|||
* @author Nick Rabinowitz (www.nickrabinowitz.com)
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Loader
|
||||
*
|
||||
*/
|
||||
// for JSLint
|
||||
/*global TimeMap */
|
||||
|
||||
/**
|
||||
* @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
|
||||
* 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
|
||||
* the API site.</p>
|
||||
*
|
||||
* <p>Depends on:</p>
|
||||
* <ul>
|
||||
* <li>lib/json2.pack.js</li>
|
||||
* <li>loaders/jsonp.js</li>
|
||||
* </ul>
|
||||
* @augments TimeMap.loaders.jsonp
|
||||
* @requires lib/json2.pack.js
|
||||
* @requires loaders/jsonp.js
|
||||
*
|
||||
* @example Usage in TimeMap.init():
|
||||
|
||||
* @example
|
||||
TimeMap.init({
|
||||
datasets: [
|
||||
{
|
||||
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>
|
||||
* {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
|
||||
* @param {Object} options All options for the loader
|
||||
* @param {Object} options.query MQL query to load
|
||||
* @param {Function} options.transformFunction Function to call on individual items before loading
|
||||
* @param {String} [options.host=http://www.freebase.com] Host url of web service
|
||||
* @param {String} [options.service=/api/service/mqlread] Path to web service on host
|
||||
* @param {mixed} [options[...]] Other options (see {@link TimeMap.loaders.jsonp})
|
||||
*/
|
||||
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";
|
||||
/**
|
||||
* Service path - default to freebase.com default
|
||||
* @name TimeMap.loaders.metaweb#QUERY_SERVICE
|
||||
* @type {String}
|
||||
*/
|
||||
loader.QUERY_SERVICE = options.service || "/api/service/mqlread";
|
||||
|
||||
// Metaweb preload functon
|
||||
/**
|
||||
* 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=";
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// Open outer envelope
|
||||
var innerEnvelope = data.qname;
|
||||
// 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
|
||||
/*
|
||||
// If error, get error message and throw
|
||||
|
@ -80,16 +104,8 @@ TimeMap.loaders.metaweb = function(options) {
|
|||
return [];
|
||||
}
|
||||
// Get result from inner envelope
|
||||
var result = innerEnvelope.result;
|
||||
return result;
|
||||
return innerEnvelope.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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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