I know quite a few JavaScript MVC frameworks out there but corMVC is what makes me exited at most for a few reasons.
corMVC stands for “client-only-required” Model-View-Controller and that means it does not depend on specific server-side technology. In case you want to demo something, it would be perfect if everything can be done on client side. Of course, you can save changes or load data from server (via Model) as the general illustration below.
Not like other JavaScript MVC solutions, corMVC is very simple and has very small footprint. It also does not require you to build the application using scaffolding or any other command-line utilities.
The whole framework is actually a 19KB JavaScript file (not minified yet) named Application.js, you’ll have to define models, views and controllers by yourself following the guidelines. It’s not hard especially for those who are familiar with modern MVC frameworks like Rails, Django or CakePHP.
Running application built on corMVC, you’ll have almost the same impression of running a server-side MVC application for the URIs (after the hash, however) are changed based on actions. The following diagram is about how the framework detects URL changes and handles events accordingly.
To get an overview of how the framework works and the interaction of model-view-controller we are going to examine the demo application called “Contacts” provided by Ben Nadel — the author of corMVC. The app, as its name tells, is a contact manager that has all basic functionalities like Search, View, Add and Delete contact info on a single web page.
Let’s look at definition of a “contact” model in “contact.js” file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Add model to the application. window.application.addModel((function( $, application ){ // I am the contact class. function Contact( id, name, phone, email ){ this.id = (id || 0); this.name = (name || ""); this.phone = (phone || ""); this.email = (email || ""); }; // I validate the contact instance. Contact.prototype.validate = function(){ // For now, we are just goint to validate TRUE on the client and let // the full validation happen on the model peristence. return( [] ); }; // ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- // // Return a new model class. return( Contact ); })( jQuery, window.application )); |
The code define a contact class with a few properties like ID, Name, Phone# and E-mail address and return the class as a model that will be used by Controllers/Views.
The controller is more interesting and it’s not too difficult to understand though.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | // Add a controller to the application. window.application.addController((function( $, application ){ // I am the controller class. function Controller(){ // Route URL events to the controller's event handlers. this.route( "/", this.index ); this.route( "/contacts/", this.index ); this.route( "/contacts/add/", this.addContact ); this.route( "/contacts/edit/:id", this.editContact ); this.route( "/contacts/delete/:id", this.deleteContact ); // Set default properties. this.currentView = null; this.contactListView = null; this.contactFormView = null; }; // Extend the core application controller (required). Controller.prototype = new application.Controller(); // I initialize the controller. I get called once the application starts // running. At that point, the DOM is available and all the other model // and view classes will have been added to the system. Controller.prototype.init = function(){ this.contactListView = application.getView( "ContactList" ); this.contactFormView = application.getView( "ContactForm" ); }; // I am the add event for this controller. Controller.prototype.addContact = function( event ){ // Show the form view. this.showView( this.contactFormView, event ); }; // I am the edit event for this controller. Controller.prototype.editContact = function( event, id ){ // Show the form view. this.showView( this.contactFormView, event ); }; // I am the delete event for this controller. Controller.prototype.deleteContact = function( event, id ){ // Delete the contact. application.getModel( "ContactService" ).deleteContact( id, function(){ application.relocateTo( "contacts" ); } ); }; // I am the default event for this controller. Controller.prototype.index = function( event ){ // Show the list view. this.showView( this.contactListView, event ); }; // I show the given view; but first, I hide any existing view. Controller.prototype.showView = function( view, event ){ // Check to see if there is a current view. If so, then hide it. if (this.currentView && this.currentView.hideView){ this.currentView.hideView(); } // Show the given view. view.showView( event.parameters ); // Store the given view as the current view. this.currentView = view; }; // ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- // // Return a new contoller instance. return( new Controller() ); })( jQuery, window.application )); |
Basically, the controller defines routes for events associated with handlers like addContact, editContact, deleteContact. In most of cases, the handlers are to show appropriated views or to send events to model for updates.
There are a number of views required by the app such as “Contact List“, “Contact Form” and a simple view for progress notification. Here are excerpt codes from “Contact List” view that mostly to interact with user and send events to controller if necessary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | // Add view to the application. window.application.addView((function( $, application ){ // I am the contact list view class. function ContactList(){ this.layout = null; this.searchForm = null; this.searchCriteria = null; this.addLink = null; this.contactList = null; this.contactTemplate = null; }; // I initialize the view. I get called once the application starts // running. At that point, the DOM is available and all the other model // and view classes will have been added to the system. ContactList.prototype.init = function(){ var self = this; // Initialize properties. this.layout = $( "#contact-list-layout" ); this.searchForm = $( "#contact-list-header form" ); this.searchCriteria = this.searchForm.find( "input" ); this.addLink = $( "#contact-list-header a" ); this.contactList = $( "#contact-list" ); this.contactTemplate = $( "#contact-list-item-template" ); // Bind the search form submit. this.searchForm.submit( function( event ){ // Hand of to the search form handler. self.searchFormHandler(); // Cancel the default event. return( false ); } ); // Bind the keypress event on the search criteria. this.searchCriteria.keyup( function( event ){ // Filter the contact list. self.filterList( this.value ); } ); // Bind the keypress event to the search criteria so we can track // the use of the special keys presses. this.searchCriteria.keypress( function( event ){ // Store the SHIFT and ALT key status of the current click. self.searchCriteria.data( "shift", event.shiftKey ); self.searchCriteria.data( "alt", event.altKey ); } ); // Bind the list-level clicking (to avoid setting to many // event handlers). this.contactList.click( function( event ){ var target = $( event.target ); // Check to see if the target is the "more" link. if (target.is( "a.more" )){ // Toggle the list item details. self.toggleDetails( target.parents( "li" ) ); // Blur the current link. target.blur(); // Prevent default event. return( false ); // Check to see if the target is a the "delete" link. } else if (target.is( "a.delete" )){ // Blur the current link. target.blur(); // Confirm that the user wants to delete the contact. if (confirm( "Delete this contact?" )){ // This is a *hack* that we have to do since jQuery click() // event won't trigger the default action of the link. application.setLocation( target.attr( "href" ) ); } // Return false to cancel default event. return( false ); } } ); }; .... // Return a new view class. return( new ContactList() ); })( jQuery, window.application )); |
Up till now, you may have had the overall knowledge of the framework and how to create a pure JavaScript MVC application. Yet, to get full understanding of corMVC, please see this great video presentation in which Ben Nadel explains why he came to the framework, how the JavaScript/jQuery were used, step-by-step application building etc. (this is a multiple-part video and a bit lengthy but I’m sure it’ll pay off.)
Recommended Reading
Eloquent JavaScript: A Modern Introduction to Programming"A concise and balanced mix of principles and pragmatics. I loved the tutorial-style game-like program development. This book rekindled my earliest... Read More >
High Performance JavaScript (Build Faster Web Application Interfaces)If you're like most developers, you rely heavily on JavaScript to build interactive and quick-responding web applications. The problem is that all ... Read More >
jQuery CompressedThe books examples are verified to work with jQuery 1.7jQuery is a JavaScript API that makes it easy to make your HTML pages come to life.... Read More >








great stuff. I love the idea. could it be modified to store contacts in a .xml file in the browser cache?
I don’t think there is a way to save xml in browser cache
How about local storage supported by HTML5?
[...] Esa es la idea de corMVC, un framework jQuery que nos implementa esta tecnología. Para ello nos ofrece window.application con una serie de métodos para trabajar cómodamente con las diferentes capas. [...]
Thanks for launching this. I will try this out. I do a lot of works with jquery, so if it can simplifies all complexities, that will be great. I also worked with php codeigniter MVC before and it was great. Lets see, how is it…
Nice work
.