adrianvlupu
12/11/2013 - 5:39 PM

JS MVC

JS MVC

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="jquery-2.0.3.min.js"></script>
    <script src="underscore.js"></script>
    <script src="backbone.js"></script>
    <script>
        //#region eventHandler
        var eventHandler = function (sender) {
            this.sender = sender;
            this.listeners = [];
        };
        eventHandler.prototype = {
            attach: function (listener) {
                this.listeners.push(listener);
            },
            trigger: function (args) {
                for (var i = 0; i < this.listeners.length; i++) {
                    this.listeners[i](this.sender, args);
                }
            }
        };
        //#endregion
        //#region Service
        var service = function () {
            var self = this;

            this.controllers = {};
        };
        service.prototype = {
            addController: function (label, controller) {
                this.controllers[label] = controller;
                controller.service = this;
            }
        };
        //#endregion

        //#region Models
        var taskModel = function () {
            var self = this;

            var _isCompleted = true;
            this.onCompletedChanged = new eventHandler(this);
            Object.defineProperty(this, 'isCompleted', {
                get: function () { return _isCompleted; },
                set: function (value) {
                    _isCompleted = value;
                    self.onCompletedChanged.trigger();
                },
                enumerable: true
            });

            var _text = '';
            this.onTextChanged = new eventHandler(this);
            Object.defineProperty(this, 'text', {
                get: function () { return _text; },
                set: function (value) {
                    _text = value;
                    self.onTextChanged.trigger();
                }
            });

            //this.modelState = new modelState();
        };
        var taskListModel = function () {
            var self = this;

            this.onCollectionChanged = new eventHandler(this);
            this.collection = [];
            this.add = function (o) {
                self.collection.push(o);
                self.onCollectionChanged.trigger();
            }
            this.remove = function (index) {
                self.collection.splice(index, 1);
                self.onCollectionChanged.trigger();
            }
        };
        //#endregion

        //#region Views
        var taskView = function (model, controls) {
            var ctl = controls || {
                txtTask: $('#txtTask'),
                btnAdd: $('#btnAddTask')
            };
            var self = this;

            //view methods
            this.clearControls = function () {
                ctl.txtTask.val('');
            };

            //view events
            this.onAdd = new eventHandler(this);
            ctl.btnAdd.click(function (e) {
                self.onAdd.trigger({ text: ctl.txtTask.val() });
                self.clearControls();
            });
        }

        var taskListView = function (model, controls) {
            var ctl = controls || {
                divTasks: $('#divTasks')
            };
            var self = this;

            //view methods
            this.updateCollection = function (s, e) {
                ctl.divTasks.empty();
                for (var i = 0; i < model.collection.length; i++) {
                    //use templateing engine of your choice
                    var template = '<input type="checkbox" {{checked}}/><label>{{text}}</label><br/>';
                    template = template.replace(/{{checked}}/g, model.collection[i].isCompleted ? 'checked="checked"' : '')
                    template = template.replace(/{{text}}/g, model.collection[i].text)
                    ctl.divTasks.append(template);
                }
            };

            //attach view to model events
            model.onCollectionChanged.attach(this.updateCollection);
        }
        //#endregion

        //#region Controllers
        var taskController = function (m, v) {
            var self = this;

            this.model = m; this.view = v;

            //attach to view events
            this.view.onAdd.attach(function (s, e) {
                self.service.controllers.taskListController.add({ text: e.text });
            });
        };

        var taskListController = function (m, v) {
            var self = this;

            this.model = m; this.view = v;

            this.add = function (o) {
                self.model.add(o);
            }
        };
        //#endregion

        $(function () {
            var tm = new taskModel();
            var tv = new taskView(tm);

            var tlm = new taskListModel();
            var tlv = new taskListView(tlm);

            var tc = new taskController(tm, tv);
            var tlc = new taskListController(tlm, tlv);

            var s = new service();
            s.addController('taskController', tc);
            s.addController('taskListController', tlc);
        });
    </script>
</head>
<body>
    <input type="text" id="txtTask" /><input type="button" id="btnAddTask" value="Add" />
    <div id="divTasks">
    </div>
</body>
</html>