Extending modules

57 views
Skip to first unread message

James Kelly

unread,
Aug 21, 2012, 3:15:37 AM8/21/12
to kern...@googlegroups.com
I have come to a point where I have been wondering if I can extend a module.  Again, I think it's my javascript skills that are letting me down here.  I don't want to instantiate a duplicate via the Kernel.register, as I want to override all the listeners.

Here's my existing module

Kernel.module.define('InspectionItemsMap', {

    renderTo: "#inspection-items-map",
    map: {},
    geojsonLayer: [],
    display: true,
    layers: {},

    mapElementName: function () {
        var self = this;
        var mapElementName = self.renderTo.substr(1, self.renderTo.length);
        return mapElementName;
    },

    hideButtonName: function () {
        var name = "hide-" + this.mapElementName() + "-button";
        return name;
    },


    init: function () {

        var self = this;

        if (self.display === false) {
            hub.quickHide(self.renderTo);
        }

        self.map = self.createMap();


        $("#" + self.hideButtonName()).click(function () {
            hub.hide(self.renderTo);
        });


        hub.listen('show-inspections-on-map', function (inspections) {
            //show the data
            self.addGeoJsonAndZoomTo(inspections);
            self.showMap();
        });

        hub.listen('show-map', function () {
            self.showMap();
        });


        hub.listen('clear-inspection-map', function () {
            self.clearMap();
        });

    },

    refreshMap: function () {
        var self = this;
        //this is a hack to refresh the map because of the dynamic nature of it's loading...
        L.Util.requestAnimFrame(self.map.invalidateSize, self.map, !1, self.map._container);
    },

    showMap: function () {
        var self = this;
        hub.show(self.renderTo);
        self.refreshMap();
    },

    addGeoJsonAndZoomTo: function (geoJson) {
        var self = this;
        var layer = self.layers.geojson;
        var map = self.map;
        self.clearMap();
        layer.addData(geoJson);
        map.addLayer(layer);
        var bounds = layer.getBounds();
        map.fitBounds(bounds);
        self.refreshMap();
    },

    clearMap: function () {
        var self = this;
        var map = self.map;
        var layer = self.layers.geojson;

        //if we have the geojsonlayer, clear it!
        if (typeof (layer !== "undefined")) {
            layer.clearLayers();
            map.removeLayer(layer);
        }
    },

    createMap: function () {
        var self = this;
        self.createLayers();
        var map = L.map(self.mapElementName());

        map.addLayer(self.layers.lur);
        map.addLayer(self.layers.mapquest);
        map.addLayer(self.layers.geojson);
        map.setView([-37.9771, 143.7560], 10);
        self.addHideControl(map);
        return map;
    },

    onEachFeature: function (feature, layer) {
        // does this feature have a property named popupContent?
        if (feature.properties && feature.properties.popupContent) {
            layer.bindPopup(feature.properties.popupContent);
        }
    },

    createLayers: function () {
        var self = this;
        var geoserver = "http://10.8.135.12:8080/geoserver/wms";

        var mapquest = new L.TileLayer("http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png", {
            maxZoom: 18,
            attribution: "Data CC-By-SA by <a href='http://openstreetmap.org/' target='_blank'>OpenStreetMap</a>, Tiles Courtesy of <a href='http://open.mapquest.com' target='_blank'>MapQuest</a>",
            subdomains: ["1", "2", "3", "4"]
        });

        var lur = new L.TileLayer.WMS(geoserver, {
            layers: 'MIDWAY:LUR',
            format: 'image/png',
            transparent: true,
            TILED: true
        });

        var geojsonLayer = L.geoJson([], { onEachFeature: self.onEachFeature });
        self.layers = { "lur": lur, "mapquest": mapquest, "geojson": geojsonLayer };

    },



    addHideControl: function (map) {
        //TODO: template this.  It's nasty.
        var self = this;

        var hideControl = L.control({ position: 'topright' });

        hideControl.onAdd = function (map) {
            var div = L.DomUtil.create('div', 'hide-map');
            div.innerHTML += '<button id= "' + self.hideButtonName() + '" class="btn">Hide Map</button>'
            return div;
        };

        hideControl.addTo(map);
    },

    render: function () {
        //my rendering magic in here...not really needed though, leaflet handles all that itself
    }
});

I wouldn't mind, rather than creating a new module with a lot of the same functions, would be to extend the existing module, but just override the init, something like below.  Am I missing something and this is already possible?

Kernel.module.extend('InspectionItemsMap', {
    renderTo: "#some-other-page-element", 
    init: function (){
       some other init listeners to handle this maps events
    }
});

Does this module look ok?  I can see some of these types of modules, particularly map based ones getting quite large as far as functions go, do you have tips for separating them out?  Do these separations get pulled out into other classes (or whatever they are called in js), or if they are being reused, attached onto an extension of the kernel?

Thanks in advance

James

alan lindsay

unread,
Aug 21, 2012, 11:19:14 AM8/21/12
to kern...@googlegroups.com
James,

You can override modules when you register them or when you initialize them. So for example you can do this:

Kernel.register('inspection-items-map1', 'InspectionItemsMap');
Kernel.register('inspection-items-map2', 'InspectionItemsMap', {
    init: function() { ... }
});

Kernel.start('inspection-items-map1');
Kernel.start('inspection-items-map2', {
    init: function() { ... }
});

This is better suited for overriding minor config changes to the module, not really extending it. While you can override functions this way, including init, it may not be what you are after. On the other hand if all you are doing is overriding init to setup different listeners it might be fine. I just realized there is an undocumented feature that allows you to extend modules:

Kernel.module.define('InspectionItemsMapVariation', {

    // This will use the following module(s) as a base definitions
    extend: 'InspectionItemsMap', 

    init: function() { ... }

});

You can even extend multiple modules (multiple parents) which will inherit in the order you specify:

Kernel.module.define('InspectionItemsMapVariation', {

    // This will use the following module(s) as a base definitions
    extend: ['InspectionItemsMap', 'AnotherModule'], 

    init: function() { ... }

});

Doing it this way affords you the advantage of keeping the extension in a separate file as well as giving it a specific name--it is a new module type. It's easier to manage than inline overrides if you are actually making a separate module type rather than changing config.

As far as general feedback on your module I will point out that in your init method you are referencing a global variable 'hub' which must be defined elsewhere if you are not getting errors. I recommend against this practice, use the local variable (this.hub, self.hub) instead, it will save you headaches. Also you can simplify your listeners a bit:

init: function() {
    
    self.hub.listen('show-map', self.showMap);
    self.hub.listen('clear-inspection-map', self.clearMap);

}

There is no to wrap these calls with anon functions.

Alan

James Kelly

unread,
Aug 21, 2012, 6:57:14 PM8/21/12
to kern...@googlegroups.com
Hi Alan

Thanks again for the advice.  I created the hub as a global early on when I was testing how to do things, I will have a look at moving all that across.

I had worked out the override behaviour, but I hadn't come across your extend method, which is exactly what I was after.  That's going to make my life a lot easier as I am finding a lot of the setup of these modules is similar, but I would still like to keep the one module per file file structure.

Cheers

James

alan lindsay

unread,
Aug 21, 2012, 7:02:33 PM8/21/12
to kern...@googlegroups.com

Glad to hear it.

Alan

Reply all
Reply to author
Forward
0 new messages