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:
It also has a map background which loads the background tiles and displays the features. So, I considered two separate files:
GoogleMap.Search.js
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.