Commit f189c265 authored by Romuald Quantin's avatar Romuald Quantin Committed by Sindre Sorhus

Close GH-162: Somajs.

parent 352327f7
......@@ -92,6 +92,9 @@ had it been designed for web apps">AngularJS</a>
<li>
<a href="reference-examples/vanillajs/index.html" data-source="https://developer.mozilla.org/en/JavaScript" data-content="You know JavaScript right? :P">Vanilla JS</a>
</li>
<li>
<a href="architecture-examples/somajs/index.html" data-source="http://somajs.github.com/somajs/" data-content="soma.js is a javascript model-view-controller (MVC) framework that is meant to help developers to write loosely-coupled applications to increase scalability and maintainability.">soma.js</a>
</li>
</ul>
</div>
<div class="span4">
......
# [soma.js](http://somajs.github.com/somajs) • [TodoMVC](http://todomvc.com)
soma.js is a javascript model-view-controller (MVC) framework that is meant to help developers to write loosely-coupled applications to increase scalability and maintainability.
The main idea behind the MVC pattern is to separate the data (model), the user interface (view) and the logic of the application (controller). They must be independent and should not know about each other in order to increase the scalability of the application.
soma.js is providing tools to make the three parts "talk" to each other, keeping the view and the model free of framework code, using only native events that can be dispatched from either the framework or the DOM itself.
## Credits
Created by [Romuald Quantin](http://www.soundstep.com) using [soma.js](http://somajs.github.com/somajs)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>soma.js • TodoMVC</title>
<link rel="stylesheet" href="../../../assets/base.css">
<!--[if IE]>
<script src="../assets/ie.js"></script>
<![endif]-->
</head>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul>
</section>
<footer id="footer"></footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Template by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<p>Created by <a href="http://soundstep.com">Romuald Quantin</a></p>
<p>With <a href="http://somajs.github.com/somajs/">soma.js</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script id="todo-list-template" type="text/x-handlebars-template">
{{#this}}
<li {{#if completed}}class="completed"{{/if}} data-id="{{id}}">
<div class="view">
<input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}>
<label>{{title}}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="{{title}}">
</li>
{{/this}}
</script>
<script id="footer-template" type="text/x-handlebars-template">
<span id="todo-count"><strong>{{active}}</strong> {{itemLabel}} left</span>
<button id="clear-completed">Clear completed ({{completed}})</button>
</script>
<script src="../../../assets/base.js"></script>
<script src="../../../assets/handlebars.min.js"></script>
<script src="../../../assets/jquery.min.js"></script>
<script src="js/lib/soma-native_v1.0.2_min.js"></script>
<script src="js/todos/models/models.js"></script>
<script src="js/todos/views/views.js"></script>
<script src="js/todos/controllers/controllers.js"></script>
<script src="js/app.js"></script>
</body>
</html>
\ No newline at end of file
var todo = window.todo || {};
(function( window ) {
'use strict';
todo.TodoApp = new soma.Application.extend({
init: function() {
this.addModel( todo.TodoModel.NAME, new todo.TodoModel() );
this.addCommand( todo.TodoEvent.RENDER, todo.TodoCommand );
this.addCommand( todo.TodoEvent.CREATE, todo.TodoCommand );
this.addCommand( todo.TodoEvent.DELETE, todo.TodoCommand );
this.addCommand( todo.TodoEvent.TOGGLE, todo.TodoCommand );
this.addCommand( todo.TodoEvent.UPDATE, todo.TodoCommand );
this.addCommand( todo.TodoEvent.TOGGLE_ALL, todo.TodoCommand );
this.addCommand( todo.TodoEvent.CLEAR_COMPLETED, todo.TodoCommand );
this.addView( todo.TodoListView.NAME, new todo.TodoListView( $('#todo-list')[0] ) );
this.addView( todo.FooterView.NAME, new todo.FooterView( $('#footer')[0] ) );
this.addView( todo.TodoInputView.NAME, new todo.TodoInputView( $('#new-todo')[0] ) );
},
start: function() {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.RENDER ) );
}
});
var app = new todo.TodoApp();
})( window );
(function(){soma={};soma.version="1.0.2";soma.type="native";if(!Function.prototype.bind){Function.prototype.bind=function c(f){var g=this;if(typeof g!="function"){throw new Error("Error, you must bind a function.")}var d=Array.prototype.slice.call(arguments,1);var e=function(){if(this instanceof e){var j=function(){};j.prototype=g.prototype;var i=new j;var h=g.apply(i,d.concat(Array.prototype.slice.call(arguments)));if(Object(h)===h){return h}return i}else{return g.apply(f,d.concat(Array.prototype.slice.call(arguments)))}};return e}}soma.applyProperties=function(d,f){for(var e in f){d[e]=f[e]}};soma.inherit=function(g,f){var d;if(f&&f.hasOwnProperty("constructor")){d=f.constructor}else{d=function(){return g.apply(this,arguments)}}soma.applyProperties(d.prototype,g.prototype);var e=function(){};e.prototype=g.prototype;d.prototype=new e();if(f){soma.applyProperties(d.prototype,f,g.prototype)}d.prototype.constructor=d;d.parent=g.prototype;d.extend=function(h){return soma.inherit(d,h)};return d};soma.extend=function(d){return soma.inherit(function(){},d)};var b=soma.extend({createPlugin:function(){return this.instance.createPlugin.apply(this.instance,arguments)},dispatchEvent:function(){this.instance.dispatchEvent.apply(this.instance,arguments)},addEventListener:function(){this.instance.addEventListener.apply(this.instance,arguments)},removeEventListener:function(){this.instance.removeEventListener.apply(this.instance,arguments)},hasEventListener:function(){return this.instance.hasEventListener.apply(this.instance,arguments)},hasCommand:function(d){return this.instance.hasCommand(d)},getCommand:function(d){return this.instance.getCommand(d)},getCommands:function(){return this.instance.getCommands()},addCommand:function(e,d){this.instance.controller.addCommand(e,d)},removeCommand:function(d){this.instance.controller.removeCommand(d)},hasWire:function(d){return this.instance.hasWire(d)},getWire:function(d){return this.instance.getWire(d)},addWire:function(e,d){return this.instance.addWire(e,d)},removeWire:function(d){this.instance.removeWire(d)},hasModel:function(d){return this.instance.hasModel(d)},getModel:function(d){return this.instance.getModel(d)},addModel:function(d,e){return this.instance.addModel(d,e)},removeModel:function(d){this.instance.removeModel(d)},getSequencer:function(d){return !!this.instance.controller?this.instance.controller.getSequencer(d):null},stopSequencerWithEvent:function(d){return !!this.instance.controller?this.instance.controller.stopSequencerWithEvent(d):null},stopSequencer:function(d){if(this.instance.controller){return this.instance.controller.stopSequencer(d)}},stopAllSequencers:function(){if(this.instance.controller){this.instance.controller.stopAllSequencers()}},isPartOfASequence:function(d){return !!this.instance.controller?this.instance.controller.isPartOfASequence(d):false},getLastSequencer:function(){return !!this.instance.controller?this.instance.controller.getLastSequencer():null},getRunningSequencers:function(){return !!this.instance.controller?this.instance.controller.getRunningSequencers():null},hasView:function(d){return this.instance.hasView(d)},getView:function(d){return this.instance.getView(d)},addView:function(e,d){return this.instance.addView(e,d)},removeView:function(d){this.instance.removeView(d)}});soma.AutoBind={blackList:["initialize","parent","constructor","$constructor","addEventListener","removeEventListener"],autobind:function(){if(this.wasAutoBound){return}var g=this;var e=g.AutoBindPattern;var f="([lL]istener|[hH]andler|[cB]allback)$";if(!e){e=f}else{e=f+"|"+e}for(var d in g){if(typeof g[d]=="function"){if(this._autobindIsBlacklisted(d)){continue}if(!d.match(e)){continue}g[d]=g[d].bind(g)}}},_autobindIsBlacklisted:function(d){var f=this.blackList;for(var e=0;e<f.length;e++){if(f[e]==d){return true}}return false}};soma.Command=b.extend({instance:null,registerInstance:function(d){this.instance=d},execute:function(d){},toString:function(){return"[soma.Command]"}});var a=soma.extend({event:null,sequenceId:null,constructor:function(d){this.event=d}});soma.SequenceCommand=soma.Command.extend({commands:null,currentCommand:null,id:null,constructor:function(d){if(d==null){throw new Error("SequenceCommand Children expect an unique id as constructor arg")}this.commands=[];this.id=d;soma.Command.call(this)},registerInstance:function(d){this.instance=d;this.initializeSubCommands()},initializeSubCommands:function(){throw new Error("Subclasses of SequenceCommand must implement initializeSubCommands()")},addSubCommand:function(d){var e=new a(d);this.commands.push(e);this.instance.controller.registerSequencedCommand(this,e)},execute:function(d){if(this.commands==null||this.commands.length===0){return}this.currentCommand=this.commands.shift();if(this.hasCommand(this.currentCommand.event.type)){this.dispatchEvent(this.currentCommand.event)}},executeNextCommand:function(){if(this.commands==null){return}this.instance.controller.unregisterSequencedCommand(this,this.currentCommand.event.type);if(this.commands.length>0){this.execute(this.commands[0].event)}else{this.commands=null;this.currentCommand=null}},getLength:function(){if(this.commands==null){return -1}return this.commands.length},stop:function(){this.commands=null;this.commands=null;this.currentCommand=null;return this.instance.controller.unregisterSequencer(this)},getCurrentCommand:function(){return this.currentCommand},getCommands:function(){return this.commands},toString:function(){return"[soma.SequenceCommand]"}});soma.ParallelCommand=soma.Command.extend({commands:null,constructor:function(){this.commands=[]},registerInstance:function(d){this.instance=d;this.initializeSubCommands()},initializeSubCommands:function(){throw new Error("Subclasses of ParallelCommand must implement initializeSubCommands()")},addSubCommand:function(d){this.commands.push(d)},execute:function(){while(this.commands.length>0){var d=this.commands.shift();if(this.hasCommand(d.type)){this.dispatchEvent(d)}}this.commands=null},getLength:function(){return this.commands!=null?this.commands.length:-1},getCommands:function(){return this.commands},toString:function(){return"[soma.ParallelCommand]"}});soma.Wire=b.extend({name:null,instance:null,constructor:function(d){this.name=d},registerInstance:function(d){this.instance=d},init:function(){},dispose:function(){},getName:function(){return this.name},setName:function(d){this.name=d},toString:function(){return"[soma.Wire]"}});soma.applyProperties(soma.Wire.prototype,soma.AutoBind);soma.IDisposable=soma.extend({dispose:function(){}});soma.SomaController=soma.extend({instance:null,constructor:function(d){this.boundInstance=this.instanceHandler.bind(this);this.boundDomtree=this.domTreeHandler.bind(this);this.commands={};this.sequencers={};this.sequencersInfo={};this.lastEvent=null;this.lastSequencer=null;this.instance=d},addInterceptor:function(d){if(!soma){throw new Error("soma package has been overwritten by local variable")}if(this.instance.body.addEventListener){this.instance.body.addEventListener(d,this.boundDomtree,true)}this.instance.addEventListener(d,this.boundInstance,-Number.MAX_VALUE)},removeInterceptor:function(d){if(this.instance.body.removeEventListener){this.instance.body.removeEventListener(d,this.boundDomtree,true)}this.instance.removeEventListener(d,this.boundInstance)},executeCommand:function(f){var d=f.type;if(this.hasCommand(d)){var g=new this.commands[d]();g.registerInstance(this.instance);g.execute(f)}},registerSequencedCommand:function(d,f){if(!(f instanceof a)){throw new Error("capsulate sequence commands in SequenceCommandProxy objects!")}var e=this.sequencersInfo;if(e[d.id]==null||this.sequencers[d.id]==null){this.lastSequencer=d;e[d.id]=[];this.sequencers[d.id]=d}f.sequenceId=d.id;e[d.id].push(f)},unregisterSequencedCommand:function(e,g){if(typeof g!="string"){throw new Error("Controller::unregisterSequencedCommand() expects commandName to be of type String, given:"+g)}var h=this.sequencersInfo;if(h[e.id]!=null&&h[e.id]!=undefined){var d=h[e.id].length;for(var f=0;f<d;f++){if(h[e.id][f].event.type==g){h[e.id][f]=null;h[e.id].splice(f,1);if(h[e.id].length==0){h[e.id]=null;delete h[e.id]}break}}}},unregisterSequencer:function(e){var g=this.sequencers;if(g[e.id]!=null&&g[e.id]!=undefined){g[e.id]=null;delete g[e.id];g=this.sequencersInfo;if(g[e.id]!=null){var d=g[e.id].length;for(var f=0;f<d;f++){g[e.id][f]=null}g[e.id]=null;delete g[e.id];return true}}return false},hasCommand:function(d){return this.commands[d]!=null},getCommand:function(d){if(this.hasCommand(d)){return this.commands[d]}return null},getCommands:function(){var e=[];var d=this.commands;for(var f in d){e.push(f)}return e},addCommand:function(d,e){if(this.hasCommand(d)){throw new Error("Error in "+this+' Command "'+d+'" already registered.')}this.commands[d]=e;this.addInterceptor(d)},removeCommand:function(d){if(!this.hasCommand(d)){return}this.commands[d]=null;delete this.commands[d];this.removeInterceptor(d)},getSequencer:function(j){var g=this.sequencersInfo;for(var h in g){var d=g[h].length;for(var f=0;f<d;f++){if(g[h][f]&&g[h][f].event.type===j.type){var e=this.sequencers[g[h][f].sequenceId];return !!e?e:null}}}return null},stopSequencerWithEvent:function(j){var g=this.sequencersInfo;for(var h in g){var d=g[h].length;for(var f=0;f<d;f++){if(g[h][f].event.type===j.type){try{this.sequencers[g[h][f].sequenceId].stop()}catch(k){return false}return true}}}return false},stopSequencer:function(d){if(d==null){return false}d.stop();return true},stopAllSequencers:function(){var e=this.sequencers;var g=this.sequencersInfo;for(var f in e){if(g[f]==null){continue}var d=g[f].length;g[f]=null;delete g[f];e[f].stop();e[f]=null;delete e[f]}},isPartOfASequence:function(d){return(this.getSequencer(d)!=null)},getRunningSequencers:function(){var d=[];var e=this.sequencers;for(var f in e){d.push(e[f])}return d},getLastSequencer:function(){return this.lastSequencer},dispose:function(){for(var e in this.commands){this.removeCommand(e)}for(var d in this.sequencers){this.sequencers[d]=null;delete this.sequencers[d]}this.commands=null;this.sequencers=null;this.lastEvent=null;this.lastSequencer=null},domTreeHandler:function(f){if(f.bubbles&&this.hasCommand(f.type)&&!f.isCloned){if(f.stopPropagation){f.stopPropagation()}else{f.cancelBubble=true}var d=f.clone();this.lastEvent=d;this.instance.dispatchEvent(d);if(!d.isDefaultPrevented()){this.executeCommand(f)}this.lastEvent=null}},instanceHandler:function(d){if(d.bubbles&&this.hasCommand(d.type)){if(this.lastEvent!=d){if(!d.isDefaultPrevented()){this.executeCommand(d)}}}this.lastEvent=null}});soma.SomaViews=soma.extend({views:null,autoBound:false,instance:null,constructor:function(d){this.views={};this.instance=d},hasView:function(d){return this.views[d]!=null},addView:function(e,d){if(this.hasView(e)){throw new Error('View "'+e+'" already exists')}if(document.attachEvent){d.instance=this.instance}if(!this.autoBound){soma.applyProperties(soma.View.prototype,soma.AutoBind);this.autoBound=true}if(d.shouldAutobind){d.autobind()}this.views[e]=d;if(d.init!=null){d.init()}return d},getView:function(d){if(this.hasView(d)){return this.views[d]}return null},getViews:function(){var e={};for(var d in this.views){e[d]=this.views[d]}return e},removeView:function(d){if(!this.hasView(d)){return}if(this.views[d]["dispose"]!=null){this.views[d].dispose()}this.views[d]=null;delete this.views[d]},dispose:function(){for(var d in this.views){this.removeView(d)}this.views=null;this.instance=null}});soma.EventDispatcher=soma.extend({listeners:null,constructor:function(){this.listeners=[]},addEventListener:function(e,f,d){if(!this.listeners||!e||!f){throw new Error("Error in EventDispatcher (addEventListener), one of the parameters is null or undefined.")}if(isNaN(d)){d=0}this.listeners.push({type:e,listener:f,priority:d,scope:this})},removeEventListener:function(f,h){if(!this.listeners){return false}if(!f||!h){throw new Error("Error in EventDispatcher (removeEventListener), one of the parameters is null or undefined.")}var e=0;var d=this.listeners.length;for(e=d-1;e>-1;e--){var g=this.listeners[e];if(g.type==f&&g.listener==h){this.listeners.splice(e,1)}}},hasEventListener:function(f){if(!this.listeners){return false}if(!f){throw new Error("Error in EventDispatcher (hasEventListener), one of the parameters is null or undefined.")}var e=0;var d=this.listeners.length;for(;e<d;++e){var g=this.listeners[e];if(g.type==f){return true}}return false},dispatchEvent:function(f){if(!this.listeners||!f){throw new Error("Error in EventDispatcher (dispatchEvent), one of the parameters is null or undefined.")}var e=[];var d;for(d=0;d<this.listeners.length;d++){var g=this.listeners[d];if(g.type==f.type){e.push(g)}}e.sort(function(i,h){return h.priority-i.priority});for(d=0;d<e.length;d++){e[d].listener.apply((f.srcElement)?f.srcElement:f.currentTarget,[f])}},getListeners:function(){return this.listeners.slice()},toString:function(){return"[soma.EventDispatcher]"},dispose:function(){this.listeners=null}});soma.Application=soma.EventDispatcher.extend({body:null,models:null,controller:null,wires:null,views:null,constructor:function(){soma.EventDispatcher.call(this);this.body=document.body;if(!this.body){throw new Error("soma requires body of type Element")}this.controller=new soma.SomaController(this);this.models=new soma.SomaModels(this);this.wires=new soma.SomaWires(this);this.views=new soma.SomaViews(this);this.init();this.registerModels();this.registerViews();this.registerCommands();this.registerWires();this.start()},createPlugin:function(){if(arguments.length==0||!arguments[0]){throw new Error("Error creating a plugin, plugin class is missing.")}var f=arguments[0];arguments[0]=this;var d=[null];for(var e=0;e<arguments.length;e++){d.push(arguments[e])}return new (Function.prototype.bind.apply(f,d))},hasCommand:function(d){return(!this.controller)?false:this.controller.hasCommand(d)},getCommand:function(d){return(!this.controller)?null:this.controller.getCommand(d)},getCommands:function(){return(!this.controller)?null:this.controller.getCommands()},addCommand:function(d,e){this.controller.addCommand(d,e)},removeCommand:function(d){this.controller.removeCommand(d)},hasWire:function(d){return(!this.wires)?false:this.wires.hasWire(d)},getWire:function(d){return(!this.wires)?null:this.wires.getWire(d)},getWires:function(){return(!this.wires)?null:this.wires.getWires()},addWire:function(e,d){return this.wires.addWire(e,d)},removeWire:function(d){this.wires.removeWire(d)},hasModel:function(d){return(!this.models)?false:this.models.hasModel(d)},getModel:function(d){return(!this.models)?null:this.models.getModel(d)},getModels:function(){return(!this.models)?null:this.models.getModels()},addModel:function(d,e){return this.models.addModel(d,e)},removeModel:function(d){this.models.removeModel(d)},hasView:function(d){return(!this.views)?false:this.views.hasView(d)},getView:function(d){return(!this.views)?null:this.views.getView(d)},getViews:function(){return(!this.views)?null:this.views.getViews()},addView:function(e,d){return this.views.addView(e,d)},removeView:function(d){this.views.removeView(d)},getSequencer:function(d){return !!this.controller?this.controller.getSequencer(d):null},isPartOfASequence:function(d){return(this.getSequencer(d)!=null)},stopSequencerWithEvent:function(d){return !!this.controller?this.controller.stopSequencerWithEvent(d):false},stopSequencer:function(d){return !!this.controller?this.controller.stopSequencer(d):false},stopAllSequencers:function(){if(this.controller){this.controller.stopAllSequencers()}},getRunningSequencers:function(){return !!this.controller?this.controller.getRunningSequencers():null},getLastSequencer:function(){return !!this.controller?this.controller.getLastSequencer():null},dispose:function(){if(this.models){this.models.dispose();this.models=null}if(this.views){this.views.dispose();this.views=null}if(this.controller){this.controller.dispose();this.controller=null}if(this.wires){this.wires.dispose();this.wires=null}this.body=null;soma.EventDispatcher.prototype.dispose.call(this)},toString:function(){return"[soma.Application]"},init:function(){},registerModels:function(){},registerViews:function(){},registerCommands:function(){},registerWires:function(){},start:function(){}});soma.SomaModels=soma.extend({models:null,instance:null,constructor:function(d){this.models={};this.instance=d},hasModel:function(d){return this.models[d]!=null},getModel:function(d){if(this.hasModel(d)){return this.models[d]}return null},getModels:function(){var f={};var e=this.models;for(var d in e){f[d]=e[d]}return f},addModel:function(d,e){if(this.hasModel(d)){throw new Error('Model "'+d+'" already exists')}this.models[d]=e;if(!e.dispatcher){e.dispatcher=this.instance}e.init();return e},removeModel:function(d){if(!this.hasModel(d)){return}this.models[d].dispose();this.models[d]=null;delete this.models[d]},dispose:function(){for(var d in this.models){this.removeModel(d)}this.models=null;this.instance=null}});soma.Model=soma.extend({name:null,data:null,dispatcher:null,constructor:function(d,f,e){this.data=f;this.dispatcher=e;if(d!=null){this.name=d}},init:function(){},dispose:function(){},dispatchEvent:function(){if(this.dispatcher){this.dispatcher.dispatchEvent.apply(this.dispatcher,arguments)}},addEventListener:function(){if(this.dispatcher){this.dispatcher.addEventListener.apply(this.dispatcher,arguments)}},removeEventListener:function(){if(this.dispatcher){this.dispatcher.addEventListener.apply(this.dispatcher,arguments)}},getName:function(){return this.name},setName:function(d){this.name=d},toString:function(){return"[soma.Model]"}});soma.View=soma.extend({instance:null,domElement:null,constructor:function(f){var e;if(f!=undefined){if(f.nodeType){e=f}else{throw new Error("domElement has to be a DOM-ELement")}}else{e=document.body}this.domElement=e},dispatchEvent:function(d){if(this.domElement.dispatchEvent){this.domElement.dispatchEvent(d)}else{if(this.instance){this.instance.dispatchEvent(d)}}},addEventListener:function(){if(this.domElement.addEventListener){this.domElement.addEventListener.apply(this.domElement,arguments)}else{if(this.instance){this.instance.addEventListener.apply(this.instance,arguments)}}},removeEventListener:function(){if(this.domElement.addEventListener){this.domElement.removeEventListener.apply(this.domElement,arguments)}else{if(this.instance){this.instance.removeEventListener.apply(this.instance,arguments)}}},init:function(){},dispose:function(){},toString:function(){return"[soma.View]"}});soma.SomaWires=soma.extend({wires:null,instance:null,constructor:function(d){this.wires={};this.instance=d},hasWire:function(d){return this.wires[d]!=null},addWire:function(e,d){if(this.hasWire(e)){throw new Error('Wire "'+e+'" already exists')}if(d.shouldAutobind){d.autobind()}this.wires[e]=d;d.registerInstance(this.instance);d.init();return d},getWire:function(d){if(this.hasWire(d)){return this.wires[d]}return null},getWires:function(){var e={};for(var d in this.wires){e[d]=this.wires[d]}return e},removeWire:function(d){if(!this.hasWire(d)){return}this.wires[d].dispose();this.wires[d]=null;delete this.wires[d]},dispose:function(){for(var d in this.wires){this.removeWire(d)}this.wires=null;this.instance=null}});soma.Mediator=soma.Wire.extend({viewComponent:null,constructor:function(d){soma.Wire.call(this,d);this.viewComponent=viewComponent},dispose:function(){this.viewComponent=null},toString:function(){return"[soma.Mediator]"}});soma.Event=soma.extend({constructor:function(g,i,f,d){var h=soma.Event.createGenericEvent(g,f,d);if(i!=null&&i!=undefined){h.params=i}h.isCloned=false;h.clone=this.clone.bind(h);h.isIE9=this.isIE9;h.isDefaultPrevented=this.isDefaultPrevented;if(this.isIE9()||!h.preventDefault||(h.getDefaultPrevented==undefined&&h.defaultPrevented==undefined)){h.preventDefault=this.preventDefault.bind(h)}if(this.isIE9()){h.IE9PreventDefault=false}return h},clone:function(){var d=soma.Event.createGenericEvent(this.type,this.bubbles,this.cancelable);d.params=this.params;d.isCloned=true;d.clone=this.clone;d.isDefaultPrevented=this.isDefaultPrevented;d.isIE9=this.isIE9;if(this.isIE9()){d.IE9PreventDefault=this.IE9PreventDefault}return d},preventDefault:function(){if(!this.cancelable){return false}this.defaultPrevented=true;if(this.isIE9()){this.IE9PreventDefault=true}this.returnValue=false;return this},isDefaultPrevented:function(){if(!this.cancelable){return false}if(this.isIE9()){return this.IE9PreventDefault}if(this.defaultPrevented!=undefined){return this.defaultPrevented}else{if(this.getDefaultPrevented!=undefined){return this.getDefaultPrevented()}}return false},isIE9:function(){return document.body.style.scrollbar3dLightColor!=undefined&&document.body.style.opacity!=undefined},toString:function(){return"[soma.Event]"}});soma.Event.createGenericEvent=function(g,f,d){var h;f=f!==undefined?f:true;if(document.createEvent){h=document.createEvent("Event");h.initEvent(g,f,!!d)}else{h=document.createEventObject();h.type=g;h.bubbles=!!f;h.cancelable=!!d}return h};soma.IResponder=soma.extend({fault:function(d){},result:function(d){}})})();
\ No newline at end of file
var todo = window.todo || {};
(function( window ) {
'use strict';
todo.TodoCommand = soma.Command.extend({
execute: function( event ) {
var model = this.getModel( todo.TodoModel.NAME );
switch( event.type ) {
case todo.TodoEvent.RENDER:
this.getView( todo.TodoListView.NAME ).render( model.data, model.getActiveLength() );
this.getView( todo.FooterView.NAME ).render( model.dataFooter );
break;
case todo.TodoEvent.CREATE:
model.addItem( event.params.todoTitle );
break;
case todo.TodoEvent.DELETE:
model.removeItem( event.params.todoId );
break;
case todo.TodoEvent.TOGGLE:
model.toggleItem( event.params.todoId );
break;
case todo.TodoEvent.TOGGLE_ALL:
model.toggleAll( event.params.toggleAll );
break;
case todo.TodoEvent.UPDATE:
model.updateItem( event.params.todoId, event.params.todoTitle );
break;
case todo.TodoEvent.CLEAR_COMPLETED:
model.clearCompleted();
break;
}
}
});
todo.TodoEvent = soma.Event.extend( {
constructor: function( type, todoTitle, todoId, toggleAll ) {
return soma.Event.call( this, type, {
todoTitle: todoTitle,
todoId: todoId,
toggleAll: toggleAll
});
}
} );
todo.TodoEvent.RENDER = 'TodoEvent.RENDER';
todo.TodoEvent.CREATE = 'TodoEvent.CREATE';
todo.TodoEvent.DELETE = 'TodoEvent.DELETE';
todo.TodoEvent.UPDATE = 'TodoEvent.UPDATE';
todo.TodoEvent.TOGGLE = 'TodoEvent.TOGGLE';
todo.TodoEvent.TOGGLE_ALL = 'TodoEvent.TOGGLE_ALL';
todo.TodoEvent.CLEAR_COMPLETED = 'TodoEvent.CLEAR_COMPLETED';
})( window );
\ No newline at end of file
var todo = window.todo || {};
(function( window ) {
'use strict';
todo.TodoModel = new soma.Model.extend({
dataFooter: null,
init: function() {
this.storeKey = 'todos-somajs';
this.data = JSON.parse( this.getStore() ) || [];
this.updateDataFooter();
},
updateDataFooter: function() {
var active = this.getActiveLength();
this.dataFooter = {
active: active,
itemLabel: active === 1 ? 'item' : 'items',
completed: this.data.length - active,
length: this.data.length
};
},
addItem: function( title ) {
this.data.push({
id: this.uuid(),
title: title,
completed: false
});
this.update();
},
removeItem: function( id ) {
this.data.splice( this.getIndexById( id ), 1 );
this.update();
},
toggleItem: function( id ) {
var item = this.data[ this.getIndexById( id ) ];
item.completed = !item.completed;
this.update();
},
updateItem: function( id, title ) {
this.data[ this.getIndexById( id ) ].title = title;
this.update();
},
toggleAll: function( toggleValue ) {
for (var i = 0; i < this.data.length; i++) {
this.data[i].completed = toggleValue;
}
this.update();
},
clearCompleted: function() {
var i = this.data.length;
while( i-- ) {
if ( this.data[i].completed ) {
this.data.splice( i, 1 );
}
}
this.update();
},
getIndexById: function( id ) {
for ( var i = 0; i < this.data.length; i++ ) {
if ( this.data[i].id === id ) {
return i;
}
}
return -1;
},
getActiveLength: function() {
var count = 0;
for ( var i = 0; i < this.data.length; i++ ) {
if ( !this.data[i].completed ) {
count++;
}
}
return count;
},
update: function() {
this.updateDataFooter();
this.setStore( this.data );
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.RENDER ) );
},
getStore: function() {
return localStorage.getItem( this.storeKey );
},
setStore: function() {
localStorage.setItem( this.storeKey, JSON.stringify( this.data ) );
},
// https://gist.github.com/1308368
uuid: function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b;}
});
todo.TodoModel.NAME = 'TodoModel';
})( window );
\ No newline at end of file
var todo = window.todo || {};
(function( window ) {
'use strict';
var ENTER_KEY = 13;
todo.TodoListView = soma.View.extend({
template: null,
init: function() {
this.template = Handlebars.compile( $('#' + this.domElement.id + '-template').html() );
$(this.domElement).on( 'click', '.destroy', this.destroy.bind(this) );
$(this.domElement).on( 'click', '.toggle', this.toggle.bind(this) );
$(this.domElement).on( 'dblclick', '.view', this.edit );
$(this.domElement).on( 'blur', '.edit', this.update.bind(this) );
$(this.domElement).on( 'keypress', '.edit', this.blurInput );
$('#toggle-all').click( this.toggleAll );
},
render: function( data, activeCount ) {
$(this.domElement).html( this.template( data ) );
$('#toggle-all').prop( 'checked', !activeCount );
$('#main').toggle( !!data.length );
},
destroy: function( event ) {
var id = $(event.target).closest('li').attr('data-id');
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.DELETE, null, id ) );
},
toggle: function( event ) {
var id = $(event.target).closest('li').attr('data-id');
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.TOGGLE, null, id ) );
},
toggleAll: function() {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.TOGGLE_ALL, null, null, $(this).prop('checked') ) );
},
edit: function( event ) {
$(this).closest('li').addClass('editing').find('.edit').select();
},
update: function( event ) {
var li = $(event.target).closest('li').removeClass('editing');
var id = li.attr('data-id');
var val = li.find('.edit').val().trim();
if ( val ) {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.UPDATE, val, id ) );
}
else {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.DELETE, null, id ) );
}
},
blurInput: function( event ) {
if (event.which === ENTER_KEY) {
event.target.blur();
}
}
});
todo.TodoListView.NAME = 'TodoListView';
todo.TodoInputView = soma.View.extend({
init: function() {
$(this.domElement).keypress( this.keyPressHandler.bind(this) );
$(this.domElement).blur( this.blur );
},
keyPressHandler: function( event ) {
if (event.which === ENTER_KEY) {
this.createItem();
}
},
createItem: function() {
var value = this.domElement.value.trim();
if (value) {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.CREATE, value ) );
}
this.domElement.value = '';
},
blur: function( event ) {
if (!this.value.trim()) {
this.value = '';
}
}
});
todo.TodoInputView.NAME = 'TodoInputView';
todo.FooterView = soma.View.extend({
template: null,
init: function() {
this.template = Handlebars.compile( $('#' + this.domElement.id + '-template').html() );
$(this.domElement).on( 'click', '#clear-completed', this.clearCompleted.bind(this) );
},
render: function( data ) {
$(this.domElement).html( this.template( data ) );
$(this.domElement).toggle( !!data.length );
$('#clear-completed').toggle( !!data.completed );
},
clearCompleted: function(event) {
this.dispatchEvent( new todo.TodoEvent( todo.TodoEvent.CLEAR_COMPLETED ) );
}
});
todo.FooterView.NAME = 'FooterView';
})( window );
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment