<htmllang="en"><head><metacharset="utf-8"><title>TodoMVC</title><metaname="description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, Spine and many more"><metaname="viewport"content="width=device-width,initial-scale=1"><metaname="twitter:card"content="summary"><metaname="twitter:title"content="TodoMVC"><metaname="twitter:site"content="@TasteJS"><metaname="twitter:description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS and many more"><metaname="twitter:image"content="https://raw.githubusercontent.com/tastejs/todomvc/gh-pages/site-assets/screenshot.png"><metaproperty="og:url"content="http://todomvc.com"><metaproperty="og:title"content="TodoMVC"><metaproperty="og:image"content="https://raw.github.com/tastejs/todomvc/gh-pages/site-assets/screenshot.png"><metaproperty="og:description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, Spine and many more"><linkrel="shortcut icon"href="site-assets/favicon.ico"><linkrel="stylesheet"href="site-assets/main.min.css"><script src="bower_components/platform/platform.js"></script><divhidden><style shim-shadowdom="">html/deep/[layout][horizontal],html/deep/[layout][vertical]{display:-ms-flexbox;display:-webkit-flex;display:flex}html/deep/[layout][horizontal][inline],html/deep/[layout][vertical][inline]{display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}html/deep/[layout][horizontal]{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}html/deep/[layout][horizontal][reverse]{-ms-flex-direction:row-reverse;-webkit-flex-direction:row-reverse;flex-direction:row-reverse}html/deep/[layout][vertical]{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}html/deep/[layout][vertical][reverse]{-ms-flex-direction:column-reverse;-webkit-flex-direction:column-reverse;flex-direction:column-reverse}html/deep/[layout][wrap]{-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}html/deep/[layout][wrap-reverse]{-ms-flex-wrap:wrap-reverse;-webkit-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}html/deep/[flex]{-ms-flex:1;-webkit-flex:1;flex:1}html/deep/[flex][auto]{-ms-flex:11auto;-webkit-flex:11auto;flex:11auto}html/deep/[flex][none]{-ms-flex:none;-webkit-flex:none;flex:none}html/deep/[flex][one]{-ms-flex:1;-webkit-flex:1;flex:1}html/deep/[flex][two]{-ms-flex:2;-webkit-flex:2;flex:2}html/deep/[flex][three]{-ms-flex:3;-webkit-flex:3;flex:3}html/deep/[flex][four]{-ms-flex:4;-webkit-flex:4;flex:4}html/deep/[flex][five]{-ms-flex:5;-webkit-flex:5;flex:5}html/deep/[flex][six]{-ms-flex:6;-webkit-flex:6;flex:6}html/deep/[flex][seven]{-ms-flex:7;-webkit-flex:7;flex:7}html/deep/[flex][eight]{-ms-flex:8;-webkit-flex:8;flex:8}html/deep/[flex][nine]{-ms-flex:9;-webkit-flex:9;flex:9}html/deep/[flex][ten]{-ms-flex:10;-webkit-flex:10;flex:10}html/deep/[flex][eleven]{-ms-flex:11;-webkit-flex:11;flex:11}html/deep/[flex][twelve]{-ms-flex:12;-webkit-flex:12;flex:12}html/deep/[layout][start]{-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}html/deep/[layout][center],html/deep/[layout][center-center]{-ms-flex-align:center;-webkit-align-items:center;align-items:center}html/deep/[layout][end]{-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}html/deep/[layout][start-justified]{-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}html/deep/[layout][center-justified],html/deep/[layout][center-center]{-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}html/deep/[layout][end-justified]{-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}html/deep/[layout][around-justified]{-ms-flex-pack:around;-webkit-justify-content:space-around;justify-content:space-around}html/deep/[layout][justified]{-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}html/deep/[self-start]{-ms-align-self:flex-start;-webkit-align-self:flex-start;align-self:flex-start}html/deep/[self-center]{-ms-align-self:center;-webkit-align-self:center;align-self:center}html/deep/[self-end]{-ms-align-self:flex-end;-webkit-align-self:flex-end;align-self:flex-end}html/deep/[self-stretch]{-ms-align-self:stretch;-webkit-align-self:stretch;align-self:stretch}html/deep/[block]{display:block}html/deep/[hidden]{display:none!important}html/deep/[relative]{position:relative}html/deep/[fit]{position:absolute;top:0;right:0;bottom:0;left:0}body[fullbleed]{margin:0;height:100vh}html/deep/[segment],html/deep/segment{display:block;position:relative;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;margin:1em.5em;padding:1em;background-color:#fff;-webkit-box-shadow:0001pxrgba(0,0,0,.1);box-shadow:0001pxrgba(0,0,0,.1);border-radius:5px5px5px5px}</style><script src="bower_components/polymer/polymer.js"></script><polymer-elementname="core-selection"attributes="multi"hiddenassetpath="bower_components/core-selection/"><script>Polymer("core-selection",{multi:false,ready:function(){this.clear()},clear:function(){this.selection=[]},getSelection:function(){returnthis.multi?this.selection:this.selection[0]},isSelected:function(item){returnthis.selection.indexOf(item)>=0},setItemSelected:function(item,isSelected){if(item!==undefined&&item!==null){if(isSelected){this.selection.push(item)}else{vari=this.selection.indexOf(item);if(i>=0){this.selection.splice(i,1)}}this.fire("core-select",{isSelected:isSelected,item:item})}},select:function(item){if(this.multi){this.toggle(item)}elseif(this.getSelection()!==item){this.setItemSelected(this.getSelection(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}});</script></polymer-element><polymer-elementname="core-selector"attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap target itemsSelector activateEvent"assetpath="bower_components/core-selector/"><template><core-selectionid="selection"multi="{{multi}}"on-core-select="{{selectionSelect}}"></core-selection><contentid="items"select="*"></content></template><script>Polymer("core-selector",{selected:null,multi:false,valueattr:"name",selectedClass:"core-selected",selectedProperty:"",selectedAttribute:"active",selectedItem:null,selectedModel:null,selectedIndex:-1,target:null,itemsSelector:"",activateEvent:"tap",notap:false,ready:function(){this.activateListener=this.activateHandler.bind(this);this.observer=newMutationObserver(this.updateSelected.bind(this));if(!this.target){this.target=this}},getitems(){if(!this.target){return[]}varnodes=this.target!==this?this.itemsSelector?this.target.querySelectorAll(this.itemsSelector):this.target.children:this.$.items.getDistributedNodes();returnArray.prototype.filter.call(nodes||[],function(n){returnn&&n.localName!=="template"})},targetChanged:function(old){if(old){this.removeListener(old);this.observer.disconnect();this.clearSelection()}if(this.target){this.addListener(this.target);this.observer.observe(this.target,{childList:true});this.updateSelected()}},addListener:function(node){Polymer.addEventListener(node,this.activateEvent,this.activateListener)},removeListener:function(node){Polymer.removeEventListener(node,this.activateEvent,this.activateListener)},getselection(){returnthis.$.selection.getSelection()},selectedChanged:function(){this.updateSelected()},updateSelected:function(){this.validateSelected();if(this.multi){this.clearSelection();this.selected&&this.selected.forEach(function(s){this.valueToSelection(s)},this)}else{this.valueToSelection(this.selected)}},validateSelected:function(){if(this.multi&&!Array.isArray(this.selected)&&this.selected!==null&&this.selected!==undefined){this.selected=[this.selected]}},clearSelection:function(){if(this.multi){this.selection.slice().forEach(function(s){this.$.selection.setItemSelected(s,false)},this)}else{this.$.selection.setItemSelected(this.selection,false)}this.selectedItem=null;this.$.selection.clear()},valueToSelection:function(value){varitem=value===null||value===undefined?null:this.items[this.valueToIndex(value)];this.$.selection.select(item)},updateSelectedItem:function(){this.selectedItem=this.selection},selectedItemChanged:function(){if(this.selectedItem){vart=this.selectedItem.templateInstance;this.selectedModel=t?t.model:undefined}else{this.selectedModel=null}this.selectedIndex=this.selectedItem?parseInt(this.valueToIndex(this.selected)):-1},valueToIndex:function(value){for(vari=0,items=this.items,c;c=items[i];i++){if(this.valueForNode(c)==value){returni}}returnvalue},valueForNode:function(node){returnnode[this.valueattr]||node.getAttribute(this.valueattr)},selectionSelect:function(e,detail){this.updateSelectedItem();if(detail.item){this.applySelection(detail.item,detail.isSelected)}},applySelection:function(item,isSelected){if(this.selectedClass){item.classList.toggle(this.selectedClass,isSelected)}if(this.selectedProperty){item[this.selectedProperty]=isSelected}if(this.selectedAttribute&&item.setAttribute){if(isSelected){item.setAttribute(this.selectedAttribute,"")}else{item.removeAttribute(this.selectedAttribute)}}},activateHandler:function(e){if(!this.notap){vari=this.findDistributedTarget(e.target,this.items);if(i>=0){varitem=this.items[i];vars=this.valueForNode(item)||i;if(this.multi){if(this.selected){this.addRemoveSelected(s)}else{this.selected=[s]}}else{this.selected=s}this.asyncFire("core-activate",{item:item})}}},addRemoveSelected:function(value){vari=this.selected.indexOf(value);if(i>=0){this.selected.splice(i,1)}else{this.selected.push(value)}this.valueToSelection(value)},findDistributedTarget:function(target,nodes){while(target&&target!=this){vari=Array.prototype.indexOf.call(nodes,target);if(i>=0){returni}target=target.parentNode}}});</script></polymer-element><polymer-elementname="paper-ripple"attributes="initialOpacity opacityDecayVelocity"assetpath="bower_components/paper-ripple/"><template><style>:host{display:block;position:relative}#canvas{pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%}:host(.circle)#canvas{border-radius:50%}</style></template><script>(function(){varwaveMaxRadius=150;functionwaveRadiusFn(touchDownMs,touchUpMs,anim){vartouchDown=touchDownMs/1e3;vartouchUp=touchUpMs/1e3;vartotalElapsed=touchDown+touchUp;varww=anim.width,hh=anim.height;varwaveRadius=Math.min(Math.sqrt(ww*ww+hh*hh),waveMaxRadius)*1.1+5;varduration=1.1-.2*(waveRadius/waveMaxRadius);vartt=totalElapsed/duration;varsize=waveRadius*(1-Math.pow(80,-tt));returnMath.abs(size)}functionwaveOpacityFn(td,tu,anim){vartouchDown=td/1e3;vartouchUp=tu/1e3;vartotalElapsed=touchDown+touchUp;if(tu<=0){returnanim.initialOpacity}returnMath.max(0,anim.initialOpacity-touchUp*anim.opacityDecayVelocity)}functionwaveOuterOpacityFn(td,tu,anim){vartouchDown=td/1e3;vartouchUp=tu/1e3;varouterOpacity=touchDown*.3;varwaveOpacity=waveOpacityFn(td,tu,anim);returnMath.max(0,Math.min(outerOpacity,waveOpacity))}functionwaveDidFinish(wave,radius,anim){varwaveOpacity=waveOpacityFn(wave.tDown,wave.tUp,anim);if(waveOpacity<.01&&radius>=Math.min(wave.maxRadius,waveMaxRadius)){returntrue}returnfalse}functionwaveAtMaximum(wave,radius,anim){varwaveOpacity=waveOpacityFn(wave.tDown,wave.tUp,anim);if(waveOpacity>=anim.initialOpacity&&radius>=Math.min(wave.maxRadius,waveMaxRadius)){returntrue}returnfalse}functiondrawRipple(ctx,x,y,radius,innerColor,outerColor){if(outerColor){ctx.fillStyle=outerColor;ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height)}ctx.beginPath();ctx.arc(x,y,radius,0,2*Math.PI,false);ctx.fillStyle=innerColor;ctx.fill()}functioncreateWave(elem){varelementStyle=window.getComputedStyle(elem);varfgColor=elementStyle.color;varwave={waveColor:fgColor,maxRadius:0,isMouseDown:false,mouseDownStart:0,mouseUpStart:0,tDown:0,tUp:0};returnwave}functionremoveWaveFromScope(scope,wave){if(scope.waves){varpos=scope.waves.indexOf(wave);scope.waves.splice(pos,1)}}varpow=Math.pow;varnow=Date.now;if(window.performance&&performance.now){now=performance.now.bind(performance)}functioncssColorWithAlpha(cssColor,alpha){varparts=cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);if(typeofalpha=="undefined"){alpha=1}if(!parts){return"rgba(255, 255, 255, "+alpha+")"}return"rgba("+parts[1]+", "+parts[2]+", "+parts[3]+", "+alpha+")"}functiondist(p1,p2){returnMath.sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2))}functiondistanceFromPointToFurthestCorner(point,size){vartl_d=dist(point,{x:0,y:0});vartr_d=dist(point,{x:size.w,y:0});varbl_d=dist(point,{x:0,y:size.h});varbr_d=dist(point,{x:size.w,y:size.h});returnMath.max(tl_d,tr_d,bl_d,br_d)}Polymer("paper-ripple",{initialOpacity:.25,opacityDecayVelocity:.8,backgroundFill:true,pixelDensity:2,eventDelegates:{down:"downAction",up:"upAction"},attached:function(){if(!this.$.canvas){varcanvas=document.createElement("canvas");canvas.id="canvas";this.shadowRoot.appendChild(canvas);this.$.canvas=canvas}},ready:function(){this.waves=[]},setupCanvas:function(){this.$.canvas.setAttribute("width",this.$.canvas.clientWidth*this.pixelDensity+"px");this.$.canvas.setAttribute("height",this.$.canvas.clientHeight*this.pixelDensity+"px");varctx=this.$.canvas.getContext("2d");ctx.scale(this.pixelDensity,this.pixelDensity);if(!this._loop){this._loop=this.animate.bind(this,ctx)}},downAction:function(e){this.setupCanvas();varwave=createWave(this.$.canvas);this.cancelled=false;wave.isMouseDown=true;wave.tDown=0;wave.tUp=0;wave.mouseUpStart=0;wave.mouseDownStart=now();varwidth=this.$.canvas.width/2;varheight=this.$.canvas.height/2;varrect=this.getBoundingClientRect();vartouchX=e.x-rect.left;vartouchY=e.y-rect.top;wave.startPosition={x:touchX,y:touchY};if(this.classList.contains("recenteringTouch")){wave.endPosition={x:width/2,y:height/2};wave.slideDistance=dist(wave.startPosition,wave.endPosition)}wave.containerSize=Math.max(width,height);wave.maxRadius=distanceFromPointToFurthestCorner(wave.startPosition,{w:width,h:height});this.waves.push(wave);requestAnimationFrame(this._loop)},upAction:function(){for(vari=0;i<this.waves.length;i++){varwave=this.waves[i];if(wave.isMouseDown){wave.isMouseDown=false;wave.mouseUpStart=now();wave.mouseDownStart=0;wave.tUp=0;break}}this._loop&&requestAnimationFrame(this._loop)},cancel:function(){this.cancelled=true},animate:function(ctx){varshouldRenderNextFrame=false;ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);vardeleteTheseWaves=[];varlongestTouchDownDuration=0;varlongestTouchUpDuration=0;varlastWaveColor=null;varanim={initialOpacity:this.initialOpacity,opacityDecayVelocity:this.opacityDecayVelocity,height:ctx.canvas.height,width:ctx.canvas.width};for(vari=0;i<this.waves.length;i++){varwave=this.waves[i];if(wave.mouseDownStart>0){wave.tDown=now()-wave.mouseDownStart}if(wave.mouseUpStart>0){wave.tUp=now()-wave.mouseUpStart}vartUp=wave.tUp;vartDown=wave.tDown;longestTouchDownDuration=Math.max(longestTouchDownDuration,tDown);longestTouchUpDuration=Math.max(longestTouchUpDuration,tUp);varradius=waveRadiusFn(tDown,tUp,anim);varwaveAlpha=waveOpacityFn(tDown,tUp,anim);varwaveColor=cssColorWithAlpha(wave.waveColor,waveAlpha);lastWaveColor=wave.waveColor;varx=wave.startPosition.x;vary=wave.startPosition.y;if(wave.endPosition){vartranslateFraction=Math.min(1,radius/wave.containerSize*2/Math.sqrt(2));x+=translateFraction*(wave.endPosition.x-wave.startPosition.x);y+=translateFraction*(wave.endPosition.y-wave.startPosition.y)}varbgFillColor=null;if(this.backgroundFill){varbgFillAlpha=waveOuterOpacityFn(tDown,tUp,anim);bgFillColor=cssColorWithAlpha(wave.waveColor,bgFillAlpha)}drawRipple(ctx,x,y,radius,waveColor,bgFillColor);varmaximumWave=waveAtMaximum(wave,radius,anim);varwaveDissipated=waveDidFinish(wave,radius,anim);varshouldKeepWave=!waveDissipated||maximumWave;varshouldRenderWaveAgain=!waveDissipated&&!maximumWave;shouldRenderNextFrame=shouldRenderNextFrame||shouldRenderWaveAgain;if(!shouldKeepWave||this.cancelled){deleteTheseWaves.push(wave)}}if(shouldRenderNextFrame){requestAnimationFrame(this._loop)}for(vari=0;i<deleteTheseWaves.length;++i){varwave=deleteTheseWaves[i];removeWaveFromScope(this,wave)}if(!this.waves.length){ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);this._loop=null}}})})();</script></polymer-element><polymer-elementname="paper-tab"attributes="noink"role="tab"assetpath="bower_components/paper-tabs/"><template><style>:host{display:block;position:relative;overflow:hidden}#tabContainer{position:absolute;top:0;right:0;bottom:0;left:0}.tab-content{transition:opacity.1scubic-bezier(0.4,0,1,1),color.1scubic-bezier(0.4,0,1,1);cursor:default;pointer-events:none}:host(:not(.core-selected)).tab-content{opacity:.6}#ink{position:absolute;top:0;right:0;bottom:0;left:0;color:#ffff8d}:host[noink]#ink{pointer-events:none}:host-context(paper-tabs[noink])#ink{pointer-events:none}</style><divid="tabContainer"center-justified=""center=""horizontal=""layout=""><divclass="tab-content"><content></content></div><paper-rippleid="ink"initialopacity="0.95"opacitydecayvelocity="0.98"></paper-ripple></div></template><script>Polymer("paper-tab",{noink:false});</script></polymer-element><polymer-elementname="paper-tabs"extends="core-selector"attributes="noink nobar"role="tablist"assetpath="bower_components/paper-tabs/"><template><style>:host{display:block;position:relative;font-size:14px;font-weight:500;height:48px;overflow:hidden}#tabsContainer{position:absolute;top:0;right:0;bottom:0;left:0;white-space:nowrap}#selectionBar{position:absolute;height:2px;bottom:0;left:0;width:0;background-color:#ffff8d;transition:width,left}#selectionBar[hidden]{display:hidden}#selectionBar.expand{transition-duration:.15s;transition-timing-function:cubic-bezier(0.4,0,1,1)}#selectionBar.contract{transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1)}polyfill-next-selector{content:'#tabsContainer > *:not(#selectionBar)'}::content>*{-ms-flex:1;-webkit-flex:1;flex:1}</style><divid="tabsContainer"horizontal=""layout=""><shadow></shadow><divid="selectionBar"hidden?="{{nobar}}"on-transitionend="{{barTransitionEnd}}"></div></div></template><script>Polymer("paper-tabs",{noink:false,nobar:false,activateEvent:"down",nostretch:false,selectedIndexChanged:function(old){vars=this.$.selectionBar.style;if(!this.selectedItem){s.width=0;s.left=0;return}varw=100/this.items.length;if(this.nostretch||old===null||old===-1){s.width=w+"%";s.left=this.selectedIndex*w+"%";return}varm=5;this.$.selectionBar.classList.add("expand");if(old<this.selectedIndex){s.width=w+w*(this.selectedIndex-old)-m+"%"}else{s.width=w+w*(old-this.selectedIndex)-m+"%";s.left=this.selectedIndex*w+m+"%"}},barTransitionEnd:function(){varcl=this.$.selectionBar.classList;if(cl.contains("expand")){cl.remove("expand");cl.add("contract");vars=this.$.selectionBar.style;varw=100/this.items.length;s.width=w+"%";s.left=this.selectedIndex*w+"%"}elseif(cl.contains("contract")){cl.remove("contract")}}});</script></polymer-element></div></head><body><divclass="container"><headerclass="row"><divclass="col-md-8"><imgclass="logo"src="site-assets/logo.svg"width="500"height="86"alt="TodoMVC"><p>Helping you <strong>select</strong> an MV* framework</p><nav><ahref="https://github.com/tastejs/todomvc/zipball/1.3.0"class="zocial red">Download (1.3)</a><ahref="https://github.com/tastejs/todomvc"class="zocial ltgray">View on GitHub</a><ahref="http://blog.tastejs.com/"class="zocial ltgray">Blog</a></nav></div><divclass="col-md-4"><imgclass="logo-icon"src="site-assets/logo-icon.png"width="330"height="330"alt="TodoMVC"></div></header><divclass="row"><divclass="col-md-4"><h2>Introduction</h2><p>Developers these days are spoiled with choice when it comes to <ahref="http://coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/">selecting</a> an <strong>MV* framework</strong> for structuring and organizing their JavaScript web apps.</p><p>Backbone, Ember, AngularJS... the list of new and stable solutions continues to grow, but just how do you decide on which to use in a sea of so many options?</p><p>To help solve this problem, we created <ahref="https://github.com/tastejs/todomvc">TodoMVC</a> - a project which offers the same Todo application implemented using MV* concepts in most of the popular JavaScript MV* frameworks of today.</p><ahref="https://twitter.com/tastejs"class="twitter-follow-button"data-show-count="false"data-show-screen-name="false"></a><ahref="https://twitter.com/share"class="twitter-share-button"data-via="tastejs"data-url="http://todomvc.com"data-text="TodoMVC - Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, and more"></a><divclass="g-plusone"data-size="medium"data-annotation="none"data-href="http://todomvc.com"></div></div><divclass="col-md-8"><style shim-shadowdom="">paper-tabs,core-toolbar{color:#353535;background-color:#f4f4f4;font-family:'Helvetica Neue',Helvetica,Arial;box-shadow:03px2pxrgba(0,0,0,.2)}paper-tabs::shadow#selectionBar{background-color:#b12d2b}paper-tab::shadowpaper-ripple#ink{color:#b12d2b}</style><paper-tabsselected="js"class="js-app-tabs"><paper-tabname="js">JavaScript</paper-tab><paper-tabname="ctojs">Compile-to-JS</paper-tab><paper-tabname="labs">Labs</paper-tab></paper-tabs><divclass="app-lists"><divclass="js-app-list"data-app-list="js"><pclass="applist-intro">
<htmllang="en"><head><metacharset="utf-8"><title>TodoMVC</title><metaname="description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, Spine and many more"><metaname="viewport"content="width=device-width,initial-scale=1"><metaname="twitter:card"content="summary"><metaname="twitter:title"content="TodoMVC"><metaname="twitter:site"content="@TasteJS"><metaname="twitter:description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS and many more"><metaname="twitter:image"content="https://raw.githubusercontent.com/tastejs/todomvc/gh-pages/site-assets/screenshot.png"><metaproperty="og:url"content="http://todomvc.com"><metaproperty="og:title"content="TodoMVC"><metaproperty="og:image"content="https://raw.github.com/tastejs/todomvc/gh-pages/site-assets/screenshot.png"><metaproperty="og:description"content="Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, Spine and many more"><linkrel="shortcut icon"href="site-assets/favicon.ico"><linkrel="stylesheet"href="site-assets/main.min.css"><script src="bower_components/platform/platform.js"></script><divhidden><style shim-shadowdom="">html/deep/[layout][horizontal],html/deep/[layout][vertical]{display:-ms-flexbox;display:-webkit-flex;display:flex}html/deep/[layout][horizontal][inline],html/deep/[layout][vertical][inline]{display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}html/deep/[layout][horizontal]{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}html/deep/[layout][horizontal][reverse]{-ms-flex-direction:row-reverse;-webkit-flex-direction:row-reverse;flex-direction:row-reverse}html/deep/[layout][vertical]{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}html/deep/[layout][vertical][reverse]{-ms-flex-direction:column-reverse;-webkit-flex-direction:column-reverse;flex-direction:column-reverse}html/deep/[layout][wrap]{-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}html/deep/[layout][wrap-reverse]{-ms-flex-wrap:wrap-reverse;-webkit-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}html/deep/[flex]{-ms-flex:1;-webkit-flex:1;flex:1}html/deep/[flex][auto]{-ms-flex:11auto;-webkit-flex:11auto;flex:11auto}html/deep/[flex][none]{-ms-flex:none;-webkit-flex:none;flex:none}html/deep/[flex][one]{-ms-flex:1;-webkit-flex:1;flex:1}html/deep/[flex][two]{-ms-flex:2;-webkit-flex:2;flex:2}html/deep/[flex][three]{-ms-flex:3;-webkit-flex:3;flex:3}html/deep/[flex][four]{-ms-flex:4;-webkit-flex:4;flex:4}html/deep/[flex][five]{-ms-flex:5;-webkit-flex:5;flex:5}html/deep/[flex][six]{-ms-flex:6;-webkit-flex:6;flex:6}html/deep/[flex][seven]{-ms-flex:7;-webkit-flex:7;flex:7}html/deep/[flex][eight]{-ms-flex:8;-webkit-flex:8;flex:8}html/deep/[flex][nine]{-ms-flex:9;-webkit-flex:9;flex:9}html/deep/[flex][ten]{-ms-flex:10;-webkit-flex:10;flex:10}html/deep/[flex][eleven]{-ms-flex:11;-webkit-flex:11;flex:11}html/deep/[flex][twelve]{-ms-flex:12;-webkit-flex:12;flex:12}html/deep/[layout][start]{-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}html/deep/[layout][center],html/deep/[layout][center-center]{-ms-flex-align:center;-webkit-align-items:center;align-items:center}html/deep/[layout][end]{-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}html/deep/[layout][start-justified]{-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}html/deep/[layout][center-justified],html/deep/[layout][center-center]{-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}html/deep/[layout][end-justified]{-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}html/deep/[layout][around-justified]{-ms-flex-pack:around;-webkit-justify-content:space-around;justify-content:space-around}html/deep/[layout][justified]{-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}html/deep/[self-start]{-ms-align-self:flex-start;-webkit-align-self:flex-start;align-self:flex-start}html/deep/[self-center]{-ms-align-self:center;-webkit-align-self:center;align-self:center}html/deep/[self-end]{-ms-align-self:flex-end;-webkit-align-self:flex-end;align-self:flex-end}html/deep/[self-stretch]{-ms-align-self:stretch;-webkit-align-self:stretch;align-self:stretch}html/deep/[block]{display:block}html/deep/[hidden]{display:none!important}html/deep/[relative]{position:relative}html/deep/[fit]{position:absolute;top:0;right:0;bottom:0;left:0}body[fullbleed]{margin:0;height:100vh}html/deep/[segment],html/deep/segment{display:block;position:relative;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;margin:1em.5em;padding:1em;background-color:#fff;-webkit-box-shadow:0001pxrgba(0,0,0,.1);box-shadow:0001pxrgba(0,0,0,.1);border-radius:5px5px5px5px}</style><script src="bower_components/polymer/polymer.js"></script><polymer-elementname="core-selection"attributes="multi"hiddenassetpath="bower_components/core-selection/"><script>Polymer("core-selection",{multi:false,ready:function(){this.clear()},clear:function(){this.selection=[]},getSelection:function(){returnthis.multi?this.selection:this.selection[0]},isSelected:function(item){returnthis.selection.indexOf(item)>=0},setItemSelected:function(item,isSelected){if(item!==undefined&&item!==null){if(isSelected){this.selection.push(item)}else{vari=this.selection.indexOf(item);if(i>=0){this.selection.splice(i,1)}}this.fire("core-select",{isSelected:isSelected,item:item})}},select:function(item){if(this.multi){this.toggle(item)}elseif(this.getSelection()!==item){this.setItemSelected(this.getSelection(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}});</script></polymer-element><polymer-elementname="core-selector"attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap target itemsSelector activateEvent"assetpath="bower_components/core-selector/"><template><core-selectionid="selection"multi="{{multi}}"on-core-select="{{selectionSelect}}"></core-selection><contentid="items"select="*"></content></template><script>Polymer("core-selector",{selected:null,multi:false,valueattr:"name",selectedClass:"core-selected",selectedProperty:"",selectedAttribute:"active",selectedItem:null,selectedModel:null,selectedIndex:-1,target:null,itemsSelector:"",activateEvent:"tap",notap:false,ready:function(){this.activateListener=this.activateHandler.bind(this);this.observer=newMutationObserver(this.updateSelected.bind(this));if(!this.target){this.target=this}},getitems(){if(!this.target){return[]}varnodes=this.target!==this?this.itemsSelector?this.target.querySelectorAll(this.itemsSelector):this.target.children:this.$.items.getDistributedNodes();returnArray.prototype.filter.call(nodes||[],function(n){returnn&&n.localName!=="template"})},targetChanged:function(old){if(old){this.removeListener(old);this.observer.disconnect();this.clearSelection()}if(this.target){this.addListener(this.target);this.observer.observe(this.target,{childList:true});this.updateSelected()}},addListener:function(node){Polymer.addEventListener(node,this.activateEvent,this.activateListener)},removeListener:function(node){Polymer.removeEventListener(node,this.activateEvent,this.activateListener)},getselection(){returnthis.$.selection.getSelection()},selectedChanged:function(){this.updateSelected()},updateSelected:function(){this.validateSelected();if(this.multi){this.clearSelection();this.selected&&this.selected.forEach(function(s){this.valueToSelection(s)},this)}else{this.valueToSelection(this.selected)}},validateSelected:function(){if(this.multi&&!Array.isArray(this.selected)&&this.selected!==null&&this.selected!==undefined){this.selected=[this.selected]}},clearSelection:function(){if(this.multi){this.selection.slice().forEach(function(s){this.$.selection.setItemSelected(s,false)},this)}else{this.$.selection.setItemSelected(this.selection,false)}this.selectedItem=null;this.$.selection.clear()},valueToSelection:function(value){varitem=value===null||value===undefined?null:this.items[this.valueToIndex(value)];this.$.selection.select(item)},updateSelectedItem:function(){this.selectedItem=this.selection},selectedItemChanged:function(){if(this.selectedItem){vart=this.selectedItem.templateInstance;this.selectedModel=t?t.model:undefined}else{this.selectedModel=null}this.selectedIndex=this.selectedItem?parseInt(this.valueToIndex(this.selected)):-1},valueToIndex:function(value){for(vari=0,items=this.items,c;c=items[i];i++){if(this.valueForNode(c)==value){returni}}returnvalue},valueForNode:function(node){returnnode[this.valueattr]||node.getAttribute(this.valueattr)},selectionSelect:function(e,detail){this.updateSelectedItem();if(detail.item){this.applySelection(detail.item,detail.isSelected)}},applySelection:function(item,isSelected){if(this.selectedClass){item.classList.toggle(this.selectedClass,isSelected)}if(this.selectedProperty){item[this.selectedProperty]=isSelected}if(this.selectedAttribute&&item.setAttribute){if(isSelected){item.setAttribute(this.selectedAttribute,"")}else{item.removeAttribute(this.selectedAttribute)}}},activateHandler:function(e){if(!this.notap){vari=this.findDistributedTarget(e.target,this.items);if(i>=0){varitem=this.items[i];vars=this.valueForNode(item)||i;if(this.multi){if(this.selected){this.addRemoveSelected(s)}else{this.selected=[s]}}else{this.selected=s}this.asyncFire("core-activate",{item:item})}}},addRemoveSelected:function(value){vari=this.selected.indexOf(value);if(i>=0){this.selected.splice(i,1)}else{this.selected.push(value)}this.valueToSelection(value)},findDistributedTarget:function(target,nodes){while(target&&target!=this){vari=Array.prototype.indexOf.call(nodes,target);if(i>=0){returni}target=target.parentNode}}});</script></polymer-element><polymer-elementname="paper-ripple"attributes="initialOpacity opacityDecayVelocity"assetpath="bower_components/paper-ripple/"><template><style>:host{display:block;position:relative}#canvas{pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%}:host(.circle)#canvas{border-radius:50%}</style></template><script>(function(){varwaveMaxRadius=150;functionwaveRadiusFn(touchDownMs,touchUpMs,anim){vartouchDown=touchDownMs/1e3;vartouchUp=touchUpMs/1e3;vartotalElapsed=touchDown+touchUp;varww=anim.width,hh=anim.height;varwaveRadius=Math.min(Math.sqrt(ww*ww+hh*hh),waveMaxRadius)*1.1+5;varduration=1.1-.2*(waveRadius/waveMaxRadius);vartt=totalElapsed/duration;varsize=waveRadius*(1-Math.pow(80,-tt));returnMath.abs(size)}functionwaveOpacityFn(td,tu,anim){vartouchDown=td/1e3;vartouchUp=tu/1e3;vartotalElapsed=touchDown+touchUp;if(tu<=0){returnanim.initialOpacity}returnMath.max(0,anim.initialOpacity-touchUp*anim.opacityDecayVelocity)}functionwaveOuterOpacityFn(td,tu,anim){vartouchDown=td/1e3;vartouchUp=tu/1e3;varouterOpacity=touchDown*.3;varwaveOpacity=waveOpacityFn(td,tu,anim);returnMath.max(0,Math.min(outerOpacity,waveOpacity))}functionwaveDidFinish(wave,radius,anim){varwaveOpacity=waveOpacityFn(wave.tDown,wave.tUp,anim);if(waveOpacity<.01&&radius>=Math.min(wave.maxRadius,waveMaxRadius)){returntrue}returnfalse}functionwaveAtMaximum(wave,radius,anim){varwaveOpacity=waveOpacityFn(wave.tDown,wave.tUp,anim);if(waveOpacity>=anim.initialOpacity&&radius>=Math.min(wave.maxRadius,waveMaxRadius)){returntrue}returnfalse}functiondrawRipple(ctx,x,y,radius,innerColor,outerColor){if(outerColor){ctx.fillStyle=outerColor;ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height)}ctx.beginPath();ctx.arc(x,y,radius,0,2*Math.PI,false);ctx.fillStyle=innerColor;ctx.fill()}functioncreateWave(elem){varelementStyle=window.getComputedStyle(elem);varfgColor=elementStyle.color;varwave={waveColor:fgColor,maxRadius:0,isMouseDown:false,mouseDownStart:0,mouseUpStart:0,tDown:0,tUp:0};returnwave}functionremoveWaveFromScope(scope,wave){if(scope.waves){varpos=scope.waves.indexOf(wave);scope.waves.splice(pos,1)}}varpow=Math.pow;varnow=Date.now;if(window.performance&&performance.now){now=performance.now.bind(performance)}functioncssColorWithAlpha(cssColor,alpha){varparts=cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);if(typeofalpha=="undefined"){alpha=1}if(!parts){return"rgba(255, 255, 255, "+alpha+")"}return"rgba("+parts[1]+", "+parts[2]+", "+parts[3]+", "+alpha+")"}functiondist(p1,p2){returnMath.sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2))}functiondistanceFromPointToFurthestCorner(point,size){vartl_d=dist(point,{x:0,y:0});vartr_d=dist(point,{x:size.w,y:0});varbl_d=dist(point,{x:0,y:size.h});varbr_d=dist(point,{x:size.w,y:size.h});returnMath.max(tl_d,tr_d,bl_d,br_d)}Polymer("paper-ripple",{initialOpacity:.25,opacityDecayVelocity:.8,backgroundFill:true,pixelDensity:2,eventDelegates:{down:"downAction",up:"upAction"},attached:function(){if(!this.$.canvas){varcanvas=document.createElement("canvas");canvas.id="canvas";this.shadowRoot.appendChild(canvas);this.$.canvas=canvas}},ready:function(){this.waves=[]},setupCanvas:function(){this.$.canvas.setAttribute("width",this.$.canvas.clientWidth*this.pixelDensity+"px");this.$.canvas.setAttribute("height",this.$.canvas.clientHeight*this.pixelDensity+"px");varctx=this.$.canvas.getContext("2d");ctx.scale(this.pixelDensity,this.pixelDensity);if(!this._loop){this._loop=this.animate.bind(this,ctx)}},downAction:function(e){this.setupCanvas();varwave=createWave(this.$.canvas);this.cancelled=false;wave.isMouseDown=true;wave.tDown=0;wave.tUp=0;wave.mouseUpStart=0;wave.mouseDownStart=now();varwidth=this.$.canvas.width/2;varheight=this.$.canvas.height/2;varrect=this.getBoundingClientRect();vartouchX=e.x-rect.left;vartouchY=e.y-rect.top;wave.startPosition={x:touchX,y:touchY};if(this.classList.contains("recenteringTouch")){wave.endPosition={x:width/2,y:height/2};wave.slideDistance=dist(wave.startPosition,wave.endPosition)}wave.containerSize=Math.max(width,height);wave.maxRadius=distanceFromPointToFurthestCorner(wave.startPosition,{w:width,h:height});this.waves.push(wave);requestAnimationFrame(this._loop)},upAction:function(){for(vari=0;i<this.waves.length;i++){varwave=this.waves[i];if(wave.isMouseDown){wave.isMouseDown=false;wave.mouseUpStart=now();wave.mouseDownStart=0;wave.tUp=0;break}}this._loop&&requestAnimationFrame(this._loop)},cancel:function(){this.cancelled=true},animate:function(ctx){varshouldRenderNextFrame=false;ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);vardeleteTheseWaves=[];varlongestTouchDownDuration=0;varlongestTouchUpDuration=0;varlastWaveColor=null;varanim={initialOpacity:this.initialOpacity,opacityDecayVelocity:this.opacityDecayVelocity,height:ctx.canvas.height,width:ctx.canvas.width};for(vari=0;i<this.waves.length;i++){varwave=this.waves[i];if(wave.mouseDownStart>0){wave.tDown=now()-wave.mouseDownStart}if(wave.mouseUpStart>0){wave.tUp=now()-wave.mouseUpStart}vartUp=wave.tUp;vartDown=wave.tDown;longestTouchDownDuration=Math.max(longestTouchDownDuration,tDown);longestTouchUpDuration=Math.max(longestTouchUpDuration,tUp);varradius=waveRadiusFn(tDown,tUp,anim);varwaveAlpha=waveOpacityFn(tDown,tUp,anim);varwaveColor=cssColorWithAlpha(wave.waveColor,waveAlpha);lastWaveColor=wave.waveColor;varx=wave.startPosition.x;vary=wave.startPosition.y;if(wave.endPosition){vartranslateFraction=Math.min(1,radius/wave.containerSize*2/Math.sqrt(2));x+=translateFraction*(wave.endPosition.x-wave.startPosition.x);y+=translateFraction*(wave.endPosition.y-wave.startPosition.y)}varbgFillColor=null;if(this.backgroundFill){varbgFillAlpha=waveOuterOpacityFn(tDown,tUp,anim);bgFillColor=cssColorWithAlpha(wave.waveColor,bgFillAlpha)}drawRipple(ctx,x,y,radius,waveColor,bgFillColor);varmaximumWave=waveAtMaximum(wave,radius,anim);varwaveDissipated=waveDidFinish(wave,radius,anim);varshouldKeepWave=!waveDissipated||maximumWave;varshouldRenderWaveAgain=!waveDissipated&&!maximumWave;shouldRenderNextFrame=shouldRenderNextFrame||shouldRenderWaveAgain;if(!shouldKeepWave||this.cancelled){deleteTheseWaves.push(wave)}}if(shouldRenderNextFrame){requestAnimationFrame(this._loop)}for(vari=0;i<deleteTheseWaves.length;++i){varwave=deleteTheseWaves[i];removeWaveFromScope(this,wave)}if(!this.waves.length){ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);this._loop=null}}})})();</script></polymer-element><polymer-elementname="paper-tab"attributes="noink"role="tab"assetpath="bower_components/paper-tabs/"><template><style>:host{display:block;position:relative;overflow:hidden}#tabContainer{position:absolute;top:0;right:0;bottom:0;left:0}.tab-content{transition:opacity.1scubic-bezier(0.4,0,1,1),color.1scubic-bezier(0.4,0,1,1);cursor:default;pointer-events:none}:host(:not(.core-selected)).tab-content{opacity:.6}#ink{position:absolute;top:0;right:0;bottom:0;left:0;color:#ffff8d}:host[noink]#ink{pointer-events:none}:host-context(paper-tabs[noink])#ink{pointer-events:none}</style><divid="tabContainer"center-justified=""center=""horizontal=""layout=""><divclass="tab-content"><content></content></div><paper-rippleid="ink"initialopacity="0.95"opacitydecayvelocity="0.98"></paper-ripple></div></template><script>Polymer("paper-tab",{noink:false});</script></polymer-element><polymer-elementname="paper-tabs"extends="core-selector"attributes="noink nobar"role="tablist"assetpath="bower_components/paper-tabs/"><template><style>:host{display:block;position:relative;font-size:14px;font-weight:500;height:48px;overflow:hidden}#tabsContainer{position:absolute;top:0;right:0;bottom:0;left:0;white-space:nowrap}#selectionBar{position:absolute;height:2px;bottom:0;left:0;width:0;background-color:#ffff8d;transition:width,left}#selectionBar[hidden]{display:hidden}#selectionBar.expand{transition-duration:.15s;transition-timing-function:cubic-bezier(0.4,0,1,1)}#selectionBar.contract{transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1)}polyfill-next-selector{content:'#tabsContainer > *:not(#selectionBar)'}::content>*{-ms-flex:1;-webkit-flex:1;flex:1}</style><divid="tabsContainer"horizontal=""layout=""><shadow></shadow><divid="selectionBar"hidden?="{{nobar}}"on-transitionend="{{barTransitionEnd}}"></div></div></template><script>Polymer("paper-tabs",{noink:false,nobar:false,activateEvent:"down",nostretch:false,selectedIndexChanged:function(old){vars=this.$.selectionBar.style;if(!this.selectedItem){s.width=0;s.left=0;return}varw=100/this.items.length;if(this.nostretch||old===null||old===-1){s.width=w+"%";s.left=this.selectedIndex*w+"%";return}varm=5;this.$.selectionBar.classList.add("expand");if(old<this.selectedIndex){s.width=w+w*(this.selectedIndex-old)-m+"%"}else{s.width=w+w*(old-this.selectedIndex)-m+"%";s.left=this.selectedIndex*w+m+"%"}},barTransitionEnd:function(){varcl=this.$.selectionBar.classList;if(cl.contains("expand")){cl.remove("expand");cl.add("contract");vars=this.$.selectionBar.style;varw=100/this.items.length;s.width=w+"%";s.left=this.selectedIndex*w+"%"}elseif(cl.contains("contract")){cl.remove("contract")}}});</script></polymer-element></div></head><body><divclass="container"><headerclass="row"><divclass="col-md-8"><imgclass="logo"src="site-assets/logo.svg"width="500"height="86"alt="TodoMVC"><p>Helping you <strong>select</strong> an MV* framework</p><nav><ahref="https://github.com/tastejs/todomvc/zipball/1.3.0"class="zocial red">Download (1.3)</a><ahref="https://github.com/tastejs/todomvc"class="zocial ltgray">View on GitHub</a><ahref="http://blog.tastejs.com/"class="zocial ltgray">Blog</a></nav></div><divclass="col-md-4"><imgclass="logo-icon"src="site-assets/logo-icon.png"width="330"height="330"alt="TodoMVC"></div></header><divclass="row"><divclass="col-md-4"><h2>Introduction</h2><p>Developers these days are spoiled with choice when it comes to <ahref="http://coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/">selecting</a> an <strong>MV* framework</strong> for structuring and organizing their JavaScript web apps.</p><p>Backbone, Ember, AngularJS... the list of new and stable solutions continues to grow, but just how do you decide on which to use in a sea of so many options?</p><p>To help solve this problem, we created <ahref="https://github.com/tastejs/todomvc">TodoMVC</a> - a project which offers the same Todo application implemented using MV* concepts in most of the popular JavaScript MV* frameworks of today.</p><ahref="https://twitter.com/tastejs"class="twitter-follow-button"data-show-count="false"data-show-screen-name="false"></a><ahref="https://twitter.com/share"class="twitter-share-button"data-via="tastejs"data-url="http://todomvc.com"data-text="TodoMVC - Helping you select an MV* framework - Todo apps for Backbone.js, Ember.js, AngularJS, and more"></a><divclass="g-plusone"data-size="medium"data-annotation="none"data-href="http://todomvc.com"></div></div><divclass="col-md-8"><h2>Examples</h2><style shim-shadowdom="">paper-tabs,core-toolbar{color:#353535;background-color:#f4f4f4;font-family:'Helvetica Neue',Helvetica,Arial;box-shadow:03px2pxrgba(0,0,0,.2)}paper-tabs::shadow#selectionBar{background-color:#b12d2b}paper-tab::shadowpaper-ripple#ink{color:#b12d2b}</style><paper-tabsselected="js"class="js-app-tabs"><paper-tabname="js">JavaScript</paper-tab><paper-tabname="ctojs">Compile-to-JS</paper-tab><paper-tabname="labs">Labs</paper-tab></paper-tabs><divclass="app-lists"><divclass="js-app-list"data-app-list="js"><pclass="applist-intro">
These are examples written in pure JavaScript.
These are examples written in pure JavaScript.
</p><ulclass="applist js"><liclass="routing"><ahref="architecture-examples/backbone"data-source="http://documentcloud.github.com/backbone/"data-content="Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.">Backbone.js</a></li><liclass="routing"><ahref="architecture-examples/angularjs"data-source="http://angularjs.org"data-content="What HTML would have been had it been designed for web apps">AngularJS</a></li><liclass="routing"><ahref="architecture-examples/emberjs"data-source="http://emberjs.com"data-content="Ember is a JavaScript framework for creating ambitious web applications that eliminates boilerplate and provides a standard application architecture.">Ember.js</a></li><liclass="routing"><ahref="architecture-examples/knockoutjs"data-source="http://knockoutjs.com"data-content="Simplify dynamic JavaScript UIs by applying the Model-View-View Model (MVVM) pattern">KnockoutJS</a></li><liclass="routing"><ahref="architecture-examples/dojo"data-source="http://dojotoolkit.org"data-content="Dojo saves you time and scales with your development process, using web standards as its platform. It’s the toolkit experienced developers turn to for building high quality desktop and mobile web applications.">Dojo</a></li><liclass="routing"><ahref="architecture-examples/yui"data-source="http://yuilibrary.com"data-content="YUI's lightweight core and modular architecture make it scalable, fast, and robust. Built by frontend engineers at Yahoo!, YUI powers the most popular websites in the world.">YUI</a></li><liclass="routing"><ahref="architecture-examples/agilityjs"data-source="http://agilityjs.com"data-content="Agility.js is an MVC library for Javascript that lets you write maintainable and reusable browser code without the infrastructural overhead found in other MVC libraries. The goal is to enable developers to write web apps at least as quickly as with jQuery, while simplifying long-term maintainability through MVC objects.">Agility.js</a></li><liclass="routing"><ahref="architecture-examples/knockback"data-source="http://kmalakoff.github.com/knockback/"data-content="Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.">Knockback.js</a></li><liclass="routing"><ahref="architecture-examples/canjs"data-source="http://canjs.us"data-content="CanJS with jQuery. CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS</a></li><liclass="routing"><ahref="architecture-examples/maria"data-source="https://github.com/petermichaux/maria"data-content="An MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC. The three core design patterns of MVC (observer, composite, and strategy) are embedded in Maria's Model, View, and Controller objects. Other patterns traditionally included in MVC implementations (e.g. factory method and template) make appearances too.">Maria</a></li><liclass="routing"><ahref="architecture-examples/polymer/index.html"data-source="http://polymer-project.org"data-content="Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. It is comprised of core platform features (e.g Shadow DOM, Custom Elements, MDV) enabled with polyfills and a next generation web application framework built on these technologies.">Polymer</a></li><liclass="routing"><ahref="architecture-examples/react"data-source="http://facebook.github.io/react/"data-content="React is a JavaScript library for building user interfaces.">React</a></li><liclass="routing"><ahref="dependency-examples/flight"data-source="http://twitter.github.com/flight"data-content="Flight is a lightweight, component-based JavaScript framework that maps behavior to DOM nodes. Twitter uses it for their web applications.">Flight</a></li></ul></div><divclass="js-app-list"data-app-list="ctojs"><pclass="applist-intro">
</p><ulclass="applist js"><liclass="routing"><ahref="architecture-examples/backbone"data-source="http://documentcloud.github.com/backbone/"data-content="Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.">Backbone.js</a></li><liclass="routing"><ahref="architecture-examples/angularjs"data-source="http://angularjs.org"data-content="What HTML would have been had it been designed for web apps">AngularJS</a></li><liclass="routing"><ahref="architecture-examples/emberjs"data-source="http://emberjs.com"data-content="Ember is a JavaScript framework for creating ambitious web applications that eliminates boilerplate and provides a standard application architecture.">Ember.js</a></li><liclass="routing"><ahref="architecture-examples/knockoutjs"data-source="http://knockoutjs.com"data-content="Simplify dynamic JavaScript UIs by applying the Model-View-View Model (MVVM) pattern">KnockoutJS</a></li><liclass="routing"><ahref="architecture-examples/dojo"data-source="http://dojotoolkit.org"data-content="Dojo saves you time and scales with your development process, using web standards as its platform. It’s the toolkit experienced developers turn to for building high quality desktop and mobile web applications.">Dojo</a></li><liclass="routing"><ahref="architecture-examples/yui"data-source="http://yuilibrary.com"data-content="YUI's lightweight core and modular architecture make it scalable, fast, and robust. Built by frontend engineers at Yahoo!, YUI powers the most popular websites in the world.">YUI</a></li><liclass="routing"><ahref="architecture-examples/agilityjs"data-source="http://agilityjs.com"data-content="Agility.js is an MVC library for Javascript that lets you write maintainable and reusable browser code without the infrastructural overhead found in other MVC libraries. The goal is to enable developers to write web apps at least as quickly as with jQuery, while simplifying long-term maintainability through MVC objects.">Agility.js</a></li><liclass="routing"><ahref="architecture-examples/knockback"data-source="http://kmalakoff.github.com/knockback/"data-content="Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.">Knockback.js</a></li><liclass="routing"><ahref="architecture-examples/canjs"data-source="http://canjs.us"data-content="CanJS with jQuery. CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS</a></li><liclass="routing"><ahref="architecture-examples/maria"data-source="https://github.com/petermichaux/maria"data-content="An MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC. The three core design patterns of MVC (observer, composite, and strategy) are embedded in Maria's Model, View, and Controller objects. Other patterns traditionally included in MVC implementations (e.g. factory method and template) make appearances too.">Maria</a></li><liclass="routing"><ahref="architecture-examples/polymer/index.html"data-source="http://polymer-project.org"data-content="Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. It is comprised of core platform features (e.g Shadow DOM, Custom Elements, MDV) enabled with polyfills and a next generation web application framework built on these technologies.">Polymer</a></li><liclass="routing"><ahref="architecture-examples/react"data-source="http://facebook.github.io/react/"data-content="React is a JavaScript library for building user interfaces.">React</a></li><liclass="routing"><ahref="dependency-examples/flight"data-source="http://twitter.github.com/flight"data-content="Flight is a lightweight, component-based JavaScript framework that maps behavior to DOM nodes. Twitter uses it for their web applications.">Flight</a></li></ul></div><divclass="js-app-list"data-app-list="ctojs"><pclass="applist-intro">