( function( window ) {

    'use strict';

    var ToMvc = {};

    /*
        Controller constructor
     */
    var Controller = function( options ) {
        this.defaults = {};
        this.views = [];
        this.models = [];
        this.events = [];

        merge.call( this, this.defaults, options );
    };

    /*
        View constructor
     */
    var View = function( options ) {

        // Controller is necessary
        if ( options && options.controller ) {
            this.controller = options.controller;
        } else {
            throw "View constructor requires controller";
        }

        // DOM element is necessary
        if ( options.el ) {
            this.el = options.el;
        } else {
            throw "View constructor requires DOM element";
        }

        // Default options
        this.defaults = {
            listeners: []
        };

        // Extend defaults
        merge.call( this, this.defaults, options );

        this.setName( options.name );
        this.controller.registerView( this.getName() );

    };

    /*
        Model constructor
     */
    var Model = function( options ) {
        this.defaults = {
            listeners: []
        };

        // Controller is necessary
        if ( options.controller ) {
            this.controller = options.controller;
        } else {
            throw "Model constructor requires controller";
        }

        merge.call( this, this.defaults, options );

        this.setName( options.name );
        this.controller.registerModel( this.getName() );
    };

    /*
        Make OOP possible
     */
    function extend() {
        var parent = this; // ToMvc.Controller || ToMvc.View || ToMvc.Model

        var extended = function( options ) {
            parent.call( this, options ); // call super constructor.
        }
        // Do the OOP trick:
        extended.prototype = Object.create( parent.prototype );
        extended.prototype.constructor = extended;

        return extended;
    }

    // Add extend option to all basic ToMvc methods
    Controller.extend = View.extend = Model.extend = extend;


    /*
        Controller
    */
    Controller.prototype.getViews = function() {
        return this.views.slice();
    };
    Controller.prototype.getModels = function() {
        return this.models.slice();
    };
    Controller.prototype.getEvents = function() {
        return this.events.slice();
    };
    Controller.prototype.registerView = function( name ) {
        this.views.push( name );
    };
    Controller.prototype.registerModel = function( name ) {
        this.models.push( name );
    };
    Controller.prototype.addEvent = function( eventname, callback, controller ) {
        this.controller.events.push( {
            'eventname': eventname,
            'callback': callback
        } );
        // console.info('events:', ToMvc.Controller.events);
    };
    Controller.prototype.triggerEvent = function( eventname, data ) {
        this.events.forEach( function( event ) {
            if ( event.eventname === eventname ) {
                event.callback( data );
            }
        } );
    };

    /*
        View
     */
    View.prototype.getDefaultName = function() {
        return 'view' + ( this.controller.getViews().length + 1 );
    };
    View.prototype.getName = function() {
        return this.name;
    };
    View.prototype.setName = function( name ) {
        this.name = name || this.getDefaultName();
    };
    View.prototype.listenTo = function( event, callback ) {
        this.controller.addEvent.call( this, event, callback );
    };
    View.prototype.broadcast = function( event, data ) {
        this.controller.triggerEvent( event, data );
    };

    /*
        Model
     */
    Model.prototype.init = function( name ) {
        this.setName( name );
        Controller.addModel( this.name );
    };
    Model.prototype.getDefaultName = function() {
        return 'model' + ( this.controller.getModels().length + 1 );
    };
    Model.prototype.getName = function() {
        return this.name;
    };
    Model.prototype.setName = function( name ) {
        this.name = name || this.getDefaultName();
    };
    Model.prototype.listenTo = function( event, callback ) {
        this.controller.addEvent.call( this, event, callback, this.lcontroller );
    };
    Model.prototype.broadcast = function( event, data ) {
        this.controller.triggerEvent( event, data );
    };

    // Wrap up
    ToMvc.version = '0.2.0';
    ToMvc.Controller = Controller;
    ToMvc.View = View;
    ToMvc.Model = Model;

    // Make ToMvc globally available
    window.ToMvc = window.ToMvc || ToMvc;

    ///////////
    // Utils //
    ///////////

    // Based on http://youmightnotneedjquery.com/
    // Extend functions to caller
    // Extend all other options to given object
    var merge = function( out ) {
        out = out || {};

        for ( var i = 1; i < arguments.length; i++ ) {
            if ( !arguments[ i ] )
                continue;

            for ( var key in arguments[ i ] ) {
                // If it is a function, make it a method of the current instance
                if ( typeof arguments[ i ][ key ] === 'function' ) {
                    this[ key ] = arguments[ i ][ key ];
                } else if ( arguments[ i ].hasOwnProperty( key ) ) {
                    // else it's just a property
                    out[ key ] = arguments[ i ][ key ];
                }
            }
        }

        return out;
    };


}( typeof window == "undefined" ? global : window ) ); // window not available in node

/*
    Example
 */
var SubView = ToMvc.View.extend();
SubView.prototype.getTest = function() {
    console.info( 'TEST!' );
}
// subclass extends superclass
// Note: must be established before adding prototpye methods
// SubView.prototype = Object.create( ToMvc.View.prototype );
// SubView.prototype.constructor = SubView;

var c = new ToMvc.Controller();
var s = new SubView( {
    controller: c,
    el: 'body'
} );
console.info( 'test de subview', s.getDefaultName() );
s.getTest();
var s2 = new SubView( {
    controller: c,
    el: 'body'
} );
console.info( 'test de subview2', s2.getDefaultName() );
s2.getTest();

var subModel = ToMvc.Model.extend();
var m = new subModel( {
    controller: c
} )
console.info( 'test de submodel', m.getDefaultName() );

// Another way to achieve the same
// Function.prototype.extends = function(superclass) {
//     this.prototype = Object.create(superclass.prototype);
//     this.prototype.constructor = this;
// }
// Subview.extends(ToMvc.View);

// var c = ToMvc.Controller.addView();
// console.info( 'c', c );


// var x = new SubView( 'aap' );
// console.info( 'views', x.getName() );
// var y = new SubView( 'neushoorn' );
// console.info( 'views', y.getName() );
// var z = new ToMvc.View( 'geit' );
// console.info( 'views', z.getName() );

@@ -5629,1298 +5629,4 @@
 ode%0A
-%0A/*%0A    Example%0A */%0Avar SubView = ToMvc.View.extend();%0ASubView.prototype.getTest = function() %7B%0A    console.info( 'TEST!' );%0A%7D%0A// subclass extends superclass%0A// Note: must be established before adding prototpye methods%0A// SubView.prototype = Object.create( ToMvc.View.prototype );%0A// SubView.prototype.constructor = SubView;%0A%0Avar c = new ToMvc.Controller();%0Avar s = new SubView( %7B%0A    controller: c,%0A    el: 'body'%0A%7D );%0Aconsole.info( 'test de subview', s.getDefaultName() );%0As.getTest();%0Avar s2 = new SubView( %7B%0A    controller: c,%0A    el: 'body'%0A%7D );%0Aconsole.info( 'test de subview2', s2.getDefaultName() );%0As2.getTest();%0A%0Avar subModel = ToMvc.Model.extend();%0Avar m = new subModel( %7B%0A    controller: c%0A%7D )%0Aconsole.info( 'test de submodel', m.getDefaultName() );%0A%0A// Another way to achieve the same%0A// Function.prototype.extends = function(superclass) %7B%0A//     this.prototype = Object.create(superclass.prototype);%0A//     this.prototype.constructor = this;%0A// %7D%0A// Subview.extends(ToMvc.View);%0A%0A// var c = ToMvc.Controller.addView();%0A// console.info( 'c', c );%0A%0A%0A// var x = new SubView( 'aap' );%0A// console.info( 'views', x.getName() );%0A// var y = new SubView( 'neushoorn' );%0A// console.info( 'views', y.getName() );%0A// var z = new ToMvc.View( 'geit' );%0A// console.info( 'views', z.getName() );%0A

Clean up code