Commit 29732c99 authored by Mike Czepiel's avatar Mike Czepiel Committed by Sindre Sorhus

Close GH-251: Montage.

parent 00580880
......@@ -166,6 +166,9 @@
<li>
<a href="http://todomvc.meteor.com" data-source="http://meteor.com" data-content="Meteor is an ultra-simple environment for building modern websites.A Meteor application is a mix of JavaScript that runs inside a client web browser, JavaScript that runs on the Meteor server inside a Node.js container, and all the supporting HTML fragments, CSS rules, and static assets. Meteor automates the packaging and transmission of these different components. And, it is quite flexible about how you choose to structure those components in your file tree.">Meteor</a>
</li>
<li>
<a href="labs/architecture-examples/montage/" data-source="https://github.com/Motorola-Mobility/montage" data-content="Montage simplifies the development of rich HTML5 applications by providing modular components, real-time two-way data binding, CommonJS dependency management, and many more conveniences.">Montage</a>
</li>
<li>
<a href="labs/architecture-examples/socketstream/README.md" data-source="http://www.socketstream.org" data-content="SocketStream is a fast, modular Node.js web framework dedicated to building realtime single-page apps">SocketStream + jQuery</a>
</li>
......
montage-todomvc
==============
This is a Montage implementation of the TodoMVC application.
TL;DR: The unbundled application code included is for reference only; it is not being executed.
The [source code for this application is available](https://github.com/mczepiel/montage-todomvc) but
in an effort to not include an unminified version of Montage itself in TodoMVC we have run the
application through our build tool, [mop](https://github.com/Motorola-Mobility/montage/tree/master/tools/mop).
Montage applications are authored as CommonJS modules using our own XHR-based dependency management,
enabling us to write pure-HTML templates and boiler-plate-free JavaScript.
Mopping bundles the framework, application code, and HTML templates together into a handful of files
formatted using AMD-style dependency management.
While it would be technically possible to bundle the framework and manually wrap unminified
application code in an AMD-compatible manner for the purposes of this example, it would
not give an accurate impression of how to author Montage applications.
In the future we hope to aid debugging deployed applications with sourcemaps.
[Montage Framework Project](https://github.com/Motorola-Mobility/montage)
#montage-todomvc .visible {display: block;}
This source diff could not be displayed because it is too large. You can view the blob instead.
define("4763f06","ui/composer/press-composer",{dependencies:["montage","ui/composer/composer","core/event/mutable-event"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/composer/composer").Composer,f=a("core/event/mutable-event").MutableEvent,g=b.PressComposer=d.create(e,{load:{value:function(){window.Touch?this._element.addEventListener("touchstart",this,!0):this._element.addEventListener("mousedown",this,!0)}},unload:{value:function(){window.Touch?this._element.removeEventListener("touchstart",this):this._element.removeEventListener("mousedown",this)}},delegate:{value:null},cancelPress:{value:function(){return this._state===g.PRESSED?(this._dispatchPressCancel(),this._endInteraction(),!0):!1}},addEventListener:{value:function(a,b,c){e.addEventListener.call(this,a,b,c),a==="longPress"&&(this._shouldDispatchLongPress=!0)}},UNPRESSED:{value:0},PRESSED:{value:1},CANCELLED:{value:2},_state:{enumerable:!1,value:0},state:{get:function(){return this._state}},_shouldDispatchLongPress:{enumerable:!1,value:!1},_longPressThreshold:{enumerable:!1,value:1e3},longPressThreshold:{get:function(){return this._longPressThreshold},set:function(a){this._longPressThreshold!==a&&(this._longPressThreshold=a)}},_longPressTimeout:{enumberable:!1,value:null},_observedPointer:{enumerable:!1,value:null},_startInteraction:{enumerable:!1,value:function(a){if("disabled"in this.component&&this.component.disabled||this._observedPointer!==null)return!1;var b=0,c;if(a.type==="touchstart"){c=a.changedTouches.length;for(;b<c;b++)if(!this.component.eventManager.componentClaimingPointer(a.changedTouches[b].identifier)){this._observedPointer=a.changedTouches[b].identifier;break}if(this._observedPointer===null)return!1;document.addEventListener("touchend",this,!1),document.addEventListener("touchcancel",this,!1)}else a.type==="mousedown"&&(this._observedPointer="mouse",document.addEventListener("mouseup",this,!1),document.addEventListener("click",this,!1));this.component.eventManager.claimPointer(this._observedPointer,this),this._dispatchPressStart(a)}},_interpretInteraction:{value:function(a){var b,c,d;if(this._observedPointer===null){this._endInteraction(a);return}b=!this.component.eventManager.isPointerClaimedByComponent(this._observedPointer,this),c=a.target;while(c!==this._element&&c&&c.parentNode)c=c.parentNode;d=c===this._element;if(b&&a.type==="click"){a.preventDefault(),this._endInteraction(a);return}if(a.type==="mouseup"){if(!b&&d){this._dispatchPress(a),this._endInteraction(a);return}if(!b&&!d){this._dispatchPressCancel(a),this._endInteraction(a);return}b&&!d&&this._endInteraction(a)}}},_endInteraction:{value:function(a){if(!a||a.type==="touchend"||a.type==="touchcancel")document.removeEventListener("touchend",this),document.removeEventListener("touchcancel",this);else if(!a||a.type==="click"||a.type==="mouseup")document.removeEventListener("click",this),document.removeEventListener("mouseup",this);this.component.eventManager.isPointerClaimedByComponent(this._observedPointer,this)&&this.component.eventManager.forfeitPointer(this._observedPointer,this),this._observedPointer=null,this._state=g.UNPRESSED}},_changedTouchisObserved:{value:function(a){if(this._observedPointer===null)return!1;var b=0,c=event.changedTouches.length;for(;b<c;b++)if(event.changedTouches[b].identifier===this._observedPointer)return b;return!1}},surrenderPointer:{value:function(a,b){var c=this.callDelegateMethod("surrenderPointer",a,b);return typeof c!="undefined"&&c===!1?!1:(this._dispatchPressCancel(),!0)}},captureTouchstart:{value:function(a){this._startInteraction(a)}},handleTouchend:{value:function(a){if(this._observedPointer===null){this._endInteraction(a);return}this._changedTouchisObserved(a.changedTouches)!==!1&&(this.component.eventManager.isPointerClaimedByComponent(this._observedPointer,this)?this._dispatchPress(a):a.preventDefault(),this._endInteraction(a))}},handleTouchcancel:{value:function(a){if(this._observedPointer===null||this._changedTouchisObserved(a.changedTouches)!==!1)this.component.eventManager.isPointerClaimedByComponent(this._observedPointer,this)&&this._dispatchPressCancel(a),this._endInteraction(a)}},captureMousedown:{value:function(a){this._startInteraction(a)}},handleClick:{value:function(a){this._interpretInteraction(a)}},handleMouseup:{value:function(a){this._interpretInteraction(a)}},_createPressEvent:{enumerable:!1,value:function(a,b){var c,d,e;return b||(b=document.createEvent("CustomEvent"),b.initCustomEvent(a,!0,!0,null)),c=h.create(),c.event=b,c.type=a,c.pointer=this._observedPointer,b.changedTouches&&(e=this._changedTouchisObserved(b.changedTouches))!==!1&&(c.touch=b.changedTouches[e]),c}},_dispatchPressStart:{enumerable:!1,value:function(a){this._state=g.PRESSED,this.dispatchEvent(this._createPressEvent("pressStart",a));if(this._shouldDispatchLongPress){var b=this;this._longPressTimeout=setTimeout(function(){b._dispatchLongPress()},this._longPressThreshold)}}},_dispatchPress:{enumerable:!1,value:function(a){this._shouldDispatchLongPress&&(clearTimeout(this._longPressTimeout),this._longPressTimeout=null),this.dispatchEvent(this._createPressEvent("press",a)),this._state=g.UNPRESSED}},_dispatchLongPress:{enumerable:!1,value:function(a){this._shouldDispatchLongPress&&(this.dispatchEvent(this._createPressEvent("longPress",a)),this._longPressTimeout=null)}},_dispatchPressCancel:{enumerable:!1,value:function(a){this._shouldDispatchLongPress&&(clearTimeout(this._longPressTimeout),this._longPressTimeout=null),this._state=g.CANCELLED,this.dispatchEvent(this._createPressEvent("pressCancel",a))}}}),h=function(){var a,b,c,e,f,g;a=d.create(d,{type:{value:"press"},_event:{enumerable:!1,value:null},event:{get:function(){return this._event},set:function(a){this._event=a}},_touch:{enumerable:!1,value:null},touch:{get:function(){return this._touch},set:function(a){this._touch=a}}}),b=["altKey","ctrlKey","metaKey","shiftKey","cancelBubble","currentTarget","defaultPrevented","eventPhase","timeStamp","preventDefault","stopImmediatePropagation","stopPropagation"],c=["clientX","clientY","pageX","pageY","screenX","screenY","target"],e=function(a){return{get:function(){return this._event[a]}}},f=function(a){return{get:function(){return this._touch?this._touch[a]:this._event[a]}}};for(g=b.length-1;g>=0;g--)d.defineProperty(a,b[g],e(b[g]));for(g=c.length-1;g>=0;g--)d.defineProperty(a,c[g],f(c[g]));return a}()}}),define("4763f06","ui/text-input",{dependencies:["montage","ui/component","ui/native-control"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/native-control").NativeControl,g=b.TextInput=d.create(f,{_hasFocus:{enumerable:!1,value:!1},_value:{enumerable:!1,value:null},_valueSyncedWithInputField:{enumerable:!1,value:!1},value:{get:function(){return this._value},set:function(a,b){if(a!==this._value){if(this.converter){var c;try{c=this.converter.revert(a),this.error=null,this._value=c}catch(d){this._value=a,this.error=d}}else this._value=a;b?this._valueSyncedWithInputField=!0:(this._valueSyncedWithInputField=!1,this.needsDraw=!0)}}},_setValue:{value:function(){var a=this.element.value;Object.getPropertyDescriptor(this,"value").set.call(this,a,!0)}},converter:{value:null},_error:{value:null},error:{get:function(){return this._error},set:function(a){this._error=a,this.errorMessage=this._error?this._error.message:null,this.needsDraw=!0}},_errorMessage:{value:null},errorMessage:{get:function(){return this._errorMessage},set:function(a){this._errorMessage=a}},_updateOnInput:{value:!0},updateOnInput:{get:function(){return!!this._updateOnInput},set:function(a){this._updateOnInput=a}},blur:{value:function(){this._element.blur()}},focus:{value:function(){this._element.focus()}},prepareForDraw:{enumerable:!1,value:function(){var a=this.element;a.addEventListener("focus",this),a.addEventListener("input",this),a.addEventListener("change",this),a.addEventListener("blur",this)}},_setElementValue:{value:function(a){this.element.value=a==null?"":a}},draw:{enumerable:!1,value:function(){Object.getPrototypeOf(g).draw.call(this);var a=this.element;this._valueSyncedWithInputField||this._setElementValue(this.converter?this.converter.convert(this._value):this._value),this.error?(a.classList.add("montage-text-invalid"),a.title=this.error.message||""):(a.classList.remove("montage-text-invalid"),a.title="")}},didDraw:{enumerable:!1,value:function(){if(this._hasFocus&&this._value!=null){var a=this._value.toString().length;this.element.setSelectionRange(a,a)}this._valueSyncedWithInputField=!0}},handleInput:{enumerable:!1,value:function(){this.converter?this.converter.allowPartialConversion===!0&&this.updateOnInput===!0&&this._setValue():this._setValue()}},handleChange:{enumerable:!1,value:function(a){this._setValue(),this._hasFocus=!1}},handleBlur:{enumerable:!1,value:function(a){this._hasFocus=!1}},handleFocus:{enumerable:!1,value:function(a){this._hasFocus=!0}}});g.addAttributes({accept:null,alt:null,autocomplete:null,autofocus:{dataType:"boolean"},checked:{dataType:"boolean"},dirname:null,disabled:{dataType:"boolean"},form:null,formaction:null,formenctype:null,formmethod:null,formnovalidate:{dataType:"boolean"},formtarget:null,height:null,list:null,maxlength:null,multiple:{dataType:"boolean"},name:null,pattern:null,placeholder:null,readonly:{dataType:"boolean"},required:{dataType:"boolean"},size:null,src:null,width:null})}}),define("1156f40","ui/main.reel/main",{dependencies:["montage","montage/ui/component","montage/ui/controller/array-controller","core/todo","montage/core/serializer","montage/core/deserializer"],factory:function(a,b,c){var d=a("montage").Montage,e=a("montage/ui/component").Component,f=a("montage/ui/controller/array-controller").ArrayController,g=a("core/todo").Todo,h=a("montage/core/serializer").Serializer,i=a("montage/core/deserializer").Deserializer,j="todos-montage";b.Main=d.create(e,{newTodoForm:{value:null},newTodoInput:{value:null},todoListController:{serializable:!1,value:null},didCreate:{value:function(){this.todoListController=f.create(),this.load()}},load:{value:function(){if(localStorage){var b=localStorage.getItem(j);if(b){var c=i.create(),d=this;try{c.initWithStringAndRequire(b,a).deserializeObject(function(a){d.todoListController.initWithContent(a)},a)}catch(e){console.error("Could not load saved tasks."),console.debug("Could not deserialize",b),console.log(e.stack)}}}}},save:{value:function(){if(localStorage){var b=this.todoListController.content,c=h.create().initWithRequire(a);localStorage.setItem(j,c.serializeObject(b))}}},prepareForDraw:{value:function(){this.newTodoForm.identifier="newTodoForm",this.newTodoForm.addEventListener("submit",this,!1),this.addEventListener("destroyTodo",this,!0),window.addEventListener("beforeunload",this,!0)}},captureDestroyTodo:{value:function(a){this.destroyTodo(a.detail.todo)}},handleNewTodoFormSubmit:{value:function(a){a.preventDefault();var b=this.newTodoInput.value.trim();if(""===b)return;this.createTodo(b),this.newTodoInput.value=null}},createTodo:{value:function(a){var b=g.create().initWithTitle(a);return this.todoListController.addObjects(b),b}},destroyTodo:{value:function(a){return this.todoListController.removeObjects(a),a}},allCompleted:{dependencies:["todoListController.organizedObjects.completed"],get:function(){return this.todoListController.organizedObjects.getProperty("completed").all()},set:function(a){this.todoListController.organizedObjects.forEach(function(b){b.completed=a})}},todosLeft:{dependencies:["todoListController.organizedObjects.completed"],get:function(){if(this.todoListController.organizedObjects){var a=this.todoListController.organizedObjects;return a.filter(function(a){return!a.completed})}}},completedTodos:{dependencies:["todoListController.organizedObjects.completed"],get:function(){if(this.todoListController.organizedObjects){var a=this.todoListController.organizedObjects;return a.filter(function(a){return a.completed})}}},handleClearCompletedButtonAction:{value:function(a){var b=this.todoListController.organizedObjects.filter(function(a){return a.completed});b.length>0&&this.todoListController.removeObjects.apply(this.todoListController,b)}},captureBeforeunload:{value:function(){this.save()}}})}}),define("4763f06","ui/composer/composer",{dependencies:["montage"],factory:function(a,b,c){var d=a("montage").Montage;b.Composer=d.create(d,{_component:{value:null},component:{get:function(){return this._component},set:function(a){this._component=a}},_element:{value:null},element:{get:function(){return this._element},set:function(a){this._element=a}},lazyLoad:{value:!1},_needsFrame:{value:!1},needsFrame:{set:function(a){this._needsFrame!==a&&(this._needsFrame=a,this._component&&a&&this._component.scheduleComposer(this))},get:function(){return this._needsFrame}},frame:{value:function(a){}},_resolveDefaults:{value:function(){this.element==null&&this.component!=null&&(this.element=this.component.element)}},_load:{value:function(){this.element||this._resolveDefaults(),this.load()}},load:{value:function(){}},unload:{value:function(){}},deserializedFromTemplate:{value:function(){this.component&&this.component.addComposer(this)}}})}}),define("4763f06","core/converter/converter",{dependencies:["montage"],factory:function(a,b,c){var d=a("montage").Montage,e="[object Function]",f="[object Boolean]",g="[object Number]",h="[object String]",i="[object Array]",j="[object Date]",k=Object.prototype.toString,l=function(a){return k.call(a)===g};b.isNumber=l;var m=function(a){return a&&typeof a!="undefined"};b.isDef=m;var n=b.Validator=d.create(d,{validate:{value:null}}),o=b.Converter=d.create(d,{allowPartialConversion:{value:!0},convert:{enumerable:!1,value:null},revert:{enumerable:!1,value:null}})}}),define("1156f40","ui/main.reel/item-count-converter",{dependencies:["montage","montage/core/converter/converter"],factory:function(a,b,c){var d=a("montage").Montage,e=a("montage/core/converter/converter").Converter;b.ItemCountConverter=d.create(e,{convert:{value:function(a){return 1===a?"item":"items"}}})}})
bundleLoaded("bundle-1-0-ff282ac.js")
\ No newline at end of file
define("1156f40","ui/main.reel/main.html",{text:'<!doctype html>\n<html> <head> <meta http-equiv=Content-Type content="text/html; charset=utf-8">\n <title>Main</title>\n <link rel=stylesheet type="text/css" href=main.css>\n <script type="text/montage-serialization">{"owner":{"properties":{"element":{"#":"mainComponent"},"newTodoForm":{"#":"newTodoForm"},"newTodoInput":{"#":"new-todo"}}},"todoRepetition":{"prototype":"montage/ui/repetition.reel","properties":{"element":{"#":"todo-list"}},"bindings":{"contentController":{"<-":"@owner.todoListController"}}},"todoView":{"prototype":"ui/todo-view.reel","properties":{"element":{"#":"todoView"}},"bindings":{"todo":{"<-":"@todoRepetition.objectAtCurrentIteration"}}},"main":{"prototype":"montage/ui/dynamic-element.reel","properties":{"element":{"#":"main"}},"bindings":{"classList.visible":{"<-":"@owner.todoListController.organizedObjects.0"}}},"footer":{"prototype":"montage/ui/dynamic-element.reel","properties":{"element":{"#":"footer"}},"bindings":{"classList.visible":{"<-":"@owner.todoListController.organizedObjects.0"}}},"toggleAllCheckbox":{"prototype":"montage/ui/native/input-checkbox.reel","properties":{"element":{"#":"toggle-all"}},"bindings":{"checked":{"<->":"@owner.allCompleted"}}},"todoCount":{"prototype":"montage/ui/dynamic-text.reel","properties":{"element":{"#":"todo-count"}},"bindings":{"value":{"<-":"@owner.todosLeft.count()"}}},"itemCountConverter":{"prototype":"ui/main.reel/item-count-converter"},"todoCountWording":{"prototype":"montage/ui/dynamic-text.reel","properties":{"element":{"#":"todo-count-wording"}},"bindings":{"value":{"<-":"@owner.todosLeft.count()","converter":{"@":"itemCountConverter"}}}},"completedCount":{"prototype":"montage/ui/dynamic-text.reel","properties":{"element":{"#":"completed-count"}},"bindings":{"value":{"<-":"@owner.completedTodos.count()"}}},"clearCompletedContainer":{"prototype":"montage/ui/dynamic-element.reel","properties":{"element":{"#":"clear-completed-container"}},"bindings":{"classList.visible":{"<-":"@owner.completedTodos.count()"}}},"clearCompletedButton":{"prototype":"montage/ui/native/button.reel","properties":{"element":{"#":"clear-completed"}},"listeners":[{"type":"action","listener":{"@":"owner"},"capture":false}]}}</script>\n</head>\n <body> <div data-montage-id=mainComponent> <section id=todoapp> <header id=header> <h1>todos</h1>\n <form data-montage-id=newTodoForm> <input data-montage-id=new-todo id=new-todo placeholder="What needs to be done?" autofocus=autofocus>\n</form>\n</header>\n <section data-montage-id=main id=main> <input data-montage-id=toggle-all id=toggle-all type=checkbox>\n <label for=toggle-all>Mark all as complete</label>\n <ul data-montage-id=todo-list id=todo-list> <li data-montage-id=todoView></li>\n</ul>\n</section>\n <footer data-montage-id=footer id=footer> <span id=todo-count>\n <strong data-montage-id=todo-count>0</strong>\n <span data-montage-id=todo-count-wording>items</span>\n left</span>\n <div data-montage-id=clear-completed-container id=clear-completed-container> <button data-montage-id=clear-completed id=clear-completed>Clear completed ( <span data-montage-id=completed-count>0</span>\n)</button>\n</div>\n</footer>\n</section>\n <footer id=info> <p>Double-click to edit a todo</p>\n <p>Created with <a href="http://github.com/motorola-mobility/montage">Montage</a>\n</p>\n <p>Source available at <a href="http://github.com/mczepiel/montage-todomvc">Montage-TodoMVC</a>\n</p>\n <p>Part of <a href="http://todomvc.com">TodoMVC</a>\n </p>\n</footer>\n</div>\n</body>\n</html>'}),define("4763f06","ui/native/button.reel/button",{dependencies:["montage","ui/component","ui/native-control","ui/composer/press-composer"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/native-control").NativeControl,g=a("ui/composer/press-composer").PressComposer,h=b.Button=d.create(f,{_preventFocus:{enumerable:!1,value:!1},preventFocus:{get:function(){return this._preventFocus},set:function(a){a===!0?this._preventFocus=!0:this._preventFocus=!1}},enabled:{dependencies:["disabled"],get:function(){return!this._disabled},set:function(a){this.disabled=!a}},converter:{value:null},_labelNode:{value:undefined,enumerable:!1},_label:{value:undefined,enumerable:!1},label:{get:function(){return this._label},set:function(a){if(a&&a.length>0&&this.converter)try{a=this.converter.convert(a),this.error&&(this.error=null)}catch(b){this.error=b}this._label=a,this._isInputElement&&(this._value=a),this.needsDraw=!0}},holdThreshold:{get:function(){return this._pressComposer.longPressThreshold},set:function(a){this._pressComposer.longPressThreshold=a}},_pressComposer:{enumberable:!1,value:null},_active:{enumerable:!1,value:!1},active:{get:function(){return this._active},set:function(a){this._active=a,this.needsDraw=!0}},blur:{value:function(){this._element.blur()}},focus:{value:function(){this._element.focus()}},didCreate:{value:function(){this._pressComposer=g.create(),this.addComposer(this._pressComposer)}},prepareForActivationEvents:{value:function(){this._pressComposer.addEventListener("pressStart",this,!1),this._pressComposer.addEventListener("press",this,!1),this._pressComposer.addEventListener("pressCancel",this,!1)}},addEventListener:{value:function(a,b,c){f.addEventListener.call(this,a,b,c),a==="hold"&&this._pressComposer.addEventListener("longPress",this,!1)}},handlePressStart:{value:function(a){this.active=!0,a.preventDefault(),this._preventFocus||this._element.focus()}},handlePress:{value:function(a){this.active=!1,this._dispatchActionEvent()}},handleKeyup:{value:function(a){a.keyCode===32&&(this.active=!1,this._dispatchActionEvent())}},handleLongPress:{value:function(a){this._pressComposer.cancelPress();var b=document.createEvent("CustomEvent");b.initCustomEvent("hold",!0,!0,null),this.dispatchEvent(b)}},handlePressCancel:{value:function(a){this.active=!1}},_isInputElement:{value:!1,enumerable:!1},didSetElement:{value:function(){f.didSetElement.call(this),this._element.setAttribute("role","button"),this._isInputElement=this._element.tagName==="INPUT",this._isInputElement?(Object.defineProperty(this,"value",{get:function(){return this._label},set:function(a){this.label=a}}),this._label===undefined&&(this._label=this._element.value)):(this._element.firstChild||this._element.appendChild(document.createTextNode("")),this._labelNode=this._element.firstChild,this._label===undefined&&(this._label=this._labelNode.data)),this.needsDraw=!0}},prepareForDraw:{value:function(){this._element.addEventListener("keyup",this,!1)}},_drawLabel:{enumerable:!1,value:function(a){this._isInputElement?this._element.setAttribute("value",a):this._labelNode.data=a}},draw:{value:function(){Object.getPrototypeOf(h).draw.call(this),this._disabled?this._element.classList.add("disabled"):this._element.classList.remove("disabled"),this._active?this._element.classList.add("active"):this._element.classList.remove("active"),this._drawLabel(this.label)}}});h.addAttributes({autofocus:{value:!1,dataType:"boolean"},disabled:{value:!1,dataType:"boolean"},form:null,formaction:null,formenctype:null,formmethod:null,formnovalidate:{dataType:"boolean"},formtarget:null,type:{value:"button"},name:null,value:null})}}),define("4763f06","ui/native-control",{dependencies:["montage","ui/component"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=b.NativeControl=d.create(e,{hasTemplate:{value:!1},element:{get:function(){return this._element},set:function(a){Object.getPropertyDescriptor(e,"element").set.call(this,a),a&&this.didSetElement()}},_elementAttributeValues:{value:{},distinct:!0},_elementAttributeDescriptors:{value:{},distinct:!0},_getElementAttributeDescriptor:{value:function(a){var b,c=this;while(c&&typeof c._elementAttributeDescriptors!="undefined"){b=c._elementAttributeDescriptors[a];if(b)break;c=Object.getPrototypeOf(c)}return b}},defineAttribute:{value:function(a,b){b=b||{};var c="_"+a,e={configurable:typeof b.configurable=="undefined"?!0:b.configurable,enumerable:typeof b.enumerable=="undefined"?!0:b.enumerable,set:function(a,b){return function(c){var d=this._getElementAttributeDescriptor(a,this);d&&"boolean"===d.dataType&&(c=c||c===""?!0:!1),typeof c!="undefined"&&this[b]!==c&&(this[b]=c,this._elementAttributeValues[a]=c,this.needsDraw=!0)}}(a,c),get:function(a,b){return function(){return this[b]}}(a,c)};d.defineProperty(this,c,{value:null}),d.defineProperty(this,a,e)}},addAttributes:{value:function(a){var b,c,d,e;this._elementAttributeDescriptors=a;for(d in a)a.hasOwnProperty(d)&&(e=a[d],e===null||String.isString(e)?(c={value:e,dataType:"string"},a[d]=c):c=e,typeof this[d]=="undefined"&&this.defineAttribute(d,c))}},didSetElement:{value:function(){var a=this.element.attributes||[],b=0,c=a.length,d,e,f,g,h;for(b=0;b<c;b++){d=a[b].name,e=a[b].value,g=this._getElementAttributeDescriptor(d,this);if(g||typeof this[d]!="undefined")if(typeof this._elementAttributeValues[d]=="undefined"){this._elementAttributeValues[d]=e;if(typeof this[d]=="undefined"||this[d]==null)this[d]=e}}h=this.element.textContent;if("textContent"in this&&h&&""!==h&&typeof this._elementAttributeValues.textContent=="undefined"){this._elementAttributeValues.textContent=h;if(typeof this.textContent=="undefined"||this.textContent===null)this.textContent=h}for(f in this._elementAttributeDescriptors){g=this._elementAttributeDescriptors[f];var i="_"+f;this[i]===null&&g!==null&&"value"in g&&(this[i]=this._elementAttributeDescriptors[f].value)}this.needsDraw=!0}},draw:{enumerable:!1,value:function(){var a=this.element,b;for(var c in this._elementAttributeValues)if(this._elementAttributeValues.hasOwnProperty(c)){var d=this[c];b=this._getElementAttributeDescriptor(c,this),b&&(b.dataType==="boolean"?d===!0?(a[c]=!0,a.setAttribute(c,c.toLowerCase())):(a[c]=!1,a.removeAttribute(c)):typeof d!="undefined"&&(c==="textContent"?a.textContent=d:a.setAttribute(c,d))),delete this._elementAttributeValues[c]}}}});f.addAttributes({accesskey:null,contenteditable:null,contextmenu:null,"class":null,dir:null,draggable:null,dropzone:null,hidden:{dataType:"boolean"},lang:null,spellcheck:null,style:null,tabindex:null,title:null})}}),define("1156f40","ui/todo-view.reel/todo-view",{dependencies:["montage","montage/ui/component"],factory:function(a,b,c){var d=a("montage").Montage,e=a("montage/ui/component").Component;b.TodoView=d.create(e,{todo:{value:null},editInput:{value:null},didCreate:{value:function(){Object.defineBinding(this,"isCompleted",{boundObject:this,boundObjectPropertyPath:"todo.completed",oneway:!0})}},prepareForDraw:{value:function(){this.element.addEventListener("dblclick",this,!1),this.element.addEventListener("blur",this,!0),this.element.addEventListener("submit",this,!1)}},captureDestroyButtonAction:{value:function(){this.dispatchDestroy()}},dispatchDestroy:{value:function(){this.dispatchEventNamed("destroyTodo",!0,!0,{todo:this.todo})}},handleDblclick:{value:function(a){this.isEditing=!0}},_isEditing:{value:!1},isEditing:{get:function(){return this._isEditing},set:function(a){if(a===this._isEditing)return;this._isEditing=a,this.needsDraw=!0}},_isCompleted:{value:!1},isCompleted:{get:function(){return this._isCompleted},set:function(a){if(a===this._isCompleted)return;this._isCompleted=a,this.needsDraw=!0}},captureBlur:{value:function(a){this.isEditing&&this.editInput.element===a.target&&this._submitTitle()}},handleSubmit:{value:function(a){this.isEditing&&(a.preventDefault(),this._submitTitle())}},_submitTitle:{value:function(){var a=this.editInput.value.trim();""===a?this.dispatchDestroy():this.todo.title=a,this.isEditing=!1}},draw:{value:function(){this.isEditing?(this.element.classList.add("editing"),this.editInput.element.select()):(this.element.classList.remove("editing"),this.editInput.element.blur()),this.isCompleted?this.element.classList.add("completed"):this.element.classList.remove("completed")}}})}}),define("1156f40","ui/todo-view.reel/todo-view.html",{text:'<!doctype html>\n<html> <head> <meta http-equiv=Content-Type content="text/html; charset=utf-8">\n <title>TodoView</title>\n <script type="text/montage-serialization">{"owner":{"properties":{"element":{"#":"todoView"},"editInput":{"@":"editInput"}}},"todoTitle":{"prototype":"montage/ui/dynamic-text.reel","properties":{"element":{"#":"todoTitle"}},"bindings":{"value":{"<-":"@owner.todo.title"}}},"todoCompletedCheckbox":{"prototype":"montage/ui/native/input-checkbox.reel","properties":{"element":{"#":"todoCompletedCheckbox"}},"bindings":{"checked":{"<->":"@owner.todo.completed"}}},"destroyButton":{"prototype":"montage/ui/native/button.reel","properties":{"element":{"#":"destroyButton"}},"listeners":[{"type":"action","listener":{"@":"owner"},"capture":true}]},"editInput":{"prototype":"montage/ui/native/input-text.reel","properties":{"element":{"#":"edit-input"}},"bindings":{"value":{"<-":"@owner.todo.title"}}}}</script>\n</head>\n <body> <li data-montage-id=todoView> <div class=view> <input data-montage-id=todoCompletedCheckbox class=toggle type=checkbox>\n <label data-montage-id=todoTitle></label>\n <button data-montage-id=destroyButton class=destroy></button>\n</div>\n <form data-montage-id=edit> <input data-montage-id=edit-input class=edit value="Rule the web">\n</form>\n</li>\n</body>\n</html>'}),define("4763f06","ui/controller/object-controller",{dependencies:["montage"],factory:function(a,b,c){var d=a("montage").Montage,e=b.ObjectController=d.create(d,{objectPrototype:{enumerable:!1,value:null},newObject:{enumerable:!1,value:function(){return this.objectPrototype.create()}},initWithContent:{value:function(a){return this.content=a,this}},content:{enumerable:!1,value:null}})}}),define("1156f40","core/todo",{dependencies:["montage"],factory:function(a,b,c){var d=a("montage").Montage;b.Todo=d.create(d,{initWithTitle:{value:function(a){return this.title=a,this}},title:{value:null},completed:{value:!1}})}})
bundleLoaded("bundle-1-1-67d5b5c.js")
\ No newline at end of file
define("4763f06","ui/controller/array-controller",{dependencies:["montage","ui/controller/object-controller","core/change-notification","ui/controller/array-controller"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/controller/object-controller").ObjectController,f=a("core/change-notification").ChangeNotification,g=b.ArrayController=d.create(e,{didCreate:{value:function(){var a=this;this.addPropertyChangeListener("selections",function(){var b=[];a._selections.forEach(function(a,c){a&&b.push(c)}),a.selectedIndexes=b}),this.addPropertyChangeListener("content",function(){a.selectedObjects=null,a.automaticallyOrganizeObjects&&a.organizeObjects()})}},_content:{value:null},content:{get:function(){return this._content},set:function(a){if(this._content===a)return;this._content=a}},delegate:{value:null},_organizedObjects:{distinct:!0,value:[]},organizedObjects:{get:function(){return this._organizedObjects}},automaticallyOrganizeObjects:{value:!0},_sortFunction:{value:null},sortFunction:{get:function(){return this._sortFunction},set:function(a){if(this._sortFunction===a)return;this._sortFunction=a,this.automaticallyOrganizeObjects&&this.organizeObjects()}},_filterFunction:{value:null},filterFunction:{get:function(){return this._filterFunction},set:function(a){if(this._filterFunction===a)return;this._filterFunction=a,this.automaticallyOrganizeObjects&&this.organizeObjects()}},_startIndex:{value:null},startIndex:{get:function(){return this._startIndex},set:function(a){if(this._startIndex===a)return;this._startIndex=a,this.automaticallyOrganizeObjects&&this.organizeObjects()}},_endIndex:{enumerable:!1,value:null},endIndex:{get:function(){return this._endIndex},set:function(a){if(this._endIndex===a)return;this._endIndex=a,this.automaticallyOrganizeObjects&&this.organizeObjects()}},_organizedObjectsIndexes:{value:null},_rangedOrganizedObjectsIndexes:{value:null},_selectedIndexes:{value:null},selectedIndexes:{get:function(){return this._selectedIndexes?this._selectedIndexes:this.selectedContentIndexes?this._selectedIndexes=this._convertIndexesFromContentToOrganized(this.selectedContentIndexes):null},set:function(a){if(this.selectedIndexes!==a){var b=a?this._convertIndexesFromOrganizedToContent(a):null,c=null;if(this.delegate&&typeof this.delegate.shouldChangeSelection=="function"){b&&(c=this.content.filter(function(a,c){return b.indexOf(c)>=0},this));if(this.delegate.shouldChangeSelection(this,c,this._selectedObjects)===!1)return}this.dispatchPropertyChange("selections","selectedContentIndexes","selectedObjects",function(){this._selectedIndexes=a,this._selectedContentIndexes=b,this._selectedObjects=null,this._selections=null})}}},_convertIndexesFromOrganizedToContent:{value:function(a){var b,c=[],d,e=a.length,f,g;d=this._rangedOrganizedObjectsIndexes?this._rangedOrganizedObjectsIndexes:this._organizedObjectsIndexes;if(d){g=d.length;for(b=0;b<e;b++)f=a[b],f<g&&f>=0&&(c[c.length]=d[f])}else for(b=0;b<e;b++)c[c.length]=a[b]+this.startIndex;return c.sort()}},_convertIndexesFromContentToOrganized:{value:function(a){var b,c=[],d,e=a.length,f;d=this._rangedOrganizedObjectsIndexes?this._rangedOrganizedObjectsIndexes:this._organizedObjectsIndexes;if(d)for(b=0;b<e;b++)f=a[b],f>=0&&(f=d.indexOf(f),f!==-1&&(c[c.length]=f));else for(b=0;b<e;b++)f=a[b]-this.startIndex,f>-1&&(this.endIndex==null||f<this.endIndex)&&(c[c.length]=f);return c.sort()}},organizeObjects:{value:function(){var a=this.content,b=this.filterFunction,c=this.sortFunction,d=0,e=0,f,g,h,i;a&&typeof b=="function"&&(f=[],a=a.filter(function(a){var c=b.call(this,a);return c&&(f[e]=d,e++),d++,c},this));if(typeof c=="function"){g=[],h=[],d=0;for(d=0;i=a[d];d++)i!==null&&typeof i=="object"?(i._montage_array_controller_index=d,h[d]=i):h[d]={_montage_array_controller_index:d,_montage_array_controller_value:i};h=h.sort(function(a,b){return a._montage_array_controller_value&&(a=a._montage_array_controller_value),b._montage_array_controller_value&&(b=b._montage_array_controller_value),c.call(this,a,b)}),a=[];for(d=0;i=h[d];d++)e=i._montage_array_controller_index,g[d]=f?f[e]:e,i._montage_array_controller_value?a[d]=i._montage_array_controller_value:(a[d]=i,delete i._montage_array_controller_index);this._organizedObjectsIndexes=g}else this._organizedObjectsIndexes=f;this._applyRangeIfNeeded(a)}},_applyRangeIfNeeded:{value:function(a){var b=this.startIndex,c=this.endIndex;a&&(typeof b=="number"||typeof c=="number")&&(b=typeof b=="number"&&b>=0?b:0,c=typeof c=="number"&&c<a.length?c:a.length,a=a.slice(b,c),this._organizedObjectsIndexes?this._rangedOrganizedObjectsIndexes=this._organizedObjectsIndexes.slice(b,c):this._rangedOrganizedObjectsIndexes=null),this.dispatchPropertyChange("organizedObjects",function(){this._organizedObjects=a?a:[]})}},_selectedObjects:{value:null},selectedObjects:{get:function(){return this._selectedObjects?this._selectedObjects:this._selectedContentIndexes?(this.content&&(this._selectedObjects=this.content.filter(function(a,b){return this._selectedContentIndexes.indexOf(b)>=0},this)),this._selectedObjects):null},set:function(a){a===null||typeof a=="undefined"?a=null:Array.isArray(a)||(a=[a]);if(this.selectedObjects===a)return;if(this.delegate&&typeof this.delegate.shouldChangeSelection=="function"&&this.delegate.shouldChangeSelection(this,a,this._selectedObjects)===!1)return;this.dispatchPropertyChange("selections","selectedContentIndexes","selectedIndexes",function(){this._selectedObjects=a,this._selectedContentIndexes=null,this._selectedIndexes=null,this._selections=null})}},_selectedContentIndexes:{value:null},selectedContentIndexes:{get:function(){if(this._selectedContentIndexes)return this._selectedContentIndexes;if(!this._selectedObjects)return null;this._selectedContentIndexes=[];var a;return this._selectedObjects.forEach(function(b){(a=this.content.indexOf(b))!==-1&&this._selectedContentIndexes.push(a)},this),this._selectedContentIndexes},set:function(a){a===null||a===!1||typeof a=="undefined"?a=null:Array.isArray(a)||(a=[a]);if(this.selectedContentIndexes===a)return;if(this.delegate&&typeof this.delegate.shouldChangeSelection=="function"){var b=a,c=null;b&&(c=this.content.filter(function(a,c){return b.indexOf(c)>=0},this));if(this.delegate.shouldChangeSelection(this,c,this._selectedObjects)===!1)return}this._selectedContentIndexes=a,this.dispatchPropertyChange("selections","selectedIndexes","selectedObjects",function(){this._selectedIndexes=null,this._selectedObjects=null,this._selections=null})}},_selections:{value:null},selections:{get:function(){if(!this._selections){this._selections=new Array(this._organizedObjects.length);if(this.selectedIndexes){var a=this._selections,b=this.selectedIndexes,c=b.length,d,e;for(d=0;d<c;d++)e=b[d],e<a.length&&(a[e]=!0)}}return this._selections}},initWithContent:{value:function(a){return this.content=a,this}},selectObjectsOnAddition:{value:!1},clearFilterFunctionOnAddition:{value:!0},add:{value:function(){var a=this.newObject();this.content.push(a),this.selectObjectsOnAddition&&(this.selectedContentIndexes=[this.content.length-1]),this.clearFilterFunctionOnAddition&&(this.filterFunction=null),this.automaticallyOrganizeObjects&&this.organizeObjects()}},addObjects:{value:function(){var a=Array.prototype.slice.call(arguments),b,c=a.length,d,e,f=this.content;f?f.push.apply(f,a):this.content=f=a;if(this.selectObjectsOnAddition){d=[],e=f.length-c;for(b=0;b<c;b++)d[b]=e++;this.selectedContentIndexes=d,this.selectedObjects=a}this.clearFilterFunctionOnAddition&&(this.filterFunction=null),this.automaticallyOrganizeObjects&&this.organizeObjects()}},remove:{value:function(){var a;return this.selectedObjects&&this.selectedObjects.length>0&&(a=this.removeObjects.apply(this,this.selectedObjects),this.automaticallyOrganizeObjects&&this.organizeObjects()),a}},removeObjects:{value:function(){var a=Array.prototype.slice.call(arguments),b;return b=this.content.filter(function(b){return a.indexOf(b)<0}),this.content=b,this.automaticallyOrganizeObjects&&this.organizeObjects(),a}},removeObjectsAtSelectedIndexes:{value:function(){return this.removeObjectsAtIndexes(this.selectedIndexes)}},removeObjectsAtIndexes:{value:function(a){var b,c;return a&&a.length>0&&(b=[],c=this.content.filter(function(c,d){return a.indexOf(d)<0?!0:(b.push(c),!1)}),this.content=c,this.automaticallyOrganizeObjects&&this.organizeObjects()),b}}})}}),define("4763f06","ui/dynamic-element.reel/dynamic-element",{dependencies:["montage","ui/component"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component;b.DynamicElement=d.create(e,{hasTemplate:{value:!1},_innerHTML:{value:null},_usingInnerHTML:{value:null},innerHTML:{get:function(){return this._innerHTML},set:function(a){this._usingInnerHTML=!0,this._innerHTML!==a&&(this._innerHTML=a,this.needsDraw=!0)}},defaultHTML:{value:""},_allowedTagNames:{value:null},allowedTagNames:{get:function(){return this._allowedTagNames},set:function(a){this._allowedTagNames!==a&&(this._allowedTagNames=a,this.needsDraw=!0)}},_classList:{value:null},_classListDirty:{value:!1},classList:{get:function(){if(this._classList===null){var a=this.element.className;this._classList=f.newWithComponent(this,a.length!==0?this.element.className.split(" "):null)}return this._classList}},_range:{value:null},prepareForDraw:{value:function(){var a=document.createRange();a.selectNodeContents(this.element),this._range=a}},_contentNode:{value:null},draw:{value:function(){var a=this.innerHTML||0===this.innerHTML?this.innerHTML:this.defaultHTML,b,c=this.allowedTagNames,d=this._range,e;this._usingInnerHTML&&(c!==null?(this._contentNode=null,d.deleteContents(),b=d.createContextualFragment(a),c.length!==0?e=b.querySelectorAll("*:not("+c.join("):not(")+")"):e=b.childNodes,e.length===0?(d.insertNode(b),d.endOffset===0&&d.selectNodeContents(this.element)):console.warn("Some Elements Not Allowed ",e)):(b=this._contentNode,b===null?(d.deleteContents(),this._contentNode=b=document.createTextNode(a),d.insertNode(b),d.endOffset===0&&d.selectNodeContents(this.element)):b.data=a)),this._classListDirty&&(this.classList.drawIntoComponent(),this._classListDirty=!1)}}});var f=d.create(d,{newWithComponent:{value:function(a,b){var c=f.create(),d,e=0;c._component=a,c._classes={};if(b!==null)while(d=b[e++])c.add(d);return c}},__dirty__:{value:!1},_component:{value:null},_classes:{value:null},_installCssClass:{value:function(a){this._classes[a]=!1,d.defineProperty(this,a,{get:function(){return this._classes[a]},set:function(b){b=!!b,b!==this._classes[a]&&(this._classes[a]=b,this._component._classListDirty=!0,this._component.needsDraw=!0)}})}},add:{value:function(a){this.undefinedSet(a,!0)}},remove:{value:function(a){this.undefinedSet(a,!1)}},toggle:{value:function(a){this.undefinedSet(a,!this.undefinedGet(a))}},contains:{value:function(a){return!!this._classes[a]}},undefinedGet:{value:function(a){return typeof this[a]=="undefined"&&this._installCssClass(a),this[a]}},undefinedSet:{value:function(a,b){typeof this[a]=="undefined"&&this._installCssClass(a),this[a]=b}},drawIntoComponent:{value:function(){var a=this._classes,b=this._component.element.classList,c;for(c in a)a.hasOwnProperty(c)&&(a[c]?b.add(c):b.remove(c))}}})}}),define("4763f06","ui/check-input",{dependencies:["montage","ui/component","ui/native-control","ui/composer/press-composer"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/native-control").NativeControl,g=a("ui/composer/press-composer").PressComposer,h=b.CheckInput=d.create(f,{blur:{value:function(){this._element.blur()}},focus:{value:function(){this._element.focus()}},draw:{value:function(){f.draw.call(this),this._element.setAttribute("aria-checked",this._checked)}},_pressComposer:{enumerable:!1,value:null},prepareForActivationEvents:{value:function(){var a=this._pressComposer=g.create();this.addComposer(a),a.addEventListener("pressStart",this,!1),a.addEventListener("press",this,!1)}},prepareForDraw:{enumerable:!1,value:function(){this._element.addEventListener("change",this)}},_fakeCheck:{enumerable:!1,value:function(){var a;this._element.checked=!this._element.checked,a=document.createEvent("HTMLEvents"),a.initEvent("change",!0,!0),this._element.dispatchEvent(a)}},_shouldFakeCheck:{enumerable:!1,value:!1},handlePressStart:{value:function(a){this._shouldFakeCheck=a.defaultPrevented}},handlePress:{value:function(a){this._shouldFakeCheck&&(this._shouldFakeCheck=!1,this._fakeCheck())}},handleChange:{enumerable:!1,value:function(a){if(!this._pressComposer||this._pressComposer.state!==g.CANCELLED)Object.getPropertyDescriptor(this,"checked").set.call(this,this.element.checked,!0),this._dispatchActionEvent()}}})}}),define("4763f06","ui/dynamic-text.reel/dynamic-text",{dependencies:["montage","ui/component"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component;b.DynamicText=d.create(e,{hasTemplate:{value:!1},_value:{value:null},value:{get:function(){return this._value},set:function(a){this._value!==a&&(this._value=a,this.needsDraw=!0)}},converter:{value:null},defaultValue:{value:""},_valueNode:{value:null},_RANGE:{value:document.createRange()},prepareForDraw:{value:function(){var a=this._RANGE;a.selectNodeContents(this.element),a.deleteContents(),this._valueNode=document.createTextNode(""),a.insertNode(this._valueNode)}},draw:{value:function(){var a=this._value,b=a||0===a?a:this.defaultValue;this.converter&&(b=this.converter.convert(b)),this._valueNode.data=b}}})}}),define("4763f06","ui/native/input-checkbox.reel/input-checkbox",{dependencies:["montage","ui/component","ui/check-input"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/check-input").CheckInput,g=b.InputCheckbox=d.create(f,{});g.addAttributes({autofocus:{value:!1,dataType:"boolean"},disabled:{value:!1,dataType:"boolean"},checked:{value:!1,dataType:"boolean"},form:null,name:null,readonly:{value:!1,dataType:"boolean"},title:null,value:{value:"on"}})}}),define("4763f06","ui/native/input-text.reel/input-text",{dependencies:["montage","ui/component","ui/text-input"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/text-input").TextInput,g=b.InputText=d.create(f,{select:{value:function(){this._element.select()}}})}})
bundleLoaded("bundle-1-2-1e5edb8.js")
\ No newline at end of file
define("4763f06","ui/repetition.reel/repetition",{dependencies:["montage","ui/component","ui/template","core/logger","core/gate","core/change-notification"],factory:function(a,b,c){var d=a("montage").Montage,e=a("ui/component").Component,f=a("ui/template").Template,g=a("core/logger").logger("repetition"),h=a("core/gate").Gate,i=a("core/change-notification").ChangeNotification,j=a("core/change-notification").PropertyChangeNotification,k=d.create(Object.prototype,{_repetition:{value:null},_fakeIndex:{value:null},_unusedIndexes:{value:null},initWithRepetition:{value:function(a){return this._repetition=a,this._fakeIndex=[],this._unusedIndexes=[],this}},automaticallyDispatchPropertyChangeListener:{value:function(){return!1}},undefinedGet:{value:function(a){if(this._repetition.objects)return this._repetition.objects[this._fakeIndex.indexOf(a)]}},0:{set:function(){throw'You cannot use a two-way binding on the "objectAtCurrentIteration" or "current" property.'},get:function(){if(this._repetition.objects)return this._repetition.objects[this._fakeIndex.indexOf("0")]}},addFakeObjectAtPosition:{value:function(a){var b;return this._unusedIndexes.length>0?b=this._unusedIndexes.pop():b=String(this._fakeIndex.length),this._fakeIndex.splice(a,0,b),b}},resetFakeObjects:{value:function(){var a=this._repetition.objects;this._fakeIndex.length=0;if(a)for(var b=0,c=a.length;b<c;b++)this._fakeIndex[b]=String(b)}},removeFakeObjectAtPosition:{value:function(a){var b;return this._unusedIndexes.unshift(this._fakeIndex.splice(a,1)[0]),this._unusedIndexes[0]}},_dispatchFakePropertyChange:{value:function(a,b){var c,d;c=i.getPropertyChangeDescriptor(this,a),c&&(d=Object.create(j),d.target=this,d.propertyPath=a,d.minus=b,d.plus=this.undefinedGet(a),b!==d.plus&&c.handleChange(d))}}}),l=b.Repetition=d.create(e,{hasTemplate:{value:!1},didCreate:{value:function(){this.addPropertyChangeListener("objects",this),this._fakeObjects=Object.create(k).initWithRepetition(this)}},clonesChildComponents:{value:!0},_emptyFunction:{value:function(){}},_updateItems:{value:function(a,b,c){var d=this._fakeObjects,e,f=a?a.length:0,g=b?b.length:0,h,i,j;h=Math.max(f,g),i=Math.min(f,g),j=g-f;for(var k=0;k<i;k++)d._dispatchFakePropertyChange(d._fakeIndex[c+k],a[c+k]);if(j>0){this._expectedChildComponentsCount+=(this._iterationChildComponentsCount||1)*j,this.canDrawGate.setField("iterationLoaded",!1);for(;k<h;k++)d.addFakeObjectAtPosition(c+k),this._addItem({index:c+k,insertionIndex:c+k})}else if(j<0){var l=c+i;for(;k<h;k++)e=d.removeFakeObjectAtPosition(l),d._dispatchFakePropertyChange(e,a[k]),this._deleteItem(l)}}},handleChange:{enumerable:!1,value:function(a){"objects"===a.currentPropertyPath&&this._isComponentExpanded&&this._updateItems(a.minus,a.plus,a.index||0)}},_fakeObjects:{value:null},_hasBeenDeserialized:{value:!1,enumerable:!1},_nextDeserializedItemIx:{enumerable:!1,value:0,distinct:!0},init:{enumerable:!1,value:function(){return this._items=[],this._itemsToAppend=[],this._nextDeserializedItemIx=0,this._itemsToRemove=[],this._deletedItems=[],this}},_contentController:{value:null},contentController:{get:function(){return this._contentController},set:function(a){if(this._contentController===a)return;this._contentController&&(Object.deleteBinding(this,"objects"),Object.deleteBinding(this,"selectedIndexes")),this._contentController=a;if(this._contentController){this._bindingDescriptors&&Object.deleteBinding(this,"objects");var b,c;b={boundObject:this._contentController,boundObjectPropertyPath:"organizedObjects",oneway:!0},c={boundObject:this._contentController,boundObjectPropertyPath:"selectedIndexes"},this._hasBeenDeserialized?(Object.defineBinding(this,"objects",b),Object.defineBinding(this,"selectedIndexes",c)):(this._controllerBindingsToInstall||(this._controllerBindingsToInstall={}),this._controllerBindingsToInstall.objects=b,this._controllerBindingsToInstall.selectedIndexes=c)}}},_objects:{enumerable:!1,value:null},_mappedObjects:{enumerable:!1,value:null},objects:{dependencies:["indexMap","indexMapEnabled"],enumerable:!1,get:function(){return!this.indexMap||!this.indexMapEnabled?this._objects:(this._objects&&!this._mappedObjects&&(this._mappedObjects=this.indexMap.map(function(a){return isNaN(a)?undefined:this._objects.getProperty(a)},this)),this._mappedObjects)},set:function(a){g.isDebug&&g.debug(this," set objects:",a?a.length:null,a,"same objects?",a===this._objects),this._mappedObjects=null,this._objects=a,this.contentController||(this.selectedIndexes=null)}},_isSelectionEnabled:{enumerable:!1,value:!1},isSelectionEnabled:{get:function(){return this._isSelectionEnabled},set:function(a){if(a===this._isSelectionEnabled)return;this._isSelectionEnabled=a,this._isComponentExpanded&&this._refreshSelectionTracking()}},_childLoadedCount:{enumerable:!1,value:0},_iterationChildComponentsCount:{enumerable:!1,value:null},_expectedChildComponentsCount:{enumerable:!1,value:null},_indexMap:{enumerable:!1,value:null},indexMap:{get:function(){return this._indexMap}},_indexMapEnabled:{enumerable:!1,value:!1},indexMapEnabled:{get:function(){return this._indexMapEnabled},set:function(a){if(a===this._indexMapEnabled)return;!this._indexMap&&a&&(this._indexMap=[]),this._indexMapEnabled=a,this.refreshIndexMap()}},_drawnIndexMap:{enumerable:!1,value:null},drawnIndexMap:{get:function(){return this._drawnIndexMap}},mapIndexToIndex:{value:function(a,b,c){this._indexMap||(this._indexMap=[]);if(b===this._indexMap[a]||!isNaN(b)&&this._indexMap.indexOf(b)>-1)return;this._indexMap[a]=b,this._indexMapAffectedIndexes[a]=!0,this._indexMapChanged=!0,(c||typeof c=="undefined")&&this.refreshIndexMap()}},clearIndexMap:{value:function(){this._indexMap.wipe()}},refreshIndexMap:{value:function(){var a=this._mappedObjects;this._mappedObjects=null,this._isComponentExpanded&&(this._updateItems(a,this.objects,0),this.needsDraw=!0)}},_indexMapChanged:{enumerable:!1,value:!1},_indexMapAffectedIndexes:{enumerable:!1,distinct:!0,value:{}},_dirtyIndexes:{enumerable:!1,distinct:!0,value:{}},_items:{enumerable:!1,value:[],distinct:!0},_itemsToAppend:{enumerable:!1,value:[],distinct:!0},_itemsToRemove:{enumerable:!1,value:[],distinct:!0},_deletedItems:{enumerable:!1,value:[],distinct:!0},_updatingItems:{value:!1},_refreshItems:{value:function(){if(this._updatingItems)return;this._updatingItems=!0;var a=this._objects?this._objects.length:0,b=this._items.length+this._itemsToAppend.length,c,d,e=this._addItem,f=this._deleteItem;this._objects&&this.indexMap&&this._indexMapEnabled&&(a=this.indexMap.length),c=a-b,0!==c&&(this.needsDraw=!0);if(c>0){this._expectedChildComponentsCount+=(this._iterationChildComponentsCount||1)*c,this.canDrawGate.setField("iterationLoaded",!1);for(d=0;d<c;d++)e.call(this)}else if(c<0)for(d=c;d<0;d++)f.call(this);this._updatingItems=!1}},_addItems:{value:function(a,b){var c=a.length;if(this._updatingItems)return;this._updatingItems=!0,this._expectedChildComponentsCount+=(this._iterationChildComponentsCount||1)*c,this.canDrawGate.setField("iterationLoaded",!1);for(var d=0;d<c;d++)this._addItem({index:b+d,insertionIndex:b+d});this._updatingItems=!1}},_addItem:{value:function(a){var b=this,c=this._items,d,e,f,g,h=this._itemsToAppend,i,j,k,l=b.canDrawGate,m;a||(a={}),i=h.push(a)-1,g=c.length+i;if("index"in a)for(m=0;m<i;m++){var n=h[m];n.index>=a.index&&n.index++}b._canDraw=!1,f=this._iterationChildComponentsCount,this._iterationTemplate.instantiateWithComponent(this,function(){if(f===0)++b._childLoadedCount===b._expectedChildComponentsCount&&(l.setField("iterationLoaded",!0),b.needsDraw=!0);else{d=b.childComponents,j=g*b._iterationChildComponentsCount,k=j+f;for(m=j;m<k;m++)e=d[m],e.needsDraw=!0,e.loadComponentTree(function(){++b._childLoadedCount===b._expectedChildComponentsCount&&(l.setField("iterationLoaded",!0),b.needsDraw=!0)})}})}},_deleteItem:{value:function(a){var b,c=a,d,e=this.childComponents,f=this._iterationChildComponentsCount,g=this._itemsToAppend,h=g.length,i=!1,j=0;for(var k=0;k<h;k++){var l=g[k];l.index>a?l.index--:l.index<a?j++:i=l.removed=!0}if(!i){if(this._items.length>0)c=a-j,b=this._items.splice(c,1)[0],b.removalIndex=c,this._itemsToRemove.push(b);else throw"BUG: _deleteItem was called on the repetition but no elements exist to be removed";this._removeIterationChildComponents(b.childComponentsIndex)}this.needsDraw=!0}},_removeIterationChildComponents:{value:function(a){var b=this.childComponents,c=this._iterationChildComponentsCount,d,e,f;if(c>0){d=b.splice(a,c),this._childLoadedCount-=c,this._expectedChildComponentsCount-=c;for(var g=0,h=d.length;g<h;g++)d[g].cleanupDeletedComponentTree(!0);e=this._items;for(var g=0;f=e[g];g++)f.childComponentsIndex>a&&(f.childComponentsIndex-=c);e=this._itemsToAppend;for(var g=0;f=e[g];g++)f.childComponentsIndex>a&&(f.childComponentsIndex-=c)}else this._childLoadedCount--,this._expectedChildComponentsCount--}},_iterationTemplate:{enumerable:!1,value:null},expandComponent:{value:function(a){this._updatingItems||this._setupIterationTemplate(),this._isComponentExpanded=!0,a&&a()}},templateDidDeserializeObject:{value:null},_setupIterationTemplate:{value:function(){var a=this._element,b=this.childComponents,c;this.setupIterationSerialization(),this.setupIterationDeserialization(),this._iterationChildComponentsCount=b.length,this._iterationChildCount=a.childNodes.length,this._iterationChildElementCount=a.children.length,this._iterationChildComponentsCount>0?(this._templateId=b[0]._suuid||b[0].uuid,this._iterationTemplate=f.templateWithComponent(this,this._templateDelegate)):(this._iterationTemplate=f.create(),this._iterationTemplate.delegate=this._templateDelegate,this._iterationTemplate.initWithComponent(this)),this._iterationTemplate.optimize(),this._removeOriginalContent=!0,g.isDebug&&g.debug(this._iterationTemplate.exportToString()),this.removeIterationSerialization();while(c=b.shift())c.needsDraw=!1;this.objects&&this.objects.length!==this._items.length&&this._updateItems([],this.objects,0)}},_templateDelegate:{value:{serializeObjectProperties:function(a,b){a.set("ownerComponent",b.ownerComponent,"reference")}}},templateDidLoad:{value:function(){var a=this._deserializedItem,b;if(a){b=a.element.childNodes,a.fragment=document.createDocumentFragment(),a.childComponentsIndex=this.childComponents.length-this._iterationChildComponentsCount;while(b.length>0)a.fragment.appendChild(b[0]);delete a.element}}},contentWillChange:{value:function(a){this._updatingItems=!0,this.reset()}},contentDidChange:{value:function(){this._updatingItems=!1,this._setupIterationTemplate()}},reset:{value:function(){this._items.wipe(),this._itemsToAppend.wipe(),this._nextDeserializedItemIx=0,this._itemsToRemove.wipe(),this._deletedItems.wipe()}},deserializedFromTemplate:{value:function(){this._isComponentExpanded&&this.setupIterationSerialization();var a=this._controllerBindingsToInstall,b;if(a){for(b in a)Object.defineBinding(this,b,a[b]);delete this._controllerBindingsToInstall}this._hasBeenDeserialized=!0}},canDraw:{value:function(){var a=this.canDrawGate.value,b,c,d=this.childComponents.length;if(a)for(c=0;c<d;c++)if(!this.childComponents[c].canDraw()){a=!1;break}return a}},prepareForDraw:{value:function(){this._refreshSelectionTracking()}},_selectedIndexesToDeselectOnDraw:{value:null},_selectedIndexes:{value:null},selectedIndexes:{get:function(){return this._selectedIndexes},set:function(a){this._selectedIndexes=a,this._markIndexesDirty(a),this._isComponentExpanded&&(this.needsDraw=!0)}},_activeIndexes:{value:null},activeIndexes:{get:function(){return this._activeIndexes},set:function(a){this._activeIndexes=a,this._markIndexesDirty(a),this._isComponentExpanded&&(this.needsDraw=!0)}},_markIndexesDirty:{value:function(a){if(a)for(var b=0,c=a.length;b<c;b++)this._dirtyIndexes[this._indexMap?this._indexMap.indexOf(a[b]):a[b]]=!0}},_refreshSelectionTracking:{value:function(){this.isSelectionEnabled?window.Touch?this.element.addEventListener("touchstart",this,!0):this.element.addEventListener("mousedown",this,!0):window.Touch?this.element.removeEventListener("touchstart",this,!0):this.element.removeEventListener("mousedown",this,!0)}},_itemIndexOfElement:{value:function(a){var b=a,c=null,d,e;if(b===this.element)return c;while(b&&b.parentNode!==this.element)b=b.parentNode;return b?(e=this.element.ownerDocument.createRange(),e.setStart(this.element,0),e.setEndAfter(b),d=this._iterationChildCount>1?1:0,c=(e.endOffset+d)/this._iterationChildCount-1,this.indexMap?this.indexMap[c]:c):null}},captureTouchstart:{value:function(a){if(this._selectionPointer||0===this._selectionPointer)return;this._observeSelectionPointer(a.changedTouches[0].identifier);var b=this._itemIndexOfElement(a.target);null!==b?this.activeIndexes=[b]:this._ignoreSelectionPointer()}},handleTouchend:{value:function(a){var b=0,c;while(b<a.changedTouches.length&&a.changedTouches[b].identifier!==this._selectionPointer)b++;b<a.changedTouches.length&&(this.eventManager.isPointerClaimedByComponent(this._selectionPointer,this)&&(c=this._itemIndexOfElement(a.target),null!==c&&(this.selectedIndexes=[c])),this._ignoreSelectionPointer())}},handleTouchcancel:{value:function(){this._ignoreSelectionPointer()}},captureMousedown:{value:function(a){this._observeSelectionPointer("mouse");var b=this._itemIndexOfElement(a.target);null!==b?this.activeIndexes=[b]:this._ignoreSelectionPointer()}},handleMouseup:{value:function(a){var b=this._itemIndexOfElement(a.target);null!==b&&(this.selectedIndexes=[b]),this._ignoreSelectionPointer()}},surrenderPointer:{value:function(a,b){return this._ignoreSelectionPointer(),!0}},_selectionPointer:{value:null},_observeSelectionPointer:{value:function(a){this._selectionPointer=a,this.eventManager.claimPointer(a,this),window.Touch?(document.addEventListener("touchend",this,!1),document.addEventListener("touchcancel",this,!1)):document.addEventListener("mouseup",this,!1)}},_ignoreSelectionPointer:{value:function(){this.eventManager.forfeitPointer(this._selectionPointer,this),this._selectionPointer=null,this.activeIndexes=[],window.Touch?(document.removeEventListener("touchend",this,!1),document.removeEventListener("touchcancel",this,!1)):document.removeEventListener("mouseup",this,!1)}},_iterationChildCount:{value:null},_iterationChildElementCount:{value:null},draw:{value:function(){var a,b,c,d,e=this._items.length,f,g=this.element,h=g.ownerDocument,i,j,k,l,m,n,o,p,q=this._indexMapChanged,r,s,t=this._iterationChildCount,u;if(!this.canDrawGate.value)return;this._removeOriginalContent&&(this._removeOriginalContent=!1,g.innerHTML="");if(1===this._iterationChildElementCount){k=g.children;for(a=0;a<k.length;a++)o=k.item(a),o&&this._dirtyIndexes[a]&&(p=o.classList,p.remove("active"),p.remove("selected"),p.remove("no-transition"),q&&this._indexMapAffectedIndexes[a]&&(p.add("no-transition"),this._dirtyIndexes[a]=!1))}q&&(this._indexMapAffectedIndexes.wipe(),this._indexMapChanged=!1,this.needsDraw=!0);var v;if(this._itemsToRemove.length>0){j=document.createRange();for(a=0;b=this._itemsToRemove[a];a++)v=b.removalIndex,j.setStart(g,v*t),j.setEnd(g,v*t+t),j.extractContents();this._itemsToRemove.wipe()}var w;if(this._itemsToAppend.length>0){for(a=0;b=this._itemsToAppend[a];a++){if(b.removed){this._removeIterationChildComponents(b.childComponentsIndex);continue}c=b.fragment,w=b.insertionIndex,delete b.fragment,delete b.insertionIndex,delete b.index,isNaN(w)?g.appendChild(c):g.insertBefore(c,g.childNodes[w*this._iterationChildCount]),this._items.splice(w,0,b)}e=this._items.length,this._itemsToAppend.wipe(),this._nextDeserializedItemIx=0}if(null!==this.selectedIndexes&&this.selectedIndexes.length>0&&1===this._iterationChildElementCount){k=g.children,i=this.selectedIndexes.length,l=Math.min(i,k.length);for(a=0;a<l;a++)s=this.indexMap?this.indexMap.indexOf(this.selectedIndexes[a]):this.selectedIndexes[a],o=k.item(s),o&&(o.classList.add("selected"),this._dirtyIndexes[s]=!0)}if(null!==this._activeIndexes&&this._activeIndexes.length>0&&1===this._iterationChildElementCount){k=this.element.children,m=this._activeIndexes.length,n=Math.min(m,k.length);for(a=0;a<n;a++)r=this.indexMap?this.indexMap.indexOf(this._activeIndexes[a]):this._activeIndexes[a],o=k.item(r),o&&(o.classList.add("active"),this._dirtyIndexes[r]=!0)}this._drawnIndexMap=this._indexMap?this.indexMap.slice(0):null}},setupIterationSerialization:{value:function(){d.defineProperty(this,"serializeSelf",{value:this.serializeIteration})}},setupIterationDeserialization:{value:function(){this.deserializeProperties=this.deserializeIteration}},removeIterationSerialization:{value:function(){delete this.serializeSelf}},propertyChangeBindingListener:{value:function(a,b,c,d,e,f,g){var h=g,i=a,j,k,l,m,n,o;if(g&&g.boundObjectPropertyPath.match(/objectAtCurrentIteration/)){if(!this._deserializedItem)return null;k=this._fakeObjects._fakeIndex[this._deserializedItem.index],h={},l=Object.keys(g),m=l.length;for(var p=0;p<m;p++)n=l[p],h[n]=g[n];o=g.boundObjectPropertyPath.replace(/objectAtCurrentIteration/,"_fakeObjects."+k),h.boundObjectPropertyPath=o,i=a.replace(/objectAtCurrentIteration/,"_fakeObjects."+k)}else if(g&&g.boundObjectPropertyPath.match(/selectionAtCurrentIteration/)){if(!this._deserializedItem)return null;k=this._fakeObjects._fakeIndex[this._deserializedItem.index],h={},l=Object.keys(g),m=l.length;for(var p=0;p<m;p++)n=l[p],h[n]=g[n];o=g.boundObjectPropertyPath.replace(/selectionAtCurrentIteration/,"contentController.selections."+k),h.boundObjectPropertyPath=o,i=a.replace(/selectionAtCurrentIteration/,"contentController.selections."+k)}return h.boundObject===this?Object.prototype.propertyChangeBindingListener.call(this,i,b,c,d,e,f,h):h.boundObject.propertyChangeBindingListener(i,b,c,d,e,f,h)}},serializeIteration:{value:function(a){a.setProperty("element",this.element);var b=this.childComponents,c=a.addObject,d,e=b.length;for(d=0;d<e;d++)c.call(a,b[d]);a.setProperty("_isComponentExpanded",!0)}},deserializeIteration:{value:function(a){var b=this._itemsToAppend[this._nextDeserializedItemIx++];b?(this._deserializedItem=b,b.element=a.get("element"),this.eventManager.registerEventHandlerForElement(this,b.element),g.debug&&g.debug(this._montage_metadata.objectName+":deserializeIteration","childNodes: ",b.element)):this._deserializedItem=null}}})}})
bundleLoaded("bundle-1-3-0070936.js")
\ No newline at end of file
var Montage = require("montage").Montage;
exports.Todo = Montage.create(Montage, {
initWithTitle: {
value: function(title) {
this.title = title;
return this;
}
},
title: {
value: null
},
completed: {
value: false
}
});
<!doctype html>
<html lang=en id=montage-todomvc> <head> <meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<title>Montage • TodoMVC</title>
<link rel=stylesheet href="../../../assets/base.css">
<link rel=stylesheet href="assets/app.css">
<script src=bundle-0-d67ccde.js data-montage="packages/montage@4763f06/" data-montage-hash=4763f06 data-application-hash=1156f40></script>
<script type="text/montage-serialization">{"owner":{"prototype":"montage/ui/loader.reel"}}</script>
</head>
<body></body>
</html>
\ No newline at end of file
var Montage = require("montage").Montage,
Converter = require("montage/core/converter/converter").Converter;
exports.ItemCountConverter = Montage.create(Converter, {
convert: {
value: function(itemCount) {
return (1 === itemCount) ? "item" : "items";
}
}
});
#main,
#footer,
#clear-completed-container {display: none;}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Main</title>
<link rel="stylesheet" type="text/css" href="main.css">
<script type="text/montage-serialization">
{
"owner": {
"properties": {
"element": {"#": "mainComponent"},
"newTodoForm": {"#": "newTodoForm"},
"newTodoInput": {"#": "new-todo"}
}
},
"todoRepetition": {
"prototype": "montage/ui/repetition.reel",
"properties": {
"element": {"#": "todo-list"}
},
"bindings": {
"contentController": {"<-": "@owner.todoListController"}
}
},
"todoView": {
"prototype": "ui/todo-view.reel",
"properties": {
"element": {"#": "todoView"}
},
"bindings": {
"todo": {"<-": "@todoRepetition.objectAtCurrentIteration"}
}
},
"main": {
"prototype": "montage/ui/dynamic-element.reel",
"properties": {
"element": {"#": "main"}
},
"bindings": {
"classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"}
}
},
"footer": {
"prototype": "montage/ui/dynamic-element.reel",
"properties": {
"element": {"#": "footer"}
},
"bindings": {
"classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"}
}
},
"toggleAllCheckbox": {
"prototype": "montage/ui/native/input-checkbox.reel",
"properties": {
"element": {"#": "toggle-all"}
},
"bindings": {
"checked": {"<->": "@owner.allCompleted"}
}
},
"todoCount": {
"prototype": "montage/ui/dynamic-text.reel",
"properties": {
"element": {"#": "todo-count"}
},
"bindings": {
"value": {"<-": "@owner.todosLeft.count()"}
}
},
"itemCountConverter": {
"prototype": "ui/main.reel/item-count-converter"
},
"todoCountWording": {
"prototype": "montage/ui/dynamic-text.reel",
"properties": {
"element": {"#": "todo-count-wording"}
},
"bindings": {
"value": {"<-": "@owner.todosLeft.count()", "converter": {"@": "itemCountConverter"}}
}
},
"completedCount": {
"prototype": "montage/ui/dynamic-text.reel",
"properties": {
"element": {"#": "completed-count"}
},
"bindings": {
"value": {"<-": "@owner.completedTodos.count()"}
}
},
"clearCompletedContainer": {
"prototype": "montage/ui/dynamic-element.reel",
"properties": {
"element": {"#": "clear-completed-container"}
},
"bindings": {
"classList.visible": {"<-": "@owner.completedTodos.count()"}
}
},
"clearCompletedButton": {
"prototype": "montage/ui/native/button.reel",
"properties": {
"element": {"#": "clear-completed"}
},
"listeners": [
{
"type": "action",
"listener": {"@": "owner"},
"capture": false
}
]
}
}
</script>
</head>
<body>
<div data-montage-id="mainComponent">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<form data-montage-id="newTodoForm">
<input data-montage-id="new-todo" id="new-todo" placeholder="What needs to be done?" autofocus>
</form>
</header>
<section data-montage-id="main" id="main">
<input data-montage-id="toggle-all" id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul data-montage-id="todo-list" id="todo-list">
<li data-montage-id="todoView"></li>
</ul>
</section>
<footer data-montage-id="footer" id="footer">
<span id="todo-count"><strong data-montage-id="todo-count">0</strong> <span data-montage-id="todo-count-wording">items</span> left</span>
<div data-montage-id="clear-completed-container" id="clear-completed-container">
<button data-montage-id="clear-completed" id="clear-completed">Clear completed (<span data-montage-id="completed-count">0</span>)</button>
</div>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created with <a href="http://github.com/motorola-mobility/montage">Montage</a> </p>
<p>Source available at <a href="http://github.com/mczepiel/montage-todomvc">Montage-TodoMVC</a> </p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
</body>
</html>
var Montage = require("montage").Montage,
Component = require("montage/ui/component").Component,
ArrayController = require("montage/ui/controller/array-controller").ArrayController,
Todo = require("core/todo").Todo,
Serializer = require("montage/core/serializer").Serializer,
Deserializer = require("montage/core/deserializer").Deserializer,
LOCAL_STORAGE_KEY = "todos-montage";
exports.Main = Montage.create(Component, {
newTodoForm: {
value: null
},
newTodoInput: {
value: null
},
todoListController: {
serializable: false,
value: null
},
didCreate: {
value: function() {
this.todoListController = ArrayController.create();
this.load();
}
},
load: {
value: function() {
if (localStorage) {
var todoSerialization = localStorage.getItem(LOCAL_STORAGE_KEY);
if (todoSerialization) {
var deserializer = Deserializer.create(),
self = this;
try {
deserializer.initWithStringAndRequire(todoSerialization, require).deserializeObject(function(todos) {
self.todoListController.initWithContent(todos);
}, require);
} catch(e) {
console.error("Could not load saved tasks.");
console.debug("Could not deserialize", todoSerialization);
console.log(e.stack);
}
}
}
}
},
save: {
value: function() {
if (localStorage) {
var todos = this.todoListController.content,
serializer = Serializer.create().initWithRequire(require);
localStorage.setItem(LOCAL_STORAGE_KEY, serializer.serializeObject(todos));
}
}
},
prepareForDraw: {
value: function() {
this.newTodoForm.identifier = "newTodoForm";
this.newTodoForm.addEventListener("submit", this, false);
this.addEventListener("destroyTodo", this, true);
window.addEventListener("beforeunload", this, true);
}
},
captureDestroyTodo: {
value: function(evt) {
this.destroyTodo(evt.detail.todo);
}
},
handleNewTodoFormSubmit: {
value: function(evt) {
evt.preventDefault();
var title = this.newTodoInput.value.trim();
if ("" === title) {
return;
}
this.createTodo(title);
this.newTodoInput.value = null;
}
},
createTodo: {
value: function(title) {
var todo = Todo.create().initWithTitle(title);
this.todoListController.addObjects(todo);
return todo;
}
},
destroyTodo: {
value: function(todo) {
this.todoListController.removeObjects(todo);
return todo;
}
},
allCompleted: {
dependencies: ["todoListController.organizedObjects.completed"],
get: function() {
return this.todoListController.organizedObjects.getProperty("completed").all();
},
set: function(value) {
this.todoListController.organizedObjects.forEach(function(member) {
member.completed = value;
});
}
},
todosLeft: {
dependencies: ["todoListController.organizedObjects.completed"],
get: function() {
if (this.todoListController.organizedObjects) {
var todos = this.todoListController.organizedObjects;
return todos.filter(function(member) {
return !member.completed;
});
}
}
},
completedTodos: {
dependencies: ["todoListController.organizedObjects.completed"],
get: function() {
if (this.todoListController.organizedObjects) {
var todos = this.todoListController.organizedObjects;
return todos.filter(function(member) {
return member.completed;
});
}
}
},
handleClearCompletedButtonAction: {
value: function(evt) {
var completedTodos = this.todoListController.organizedObjects.filter(function(todo) {
return todo.completed;
});
if (completedTodos.length > 0) {
this.todoListController.removeObjects.apply(this.todoListController, completedTodos);
}
}
},
captureBeforeunload: {
value: function() {
this.save();
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TodoView</title>
<script type="text/montage-serialization">
{
"owner": {
"properties": {
"element": {"#": "todoView"},
"editInput": {"@": "editInput"}
}
},
"todoTitle": {
"prototype": "montage/ui/dynamic-text.reel",
"properties": {
"element": {"#": "todoTitle"}
},
"bindings": {
"value": {"<-": "@owner.todo.title"}
}
},
"todoCompletedCheckbox": {
"prototype": "montage/ui/native/input-checkbox.reel",
"properties": {
"element": {"#": "todoCompletedCheckbox"}
},
"bindings": {
"checked": {"<->": "@owner.todo.completed"}
}
},
"destroyButton": {
"prototype": "montage/ui/native/button.reel",
"properties": {
"element": {"#": "destroyButton"}
},
"listeners": [
{
"type": "action",
"listener": {"@": "owner"},
"capture": true
}
]
},
"editInput": {
"prototype": "montage/ui/native/input-text.reel",
"properties": {
"element": {"#": "edit-input"}
},
"bindings": {
"value": {"<-": "@owner.todo.title"}
}
}
}
</script>
</head>
<body>
<li data-montage-id="todoView">
<div class="view">
<input data-montage-id="todoCompletedCheckbox" class="toggle" type="checkbox">
<label data-montage-id="todoTitle"></label>
<button data-montage-id="destroyButton" class="destroy"></button>
</div>
<form data-montage-id="edit">
<input data-montage-id="edit-input" class="edit" value="Rule the web">
</form>
</li>
</body>
</html>
var Montage = require("montage").Montage,
Component = require("montage/ui/component").Component;
exports.TodoView = Montage.create(Component, {
todo: {
value: null
},
editInput: {
value: null
},
didCreate: {
value: function() {
Object.defineBinding(this, "isCompleted", {
boundObject: this,
boundObjectPropertyPath: "todo.completed",
oneway: true
});
}
},
prepareForDraw: {
value: function() {
this.element.addEventListener("dblclick", this, false);
this.element.addEventListener("blur", this, true);
this.element.addEventListener("submit", this, false);
}
},
captureDestroyButtonAction: {
value: function() {
this.dispatchDestroy();
}
},
dispatchDestroy: {
value: function() {
this.dispatchEventNamed("destroyTodo", true, true, {todo: this.todo})
}
},
handleDblclick: {
value: function(evt) {
this.isEditing = true;
}
},
_isEditing: {
value: false
},
isEditing: {
get: function() {
return this._isEditing;
},
set: function(value) {
if (value === this._isEditing) {
return;
}
this._isEditing = value;
this.needsDraw = true;
}
},
_isCompleted: {
value: false
},
isCompleted: {
get: function() {
return this._isCompleted;
},
set: function(value) {
if (value === this._isCompleted) {
return;
}
this._isCompleted = value;
this.needsDraw = true;
}
},
captureBlur: {
value: function(evt) {
if (this.isEditing && this.editInput.element === evt.target) {
this._submitTitle();
}
}
},
handleSubmit: {
value: function(evt) {
if (this.isEditing) {
evt.preventDefault();
this._submitTitle();
}
}
},
_submitTitle: {
value: function() {
var title = this.editInput.value.trim();
if ("" === title) {
this.dispatchDestroy();
} else {
this.todo.title = title;
}
this.isEditing = false;
}
},
draw: {
value: function() {
if (this.isEditing) {
this.element.classList.add("editing");
this.editInput.element.select();
} else {
this.element.classList.remove("editing");
this.editInput.element.blur();
}
if (this.isCompleted) {
this.element.classList.add("completed");
} else {
this.element.classList.remove("completed");
}
}
}
});
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