1 /*
  2  * Timemap.js Copyright 2010 Nick Rabinowitz.
  3  * Licensed under the MIT License (see LICENSE.txt)
  4  */
  5 
  6 /**
  7  * @fileOverview
  8  * TimeMap Export Functions
  9  *
 10  * <p>Functions in this file allow TimeMap, TimeMapDataset, and TimeMapItem
 11  * objects to be serialized to a JSON string suitable for loading back into
 12  * TimeMap.init(). This allows for a range of server-side options for
 13  * data persistence and management.</p>
 14  * 
 15  * @requires json2: lib/json2.pack.js
 16  *
 17  * @author Nick Rabinowitz (www.nickrabinowitz.com)
 18  */
 19 
 20 /*globals TimeMap, TimeMapDataset, TimeMapItem */
 21  
 22 /**
 23  * Clean up TimeMap into a nice object for serialization
 24  * This is called automatically by the JSON.stringify() function
 25  */
 26 TimeMap.prototype.toJSON = function() {
 27     var data = {
 28         'options': this.makeOptionData,
 29         'datasets': this.datasets
 30     };
 31     data = this.addExportData(data);
 32     return data;
 33 };
 34 
 35 /**
 36  * Make a cleaned up object for the TimeMap options
 37  */
 38 TimeMap.prototype.makeOptionData = function() {
 39     var data = {}, util = TimeMap.util;
 40     // copy options
 41     var opts = this.opts;
 42     for (var k in opts) {
 43         if (opts.hasOwnProperty(k)) {
 44             data[k] = opts[k];
 45         }
 46     }
 47     // clean up: mapCenter
 48     if (data.mapCenter) {
 49         data.mapCenter = util.makePoint(data.mapCenter);
 50     }
 51     // clean up: mapType
 52     if (data.mapType) {
 53         data.mapType = util.revHash(TimeMap.mapTypes, data.mapType);
 54     }
 55     // clean up: mapTypes
 56     if (data.mapTypes) {
 57         var mts=[], mt;
 58         for (var x=0; x<data.mapTypes.length; x++) {
 59             mt = util.revHash(TimeMap.mapTypes, data.mapTypes[x]);
 60             if (mt) {
 61                 mts.push(mt);
 62             }
 63         }
 64         data.mapTypes = mts;
 65     }
 66     // clean up: bandIntervals
 67     if (data.bandIntervals) {
 68         data.bandIntervals = util.revHash(TimeMap.intervals, data.bandIntervals);
 69     }
 70     // including themes here too - might be a TimeMap attribute
 71     var themes=[], t, id;
 72     for (id in this.datasets) {
 73         if (this.datasets.hasOwnProperty(id)) {
 74             t = util.revHash(TimeMapDataset.themes, this.datasets[id].opts.theme);
 75             if (t) {
 76                 themes.push(t);
 77             }
 78         }
 79     }
 80     data.themes = t;
 81     return data;
 82 };
 83 
 84 /**
 85  * Specify additional data for export. Replace this function to change settings.
 86  *
 87  * @param {Object} data      Initial map of export data
 88  * @return {Object}          Expanded map of export data
 89  */
 90 TimeMap.prototype.addExportData = function(data) {
 91     data.options = data.options || {};
 92     // set any additional server info (e.g. a database key) in opts.saveOpts
 93     data.options.saveOpts = this.opts.saveOpts;
 94     return data;
 95 };
 96 
 97 /**
 98  * Clean up dataset into a nice object for serialization
 99  * This is called automatically by the JSON.stringify() function.
100  *
101  * <p>Note that, at the moment, this function only supports fully-serialized
102  * datasets - so external data imported with JSON or KML will be serialized
103  * in full and no longer connected to their original file.</p>
104  */
105 TimeMapDataset.prototype.toJSON = function() {
106     var data = {
107         'title': this.getTitle(),
108         'theme': TimeMap.util.revHash(TimeMapDataset.themes, this.opts.theme),
109         'data': {
110             'type':'basic', // only type supported by serialization at the moment
111             'value': this.getItems()
112         }
113     };
114     data = this.addExportData(data);
115     return data;
116 };
117 
118 /**
119  * Specify additional data for export. Replace this function to change settings.
120  *
121  * @param {Object} data      Initial map of export data
122  * @return {Object}          Expanded map of export data
123  */
124 TimeMapDataset.prototype.addExportData = function(data) {
125     data.options = data.options || {};
126     // set any additional server info (e.g. a database key) in opts.saveOpts
127     data.options.saveOpts = this.opts.saveOpts;
128     return data;
129 };
130 
131 // XXX: export items to KML with placemark.getKmlAsync?
132 
133 /**
134  * Clean up item into a nice object for serialization.
135  * This is called automatically by the JSON.stringify() function
136  */
137 TimeMapItem.prototype.toJSON = function() {
138     // any additional info (e.g. a database key) should be set in opts.saveOpts
139     var data = {
140         'title': this.getTitle(),
141         'options': {
142             'description': this.opts.description
143         }
144     };
145     // add event info
146     if (this.event) {
147         data.start = this.event.getStart();
148         if (!this.event.isInstant()) {
149             data.end = this.event.getEnd();
150         }
151     }
152     // add placemark info
153     if (this.placemark) {
154         var util = TimeMap.util;
155         // internal function - takes type, placemark, data
156         var makePlacemarkJSON = function(type, pm, pdata) {
157             type = type || util.getPlacemarkType(pm);
158             switch (type) {
159                 case "marker":
160                     pdata.point = util.makePoint(pm.getLatLng());
161                     break;
162                 case "polyline":
163                 case "polygon":
164                     var line = [];
165                     for (var x=0; x<pm.getVertexCount(); x++) {
166                         line.push(util.makePoint(pm.getVertex(x)));
167                     }
168                     pdata[type] = line;
169                     break;
170             }
171             return pdata;
172         };
173         if (this.getType() == 'array') {
174             data.placemarks = [];
175             for (var i=0; i<this.placemark.length; i++) {
176                 data.placemarks.push(makePlacemarkJSON(false, this.placemark[i], {}));
177             }
178         } else {
179             data = makePlacemarkJSON(this.getType(), this.placemark, data);
180         }
181     }
182     data = this.addExportData(data);
183     return data;
184 };
185 
186 /**
187  * Specify additional data for export. Replace this function to change settings.
188  *
189  * @param {Object} data      Initial map of export data
190  * @return {Object}          Expanded map of export data
191  */
192 TimeMapItem.prototype.addExportData = function(data) {
193     data.options = data.options || {};
194     // set any additional server info (e.g. a database key) in opts.saveOpts
195     data.options.saveOpts = this.opts.saveOpts;
196     return data;
197 };
198 
199 /**
200  * Util function: get the key from the map if the value is found
201  *
202  * @param {Object} map      Object to search
203  * @param {?} val           Value to look for
204  * @return {String}         Key if found, null if not
205  */
206 TimeMap.util.revHash = function(map, val) {
207     for (var k in map) {
208         if (map[k] == val) {
209             return k;
210         }
211     }
212     // nothing found
213     return null;
214 };
215