MVC by Alex

The article describes an implementation of Model-View-Controller software design pattern in JavaScript. http://www.alexatnet.com/articles/model-view-controller-mvc-javascript

by Andy Bulka

HTML

<select id="list" size="10" style="width: 15em"></select><br/>
<button id="plusBtn">  +  </button>
<button id="minusBtn">  -  </button>

JavaScript

// This version is altered, in that it takes out the 
// wiring up of things and put that externally.
//
// This version also fixes the bug where selected value is lost 
// every time you add or remove a value.  Now, not only is preserved, 
// it decrements as you delete items from the list.  
// More importantly, the view now no longer alters the model's 
// selected index (Alex acknowledged all changes to model should
// go through controller).
//
// - ANDY

/**
 * The Model. Model stores items and notifies
 * observers about changes.
 */
var ListModel = function (items) {
    this._items = items;
    this._selectedIndex = -1;
 
    this.itemAdded = new Event(this);
    this.itemRemoved = new Event(this);
    this.selectedIndexChanged = new Event(this);
};
 
ListModel.prototype = {
 
    getItems : function () {
        return [].concat(this._items);
    },
 
    addItem : function (item) {
        this._items.push(item);
        this.itemAdded.notify({item: item});
    },
 
    removeItemAt : function (index) {
        var item = this._items[index];
        this._items.splice(index, 1);
        this.itemRemoved.notify({item: item});
        maxindex = this._items.length - 1;    // NEW
        if (this._selectedIndex > maxindex) {  // NEW
            this.setSelectedIndex(maxindex);   // NEW
        }
    },
 
    getSelectedIndex : function () {
        return this._selectedIndex;
    },
 
    setSelectedIndex : function (index) {
        var previousIndex = this._selectedIndex;
        this._selectedIndex = index;
        this.selectedIndexChanged.notify({previous: previousIndex});
    }
};

// Event is a simple class for implementing the Observer pattern:

var Event = function (sender) {
    this._sender = sender;
    this._listeners = [];
};
 
Event.prototype = {
    attach : function (listener) {
        this._listeners.push(listener);
    },
    notify : function (args) {
        for (var i = 0; i < this._listeners.length; i++) {
           ...