|
49 | 49 |
|
50 | 50 | // the global options
|
51 | 51 | self.options = self.extendDefaultOptions(options);
|
| 52 | + |
| 53 | + // Save initial HTML content (used by destroy method) |
| 54 | + self.initialHTMLContent = self.$container.html(); |
52 | 55 |
|
53 | 56 | // zoom TimeOut handler (used to set and clear)
|
54 | 57 | self.zoomTO = 0;
|
|
216 | 219 | self.onUpdateEvent(e, opt);
|
217 | 220 | });
|
218 | 221 |
|
219 |
| - // Handle resizing of the map |
| 222 | + // Handle map size |
220 | 223 | if (self.options.map.width) {
|
| 224 | + // NOT responsive: map has a fixed width |
221 | 225 | self.paper.setSize(self.options.map.width, self.mapConf.height * (self.options.map.width / self.mapConf.width));
|
222 | 226 |
|
223 | 227 | // Create the legends for plots taking into account the scale of the map
|
224 | 228 | self.createLegends("plot", self.plots, (self.options.map.width / self.mapConf.width));
|
225 | 229 | } else {
|
226 |
| - $(window).on("resize." + pluginName, function () { |
227 |
| - clearTimeout(self.resizeTO); |
228 |
| - self.resizeTO = setTimeout(function () { |
229 |
| - self.$map.trigger("resizeEnd." + pluginName); |
230 |
| - }, 150); |
231 |
| - }); |
232 |
| - |
233 |
| - // Create the legends for plots taking into account the scale of the map |
234 |
| - var createPlotLegend = function () { |
235 |
| - self.createLegends("plot", self.plots, (self.$map.width() / self.mapConf.width)); |
236 |
| - |
237 |
| - self.$map.off("resizeEnd." + pluginName, createPlotLegend); |
238 |
| - }; |
239 |
| - |
240 |
| - self.$map.on("resizeEnd." + pluginName, function () { |
241 |
| - var containerWidth = self.$map.width(); |
242 |
| - if (self.paper.width != containerWidth) { |
243 |
| - self.paper.setSize(containerWidth, self.mapConf.height * (containerWidth / self.mapConf.width)); |
244 |
| - } |
245 |
| - }).on("resizeEnd." + pluginName, createPlotLegend).trigger("resizeEnd." + pluginName); |
| 230 | + // Responsive: handle resizing of the map |
| 231 | + self.handleMapResizing(); |
246 | 232 | }
|
247 | 233 |
|
248 | 234 | // Hook that allows to add custom processing on the map
|
249 | 235 | if (self.options.map.afterInit) self.options.map.afterInit(self.$container, self.paper, self.areas, self.plots, self.options);
|
250 | 236 |
|
251 | 237 | $(self.paper.desc).append(" and Mapael " + self.version + " (http://www.vincentbroute.fr/mapael/)");
|
252 | 238 | },
|
| 239 | + |
| 240 | + /* |
| 241 | + * Destroy mapael |
| 242 | + * This function effectively detach mapael from the container |
| 243 | + * - Set the container back to the way it was before mapael instanciation |
| 244 | + * - Remove all data associated to it (memory can then be free'ed by browser) |
| 245 | + * |
| 246 | + * This method can be call directly by user: |
| 247 | + * $(".mapcontainer").data("mapael").destroy(); |
| 248 | + * |
| 249 | + * This method is also automatically called if the user try to call mapael |
| 250 | + * on a container already containing a mapael instance |
| 251 | + */ |
| 252 | + destroy: function() { |
| 253 | + var self = this; |
| 254 | + // Empty the container (this will also detach all event listeners) |
| 255 | + self.$container.empty(); |
| 256 | + // Detach the global resize event handler |
| 257 | + if (self.onResizeEvent) $(window).off("resize." + pluginName, self.onResizeEvent); |
| 258 | + // Replace initial HTML content |
| 259 | + self.$container.html(self.initialHTMLContent); |
| 260 | + // Remove mapael class |
| 261 | + self.$container.removeClass(pluginName); |
| 262 | + // Remove the data |
| 263 | + self.$container.removeData(pluginName); |
| 264 | + // Remove all internal reference |
| 265 | + self.container = undefined; |
| 266 | + self.$container = undefined; |
| 267 | + self.options = undefined; |
| 268 | + self.paper = undefined; |
| 269 | + self.$map = undefined; |
| 270 | + self.$tooltip = undefined; |
| 271 | + self.mapConf = undefined; |
| 272 | + self.areas = undefined; |
| 273 | + self.plots = undefined; |
| 274 | + self.links = undefined; |
| 275 | + }, |
| 276 | + |
| 277 | + handleMapResizing: function() { |
| 278 | + var self = this; |
| 279 | + // Create the legends for plots taking into account the scale of the map |
| 280 | + var createPlotLegend = function () { |
| 281 | + self.createLegends("plot", self.plots, (self.$map.width() / self.mapConf.width)); |
| 282 | + |
| 283 | + self.$map.off("resizeEnd." + pluginName, createPlotLegend); |
| 284 | + }; |
| 285 | + |
| 286 | + // onResizeEvent: call when the window element trigger the resize event |
| 287 | + // We create it inside this function (and not in the prototype) in order to have a closure |
| 288 | + // Otherwise, in the prototype, 'this' when triggered is *not* the mapael object but the global window |
| 289 | + self.onResizeEvent = function () { |
| 290 | + // Clear any previous setTimeout (avoid too much triggering) |
| 291 | + clearTimeout(self.resizeTO); |
| 292 | + // setTimeout to wait for the user to finish its resizing |
| 293 | + self.resizeTO = setTimeout(function () { |
| 294 | + self.$map.trigger("resizeEnd." + pluginName); |
| 295 | + }, 150); |
| 296 | + }; |
| 297 | + |
| 298 | + // Attach resize handler |
| 299 | + $(window).on("resize." + pluginName, self.onResizeEvent); |
| 300 | + |
| 301 | + self.$map.on("resizeEnd." + pluginName, function () { |
| 302 | + var containerWidth = self.$map.width(); |
| 303 | + if (self.paper.width != containerWidth) { |
| 304 | + self.paper.setSize(containerWidth, self.mapConf.height * (containerWidth / self.mapConf.width)); |
| 305 | + } |
| 306 | + }).on("resizeEnd." + pluginName, createPlotLegend).trigger("resizeEnd." + pluginName); |
| 307 | + }, |
253 | 308 |
|
254 | 309 | /*
|
255 | 310 | * Extend the user option with the default one
|
|
1856 | 1911 | $.fn[pluginName] = function (options) {
|
1857 | 1912 | // Call Mapael on each element
|
1858 | 1913 | return this.each(function () {
|
1859 |
| - // Avoid multiple instanciation |
1860 |
| - if ($.data(this, pluginName)) throw new Error("Mapael already exists on this element."); |
| 1914 | + // Avoid leaking problem on multiple instanciation by removing an old mapael object on a container |
| 1915 | + if ($.data(this, pluginName)) { |
| 1916 | + $.data(this, pluginName).destroy(); |
| 1917 | + } |
1861 | 1918 | // Create Mapael and save it as jQuery data
|
1862 |
| - // This allow external access to Mapael using $(".mapcontainer").data.mapael |
| 1919 | + // This allow external access to Mapael using $(".mapcontainer").data("mapael") |
1863 | 1920 | $.data(this, pluginName, new Mapael(this, options));
|
1864 | 1921 | });
|
1865 | 1922 | };
|
|
0 commit comments