8

I've some js files organized this way (see source):

  • gmaps4rails.base.js : contains all the logic

    • gmaps4rails.googlemaps.js : contains functions

    • gmaps4rails.bing.js : contains functions with the same name as the previous file

So basically, base calls createMarkers() which is in both googlemaps and bing.

From now, I load only one among gmaps4rails.googlemaps.js and gmaps4rails.googlemaps.js, depending on the map API I need, so it works fine.

Now I'd like to be able to have all files loaded (and keep them separate) BUT of course only include the code of the desired maps API.

Basically I think about something like:

if desiredApi == "googlemaps"
   include GoogleMapsNameSpace content in BaseNameSpace

Thanks in advance.

Flambino
  • 18,507
  • 2
  • 39
  • 58
apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • Are you trying to implement a strategy pattern for the `createMarkers()` function? – Wyatt Aug 25 '11 at 17:22
  • 1
    Are those functions global? If yes, that's the issue right there. You don't want to have a script that contains a bunch of global functions that pollute the global namespace - instead, for each script you want to define **one** global name (the namespace), and then put everything (those functions) inside that namespace. If you had done it like so, you would have been able to include (and use) both scripts easily... – Šime Vidas Aug 25 '11 at 17:29
  • @whatgoodisaroad: I'm not familiar enough with js to answer this, I'll check the definition – apneadiving Aug 25 '11 at 20:10
  • @Šime Vidas: I do have two namespaces `Base` and `GoogleMaps` how could I merge one in the other? – apneadiving Aug 25 '11 at 20:14
  • @apneadiving It's not really a JS term, the strategy pattern is a generic [design pattern](http://en.wikipedia.org/wiki/Strategy_pattern). Basically, it allows you to invoke any of a number of implementations via a unified interface. – Wyatt Aug 25 '11 at 20:27
  • @apnea Unfortunately, your scripts `googlemaps.js` and `bing.js` merely **augment** the existing `Gmaps4Rails` object - they do not create a new namespace. As a result, if you load both scripts, they will write / overwrite the same property names of the `Gmaps4Rails` object. What you could do is repeatedly load those scripts (whenever you need them) - that will trigger the overwrite (because they are executed again). – Šime Vidas Aug 25 '11 at 21:38
  • @Šime Vidas: Yep, in my comment, I was simply anticipating a potential solution. But is it possible to merge 2 namespaces? – apneadiving Aug 25 '11 at 21:45

2 Answers2

2

If I understand correctly you just want to be able to use either the google maps API or the bing API or someother based on the user selection (or some other criteria)? For that, instead of trying to merge the correct API into your base object, why don't you just refer a 'mapService' from your base object and select the mapService based on the criteria you want?

Something like this:

Map = function(service, canvasId) {
    var mapService = MapServices[service];

    return {
        initialize: function() {
            var theMap = mapService.createMap();
            mapService.render(canvasId);
        }
// more functionality for your base object (that the outside world calls) goes here

    }
}

var MapServices = MapServices || {};

MapServices.google = {
  createMap: function() {},
  render: function(canvas) {
    $("#"+canvas).html("I'm a google map");
  },
  createMarker: function(args) {}
// all your map functionality goes here calling google specific functions
};

// this could be in a different js
MapServices.bing = {
  createMap: function() {},
  render: function(canvas) {
    $("#"+canvas).html("I'm a bing map");
  }, 
  createMarker: function(args) {},
// all your map functionality goes here calling bing specific functions
}

$(function() {
  var theMap = new Map("google", "theDiv");
  theMap.initialize();
});

Is this what you want to do?

Hope this helps

Jaime
  • 6,736
  • 1
  • 26
  • 42
  • I ended up doing basic inheritance (my source codeis updated if you're curious). Whatever, your approach fits too! – apneadiving Aug 27 '11 at 07:22
2

I think you are looking for some kind of asynchronous loader. CommonJS has proposed Modules 1.1 and the Asynchronous Module Definition (AMD) API that do this. There are quite a few implementations of async loaders, as listed in this Google spreadsheet. Of which, a few of them are AMD-compliant, for example:

This blog entry has a nice discussion on this topic.

Also see this SO post: Namespace a dynamically loaded javascript file's contents

Community
  • 1
  • 1
William Niu
  • 15,798
  • 7
  • 53
  • 93
  • Thanks for these resources and +1. They have great added value. I finally ended up doing basic inheritance (source code updated if you're curious). – apneadiving Aug 27 '11 at 07:23