Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

A while ago I started working on a web application which has a lot of JavaScript code due to having a lot of client-side logic.

Before starting, I had had a quick look at a couple of JavaScript frameworks and micro-frameworks like AngularJS, EmberJS, BackboneJS, Knockout, etc.

Eventually, I decided not to use any toolkits or helper, and implemented a simple MVC pattern based on my own understanding. Now that the application is completed, I am reviewing the code and trying to figure out to improve the code and its structure. Here is what I have:

I created a JavaScript file for each section of the application, for instance, let's consider the Google map as an example: It has a search bar as follows:

Google map search

It also has a map background which loads the background tiles and displays the features. So, I considered two separate files:

  1. GoogleMap.Search.js
  2. GoogleMap.Map.js

In each file, I tried to implement the MVC pattern, let's consider GoogleMap.Map.js. It's supposed to render the background tiles and zoom to the default extent of the map, but also let the user come back to the default extent of the map by clicking on a button.

I would implement it like this:

var GoogleMap = GoogleMap || {};  

GoogleMap.mapModel = {
    $resetMapButtonTrigger: $("#map-reset-button"),
    mapPluginInstance: new mapPlugin();
    defaultExtent : [51.2301467,-0.6193916],
    $mapContainer: $("#map"),
    $mapTitle: $("#mapTitle")

};

GoogleMap.mapController = {
    init: function() {
        GoogleMap.mapModel.$resetMapButtonTrigger.on("click", function() {

       });
    },

    reset: function() {
            GoogleMap.mapModel.mapPluginInstance.zoomToExtnet(GoogleMap.mapModel.defaultExtent);

              $.ajax({
            url: GoogleMap.globalUrls.clearCache,
            data: {

            },
            type: "Post",
            contentType: "application/json; charset=utf-8",
            success: function(data) {

            }

        }).fail(function() {
            GoogleMap.common.notifyError("Error occured");

        });
    }

       $("#visualisation").html("");


        var svg = dimple.newSvg("#visualisation", 600, 370);
        var map = new dimple.map(svg, data);
        map.setBounds(60, 30, 505, 305);
        var x = map.addCategoryAxis("x", "Time");
        x.addOrderRule("Time");
        map.addMeasureAxis("y", "Speed");
        var serie = map.addSeries("Type", dimple.plot.line);
        serie.addEventHandler("click", function(e) {
            return;
            var time = e.xValue;
            GoogleMap.mapController.speedCountPerTime(time);
        });
        map.addLegend(60, 10, 500, 20, "right");
        map.draw();


    },
        $("#visualisation").html("Loading ...");

        var action = GoogleMap.globalUrls.mapControllerRendermapAction;
        $.ajax({
            url: action,
            traditional: true,

            data: {
                percentile: GoogleMap.mapModel.$percentile.val()

            },
            type: "Post",
            dataType: "json",
            success: function(data) {
                GoogleMap.mapController.draw(data);
            }

        }).fail(function() {
            $("#headerLoading").html("error with loading map");

        });
    }
};

GoogleMap.mapView = {
    init: function() {
        var map = GoogleMap.mapModel.mapPluginInstance;
        map.render(GoogleMap.mapModel.$mapContainer);
        map.zoomToExtnet(GoogleMap.mapModel.defaultExtent);
       },

    clear: function() {
        GoogleMap.mapModel.$mapTitle.html("");
    }

};

GoogleMap.mapView.init();
GoogleMap.mapController.init();

In above sample, the default namespace has been defined; the name of the application.

Then, the model, controller and the view has been defined through the object literal syntax.

I have tried to put plugins like GoogleMaps or leaflet or whatever, and HTML controls which keep application data like page title for example in the model.

Then, in the controller, I tried to break the logic into the different functions and do the application concerns like AJAX calls or validations. In the view, I tried to keep functions which are related to the UI and DOM elements, like clearing/rendering the DOM.
It was possible to mix view functions with the controller functions, but I tried to avoid it.

Because I am originally back-end developer, I probably wrote the code from the perspective of a back-end developer.
I don't know if I am doing the whole thing incorrectly? I don't know how can I apply Object-Oriented principles, Dependency Injection and other best practises in my code.

share|improve this question
1  
The frameworks you mentioned use MVVM, not MVC. If you want barebones MVVM, and don't want to reinvent the wheel, Knockout is probably the best choice. – Robert Harvey Oct 21 '15 at 18:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.