├── README.md
├── LICENSE
└── uMVC.js
/README.md:
--------------------------------------------------------------------------------
1 | uMVC
2 | ====
3 |
4 | A micro MVC framework for JavaScript applications.
5 |
6 | I tweeted:
7 |
8 | > You can write an MVC framework in one hundred lines of JavaScript & write about its effective use for one hundred thousand lines of English.
9 |
10 | I wondered exactly how small I could write a respectable MVC framework that included the observer, composite, and strategy patterns.
11 |
12 | Hopefully this code is educational for those new to the MVC paradigm.
13 |
14 | If you are looking for a more fully-featured MVC framework that follows the same principles of uMVC to use in real browser applications, I suggest you take a look at [Maria](https://github.com/petermichaux/maria).
15 |
16 |
17 | Author
18 | ------
19 |
20 | Peter Michaux
21 | petermichaux@gmail.com
22 | http://peter.michaux.ca/
23 | [@petermichaux](https://twitter.com/petermichaux)
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012, Peter Michaux
2 | All rights reserved.
3 |
4 | Redistribution and use of this software in source and binary forms, with or
5 | without modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright notice,
9 | this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/uMVC.js:
--------------------------------------------------------------------------------
1 | var uMVC = {};
2 | uMVC.Model = function() {
3 | this._observers = [];
4 | };
5 | uMVC.Model.prototype.observe = function(observer) {
6 | this._observers.push(observer);
7 | };
8 | uMVC.Model.prototype.unobserve = function(observer) {
9 | for (var i = 0, ilen = this._observers.length; i < ilen; i++) {
10 | if (this._observers[i] === observer) {
11 | this._observers.splice(i, 1);
12 | return;
13 | }
14 | }
15 | };
16 | uMVC.Model.prototype.notify = function(data) {
17 | var observers = this._observers.slice(0);
18 | for (var i = 0, ilen = observers.length; i < ilen; i++) {
19 | observers[i].update(data);
20 | }
21 | };
22 | uMVC.View = function() {
23 | this._subViews = [];
24 | };
25 | uMVC.View.prototype.update = function() {};
26 | uMVC.View.prototype.getModel = function() {
27 | return this._model;
28 | };
29 | uMVC.View.prototype.setModel = function(model) {
30 | this._setModelAndController(model, this._controller);
31 | };
32 | uMVC.View.prototype.getDefaultController = function() {
33 | return new uMVC.Controller();
34 | };
35 | uMVC.View.prototype.getController = function() {
36 | if (!this._controller) this.setController(this.getDefaultController());
37 | return this._controller;
38 | };
39 | uMVC.View.prototype.setController = function(controller) {
40 | this._setModelAndController(this._model, controller);
41 | };
42 | uMVC.View.prototype._setModelAndController = function(model, controller) {
43 | if (this._model !== model) {
44 | if (this._model) this._model.unobserve(this);
45 | if (model) model.observe(this);
46 | this._model = model;
47 | }
48 | if (controller) {
49 | controller.setView(this);
50 | controller.setModel(model);
51 | }
52 | this._controller = controller;
53 | };
54 | uMVC.View.prototype.getSubViews = function() {
55 | return this._subViews.slice(0);
56 | };
57 | uMVC.View.prototype.addSubView = function(subView) {
58 | var previousSuperView = subView.getSuperView();
59 | if (previousSuperView) previousSuperView.removeSubView(subView);
60 | this._subViews.push(subView);
61 | subView.setSuperView(this);
62 | };
63 | uMVC.View.prototype.removeSubView = function(subView) {
64 | for (var i = 0, ilen = this._subViews.length; i < ilen; i++) {
65 | if (this._subViews[i] === subView) {
66 | this._subViews[i].setSuperView(null);
67 | this._subViews.splice(i, 1);
68 | return;
69 | }
70 | }
71 | };
72 | uMVC.View.prototype.setSuperView = function(superView) {
73 | this._superView = superView;
74 | };
75 | uMVC.View.prototype.getSuperView = function() {
76 | return this._superView;
77 | };
78 | uMVC.View.prototype.destroy = function() {
79 | if (this._model) {
80 | this._model.unobserve(this);
81 | }
82 | for (var i = 0, ilen = this._subViews.length; i < ilen; i++) {
83 | this._subViews[i].destroy();
84 | }
85 | };
86 | uMVC.Controller = function() {};
87 | uMVC.Controller.prototype.getModel = function() {
88 | return this._model;
89 | };
90 | uMVC.Controller.prototype.setModel = function(model) {
91 | this._model = model;
92 | };
93 | uMVC.Controller.prototype.getView = function() {
94 | return this._view;
95 | };
96 | uMVC.Controller.prototype.setView = function(view) {
97 | this._view = view;
98 | };
--------------------------------------------------------------------------------