From 3e6e853bd02decc37340919907044860bdb3e6c6 Mon Sep 17 00:00:00 2001 From: Stephen Sawchuk Date: Thu, 16 May 2013 11:52:56 -0400 Subject: [PATCH] add more helpful readmes and learn.json. --- .gitignore | 1 + CNAME | 1 - .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/agilityjs/index.html | 2 +- architecture-examples/agilityjs/readme.md | 33 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + .../angularjs-perf/index.html | 4 +- .../angularjs-perf/readme.md | 39 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/angularjs/index.html | 4 +- architecture-examples/angularjs/readme.md | 36 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/backbone/index.html | 2 +- architecture-examples/backbone/readme.md | 29 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/canjs/index.html | 50 +- architecture-examples/canjs/readme.md | 60 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/closure/index.html | 2 +- architecture-examples/closure/readme.md | 49 +- architecture-examples/dart/.bowerrc | 3 + architecture-examples/dart/bower.json | 7 + architecture-examples/dart/readme.md | 46 +- architecture-examples/dart/web/assets/base.js | 38 - architecture-examples/dart/web/assets/ie.js | 27 - .../todomvc-common}/base.css | 179 +- .../bower_components/todomvc-common/base.js | 182 + .../todomvc-common}/bg.png | Bin architecture-examples/dart/web/index.html | 9 +- architecture-examples/dojo/bower.json | 7 + .../bower_components/todomvc-common}/base.css | 181 +- .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common}/bg.png | Bin architecture-examples/dojo/index-1.7.html | 14 +- architecture-examples/dojo/index.html | 34 +- architecture-examples/dojo/readme.md | 55 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/emberjs/index.html | 156 +- architecture-examples/emberjs/readme.md | 31 + architecture-examples/gwt/bower.json | 7 + .../bower_components/todomvc-common}/base.css | 254 +- .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common}/bg.png | Bin architecture-examples/gwt/css/app.css | 8 +- architecture-examples/gwt/index.html | 28 +- architecture-examples/gwt/readme.md | 58 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/jquery/index.html | 96 +- architecture-examples/jquery/readme.md | 32 + architecture-examples/knockback/bower.json | 9 + .../backbone.localStorage.js | 217 + .../bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes architecture-examples/knockback/index.html | 15 +- architecture-examples/knockback/readme.md | 39 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/knockoutjs/index.html | 116 +- architecture-examples/knockoutjs/readme.md | 37 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/maria/index.html | 2 +- architecture-examples/maria/readme.md | 18 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + architecture-examples/spine/index.html | 2 +- architecture-examples/spine/readme.md | 48 +- architecture-examples/yui/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes architecture-examples/yui/index.html | 8 +- architecture-examples/yui/readme.md | 26 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + .../backbone_require/index.html | 2 +- .../backbone_require/readme.md | 29 + dependency-examples/emberjs_require/readme.md | 4 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + dependency-examples/flight/index.html | 54 +- dependency-examples/flight/readme.md | 19 + .../ariatemplates/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../ariatemplates/css/app.css | 215 - .../ariatemplates/index.html | 14 +- .../ariatemplates/readme.md | 27 + .../backbone.xmpp/bower.json | 11 + .../Strophe.js}/strophe.js | 680 +- .../bower_components/backbone/backbone.js | 1571 ++ .../bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/lodash/lodash.js | 5557 +++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../backbone.xmpp/index.html | 21 +- .../backbone.xmpp/{README.md => readme.md} | 0 .../backbone_marionette/README.md | 28 - .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + .../backbone_marionette/index.html | 156 +- .../backbone_marionette/readme.md | 35 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/architecture-examples/batman/index.html | 2 +- labs/architecture-examples/batman/readme.md | 41 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/architecture-examples/cujo/index.html | 2 +- labs/architecture-examples/derby/README.md | 31 - .../public/components/todomvc-common/base.css | 141 + .../public/components/todomvc-common/base.js | 144 + labs/architecture-examples/derby/readme.md | 65 + .../derby/views/todos/index.html | 2 +- labs/architecture-examples/dermis/README.md | 9 - labs/architecture-examples/dermis/bower.json | 9 + .../dermis/bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/requirejs/require.js | 2045 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/dermis/index.html | 15 +- labs/architecture-examples/dermis/readme.md | 26 + labs/architecture-examples/dijon/bower.json | 9 + .../handlebars.js/handlebars.js | 2201 ++ .../dijon/bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/dijon/index.html | 13 +- labs/architecture-examples/dijon/readme.md | 25 +- labs/architecture-examples/duel/.bowerrc | 3 + labs/architecture-examples/duel/bower.json | 7 + labs/architecture-examples/duel/readme.md | 48 +- .../src/main/resources/views/HomePage.duel | 8 +- .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../duel/src/main/webapp/css/styles.merge | 7 +- .../duel/src/main/webapp/js/scripts.merge | 3 + ...2117dcda6b1a71004e818c348c9de5fc80966a.css | 1 - ...86ce6c04dc2c3e1a7111b0000b1252c883d20c.js} | 11 +- ...64469b1882372019d07f8c1174b1d64507e56d.css | 1 + .../architecture-examples/duel/www/index.html | 10 +- labs/architecture-examples/epitome/bower.json | 8 + .../bower_components/epitome/Epitome-min.js | 1 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/epitome/index.html | 17 +- .../epitome/js/lib/Epitome-min.js | 1 - labs/architecture-examples/epitome/readme.md | 24 +- labs/architecture-examples/extjs/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/extjs/css/app.css | 244 +- labs/architecture-examples/extjs/index.html | 9 +- labs/architecture-examples/extjs/readme.md | 23 + .../extjs_deftjs/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../extjs_deftjs/css/app.css | 10 +- .../extjs_deftjs/index.html | 28 +- .../extjs_deftjs/{README.md => readme.md} | 27 +- labs/architecture-examples/kendo/bower.json | 8 + .../kendo/bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/kendo/index.html | 11 +- labs/architecture-examples/kendo/readme.md | 27 + .../bower.json | 9 + .../director/build/director.js | 712 + .../bower_components/knockout.js/knockout.js | 85 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../index.html | 121 +- .../js/lib/knockout.min.js | 86 - .../knockoutjs_classBindingProvider/readme.md | 37 +- labs/architecture-examples/meteor/.bowerrc | 3 + labs/architecture-examples/meteor/app.html | 6 +- labs/architecture-examples/meteor/bower.json | 8 + .../director/build/director.js | 712 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../meteor/client/lib/base.js | 7 - .../meteor/client/lib/director-1.1.3.min.js | 7 - .../meteor/client/lib/ie.js | 25 - labs/architecture-examples/meteor/readme.md | 62 +- labs/architecture-examples/montage/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/montage/index.html | 38 +- labs/architecture-examples/montage/readme.md | 48 +- labs/architecture-examples/o_O/bower.json | 8 + .../o_O/bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/o_O/index.html | 11 +- labs/architecture-examples/o_O/readme.md | 17 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/architecture-examples/olives/index.html | 2 +- labs/architecture-examples/olives/readme.md | 18 +- .../plastronjs/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../plastronjs/index.html | 10 +- .../plastronjs/readme.md | 61 +- labs/architecture-examples/puremvc/README.md | 23 - .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/architecture-examples/puremvc/index.html | 140 +- labs/architecture-examples/puremvc/readme.md | 39 + .../architecture-examples/rappidjs/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../rappidjs/css/app.css | 3 - .../architecture-examples/rappidjs/index.html | 28 +- labs/architecture-examples/rappidjs/readme.md | 24 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/architecture-examples/sammyjs/index.html | 2 +- labs/architecture-examples/sammyjs/readme.md | 35 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + .../serenadejs/index.html | 2 +- .../serenadejs/readme.md | 30 +- .../socketstream/README.md | 12 - .../client/code/libs/todomvc-common/base.css | 141 + .../client/code/libs/todomvc-common/base.js | 144 + .../socketstream/client/views/app.html | 2 +- .../socketstream/package.json | 5 +- .../socketstream/readme.md | 37 + labs/architecture-examples/somajs/bower.json | 9 + .../handlebars.js/handlebars.js | 2201 ++ .../somajs/bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/somajs/index.html | 13 +- labs/architecture-examples/somajs/readme.md | 31 +- labs/architecture-examples/stapes/bower.json | 10 + .../handlebars.js/handlebars.js | 2201 ++ .../stapes/bower_components/jquery/jquery.js | 8755 +++++++ .../stapes/bower_components/stapes/stapes.js | 388 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes labs/architecture-examples/stapes/index.html | 14 +- .../stapes/js/lib/stapes.js | 24 - labs/architecture-examples/stapes/readme.md | 18 + labs/architecture-examples/thorax/bower.json | 8 + .../bower_components}/backbone/backbone.js | 0 .../handlebars.js/handlebars.js | 2239 ++ .../thorax/bower_components/jquery/jquery.js | 8755 +++++++ .../thorax/bower_components/thorax/thorax.js | 2670 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../underscore}/underscore.js | 733 +- labs/architecture-examples/thorax/index.html | 16 +- .../thorax/js/lib/thorax.js | 16884 ------------- .../thorax/{README.md => readme.md} | 36 +- .../typescript-angular/ReadMe.md | 64 - .../typescript-angular/bower.json | 8 + .../bower_components/angular/angular.js | 14733 +++++++++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../typescript-angular/index.html | 18 +- .../typescript-angular/readme.md | 83 + .../typescript-backbone/bower.json | 9 + .../bower_components/backbone/backbone.js | 1571 ++ .../bower_components/jquery/jquery.js | 8755 +++++++ .../bower_components/lodash/lodash.js | 5557 +++++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../typescript-backbone/index.html | 128 +- .../typescript-backbone/readme.md | 97 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + .../angularjs_require/index.html | 18 +- .../angularjs_require/readme.md | 36 + .../backbone_marionette_require/.jshintignore | 3 - .../backbone_marionette_require/app.build.js | 4 +- .../backbone_marionette_require/bower.json | 9 + .../bower_components/jquery/jquery.js | 9597 ++++++++ .../bower_components/requirejs/require.js | 2045 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../bower_components/underscore/underscore.js | 1226 + .../index-dev.html | 53 +- .../backbone_marionette_require/index.html | 53 +- .../js/lib/require.js | 35 - .../backbone_marionette_require/js/main.js | 4 +- .../backbone_marionette_require/r.js | 15483 ------------ .../backbone_marionette_require/readme.md | 35 + .../canjs_require/bower.json | 9 + .../bower_components/CanJS/amd/can.js | 9 + .../CanJS/amd/can/construct.js | 178 + .../CanJS/amd/can/construct/proxy.js | 68 + .../CanJS/amd/can/construct/super.js | 48 + .../bower_components/CanJS/amd/can/control.js | 270 + .../CanJS/amd/can/control/plugin.js | 108 + .../CanJS/amd/can/control/route.js | 36 + .../bower_components/CanJS/amd/can/model.js | 428 + .../bower_components/CanJS/amd/can/observe.js | 660 + .../CanJS/amd/can/observe/attributes.js | 160 + .../CanJS/amd/can/observe/backup.js | 45 + .../CanJS/amd/can/observe/compute.js | 220 + .../CanJS/amd/can/observe/delegate.js | 205 + .../CanJS/amd/can/observe/list.js | 106 + .../CanJS/amd/can/observe/setter.js | 59 + .../CanJS/amd/can/observe/validations.js | 197 + .../bower_components/CanJS/amd/can/route.js | 321 + .../CanJS/amd/can/util/array/each.js | 35 + .../CanJS/amd/can/util/can.js | 29 + .../CanJS/amd/can/util/deferred.js | 174 + .../CanJS/amd/can/util/dojo.js | 526 + .../CanJS/amd/can/util/event.js | 62 + .../CanJS/amd/can/util/fixture.js | 614 + .../CanJS/amd/can/util/fragment.js | 68 + .../CanJS/amd/can/util/hashchange.js | 27 + .../CanJS/amd/can/util/jquery.js | 73 + .../CanJS/amd}/can/util/library.js | 8 +- .../CanJS/amd/can/util/mootools.js | 362 + .../CanJS/amd/can/util/object.js | 133 + .../CanJS/amd/can/util/object/isplain.js | 40 + .../CanJS/amd/can/util/string.js | 130 + .../CanJS/amd/can/util/string/deparam.js | 61 + .../CanJS/amd/can/util/yui.js | 391 + .../CanJS/amd/can/util/zepto.js | 233 + .../bower_components/CanJS/amd/can/view.js | 409 + .../CanJS/amd/can/view/ejs.js | 99 + .../CanJS/amd/can/view/modifiers.js | 158 + .../CanJS/amd/can/view/mustache.js | 855 + .../CanJS/amd/can/view/render.js | 475 + .../CanJS/amd/can/view/scanner.js | 443 + .../bower_components/jquery/jquery.js | 9597 ++++++++ .../bower_components/requirejs/require.js | 2045 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../canjs_require/index.html | 31 +- .../canjs_require/js/app.js | 6 +- .../canjs_require/js/lib/can.js | 9 - .../canjs_require/js/lib/can/construct.js | 178 - .../js/lib/can/construct/proxy.js | 68 - .../js/lib/can/construct/super.js | 48 - .../canjs_require/js/lib/can/control.js | 270 - .../js/lib/can/control/plugin.js | 108 - .../canjs_require/js/lib/can/control/route.js | 36 - .../canjs_require/js/lib/can/model.js | 405 - .../canjs_require/js/lib/can/observe.js | 650 - .../js/lib/can/observe/attributes.js | 154 - .../js/lib/can/observe/backup.js | 45 - .../js/lib/can/observe/compute.js | 210 - .../js/lib/can/observe/delegate.js | 205 - .../canjs_require/js/lib/can/observe/list.js | 106 - .../js/lib/can/observe/setter.js | 59 - .../js/lib/can/observe/validations.js | 198 - .../canjs_require/js/lib/can/route.js | 315 - .../js/lib/can/util/array/each.js | 35 - .../canjs_require/js/lib/can/util/can.js | 20 - .../canjs_require/js/lib/can/util/deferred.js | 174 - .../canjs_require/js/lib/can/util/dojo.js | 526 - .../canjs_require/js/lib/can/util/event.js | 62 - .../canjs_require/js/lib/can/util/fixture.js | 603 - .../canjs_require/js/lib/can/util/fragment.js | 68 - .../canjs_require/js/lib/can/util/jquery.js | 63 - .../canjs_require/js/lib/can/util/mootools.js | 288 - .../canjs_require/js/lib/can/util/object.js | 133 - .../js/lib/can/util/object/extend.js | 75 - .../js/lib/can/util/object/isplain.js | 40 - .../canjs_require/js/lib/can/util/string.js | 130 - .../js/lib/can/util/string/deparam.js | 59 - .../canjs_require/js/lib/can/util/yui.js | 389 - .../canjs_require/js/lib/can/util/zepto.js | 233 - .../canjs_require/js/lib/can/view.js | 397 - .../canjs_require/js/lib/can/view/ejs.js | 99 - .../js/lib/can/view/modifiers.js | 158 - .../canjs_require/js/lib/can/view/mustache.js | 772 - .../canjs_require/js/lib/can/view/render.js | 457 - .../canjs_require/js/lib/can/view/scanner.js | 436 - .../canjs_require/readme.md | 95 +- .../chaplin-brunch/README.md | 15 - .../chaplin-brunch/app/assets/index.html | 4 +- .../chaplin-brunch/bower.json | 7 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../chaplin-brunch/public/index.html | 8 +- .../chaplin-brunch/readme.md | 60 + .../bower_components/todomvc-common/base.css | 147 +- .../bower_components/todomvc-common/base.js | 144 + .../enyo_backbone/index.html | 23 +- .../enyo_backbone/js/views/WindowView.js | 2 +- .../enyo_backbone/readme.md | 28 + .../knockoutjs_require/README.md | 3 - .../knockoutjs_require/bower.json | 9 + .../bower_components/knockout.js/knockout.js | 85 + .../bower_components/requirejs/require.js | 2045 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../knockoutjs_require/index.html | 32 +- .../js/libs/knockout-2.1.0.debug.js | 3443 --- .../js/libs/knockout-2.1.0.js | 86 - .../knockoutjs_require/js/main.js | 3 +- .../knockoutjs_require/readme.md | 36 + .../stapes_require/bower.json | 11 + .../handlebars.js/handlebars.js | 2201 ++ .../bower_components/requirejs/require.js | 2045 ++ .../bower_components/stapes/stapes.js | 388 + .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../bower_components/zepto/zepto.js | 1589 ++ .../stapes_require/index.html | 14 +- .../stapes_require/js/app.js | 15 +- .../js/controllers/todoController.js | 2 +- .../stapes_require/js/lib/.gitignore | 1 - .../stapes_require/js/lib/require.js | 33 - .../stapes_require/js/lib/stapes.js | 24 - .../stapes_require/js/lib/zepto.js | 2 - .../stapes_require/js/models/todoModel.js | 2 +- .../stapes_require/js/stores/todoStore.js | 2 +- .../stapes_require/js/views/todoView.js | 2 +- .../stapes_require/readme.md | 18 + .../thorax_lumbar/README.md | 9 - .../thorax_lumbar/bower.json | 10 + .../bower_components/backbone/backbone.js | 1533 ++ .../handlebars.js/handlebars.js | 2239 ++ .../bower_components/jquery/jquery.js | 8755 +++++++ .../lumbar-loader}/lumbar-loader-backbone.js | 5 +- .../lumbar-loader}/lumbar-loader-events.js | 3 +- .../lumbar-loader-localstorage.js | 6 +- .../lumbar-loader}/lumbar-loader-standard.js | 1 + .../lumbar-loader}/lumbar-loader.js | 3 +- .../script.js/dist}/script.js | 44 +- .../bower_components/thorax/thorax.js | 2670 ++ .../bower_components/todomvc-common/base.css | 555 + .../bower_components/todomvc-common/base.js | 182 + .../bower_components/todomvc-common/bg.png | Bin 0 -> 2126 bytes .../bower_components/underscore/underscore.js | 1226 + .../thorax_lumbar/lumbar.json | 154 +- .../thorax_lumbar/public/base.js | 20482 ++++++++-------- .../thorax_lumbar/public/index.html | 9 +- .../thorax_lumbar/public/todomvc.js | 10 +- .../thorax_lumbar/readme.md | 35 + .../thorax_lumbar/src/js/lib/thorax.js | 16884 ------------- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + labs/dependency-examples/troopjs/index.html | 2 +- labs/dependency-examples/troopjs/readme.md | 16 + learn.json | 1802 ++ learn.template.json | 59 + tasks/Gruntfile.js | 42 + tasks/package.json | 10 + .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 152 +- template/readme.md | 44 +- .../bower_components/todomvc-common/base.css | 141 + .../bower_components/todomvc-common/base.js | 144 + vanilla-examples/vanillajs/index.html | 2 +- vanilla-examples/vanillajs/readme.md | 5 + 489 files changed, 235152 insertions(+), 74636 deletions(-) delete mode 100644 CNAME create mode 100644 architecture-examples/agilityjs/readme.md create mode 100644 architecture-examples/angularjs/readme.md create mode 100644 architecture-examples/backbone/readme.md create mode 100644 architecture-examples/dart/.bowerrc create mode 100644 architecture-examples/dart/bower.json delete mode 100644 architecture-examples/dart/web/assets/base.js delete mode 100644 architecture-examples/dart/web/assets/ie.js rename architecture-examples/dart/web/{assets => bower_components/todomvc-common}/base.css (76%) create mode 100644 architecture-examples/dart/web/bower_components/todomvc-common/base.js rename architecture-examples/dart/web/{assets => bower_components/todomvc-common}/bg.png (100%) create mode 100644 architecture-examples/dojo/bower.json rename {labs/architecture-examples/meteor/client/css => architecture-examples/dojo/bower_components/todomvc-common}/base.css (76%) create mode 100644 architecture-examples/dojo/bower_components/todomvc-common/base.js rename {labs/architecture-examples/duel/src/main/webapp/css => architecture-examples/dojo/bower_components/todomvc-common}/bg.png (100%) create mode 100644 architecture-examples/emberjs/readme.md create mode 100644 architecture-examples/gwt/bower.json rename {labs/architecture-examples/duel/src/main/webapp/css => architecture-examples/gwt/bower_components/todomvc-common}/base.css (69%) create mode 100644 architecture-examples/gwt/bower_components/todomvc-common/base.js rename {labs/architecture-examples/meteor/client/images => architecture-examples/gwt/bower_components/todomvc-common}/bg.png (100%) create mode 100644 architecture-examples/jquery/readme.md create mode 100644 architecture-examples/knockback/bower.json create mode 100644 architecture-examples/knockback/bower_components/Backbone.localStorage/backbone.localStorage.js create mode 100644 architecture-examples/knockback/bower_components/jquery/jquery.js create mode 100644 architecture-examples/knockback/bower_components/todomvc-common/base.css create mode 100644 architecture-examples/knockback/bower_components/todomvc-common/base.js create mode 100644 architecture-examples/knockback/bower_components/todomvc-common/bg.png create mode 100644 architecture-examples/maria/readme.md create mode 100644 architecture-examples/yui/bower.json create mode 100644 architecture-examples/yui/bower_components/todomvc-common/base.css create mode 100644 architecture-examples/yui/bower_components/todomvc-common/base.js create mode 100644 architecture-examples/yui/bower_components/todomvc-common/bg.png create mode 100644 architecture-examples/yui/readme.md create mode 100644 dependency-examples/backbone_require/readme.md create mode 100644 dependency-examples/flight/readme.md create mode 100644 labs/architecture-examples/ariatemplates/bower.json create mode 100644 labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/ariatemplates/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/ariatemplates/css/app.css create mode 100644 labs/architecture-examples/ariatemplates/readme.md create mode 100644 labs/architecture-examples/backbone.xmpp/bower.json rename labs/architecture-examples/backbone.xmpp/{js/lib => bower_components/Strophe.js}/strophe.js (84%) create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/backbone/backbone.js create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/lodash/lodash.js create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/backbone.xmpp/bower_components/todomvc-common/bg.png rename labs/architecture-examples/backbone.xmpp/{README.md => readme.md} (100%) delete mode 100644 labs/architecture-examples/backbone_marionette/README.md create mode 100644 labs/architecture-examples/backbone_marionette/readme.md delete mode 100644 labs/architecture-examples/derby/README.md create mode 100644 labs/architecture-examples/derby/readme.md delete mode 100644 labs/architecture-examples/dermis/README.md create mode 100644 labs/architecture-examples/dermis/bower.json create mode 100644 labs/architecture-examples/dermis/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/dermis/bower_components/requirejs/require.js create mode 100644 labs/architecture-examples/dermis/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/dermis/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/dermis/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/dermis/readme.md create mode 100644 labs/architecture-examples/dijon/bower.json create mode 100644 labs/architecture-examples/dijon/bower_components/handlebars.js/handlebars.js create mode 100644 labs/architecture-examples/dijon/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/dijon/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/dijon/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/dijon/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/duel/.bowerrc create mode 100644 labs/architecture-examples/duel/bower.json create mode 100644 labs/architecture-examples/duel/src/main/webapp/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/duel/src/main/webapp/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/duel/src/main/webapp/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/duel/www/cdn/502117dcda6b1a71004e818c348c9de5fc80966a.css rename labs/architecture-examples/duel/www/cdn/{1de7392f10ea2465d68b839144090d158ba7730f.js => cb86ce6c04dc2c3e1a7111b0000b1252c883d20c.js} (71%) create mode 100644 labs/architecture-examples/duel/www/cdn/d764469b1882372019d07f8c1174b1d64507e56d.css create mode 100644 labs/architecture-examples/epitome/bower.json create mode 100644 labs/architecture-examples/epitome/bower_components/epitome/Epitome-min.js create mode 100644 labs/architecture-examples/epitome/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/epitome/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/epitome/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/epitome/js/lib/Epitome-min.js create mode 100644 labs/architecture-examples/extjs/bower.json create mode 100644 labs/architecture-examples/extjs/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/extjs/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/extjs/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/extjs/readme.md create mode 100644 labs/architecture-examples/extjs_deftjs/bower.json create mode 100644 labs/architecture-examples/extjs_deftjs/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/extjs_deftjs/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/extjs_deftjs/bower_components/todomvc-common/bg.png rename labs/architecture-examples/extjs_deftjs/{README.md => readme.md} (62%) create mode 100644 labs/architecture-examples/kendo/bower.json create mode 100644 labs/architecture-examples/kendo/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/kendo/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/kendo/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/kendo/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/kendo/readme.md create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower.json create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower_components/director/build/director.js create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower_components/knockout.js/knockout.js create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/knockoutjs_classBindingProvider/js/lib/knockout.min.js create mode 100644 labs/architecture-examples/meteor/.bowerrc create mode 100644 labs/architecture-examples/meteor/bower.json create mode 100644 labs/architecture-examples/meteor/client/bower_components/director/build/director.js create mode 100644 labs/architecture-examples/meteor/client/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/meteor/client/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/meteor/client/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/meteor/client/lib/base.js delete mode 100644 labs/architecture-examples/meteor/client/lib/director-1.1.3.min.js delete mode 100644 labs/architecture-examples/meteor/client/lib/ie.js create mode 100644 labs/architecture-examples/montage/bower.json create mode 100644 labs/architecture-examples/montage/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/montage/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/montage/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/o_O/bower.json create mode 100644 labs/architecture-examples/o_O/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/o_O/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/o_O/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/o_O/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/o_O/readme.md create mode 100644 labs/architecture-examples/plastronjs/bower.json create mode 100644 labs/architecture-examples/plastronjs/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/plastronjs/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/plastronjs/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/puremvc/README.md create mode 100644 labs/architecture-examples/puremvc/readme.md create mode 100644 labs/architecture-examples/rappidjs/bower.json create mode 100644 labs/architecture-examples/rappidjs/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/rappidjs/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/rappidjs/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/rappidjs/css/app.css create mode 100644 labs/architecture-examples/rappidjs/readme.md delete mode 100644 labs/architecture-examples/socketstream/README.md create mode 100644 labs/architecture-examples/socketstream/readme.md create mode 100644 labs/architecture-examples/somajs/bower.json create mode 100644 labs/architecture-examples/somajs/bower_components/handlebars.js/handlebars.js create mode 100644 labs/architecture-examples/somajs/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/somajs/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/somajs/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/somajs/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/stapes/bower.json create mode 100644 labs/architecture-examples/stapes/bower_components/handlebars.js/handlebars.js create mode 100644 labs/architecture-examples/stapes/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/stapes/bower_components/stapes/stapes.js create mode 100644 labs/architecture-examples/stapes/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/stapes/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/stapes/bower_components/todomvc-common/bg.png delete mode 100644 labs/architecture-examples/stapes/js/lib/stapes.js create mode 100644 labs/architecture-examples/stapes/readme.md create mode 100644 labs/architecture-examples/thorax/bower.json rename labs/architecture-examples/{typescript-backbone/js/libs => thorax/bower_components}/backbone/backbone.js (100%) create mode 100644 labs/architecture-examples/thorax/bower_components/handlebars.js/handlebars.js create mode 100644 labs/architecture-examples/thorax/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/thorax/bower_components/thorax/thorax.js create mode 100644 labs/architecture-examples/thorax/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/thorax/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/thorax/bower_components/todomvc-common/bg.png rename labs/{dependency-examples/backbone_marionette_require/js/lib => architecture-examples/thorax/bower_components/underscore}/underscore.js (61%) delete mode 100644 labs/architecture-examples/thorax/js/lib/thorax.js rename labs/architecture-examples/thorax/{README.md => readme.md} (53%) delete mode 100644 labs/architecture-examples/typescript-angular/ReadMe.md create mode 100644 labs/architecture-examples/typescript-angular/bower.json create mode 100644 labs/architecture-examples/typescript-angular/bower_components/angular/angular.js create mode 100644 labs/architecture-examples/typescript-angular/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/typescript-angular/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/typescript-angular/bower_components/todomvc-common/bg.png create mode 100644 labs/architecture-examples/typescript-angular/readme.md create mode 100644 labs/architecture-examples/typescript-backbone/bower.json create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/backbone/backbone.js create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/jquery/jquery.js create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/lodash/lodash.js create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/todomvc-common/base.css create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/todomvc-common/base.js create mode 100644 labs/architecture-examples/typescript-backbone/bower_components/todomvc-common/bg.png create mode 100644 labs/dependency-examples/angularjs_require/readme.md create mode 100644 labs/dependency-examples/backbone_marionette_require/bower.json create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/jquery/jquery.js create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/requirejs/require.js create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/todomvc-common/bg.png create mode 100644 labs/dependency-examples/backbone_marionette_require/bower_components/underscore/underscore.js delete mode 100644 labs/dependency-examples/backbone_marionette_require/js/lib/require.js delete mode 100644 labs/dependency-examples/backbone_marionette_require/r.js create mode 100644 labs/dependency-examples/backbone_marionette_require/readme.md create mode 100644 labs/dependency-examples/canjs_require/bower.json create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/construct.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/construct/proxy.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/construct/super.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/control.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/control/plugin.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/control/route.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/model.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/attributes.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/backup.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/compute.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/delegate.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/list.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/setter.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/observe/validations.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/route.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/array/each.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/can.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/deferred.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/dojo.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/event.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/fixture.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/fragment.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/hashchange.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/jquery.js rename labs/dependency-examples/canjs_require/{js/lib => bower_components/CanJS/amd}/can/util/library.js (52%) create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/mootools.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/object.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/object/isplain.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/string.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/string/deparam.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/yui.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/util/zepto.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view/ejs.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view/modifiers.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view/mustache.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view/render.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/CanJS/amd/can/view/scanner.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/jquery/jquery.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/requirejs/require.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/canjs_require/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/canjs_require/bower_components/todomvc-common/bg.png delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/construct.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/construct/proxy.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/construct/super.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/control.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/control/plugin.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/control/route.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/model.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/attributes.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/backup.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/compute.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/delegate.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/list.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/setter.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/observe/validations.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/route.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/array/each.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/can.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/deferred.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/dojo.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/event.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/fixture.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/fragment.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/jquery.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/mootools.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/object.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/object/extend.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/object/isplain.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/string.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/string/deparam.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/yui.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/util/zepto.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view/ejs.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view/modifiers.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view/mustache.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view/render.js delete mode 100644 labs/dependency-examples/canjs_require/js/lib/can/view/scanner.js delete mode 100644 labs/dependency-examples/chaplin-brunch/README.md create mode 100644 labs/dependency-examples/chaplin-brunch/bower.json create mode 100644 labs/dependency-examples/chaplin-brunch/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/chaplin-brunch/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/chaplin-brunch/bower_components/todomvc-common/bg.png create mode 100644 labs/dependency-examples/chaplin-brunch/readme.md create mode 100644 labs/dependency-examples/enyo_backbone/readme.md delete mode 100644 labs/dependency-examples/knockoutjs_require/README.md create mode 100644 labs/dependency-examples/knockoutjs_require/bower.json create mode 100644 labs/dependency-examples/knockoutjs_require/bower_components/knockout.js/knockout.js create mode 100644 labs/dependency-examples/knockoutjs_require/bower_components/requirejs/require.js create mode 100644 labs/dependency-examples/knockoutjs_require/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/knockoutjs_require/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/knockoutjs_require/bower_components/todomvc-common/bg.png delete mode 100644 labs/dependency-examples/knockoutjs_require/js/libs/knockout-2.1.0.debug.js delete mode 100644 labs/dependency-examples/knockoutjs_require/js/libs/knockout-2.1.0.js create mode 100644 labs/dependency-examples/knockoutjs_require/readme.md create mode 100644 labs/dependency-examples/stapes_require/bower.json create mode 100644 labs/dependency-examples/stapes_require/bower_components/handlebars.js/handlebars.js create mode 100644 labs/dependency-examples/stapes_require/bower_components/requirejs/require.js create mode 100644 labs/dependency-examples/stapes_require/bower_components/stapes/stapes.js create mode 100644 labs/dependency-examples/stapes_require/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/stapes_require/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/stapes_require/bower_components/todomvc-common/bg.png create mode 100644 labs/dependency-examples/stapes_require/bower_components/zepto/zepto.js delete mode 100644 labs/dependency-examples/stapes_require/js/lib/.gitignore delete mode 100644 labs/dependency-examples/stapes_require/js/lib/require.js delete mode 100644 labs/dependency-examples/stapes_require/js/lib/stapes.js delete mode 100644 labs/dependency-examples/stapes_require/js/lib/zepto.js create mode 100644 labs/dependency-examples/stapes_require/readme.md delete mode 100644 labs/dependency-examples/thorax_lumbar/README.md create mode 100644 labs/dependency-examples/thorax_lumbar/bower.json create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/backbone/backbone.js create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/handlebars.js/handlebars.js create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/jquery/jquery.js rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/lumbar-loader}/lumbar-loader-backbone.js (93%) rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/lumbar-loader}/lumbar-loader-events.js (94%) rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/lumbar-loader}/lumbar-loader-localstorage.js (89%) rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/lumbar-loader}/lumbar-loader-standard.js (95%) rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/lumbar-loader}/lumbar-loader.js (98%) rename labs/dependency-examples/thorax_lumbar/{src/js/lib => bower_components/script.js/dist}/script.js (74%) create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/thorax/thorax.js create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/todomvc-common/base.css create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/todomvc-common/base.js create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/todomvc-common/bg.png create mode 100644 labs/dependency-examples/thorax_lumbar/bower_components/underscore/underscore.js create mode 100644 labs/dependency-examples/thorax_lumbar/readme.md delete mode 100644 labs/dependency-examples/thorax_lumbar/src/js/lib/thorax.js create mode 100644 labs/dependency-examples/troopjs/readme.md create mode 100644 learn.json create mode 100644 learn.template.json create mode 100644 tasks/Gruntfile.js create mode 100644 tasks/package.json create mode 100644 vanilla-examples/vanillajs/readme.md diff --git a/.gitignore b/.gitignore index e43b0f9889..3a0553dc58 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +tasks/node_modules diff --git a/CNAME b/CNAME deleted file mode 100644 index f95c6169f4..0000000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -todomvc.com \ No newline at end of file diff --git a/architecture-examples/agilityjs/bower_components/todomvc-common/base.css b/architecture-examples/agilityjs/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/agilityjs/bower_components/todomvc-common/base.css +++ b/architecture-examples/agilityjs/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/agilityjs/bower_components/todomvc-common/base.js b/architecture-examples/agilityjs/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/agilityjs/bower_components/todomvc-common/base.js +++ b/architecture-examples/agilityjs/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + ''; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/agilityjs/index.html b/architecture-examples/agilityjs/index.html index 9a50134ada..ab14b90da7 100644 --- a/architecture-examples/agilityjs/index.html +++ b/architecture-examples/agilityjs/index.html @@ -1,5 +1,5 @@ - + diff --git a/architecture-examples/agilityjs/readme.md b/architecture-examples/agilityjs/readme.md new file mode 100644 index 0000000000..f434e7644e --- /dev/null +++ b/architecture-examples/agilityjs/readme.md @@ -0,0 +1,33 @@ +# Agility.js TodoMVC Example + +> [Agility.js](http://agilityjs.com) is an MVC library for Javascript that lets you write maintainable and reusable browser code without the verbose or 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 - agilityjs.com](http://agilityjs.com)_ + + +## Learning Agility.js + +The [Agility.js website](http://agilityjs.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Official Documentation](http://agilityjs.com/docs/docs.html) +* [Try it out on JSBin](http://jsbin.com/agility/224/edit) +* [Applications built with Agility.js](http://agilityjs.com/docs/gallery.html) + +Articles and guides from the community: + +* [Step by step from jQuery to Agility.js](https://gist.github.com/pindia/3166678) + +Get help from other Agility.js users: + +* [Google Groups mailing list](http://groups.google.com/group/agilityjs) +* [agility.js on Stack Overflow](http://stackoverflow.com/questions/tagged/agility.js) +* [Agility.js on Twitter](https://twitter.com/agilityjs) +* [Agility.js on Google +](https://plus.google.com/116251025970928820842/posts) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Credit +This TodoMVC application was created by [tshm](https://github.com/tshm). diff --git a/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.css b/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.css +++ b/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.js b/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.js +++ b/architecture-examples/angularjs-perf/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + ''; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/angularjs-perf/index.html b/architecture-examples/angularjs-perf/index.html index fbf7ca7e19..28fe6e5622 100644 --- a/architecture-examples/angularjs-perf/index.html +++ b/architecture-examples/angularjs-perf/index.html @@ -1,11 +1,11 @@ - + AngularJS • TodoMVC - +
diff --git a/architecture-examples/angularjs-perf/readme.md b/architecture-examples/angularjs-perf/readme.md index a554a323d8..fbc7dfe636 100644 --- a/architecture-examples/angularjs-perf/readme.md +++ b/architecture-examples/angularjs-perf/readme.md @@ -1,5 +1,42 @@ -# AngularJS (performance optimized) TodoMVC app +# AngularJS (Performance Optimized) TodoMVC Example +> HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop. + +> _[AngularJS - angularjs.com](http://angularjs.com)_ + + +## Learning AngularJS +The [AngularJS website](http://angularjs.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Tutorial](http://docs.angularjs.org/tutorial) +* [API Reference](http://docs.angularjs.org/api) +* [Developer Guide](http://docs.angularjs.org/guide) +* [Applications built with AngularJS](http://builtwith.angularjs.org) +* [Blog](http://blog.angularjs.org) +* [FAQ](http://docs.angularjs.org/misc/faq) +* [AngularJS Meetups](http://www.youtube.com/angularjs) + +Articles and guides from the community: + +* [Code School AngularJS course](http://www.codeschool.com/code_tv/angularjs-part-1) +* [5 Awesome AngularJS Features](http://net.tutsplus.com/tutorials/javascript-ajax/5-awesome-angularjs-features) +* [Using Yeoman with AngularJS](http://briantford.com/blog/angular-yeoman.html) +* [me&ngular - an introduction to MVW](http://stephenplusplus.github.io/meangular) + +Get help from other AngularJS users: + +* [Walkthroughs and Tutorials on YouTube](http://www.youtube.com/playlist?list=PL1w1q3fL4pmgqpzb-XhG7Clgi67d_OHXz) +* [Google Groups mailing list](https://groups.google.com/forum/?fromgroups#!forum/angular) +* [angularjs on Stack Overflow](http://stackoverflow.com/questions/tagged/angularjs) +* [AngularJS on Twitter](https://twitter.com/angularjs) +* [AngularjS on Google +](https://plus.google.com/+AngularJS/posts) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Implementation The normal AngularJS TodoMVC implemetation performs deep watching of the todos array object. This means that it keeps an in-memory copy of the complete array that is used for dirty checking in order to detect model mutations. For smaller applications such as TodoMVC, this is completely fine as one trades off a little memory and performance for the sake of simplicity. In larger more complex applications however, where one might be working with 100s or 1000s of large objects one definitely should avoid using this approach. This implementation of the AngularJS app demonstrates the correct way to approach this problem when working in larger apps. diff --git a/architecture-examples/angularjs/bower_components/todomvc-common/base.css b/architecture-examples/angularjs/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/angularjs/bower_components/todomvc-common/base.css +++ b/architecture-examples/angularjs/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/angularjs/bower_components/todomvc-common/base.js b/architecture-examples/angularjs/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/angularjs/bower_components/todomvc-common/base.js +++ b/architecture-examples/angularjs/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + ''; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/angularjs/index.html b/architecture-examples/angularjs/index.html index 682be02150..a2e97f1805 100644 --- a/architecture-examples/angularjs/index.html +++ b/architecture-examples/angularjs/index.html @@ -1,11 +1,11 @@ - + AngularJS • TodoMVC - +
diff --git a/architecture-examples/angularjs/readme.md b/architecture-examples/angularjs/readme.md new file mode 100644 index 0000000000..84eb601c04 --- /dev/null +++ b/architecture-examples/angularjs/readme.md @@ -0,0 +1,36 @@ +# AngularJS TodoMVC Example + +> HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop. + +> _[AngularJS - angularjs.com](http://angularjs.com)_ + + +## Learning AngularJS +The [AngularJS website](http://angularjs.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Tutorial](http://docs.angularjs.org/tutorial) +* [API Reference](http://docs.angularjs.org/api) +* [Developer Guide](http://docs.angularjs.org/guide) +* [Applications built with AngularJS](http://builtwith.angularjs.org) +* [Blog](http://blog.angularjs.org) +* [FAQ](http://docs.angularjs.org/misc/faq) +* [AngularJS Meetups](http://www.youtube.com/angularjs) + +Articles and guides from the community: + +* [Code School AngularJS course](http://www.codeschool.com/code_tv/angularjs-part-1) +* [5 Awesome AngularJS Features](http://net.tutsplus.com/tutorials/javascript-ajax/5-awesome-angularjs-features) +* [Using Yeoman with AngularJS](http://briantford.com/blog/angular-yeoman.html) +* [me&ngular - an introduction to MVW](http://stephenplusplus.github.io/meangular) + +Get help from other AngularJS users: + +* [Walkthroughs and Tutorials on YouTube](http://www.youtube.com/playlist?list=PL1w1q3fL4pmgqpzb-XhG7Clgi67d_OHXz) +* [Google Groups mailing list](https://groups.google.com/forum/?fromgroups#!forum/angular) +* [angularjs on Stack Overflow](http://stackoverflow.com/questions/tagged/angularjs) +* [AngularJS on Twitter](https://twitter.com/angularjs) +* [AngularjS on Google +](https://plus.google.com/+AngularJS/posts) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/architecture-examples/backbone/bower_components/todomvc-common/base.css b/architecture-examples/backbone/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/backbone/bower_components/todomvc-common/base.css +++ b/architecture-examples/backbone/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/backbone/bower_components/todomvc-common/base.js b/architecture-examples/backbone/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/backbone/bower_components/todomvc-common/base.js +++ b/architecture-examples/backbone/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/backbone/index.html b/architecture-examples/backbone/index.html index 801bf8eb9b..3e55b9cb91 100644 --- a/architecture-examples/backbone/index.html +++ b/architecture-examples/backbone/index.html @@ -1,5 +1,5 @@ - + diff --git a/architecture-examples/backbone/readme.md b/architecture-examples/backbone/readme.md new file mode 100644 index 0000000000..7214c2ab24 --- /dev/null +++ b/architecture-examples/backbone/readme.md @@ -0,0 +1,29 @@ +# Backbone.js TodoMVC Example + +> 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 - backbonejs.org](http://backbonejs.org)_ + + +## Learning Backbone.js + +The [Backbone.js website](http://backbonejs.org) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Annotated source code](http://backbonejs.org/docs/backbone.html) +* [Applications built with Backbone.js](http://backbonejs.org/#examples) +* [FAQ](http://backbonejs.org/#faq) + +Articles and guides from the community: + +* [Developing Backbone.js Applications](http://addyosmani.github.io/backbone-fundamentals) +* [Collection of tutorials, blog posts, and example sites](https://github.com/documentcloud/backbone/wiki/Tutorials%2C-blog-posts-and-example-sites) + +Get help from other Backbone.js users: + +* [Backbone.js on StackOverflow](http://stackoverflow.com/questions/tagged/backbone.js) +* [Google Groups mailing list](https://groups.google.com/forum/#!forum/backbonejs) +* [Backbone.js on Twitter](http://twitter.com/documentcloud) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/architecture-examples/canjs/bower_components/todomvc-common/base.css b/architecture-examples/canjs/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/canjs/bower_components/todomvc-common/base.css +++ b/architecture-examples/canjs/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/canjs/bower_components/todomvc-common/base.js b/architecture-examples/canjs/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/canjs/bower_components/todomvc-common/base.js +++ b/architecture-examples/canjs/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/canjs/index.html b/architecture-examples/canjs/index.html index cc315515c2..c3bb8d60aa 100644 --- a/architecture-examples/canjs/index.html +++ b/architecture-examples/canjs/index.html @@ -1,28 +1,26 @@ - - - - - CanJS • TodoMVC - - - -
-
-
-

Double-click to edit a todo

-

Written by Bitovi

-

Part of TodoMVC

-
- - - - - - - - - - - + + + + + CanJS • TodoMVC + + + +
+
+
+

Double-click to edit a todo

+

Written by Bitovi

+

Part of TodoMVC

+
+ + + + + + + + + diff --git a/architecture-examples/canjs/readme.md b/architecture-examples/canjs/readme.md index 80eeccd63f..6b7eedae80 100644 --- a/architecture-examples/canjs/readme.md +++ b/architecture-examples/canjs/readme.md @@ -1,42 +1,64 @@ -# CanJS +# CanJS TodoMVC Example -CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides: +> CanJS is a MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy. - - *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 - - *can.route* - routing support +> _[CanJS - canjs.com](http://canjs.com)_ -And works with jQuery, Zepto, YUI, Dojo and Mootools. -## CanJS and JavaScriptMVC +## Learning CanJS -*CanJS* is the extracted, more modern and more library-like MVC parts of [JavaScriptMVC](http://javascriptmvc.com) -(formerly known as *jQueryMX*). +The [CanJS website](http://canjs.com) is a great resource for getting started. -*JavaScriptMVC 3.3* uses CanJS for the MVC structure so this TodoMVC example **applies to JavaScriptMVC** as well. -Additionally JavaScriptMVC contains: +Here are some links you may find helpful: -- [CanJS](http://canjs.us) - For the MVC parts +* [Documentation](http://donejs.com/docs.html#!canjs) +* [Why CanJS](http://canjs.com/#why_canjs) +* [Applications built with CanJS](http://canjs.com/#examples) +* [Blog](http://bitovi.com/blog/tag/canjs) +* [Getting started video](http://www.youtube.com/watch?v=GdT4Oq6ZQ68) + +Articles and guides from the community: + +* [Diving into CanJS](http://net.tutsplus.com/tutorials/javascript-ajax/diving-into-canjs) + +Get help from other CanJS users: + +* [CanJS on StackOverflow](http://stackoverflow.com/questions/tagged/canjs) +* [CanJS Forums](http://forum.javascriptmvc.com/#Forum/canjs) +* [CanJS on Twitter](http://twitter.com/canjs) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Implementation + +### CanJS and JavaScriptMVC + +CanJS is the extracted, more modern and more library-like MVC parts of [JavaScriptMVC](http://javascriptmvc.com), formerly known as jQueryMX. + +JavaScriptMVC 3.3 uses CanJS for the MVC structure so this TodoMVC example applies to JavaScriptMVC as well. + +Additionally, JavaScriptMVC contains: + +- [CanJS](http://canjs.com) - For the MVC parts - [jQuery++](http://jquerypp.com) - jQuery's missing utils and special events - [StealJS](http://javascriptmvc.com/docs.html#!stealjs) - A JavaScript package manager - [DocumentJS](http://javascriptmvc.com/docs.html#!DocumentJS) - A documentation engine - [FuncUnit](http://funcunit.com) - jQuery style functional unit testing -## View engines + +### View engines CanJS supports both live binding [EJS](http://canjs.us/#can_ejs) and [Mustache/Handlebars](http://canjs.us/#can_mustache) templates. By default the Mustache view will be used but an EJS example is available as well. You can easily change it by modifying the `view` option in the `js/app.js` file: ```js -Models.Todo.findAll({}, function(todos) { +Models.Todo.findAll({}, function (todos) { new Todos('#todoapp', { todos: todos, - state : can.route, - view : 'views/todos.ejs' + state: can.route, + view: 'views/todos.ejs' }); }); ``` diff --git a/architecture-examples/closure/bower_components/todomvc-common/base.css b/architecture-examples/closure/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/closure/bower_components/todomvc-common/base.css +++ b/architecture-examples/closure/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/closure/bower_components/todomvc-common/base.js b/architecture-examples/closure/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/closure/bower_components/todomvc-common/base.js +++ b/architecture-examples/closure/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/closure/index.html b/architecture-examples/closure/index.html index 32d9b04a99..7a8fb31d40 100644 --- a/architecture-examples/closure/index.html +++ b/architecture-examples/closure/index.html @@ -1,5 +1,5 @@ - + diff --git a/architecture-examples/closure/readme.md b/architecture-examples/closure/readme.md index 25379d7a95..23ed7610c7 100644 --- a/architecture-examples/closure/readme.md +++ b/architecture-examples/closure/readme.md @@ -1,8 +1,39 @@ -# TodoMVC Closure Architecture Example +# Closure Tools TodoMVC Example -## Introduction +> The Closure Tools project is an effort by Google engineers to open source the tools used in many of Google's sites and web applications for use by the wider Web development community. + +> _[Closure Tools - developers.google.com/closure](https://developers.google.com/closure)_ + + +## Learning Closure Tools + +The [Closure Tools website](https://developers.google.com/closure) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](https://developers.google.com/closure/library/docs/overview) +* [API Reference](http://docs.closure-library.googlecode.com/git/index.html) +* [Blog](http://closuretools.blogspot.com) +* [FAQ](https://developers.google.com/closure/faq) + +Articles and guides from the community: + +* [Examples, walkthroughs, and articles](http://www.googleclosure.com) +* [First Adventure in Google Closure](http://www.codeproject.com/Articles/265364/First-Adventures-in-Google-Closure) + +Get help from other Closure Tools users: + +* [Google Groups mailing list](https://groups.google.com/group/closure-library-discuss) +* [Closure Tools on Twitter](http://twitter.com/closuretools) +* [Closure Tools on Google +](https://plus.google.com/communities/113969319608324762672) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Implementation + +Note this project breaks with the convention of the others and uses spaces in place of tabs within JavaScript files. This is to comply with the Google style guidelines which the Closure Linter enforces (see [Linting](#linting) below). -An example making use of the [Closure toolkit](https://developers.google.com/closure/). Note this project breaks with the convention of the others and uses spaces in place of tabs within JavaScript files. This is to comply with the Google style guidelines which the Closure Linter enforces (see Linting below). ## Running @@ -29,6 +60,7 @@ The linter must be installed before use, the installation package is included in (or whatever floats your OSs boat) + ## Compiling To compile the code from the command line run Plovr like so - @@ -37,14 +69,7 @@ To compile the code from the command line run Plovr like so - This will overwrite the js/compiled.js file with the new version, be sure to change the script tag reference in the HTML page. -## Credits - -Template by [Sindre Sorhus](http://github.com/sindresorhus) - -Created by [Chris Price](http://www.scottlogic.co.uk/blog/chris/) -Part of [TodoMVC](http://todomvc.com) - -## License +## Credits -Public Domain +This TodoMVC application was created by [Chris Price](http://www.scottlogic.co.uk/blog/chris/). diff --git a/architecture-examples/dart/.bowerrc b/architecture-examples/dart/.bowerrc new file mode 100644 index 0000000000..e0a4aac989 --- /dev/null +++ b/architecture-examples/dart/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "web/bower_components" +} diff --git a/architecture-examples/dart/bower.json b/architecture-examples/dart/bower.json new file mode 100644 index 0000000000..1cab3809ac --- /dev/null +++ b/architecture-examples/dart/bower.json @@ -0,0 +1,7 @@ +{ + "name": "dart", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6" + } +} \ No newline at end of file diff --git a/architecture-examples/dart/readme.md b/architecture-examples/dart/readme.md index 5a73811dbc..0286acdfd1 100644 --- a/architecture-examples/dart/readme.md +++ b/architecture-examples/dart/readme.md @@ -1,10 +1,37 @@ -# Dart • [TodoMVC](http://todomvc.com) +# Dart TodoMVC Example -A TodoMVC sample built with Dart. It does not use a MVC framework - it's a Vanilla Dart sample. +> Dart is a class-based, object-oriented language with lexical scoping, closures, and optional static typing. Dart helps you build structured modern web apps and is easy to learn for a wide range of developers. -Dart firstly targets the development of modern and large scale browser-side web apps. It's an object oriented language with a C-style syntax. +> _[Dart - dartlang.org](http://dartlang.org)_ -## Run + +## Learning Dart + +The [Dart website](http://www.dartlang.org) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](http://www.dartlang.org/docs/technical-overview) +* [API Reference](http://api.dartlang.org/docs/releases/latest) +* [A Tour of the Dart Language](http://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html) +* [Articles](http://www.dartlang.org/articles) +* [Tutorials](http://www.dartlang.org/docs/tutorials) +* [FAQ](http://www.dartlang.org/support/faq.html) + +Articles and guides from the community: + +* [Getting started with Google Dart](http://www.techrepublic.com/blog/webmaster/getting-started-with-google-dart/931) + +Get help from other Dart users: + +* [Dart on StackOverflow](http://stackoverflow.com/questions/tagged/dart) +* [Dart on Twitter](http://twitter.com/dart_lang) +* [Dart on Google +](https://plus.google.com/+dartlang/posts) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Running Dart compiles to JavaScript and thus runs across modern browsers. Dart also can run in its own virtual machine. @@ -12,18 +39,20 @@ Both Dart files and JS compilation result are provided in this sample, therefore To edit and debug the code, you can use Dart Editor. The editor ships with the [SDK](http://dartlang.org) and [Dartium](http://www.dartlang.org/dartium/), a dedicated version of Chromium with an embedded Dart VM. -## How to compile to JS + +## Compiling ``` cd web/dart -dart2js app.dart -oapp.dart.js +dart2js app.dart -oapp.dart.js ``` The dart2js compilator can be found in the SDK. The currently provided JS is minified (dart2js [...] --minify). -## Dart syntax analysis + +## Syntax Analysis ``` cd web/dart @@ -36,6 +65,7 @@ Dart SDK is still under active development, and new releases include breaking ch Build history can be seen [here](https://drone.io/mlorber/todomvc-dart) + ## Credit -Made by [Mathieu Lorber](http://mlorber.net) +This TodoMVC application was created by [Mathieu Lorber](http://mlorber.net). diff --git a/architecture-examples/dart/web/assets/base.js b/architecture-examples/dart/web/assets/base.js deleted file mode 100644 index 4da326723e..0000000000 --- a/architecture-examples/dart/web/assets/base.js +++ /dev/null @@ -1,38 +0,0 @@ -(function () { - 'use strict'; - - if (location.hostname === 'todomvc.com') { - window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); - } - - function getSourcePath() { - // If accessed via tastejs.github.io/todomvc/, strip the project path. - if (location.hostname.indexOf('github.io') > 0) { - return location.pathname.replace(/todomvc\//, ''); - } - return location.pathname; - } - - function appendSourceLink() { - var sourceLink = document.createElement('a'); - var paragraph = document.createElement('p'); - var footer = document.getElementById('info'); - var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; - - if (footer) { - sourceLink.href = urlBase + getSourcePath(); - sourceLink.appendChild(document.createTextNode('Check out the source')); - paragraph.appendChild(sourceLink); - footer.appendChild(paragraph); - } - } - - function redirect() { - if (location.hostname === 'tastejs.github.io') { - location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); - } - } - - appendSourceLink(); - redirect(); -})(); diff --git a/architecture-examples/dart/web/assets/ie.js b/architecture-examples/dart/web/assets/ie.js deleted file mode 100644 index 82e6a63dcb..0000000000 --- a/architecture-examples/dart/web/assets/ie.js +++ /dev/null @@ -1,27 +0,0 @@ -/*! HTML5 Shiv pre3.5 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed - Uncompressed source: https://github.com/aFarkas/html5shiv */ -(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x";c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d>>0;if("[object Function]"!=m(a))throw new TypeError; -for(;c>>0,e=Array(c);if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g>>0,e=[];if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e>>0;if("[object Function]"!=m(a))throw new TypeError; -if(!b&&1==arguments.length)throw new TypeError;var c=0,e;if(2<=arguments.length)e=arguments[1];else{do{if(c in d){e=d[c++];break}if(++c>=b)throw new TypeError;}while(1)}for(;c>>0;if("[object Function]"!=m(a))throw new TypeError;if(!b&&1==arguments.length)throw new TypeError;var c,b=b-1;if(2<=arguments.length)c=arguments[1];else{do{if(b in d){c=d[b--]; -break}if(0>--b)throw new TypeError;}while(1)}do b in this&&(c=a.call(void 0,c,d[b],b,d));while(b--);return c};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(a){var d=i(this),b=d.length>>>0;if(!b)return-1;var c=0;1>>0;if(!b)return-1;var c=b-1;1c?"-":9999=c?-4:-6);for(d=a.length;d--;)b=a[d],10>b&&(a[d]="0"+b);return c+"-"+a.slice(0,2).join("-")+"T"+a.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};if(!Date.now)Date.now=function(){return(new Date).getTime()};if(!Date.prototype.toJSON)Date.prototype.toJSON=function(){if("function"!=typeof this.toISOString)throw new TypeError;return this.toISOString()}; -if(!Date.parse||864E13!==Date.parse("+275760-09-13T00:00:00.000Z"))Date=function(a){var d=function g(b,d,c,f,h,i,j){var k=arguments.length;return this instanceof a?(k=1==k&&""+b===b?new a(g.parse(b)):7<=k?new a(b,d,c,f,h,i,j):6<=k?new a(b,d,c,f,h,i):5<=k?new a(b,d,c,f,h):4<=k?new a(b,d,c,f):3<=k?new a(b,d,c):2<=k?new a(b,d):1<=k?new a(b):new a,k.constructor=g,k):a.apply(this,arguments)},b=RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"), -c;for(c in a)d[c]=a[c];d.now=a.now;d.UTC=a.UTC;d.prototype=a.prototype;d.prototype.constructor=d;d.parse=function(d){var c=b.exec(d);if(c){c.shift();for(var f=1;7>f;f++)c[f]=+(c[f]||(3>f?1:0)),1==f&&c[f]--;var h=+c.pop(),i=+c.pop(),j=c.pop(),f=0;if(j){if(23=h?(c[0]=h+400,a.UTC.apply(this,c)+f-126227808E5):a.UTC.apply(this,c)+f}return a.parse.apply(this,arguments)};return d}(Date);j="\t\n\u000b\u000c\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff"; -if(!String.prototype.trim||j.trim()){j="["+j+"]";var A=RegExp("^"+j+j+"*"),B=RegExp(j+j+"*$");String.prototype.trim=function(){return(""+this).replace(A,"").replace(B,"")}}var v=function(a){a=+a;a!==a?a=0:0!==a&&a!==1/0&&a!==-(1/0)&&(a=(0<",">"+this.innerHTML+"<");c.innerHTML="";return a},d=function(a){var b=this.parentNode;if(null===b)throw DOMException.code= -DOMException.NOT_FOUND_ERR,DOMException;for(c.innerHTML=a;a=c.firstChild;)b.insertBefore(a,this);b.removeChild(this)};if(Object.defineProperty){b={get:b,set:d,enumerable:!0,configurable:!0};try{Object.defineProperty(a,"outerHTML",b)}catch(f){-2146823252===f.number&&(b.enumerable=!1,Object.defineProperty(a,"outerHTML",b))}}else Object.prototype.__defineGetter__&&Object.prototype.__defineSetter__&&(a.__defineGetter__("outerHTML",b),a.__defineSetter__("outerHTML",d))}(self); \ No newline at end of file diff --git a/architecture-examples/dart/web/assets/base.css b/architecture-examples/dart/web/bower_components/todomvc-common/base.css similarity index 76% rename from architecture-examples/dart/web/assets/base.css rename to architecture-examples/dart/web/bower_components/todomvc-common/base.css index 672d939970..a726662053 100644 --- a/architecture-examples/dart/web/assets/base.css +++ b/architecture-examples/dart/web/bower_components/todomvc-common/base.css @@ -155,22 +155,11 @@ label[for='toggle-all'] { #toggle-all { position: absolute; - top: -56px; - left: -15px; - width: 65px; - height: 41px; + top: -42px; + left: -4px; + width: 40px; text-align: center; border: none; /* Mobile Safari */ - -webkit-appearance: none; - /*-moz-appearance: none;*/ - -ms-appearance: none; - -o-appearance: none; - appearance: none; - -webkit-transform: rotate(90deg); - /*-moz-transform: rotate(90deg);*/ - -ms-transform: rotate(90deg); - /*-o-transform: rotate(90deg);*/ - transform: rotate(90deg); } #toggle-all:before { @@ -219,7 +208,8 @@ label[for='toggle-all'] { #todo-list li .toggle { text-align: center; width: 40px; - height: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; position: absolute; top: 0; bottom: 0; @@ -233,7 +223,6 @@ label[for='toggle-all'] { } #todo-list li .toggle:after { - font-size: 18px; content: '✔'; line-height: 43px; /* 40 + a couple of pixels visual adjustment */ font-size: 20px; @@ -403,8 +392,164 @@ label[for='toggle-all'] { #todo-list li .toggle { background: none; } + + #todo-list li .toggle { + height: 40px; + } + + #toggle-all { + top: -56px; + left: -15px; + width: 65px; + height: 41px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } } .hidden{ display:none; -} \ No newline at end of file +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/dart/web/bower_components/todomvc-common/base.js b/architecture-examples/dart/web/bower_components/todomvc-common/base.js new file mode 100644 index 0000000000..5ca690ece1 --- /dev/null +++ b/architecture-examples/dart/web/bower_components/todomvc-common/base.js @@ -0,0 +1,182 @@ +(function () { + 'use strict'; + + if (location.hostname === 'todomvc.com') { + window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); + } + + function getSourcePath() { + // If accessed via tastejs.github.io/todomvc/, strip the project path. + if (location.hostname.indexOf('github.io') > 0) { + return location.pathname.replace(/todomvc\//, ''); + } + return location.pathname; + } + + function appendSourceLink() { + var sourceLink = document.createElement('a'); + var paragraph = document.createElement('p'); + var footer = document.getElementById('info'); + var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; + + if (footer) { + sourceLink.href = urlBase + getSourcePath(); + sourceLink.appendChild(document.createTextNode('Check out the source')); + paragraph.appendChild(sourceLink); + footer.appendChild(paragraph); + } + } + + function redirect() { + if (location.hostname === 'tastejs.github.io') { + location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); + } + } + + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + + appendSourceLink(); + redirect(); + getFile('learn.json', Learn); +})(); diff --git a/architecture-examples/dart/web/assets/bg.png b/architecture-examples/dart/web/bower_components/todomvc-common/bg.png similarity index 100% rename from architecture-examples/dart/web/assets/bg.png rename to architecture-examples/dart/web/bower_components/todomvc-common/bg.png diff --git a/architecture-examples/dart/web/index.html b/architecture-examples/dart/web/index.html index fd25cb84eb..c0502a69e4 100644 --- a/architecture-examples/dart/web/index.html +++ b/architecture-examples/dart/web/index.html @@ -1,13 +1,10 @@ - + Dart • TodoMVC - - +
@@ -41,7 +38,7 @@

todos

Created by Mathieu Lorber

Part of TodoMVC

- + diff --git a/architecture-examples/dojo/bower.json b/architecture-examples/dojo/bower.json new file mode 100644 index 0000000000..e049881286 --- /dev/null +++ b/architecture-examples/dojo/bower.json @@ -0,0 +1,7 @@ +{ + "name": "todmvc-dojo", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6" + } +} diff --git a/labs/architecture-examples/meteor/client/css/base.css b/architecture-examples/dojo/bower_components/todomvc-common/base.css similarity index 76% rename from labs/architecture-examples/meteor/client/css/base.css rename to architecture-examples/dojo/bower_components/todomvc-common/base.css index e5f87bac4d..a726662053 100644 --- a/labs/architecture-examples/meteor/client/css/base.css +++ b/architecture-examples/dojo/bower_components/todomvc-common/base.css @@ -23,7 +23,7 @@ button { body { font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.4em; - background: #eaeaea url('./client/images/bg.png'); + background: #eaeaea url('bg.png'); color: #4d4d4d; width: 550px; margin: 0 auto; @@ -155,22 +155,11 @@ label[for='toggle-all'] { #toggle-all { position: absolute; - top: -56px; - left: -15px; - width: 65px; - height: 41px; + top: -42px; + left: -4px; + width: 40px; text-align: center; border: none; /* Mobile Safari */ - -webkit-appearance: none; - /*-moz-appearance: none;*/ - -ms-appearance: none; - -o-appearance: none; - appearance: none; - -webkit-transform: rotate(90deg); - /*-moz-transform: rotate(90deg);*/ - -ms-transform: rotate(90deg); - /*-o-transform: rotate(90deg);*/ - transform: rotate(90deg); } #toggle-all:before { @@ -219,7 +208,8 @@ label[for='toggle-all'] { #todo-list li .toggle { text-align: center; width: 40px; - height: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; position: absolute; top: 0; bottom: 0; @@ -233,7 +223,6 @@ label[for='toggle-all'] { } #todo-list li .toggle:after { - font-size: 18px; content: '✔'; line-height: 43px; /* 40 + a couple of pixels visual adjustment */ font-size: 20px; @@ -403,8 +392,164 @@ label[for='toggle-all'] { #todo-list li .toggle { background: none; } + + #todo-list li .toggle { + height: 40px; + } + + #toggle-all { + top: -56px; + left: -15px; + width: 65px; + height: 41px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } } .hidden{ display:none; -} \ No newline at end of file +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/dojo/bower_components/todomvc-common/base.js b/architecture-examples/dojo/bower_components/todomvc-common/base.js new file mode 100644 index 0000000000..5ca690ece1 --- /dev/null +++ b/architecture-examples/dojo/bower_components/todomvc-common/base.js @@ -0,0 +1,182 @@ +(function () { + 'use strict'; + + if (location.hostname === 'todomvc.com') { + window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); + } + + function getSourcePath() { + // If accessed via tastejs.github.io/todomvc/, strip the project path. + if (location.hostname.indexOf('github.io') > 0) { + return location.pathname.replace(/todomvc\//, ''); + } + return location.pathname; + } + + function appendSourceLink() { + var sourceLink = document.createElement('a'); + var paragraph = document.createElement('p'); + var footer = document.getElementById('info'); + var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; + + if (footer) { + sourceLink.href = urlBase + getSourcePath(); + sourceLink.appendChild(document.createTextNode('Check out the source')); + paragraph.appendChild(sourceLink); + footer.appendChild(paragraph); + } + } + + function redirect() { + if (location.hostname === 'tastejs.github.io') { + location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); + } + } + + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + + appendSourceLink(); + redirect(); + getFile('learn.json', Learn); +})(); diff --git a/labs/architecture-examples/duel/src/main/webapp/css/bg.png b/architecture-examples/dojo/bower_components/todomvc-common/bg.png similarity index 100% rename from labs/architecture-examples/duel/src/main/webapp/css/bg.png rename to architecture-examples/dojo/bower_components/todomvc-common/bg.png diff --git a/architecture-examples/dojo/index-1.7.html b/architecture-examples/dojo/index-1.7.html index a454b3014a..dccff5aec6 100644 --- a/architecture-examples/dojo/index-1.7.html +++ b/architecture-examples/dojo/index-1.7.html @@ -1,25 +1,21 @@ - + Dojo • TodoMVC - - + - -
+
+
- - + diff --git a/architecture-examples/dojo/index.html b/architecture-examples/dojo/index.html index a27bed088d..25564d1e3f 100644 --- a/architecture-examples/dojo/index.html +++ b/architecture-examples/dojo/index.html @@ -1,49 +1,31 @@ - + Dojo • TodoMVC - - + - -
+
- + diff --git a/architecture-examples/dojo/readme.md b/architecture-examples/dojo/readme.md index e50d132b15..ef02dbabe0 100644 --- a/architecture-examples/dojo/readme.md +++ b/architecture-examples/dojo/readme.md @@ -1,24 +1,53 @@ -# Dojo TodoMVC app +# Dojo TodoMVC Example -## Building +> 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 - dojotoolkit.org](http://dojotoolkit.org)_ + + +## Learning Dojo + +The [Dojo website](http://dojotoolkit.org) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](http://dojotoolkit.org/documentation) +* [Getting started guide](https://dojotoolkit.org/reference-guide/1.8/quickstart) +* [API Reference](http://dojotoolkit.org/api) +* [Blog](http://dojotoolkit.org/blog) + +Articles and guides from the community: + +* [Getting StartED with Dojo](http://startdojo.com) + +Get help from other Dojo users: + +* [Dojo on StackOverflow](http://stackoverflow.com/questions/tagged/dojo) +* [Mailing list](http://dojotoolkit.org/community) +* [Dojo on Twitter](http://twitter.com/dojo) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Running To build the Dojo app, you first need to download and extract the [Dojo SDK](https://dojotoolkit.org/download/#sdk). At the root folder of the extracted SDK, copy or symlink the complete `todomvc` folder, so your directory structure looks like this: - dojo-release/ - ├── dijit - ├── dojo - ├── dojox - ├── todomvc - └── util + dojo-release/ + ├── dijit + ├── dojo + ├── dojox + ├── todomvc + └── util -Enter the `dojo-release/util` folder and run these commands to build the -`dojo.js` file including all required resources and copy it back into the -todomvc folder. You need either java or node on your system to run these: +Enter the `dojo-release/util` folder and run these commands to build the `dojo.js` file including all required resources and copy it back into the todomvc folder. You need either java or node on your system to run these: - buildscripts/build.sh --profile ../todomvc/architecture-examples/dojo/profiles/todomvc.profile.js -r - cp ../release/dojo/dojo/dojo.js ../todomvc/architecture-examples/dojo/js/lib/dojo-1.8/dojo.js +``` +buildscripts/build.sh --profile ../todomvc/architecture-examples/dojo/profiles/todomvc.profile.js -r +cp ../release/dojo/dojo/dojo.js ../todomvc/architecture-examples/dojo/js/lib/dojo-1.8/dojo.js +``` After a new release of Dojo, you may need to copy more files for this to work. Check out the `js/lib/` folder for other files that are required from the diff --git a/architecture-examples/emberjs/bower_components/todomvc-common/base.css b/architecture-examples/emberjs/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/emberjs/bower_components/todomvc-common/base.css +++ b/architecture-examples/emberjs/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/emberjs/bower_components/todomvc-common/base.js b/architecture-examples/emberjs/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/emberjs/bower_components/todomvc-common/base.js +++ b/architecture-examples/emberjs/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/emberjs/index.html b/architecture-examples/emberjs/index.html index ceafb7461b..acea43f5c3 100644 --- a/architecture-examples/emberjs/index.html +++ b/architecture-examples/emberjs/index.html @@ -1,80 +1,80 @@ - - - - - ember.js • TodoMVC - - - - - - - - - - - - - - - - - - - + + + + + ember.js • TodoMVC + + + + + + + + + + + + + + + + + + + diff --git a/architecture-examples/emberjs/readme.md b/architecture-examples/emberjs/readme.md new file mode 100644 index 0000000000..621888ee0b --- /dev/null +++ b/architecture-examples/emberjs/readme.md @@ -0,0 +1,31 @@ +# Ember.js TodoMVC Example + +> A framework for creating ambitious web applications. + +> _[Ember.js - emberjs.com](http://emberjs.com)_ + + +## Learning Ember.js + +The [Ember.js website](http://emberjs.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Guides](http://emberjs.com/guides) +* [API Reference](http://emberjs.com/api) +* [Screencast - Building an App with Ember.js](https://www.youtube.com/watch?v=Ga99hMi7wfY) +* [Applications built with Ember.js](http://emberjs.com/ember-users) +* [Blog](http://emberjs.com/blog) + +Articles and guides from the community: + +* [Getting Into Ember.js](http://net.tutsplus.com/tutorials/javascript-ajax/getting-into-ember-js) +* [EmberWatch](http://emberwatch.com) + +Get help from other Ember.js users: + +* [Ember.js on StackOverflow](http://stackoverflow.com/questions/tagged/ember.js) +* [Ember.js on Twitter](http://twitter.com/emberjs) +* [Ember.js on Google +](https://plus.google.com/communities/106387049790387471205) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/architecture-examples/gwt/bower.json b/architecture-examples/gwt/bower.json new file mode 100644 index 0000000000..c0a637869f --- /dev/null +++ b/architecture-examples/gwt/bower.json @@ -0,0 +1,7 @@ +{ + "name": "gwt", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6" + } +} \ No newline at end of file diff --git a/labs/architecture-examples/duel/src/main/webapp/css/base.css b/architecture-examples/gwt/bower_components/todomvc-common/base.css similarity index 69% rename from labs/architecture-examples/duel/src/main/webapp/css/base.css rename to architecture-examples/gwt/bower_components/todomvc-common/base.css index d843ad862d..a726662053 100644 --- a/labs/architecture-examples/duel/src/main/webapp/css/base.css +++ b/architecture-examples/gwt/bower_components/todomvc-common/base.css @@ -23,7 +23,7 @@ button { body { font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.4em; - background: #eeeeee url('bg.png'); + background: #eaeaea url('bg.png'); color: #4d4d4d; width: 550px; margin: 0 auto; @@ -57,6 +57,15 @@ body { height: 100%; } +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todoapp input:-moz-placeholder { + font-style: italic; + color: #a9a9a9; +} + #todoapp h1 { position: absolute; top: -120px; @@ -79,7 +88,7 @@ body { border-radius: inherit; } -#todoapp header:before { +#header:before { content: ''; position: absolute; top: 0; @@ -96,20 +105,13 @@ body { background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); - border-radius: inherit; -} - -#todoapp input::-webkit-input-placeholder { - font-style: italic; -} - -#todoapp input:-moz-placeholder { - font-style: italic; - color: #a9a9a9; + border-top-left-radius: 1px; + border-top-right-radius: 1px; } #new-todo, .edit { + position: relative; margin: 0; width: 100%; font-size: 24px; @@ -137,7 +139,6 @@ body { padding: 16px 16px 16px 60px; border: none; background: rgba(0, 0, 0, 0.02); - position: relative; z-index: 2; box-shadow: none; } @@ -155,18 +156,10 @@ label[for='toggle-all'] { #toggle-all { position: absolute; top: -42px; - left: 12px; + left: -4px; + width: 40px; text-align: center; - -webkit-appearance: none; - /*-moz-appearance: none;*/ - -ms-appearance: none; - -o-appearance: none; - appearance: none; - -webkit-transform: rotate(90deg); - /*-moz-transform: rotate(90deg);*/ - -ms-transform: rotate(90deg); - /*-o-transform: rotate(90deg);*/ - transform: rotate(90deg); + border: none; /* Mobile Safari */ } #toggle-all:before { @@ -180,15 +173,6 @@ label[for='toggle-all'] { color: #737373; } -/* Need this ugly hack, since only -WebKit supports styling of inputs */ -@media screen and (-webkit-min-device-pixel-ratio:0) { - #toggle-all { - top: -52px; - left: -11px; - } -} - #todo-list { margin: 0; padding: 0; @@ -223,7 +207,14 @@ WebKit supports styling of inputs */ #todo-list li .toggle { text-align: center; - width: 35px; + width: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; + position: absolute; + top: 0; + bottom: 0; + margin: auto 0; + border: none; /* Mobile Safari */ -webkit-appearance: none; /*-moz-appearance: none;*/ -ms-appearance: none; @@ -232,9 +223,8 @@ WebKit supports styling of inputs */ } #todo-list li .toggle:after { - font-size: 18px; content: '✔'; - line-height: 40px; + line-height: 43px; /* 40 + a couple of pixels visual adjustment */ font-size: 20px; color: #d9d9d9; text-shadow: 0 -1px 0 #bfbfbf; @@ -249,8 +239,10 @@ WebKit supports styling of inputs */ #todo-list li label { word-break: break-word; - margin: 20px 15px; - display: inline-block; + padding: 15px; + margin-left: 45px; + display: block; + line-height: 1.2; -webkit-transition: color 0.4s; -moz-transition: color 0.4s; -ms-transition: color 0.4s; @@ -258,7 +250,7 @@ WebKit supports styling of inputs */ transition: color 0.4s; } -#todo-list li.complete label { +#todo-list li.completed label { color: #a9a9a9; text-decoration: line-through; } @@ -266,10 +258,12 @@ WebKit supports styling of inputs */ #todo-list li .destroy { display: none; position: absolute; - top: 10px; + top: 0; right: 10px; + bottom: 0; width: 40px; height: 40px; + margin: auto 0; font-size: 22px; color: #a88a8a; -webkit-transition: all 0.2s; @@ -312,6 +306,7 @@ WebKit supports styling of inputs */ right: 0; bottom: -31px; left: 0; + height: 20px; z-index: 1; text-align: center; } @@ -322,13 +317,13 @@ WebKit supports styling of inputs */ right: 0; bottom: 31px; left: 0; - height: 100px; + height: 50px; z-index: -1; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 6px 0 -3px rgba(255, 255, 255, 0.8), 0 7px 1px -3px rgba(0, 0, 0, 0.3), - 0 42px 0 -6px rgba(255, 255, 255, 0.8), - 0 43px 2px -6px rgba(0, 0, 0, 0.2); + 0 43px 0 -6px rgba(255, 255, 255, 0.8), + 0 44px 2px -6px rgba(0, 0, 0, 0.2); } #todo-count { @@ -361,12 +356,12 @@ WebKit supports styling of inputs */ #clear-completed { float: right; + position: relative; line-height: 20px; text-decoration: none; background: rgba(0, 0, 0, 0.1); font-size: 11px; padding: 0 10px; - position: relative; border-radius: 3px; box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); } @@ -387,3 +382,174 @@ WebKit supports styling of inputs */ #info a { color: inherit; } + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox and Opera +*/ +@media screen and (-webkit-min-device-pixel-ratio:0) { + #toggle-all, + #todo-list li .toggle { + background: none; + } + + #todo-list li .toggle { + height: 40px; + } + + #toggle-all { + top: -56px; + left: -15px; + width: 65px; + height: 41px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +.hidden{ + display:none; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/gwt/bower_components/todomvc-common/base.js b/architecture-examples/gwt/bower_components/todomvc-common/base.js new file mode 100644 index 0000000000..5ca690ece1 --- /dev/null +++ b/architecture-examples/gwt/bower_components/todomvc-common/base.js @@ -0,0 +1,182 @@ +(function () { + 'use strict'; + + if (location.hostname === 'todomvc.com') { + window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); + } + + function getSourcePath() { + // If accessed via tastejs.github.io/todomvc/, strip the project path. + if (location.hostname.indexOf('github.io') > 0) { + return location.pathname.replace(/todomvc\//, ''); + } + return location.pathname; + } + + function appendSourceLink() { + var sourceLink = document.createElement('a'); + var paragraph = document.createElement('p'); + var footer = document.getElementById('info'); + var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; + + if (footer) { + sourceLink.href = urlBase + getSourcePath(); + sourceLink.appendChild(document.createTextNode('Check out the source')); + paragraph.appendChild(sourceLink); + footer.appendChild(paragraph); + } + } + + function redirect() { + if (location.hostname === 'tastejs.github.io') { + location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); + } + } + + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
' + example.name + '
' + + '

' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + + appendSourceLink(); + redirect(); + getFile('learn.json', Learn); +})(); diff --git a/labs/architecture-examples/meteor/client/images/bg.png b/architecture-examples/gwt/bower_components/todomvc-common/bg.png similarity index 100% rename from labs/architecture-examples/meteor/client/images/bg.png rename to architecture-examples/gwt/bower_components/todomvc-common/bg.png diff --git a/architecture-examples/gwt/css/app.css b/architecture-examples/gwt/css/app.css index dcc3949f86..39ce370449 100644 --- a/architecture-examples/gwt/css/app.css +++ b/architecture-examples/gwt/css/app.css @@ -1,13 +1,13 @@ /* The CSS that is common to all TodoMVC implementations, base.css, styles the selected routing filter using the following selector: - + #filters li a.selected - + In the GWT implementation, a Hyperlink widget is used for the routing filters. This widget allows you to specify a history - and will handle the clicks accordingly. The HTML for this widget is as follows: - +
- + Where the 'div' element represents the hyperlink GWT widget. This results in the following GWT specific style. */ diff --git a/architecture-examples/gwt/index.html b/architecture-examples/gwt/index.html index 72aac46d5b..d9a11a3dc3 100644 --- a/architecture-examples/gwt/index.html +++ b/architecture-examples/gwt/index.html @@ -1,16 +1,14 @@ - - - - - - GWT • TodoMVC - - - - - - - + + + + + + Google Web Toolkit • TodoMVC + + + + + + + diff --git a/architecture-examples/gwt/readme.md b/architecture-examples/gwt/readme.md index 452eac1336..30c1291e75 100644 --- a/architecture-examples/gwt/readme.md +++ b/architecture-examples/gwt/readme.md @@ -1,20 +1,42 @@ -## TodoMVC - GWT Version +# Google Web Toolkit TodoMVC Example -This is a Google Web Toolkit (GWT) implementation of the TodoMVC application. The GWT version -is rather different to all the other TodoMVC versions (Backbone, Knockout etc ...) in that it is -written in Java which is compiled to JavaScript. The files within the `gwttodo` folder are the result -of running the GWT compilation process on the Java files found within the src folder. The UI -pattern used by this application is Model-View-Presenter. +> Google Web Toolkit (GWT) is a development toolkit for building and optimizing complex browser-based applications. GWT is used by many products at Google, including Google AdWords and Orkut. It's open source, completely free, and used by thousands of developers around the world. -Whilst this application is very different to the other TodoMVC implementations, it still makes for -an interesting comparison. Large-scale JavaScript applications are often written with GWT or Closure, -with the resulting JavaScript code delivered to the client being compiled. +> _[Google Web Toolkit - developers.google.com/web-toolkit](https://developers.google.com/web-toolkit)_ -You can read more about the implementation on my blog: -http://www.scottlogic.co.uk/blog/colin/2012/03/developing-a-gwt-todomvc-application/ +## Learning Google Web Toolkit -### Folder structure +The [Google Web Toolkit website](https://developers.google.com/web-toolkit/) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](https://developers.google.com/web-toolkit/doc/latest/DevGuide) +* [Getting Started with the GWT SDK](https://developers.google.com/web-toolkit/gettingstarted) +* [Articles](https://developers.google.com/web-toolkit/articles) +* [Case Studies](https://developers.google.com/web-toolkit/casestudies) +* [Blog](http://googlewebtoolkit.blogspot.com) +* [FAQ](https://developers.google.com/web-toolkit/doc/latest/FAQ) + +Get help from other Google Web Toolkit users: + +* [Google Web Toolkit on StackOverflow](http://stackoverflow.com/questions/tagged/gwt) +* [Mailing list on Google Groups](http://groups.google.com/group/Google-Web-Toolkit) +* [Google Web Toolkit on Twitter](http://twitter.com/googledevtools) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Implementation + +This application is rather different than most of the other TodoMVC versions in that it is written in Java which is compiled to JavaScript. The files within the `gwttodo` folder are the result of running the GWT compilation process on the Java files found within the src folder. The UI pattern used by this application is Model-View-Presenter. + +Whilst this application is very different to the other implementations, it still makes for an interesting comparison. Large-scale JavaScript applications are often written with GWT or Closure, with the resulting JavaScript code delivered to the client being compiled. + +You can read more about the implementation on [my blog](http://www.scottlogic.co.uk/blog/colin/2012/03/developing-a-gwt-todomvc-application). + + +## Folder Structure - `css` - includes GWT specific `app.css`, most styling is taken from the base CSS file `../../assets/base.css` - `gwttodo` - the GWT compiled output, this includes various HTML files, which contain the JavaScript @@ -23,14 +45,8 @@ folder also includes some redundant files, see the issue Demo, ') + + ' Source' + + '

'; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

' + linkGroup.heading + '

' + + '
    ' + + linkGroup.links.map(function (link) { + return '' + + '
  • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
  • '; + }).join('') + + '
'; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/jquery/index.html b/architecture-examples/jquery/index.html index 86a49efed9..2c9f56e4f9 100644 --- a/architecture-examples/jquery/index.html +++ b/architecture-examples/jquery/index.html @@ -1,52 +1,52 @@ - - - - - jQuery • TodoMVC - - - - -
- -
- - -
    -
    -
    - 0 item left - -
    + + + + + jQuery • TodoMVC + + + + +
    + +
    + + +
      -
      -

      Double-click to edit a todo

      -

      Created by Sindre Sorhus

      -

      Part of TodoMVC

      +
      + 0 item left +
      - - - - - - - +
      + + + + + + + + diff --git a/architecture-examples/jquery/readme.md b/architecture-examples/jquery/readme.md new file mode 100644 index 0000000000..a04a23e658 --- /dev/null +++ b/architecture-examples/jquery/readme.md @@ -0,0 +1,32 @@ +# jQuery TodoMVC Example + +> jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript. + +> _[jQuery - jquery.com](http://jquery.com)_ + + +## Learning jQuery + +The [jQuery website](http://jquery.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [How jQuery Works](http://learn.jquery.com/about-jquery/how-jquery-works) +* [API Reference](http://api.jquery.com) +* [Plugins](http://plugins.jquery.com) +* [Brower Support](http://jquery.com/browser-support) +* [Blog](http://blog.jquery.com) + +Articles and guides from the community: + +* [Try jQuery](http://try.jquery.com) +* [10 Things I Learned From the jQuery Source](http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source) + +Get help from other jQuery users: + +* [jQuery on StackOverflow](http://stackoverflow.com/questions/tagged/jquery) +* [Forums](http://forum.jquery.com) +* [jQuery on Twitter](http://twitter.com/jquery) +* [jQuery on Google +](https://plus.google.com/102828491884671003608/posts) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/architecture-examples/knockback/bower.json b/architecture-examples/knockback/bower.json new file mode 100644 index 0000000000..947780ffb9 --- /dev/null +++ b/architecture-examples/knockback/bower.json @@ -0,0 +1,9 @@ +{ + "name": "todomvc-knockback", + "version": "0.0.0", + "dependencies": { + "jquery": "~2.0.0", + "todomvc-common": "~0.1.6", + "Backbone.localStorage": "~1.1.3" + } +} diff --git a/architecture-examples/knockback/bower_components/Backbone.localStorage/backbone.localStorage.js b/architecture-examples/knockback/bower_components/Backbone.localStorage/backbone.localStorage.js new file mode 100644 index 0000000000..792f51d6ce --- /dev/null +++ b/architecture-examples/knockback/bower_components/Backbone.localStorage/backbone.localStorage.js @@ -0,0 +1,217 @@ +/** + * Backbone localStorage Adapter + * Version 1.1.3 + * + * https://github.com/jeromegn/Backbone.localStorage + */ +(function (root, factory) { + if (typeof exports === 'object') { + module.exports = factory(require("underscore"), require("backbone")); + } else if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define(["underscore","backbone"], function(_, Backbone) { + // Use global variables if the locals are undefined. + return factory(_ || root._, Backbone || root.Backbone); + }); + } else { + // RequireJS isn't being used. Assume underscore and backbone are loaded in - + + - + @@ -67,4 +64,4 @@

      todos

      - \ No newline at end of file + diff --git a/architecture-examples/knockback/readme.md b/architecture-examples/knockback/readme.md index 53fcc1009b..24174635f5 100644 --- a/architecture-examples/knockback/readme.md +++ b/architecture-examples/knockback/readme.md @@ -1,14 +1,39 @@ -# Knockback.js • [TodoMVC](http://todomvc.com) +# Knockback.js TodoMVC Example -## Getting started +> Both Knockout.js and Backbone.js have their strengths and weaknesses, but together they are amazing! With Knockback.js, you can use the strong ORM provided by Backbone and create dynamic views using Knockout bindings. -You need [CoffeScript](http://coffeescript.org) to compile if you make changes to the files in the `src` folder. +> _[Knockback.js - kmalakoff.github.io/knockback](http://kmalakoff.github.io/knockback)_ -## Compile +## Learning Knockback.js -Open Terminal in this folder. +The [Knockback.js website](http://kmalakoff.github.io/knockback) is a great resource for getting started. -- `cake build` to compile once +Here are some links you may find helpful: -- `cake watch` to compile on save \ No newline at end of file +* [Getting Started with Knockback.js](http://kmalakoff.github.io/knockback/getting_started_introduction.html) +* [Tutorials](http://kmalakoff.github.io/knockback/tutorials_introduction.html) +* [API Reference](http://kmalakoff.github.io/knockback/doc/index.html) +* [Knockback.js Reference App](http://kmalakoff.github.io/knockback/app_knockback_reference.html) +* [Knockback.js on Twitter](http://twitter.com/knockbackjs) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Running + +This app is written in [CoffeeScript](http://coffeescript.org/). If you wish to make changes, follow these steps to re-compile the code. + +To install CoffeeScript globally: + + npm install -g coffee-script + +To compile once: + + # from architecture-examples/knockback + cake build + +To compile on save + + # from architecture-examples/knockback + cake watch diff --git a/architecture-examples/knockoutjs/bower_components/todomvc-common/base.css b/architecture-examples/knockoutjs/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/knockoutjs/bower_components/todomvc-common/base.css +++ b/architecture-examples/knockoutjs/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/knockoutjs/bower_components/todomvc-common/base.js b/architecture-examples/knockoutjs/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/knockoutjs/bower_components/todomvc-common/base.js +++ b/architecture-examples/knockoutjs/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
      ' + example.name + '
      ' + + '

      ' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

      '; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

      ' + linkGroup.heading + '

      ' + + '
        ' + + linkGroup.links.map(function (link) { + return '' + + '
      • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
      • '; + }).join('') + + '
      '; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/knockoutjs/index.html b/architecture-examples/knockoutjs/index.html index 6a8b22a71d..c11101e333 100644 --- a/architecture-examples/knockoutjs/index.html +++ b/architecture-examples/knockoutjs/index.html @@ -1,62 +1,62 @@ - - - - - Knockout.js • TodoMVC - - - -
      - -
      - - -
        -
      • -
        - - - -
        - -
      • -
      -
      - + + + + + Knockout.js • TodoMVC + + + +
      + +
      + + +
        +
      • +
        + + + +
        + +
      • +
      -
      -

      Double-click to edit a todo

      -

      Original Knockout version from Ashish Sharma

      -

      Rewritten to use Knockout 2.0 and standard template by Ryan Niemeyer

      -

      Patches/fixes for cross-browser compat: Addy Osmani

      -

      Part of TodoMVC

      + - - - - - +
      +
      +

      Double-click to edit a todo

      +

      Original Knockout version from Ashish Sharma

      +

      Rewritten to use Knockout 2.0 and standard template by Ryan Niemeyer

      +

      Patches/fixes for cross-browser compat: Addy Osmani

      +

      Part of TodoMVC

      +
      + + + + + diff --git a/architecture-examples/knockoutjs/readme.md b/architecture-examples/knockoutjs/readme.md index a4cccc9abc..1bf455a974 100644 --- a/architecture-examples/knockoutjs/readme.md +++ b/architecture-examples/knockoutjs/readme.md @@ -1,3 +1,36 @@ -# Knockout.js TodoMVC app +# Knockout.js TodoMVC Example -[ashish101](https://github.com/ashish01/knockoutjs-todos) wrote the original version of this application, which was then refactored by Addy Osmani and later rewritten by TodoMVC contributors. +> Knockout.js helps you simplify dynamic JavaScript UIs using the Model-View-ViewModel (MVVM) pattern. + +> _[Knockout.js - knockoutjs.com](http://knockoutjs.com)_ + + +## Learning Knockout.js + +The [Knockout.js website](http://knockoutjs.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](http://knockoutjs.com/documentation/introduction.html) +* [Tutorials](http://learn.knockoutjs.com) +* [Live examples](http://knockoutjs.com/examples) + +Articles and guides from the community: + +* [Getting Started with Knockout.js](http://www.adobe.com/devnet/html5/articles/getting-started-with-knockoutjs.html) +* [Into the Ring with Knockout.js](http://net.tutsplus.com/tutorials/javascript-ajax/into-the-ring-with-knockout-js) +* [Beginners Guide to Knockout.js](http://www.sitepoint.com/beginners-guide-to-knockoutjs-part-1) + +Get help from other Knockout.js users: + +* [Knockout.js on StackOverflow](http://stackoverflow.com/questions/tagged/knockout) +* [Mailing list on Google Groups](http://groups.google.com/group/knockoutjs) +* [Knockout.js on Twitter](http://twitter.com/knockoutjs) +* [Knockout.js on Google +](https://plus.google.com/communities/106789046312204355684/stream/c5bfcfdf-3690-44a6-b015-35aad4f4e42e) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Credit + +This TodoMVC application was originally created by [ashish101](https://github.com/ashish01/knockoutjs-todos), then refactored by Addy Osmani and later rewritten by TodoMVC contributors. diff --git a/architecture-examples/maria/bower_components/todomvc-common/base.css b/architecture-examples/maria/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/maria/bower_components/todomvc-common/base.css +++ b/architecture-examples/maria/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/maria/bower_components/todomvc-common/base.js b/architecture-examples/maria/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/maria/bower_components/todomvc-common/base.js +++ b/architecture-examples/maria/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
      ' + example.name + '
      ' + + '

      ' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

      '; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

      ' + linkGroup.heading + '

      ' + + '
        ' + + linkGroup.links.map(function (link) { + return '' + + '
      • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
      • '; + }).join('') + + '
      '; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/maria/index.html b/architecture-examples/maria/index.html index dbacde3ef0..5c1b528532 100644 --- a/architecture-examples/maria/index.html +++ b/architecture-examples/maria/index.html @@ -1,5 +1,5 @@ - + Maria • TodoMVC diff --git a/architecture-examples/maria/readme.md b/architecture-examples/maria/readme.md new file mode 100644 index 0000000000..1e8b58c55e --- /dev/null +++ b/architecture-examples/maria/readme.md @@ -0,0 +1,18 @@ +# Maria TodoMVC Example + +> The MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC. + +> _[Maria - peter.michaux.ca/maria](http://peter.michaux.ca/maria)_ + + +## Learning Maria + +The [Maria website](http://peter.michaux.ca/maria) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Quick Start Tutorial](http://peter.michaux.ca/maria/quick-start-tutorial-for-the-impatient.html) +* [API Reference](http://peter.michaux.ca/maria/api/maria.html) +* [GitHub](https://github.com/petermichaux/maria) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/architecture-examples/spine/bower_components/todomvc-common/base.css b/architecture-examples/spine/bower_components/todomvc-common/base.css index 8d1db3a696..a726662053 100644 --- a/architecture-examples/spine/bower_components/todomvc-common/base.css +++ b/architecture-examples/spine/bower_components/todomvc-common/base.css @@ -412,3 +412,144 @@ label[for='toggle-all'] { .hidden{ display:none; } + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/spine/bower_components/todomvc-common/base.js b/architecture-examples/spine/bower_components/todomvc-common/base.js index 4da326723e..5ca690ece1 100644 --- a/architecture-examples/spine/bower_components/todomvc-common/base.js +++ b/architecture-examples/spine/bower_components/todomvc-common/base.js @@ -33,6 +33,150 @@ } } + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
      ' + example.name + '
      ' + + '

      ' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

      '; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

      ' + linkGroup.heading + '

      ' + + '
        ' + + linkGroup.links.map(function (link) { + return '' + + '
      • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
      • '; + }).join('') + + '
      '; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + appendSourceLink(); redirect(); + getFile('learn.json', Learn); })(); diff --git a/architecture-examples/spine/index.html b/architecture-examples/spine/index.html index e11f9697a9..3ca60e2fa9 100644 --- a/architecture-examples/spine/index.html +++ b/architecture-examples/spine/index.html @@ -1,5 +1,5 @@ - + diff --git a/architecture-examples/spine/readme.md b/architecture-examples/spine/readme.md index 5a2fb7e2d9..7a18bad8de 100644 --- a/architecture-examples/spine/readme.md +++ b/architecture-examples/spine/readme.md @@ -1,20 +1,52 @@ -# Spine.js TodoMVC app +# Spine.js TodoMVC Example +> Build Awesome JavaScript MVC Applications. -## Getting started +> _[Spine - spinejs.com](http://spinejs.com)_ -[CoffeeScript](http://coffeescript.org) is required to compile this application if you make changes to the files in the `src` folder. +## Learning Spine -### Compile +The [Spine website](http://spinejs.com) is a great resource for getting started. -Open Terminal in this folder. +Here are some links you may find helpful: -- `cake build` to compile once +* [Documentation](http://spinejs.com/docs/) +* [Step by Step Tutorials](http://spinejs.com/docs/example) +* [API Reference](http://spinejs.com/api/index) -- `cake watch` to compile on save +Articles and guides from the community: + +* [Building JavaScript Web Apps With MVC & Spine.js](http://addyosmani.com/blog/building-apps-spinejs) + +Get help from other Spine users: + +* [Spine on StackOverflow](http://stackoverflow.com/questions/tagged/spine.js) +* [Mailing list on Google Groups](https://groups.google.com/forum/#!forum/spinejs) +* [Spine's author, Alex MacCaw, on Twitter](http://twitter.com/maccman) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ + + +## Running + +This app is written in [CoffeeScript](http://coffeescript.org/). If you wish to make changes, follow these steps to re-compile the code. + +To install CoffeeScript globally: + + npm install -g coffee-script + +To compile once: + + # from architecture-examples/knockback + cake build + +To compile on save + + # from architecture-examples/knockback + cake watch ## Credit -Created by [Sindre Sorhus](https://github.com/sindresorhus) +This TodoMVC application was created by [Sindre Sorhus](https://github.com/sindresorhus). diff --git a/architecture-examples/yui/bower.json b/architecture-examples/yui/bower.json new file mode 100644 index 0000000000..b1a6bc4656 --- /dev/null +++ b/architecture-examples/yui/bower.json @@ -0,0 +1,7 @@ +{ + "name": "todomvc-yui", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6" + } +} diff --git a/architecture-examples/yui/bower_components/todomvc-common/base.css b/architecture-examples/yui/bower_components/todomvc-common/base.css new file mode 100644 index 0000000000..a726662053 --- /dev/null +++ b/architecture-examples/yui/bower_components/todomvc-common/base.css @@ -0,0 +1,555 @@ +html, +body { + margin: 0; + padding: 0; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + color: inherit; + -webkit-appearance: none; + /*-moz-appearance: none;*/ + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eaeaea url('bg.png'); + color: #4d4d4d; + width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +#todoapp { + background: #fff; + background: rgba(255, 255, 255, 0.9); + margin: 130px 0 40px 0; + border: 1px solid #ccc; + position: relative; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.15); +} + +#todoapp:before { + content: ''; + border-left: 1px solid #f5d6d6; + border-right: 1px solid #f5d6d6; + width: 2px; + position: absolute; + top: 0; + left: 40px; + height: 100%; +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todoapp input:-moz-placeholder { + font-style: italic; + color: #a9a9a9; +} + +#todoapp h1 { + position: absolute; + top: -120px; + width: 100%; + font-size: 70px; + font-weight: bold; + text-align: center; + color: #b3b3b3; + color: rgba(255, 255, 255, 0.3); + text-shadow: -1px -1px rgba(0, 0, 0, 0.2); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + -ms-text-rendering: optimizeLegibility; + -o-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +#header { + padding-top: 15px; + border-radius: inherit; +} + +#header:before { + content: ''; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 15px; + z-index: 2; + border-bottom: 1px solid #6c615c; + background: #8d7d77; + background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8))); + background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); + border-top-left-radius: 1px; + border-top-right-radius: 1px; +} + +#new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + color: inherit; + padding: 6px; + border: 1px solid #999; + box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +#new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.02); + z-index: 2; + box-shadow: none; +} + +#main { + position: relative; + z-index: 2; + border-top: 1px dotted #adadad; +} + +label[for='toggle-all'] { + display: none; +} + +#toggle-all { + position: absolute; + top: -42px; + left: -4px; + width: 40px; + text-align: center; + border: none; /* Mobile Safari */ +} + +#toggle-all:before { + content: '»'; + font-size: 28px; + color: #d9d9d9; + padding: 0 25px 7px; +} + +#toggle-all:checked:before { + color: #737373; +} + +#todo-list { + margin: 0; + padding: 0; + list-style: none; +} + +#todo-list li { + position: relative; + font-size: 24px; + border-bottom: 1px dotted #ccc; +} + +#todo-list li:last-child { + border-bottom: none; +} + +#todo-list li.editing { + border-bottom: none; + padding: 0; +} + +#todo-list li.editing .edit { + display: block; + width: 506px; + padding: 13px 17px 12px 17px; + margin: 0 0 0 43px; +} + +#todo-list li.editing .view { + display: none; +} + +#todo-list li .toggle { + text-align: center; + width: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; + position: absolute; + top: 0; + bottom: 0; + margin: auto 0; + border: none; /* Mobile Safari */ + -webkit-appearance: none; + /*-moz-appearance: none;*/ + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} + +#todo-list li .toggle:after { + content: '✔'; + line-height: 43px; /* 40 + a couple of pixels visual adjustment */ + font-size: 20px; + color: #d9d9d9; + text-shadow: 0 -1px 0 #bfbfbf; +} + +#todo-list li .toggle:checked:after { + color: #85ada7; + text-shadow: 0 1px 0 #669991; + bottom: 1px; + position: relative; +} + +#todo-list li label { + word-break: break-word; + padding: 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + -webkit-transition: color 0.4s; + -moz-transition: color 0.4s; + -ms-transition: color 0.4s; + -o-transition: color 0.4s; + transition: color 0.4s; +} + +#todo-list li.completed label { + color: #a9a9a9; + text-decoration: line-through; +} + +#todo-list li .destroy { + display: none; + position: absolute; + top: 0; + right: 10px; + bottom: 0; + width: 40px; + height: 40px; + margin: auto 0; + font-size: 22px; + color: #a88a8a; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + -ms-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; +} + +#todo-list li .destroy:hover { + text-shadow: 0 0 1px #000, + 0 0 10px rgba(199, 107, 107, 0.8); + -webkit-transform: scale(1.3); + -moz-transform: scale(1.3); + -ms-transform: scale(1.3); + -o-transform: scale(1.3); + transform: scale(1.3); +} + +#todo-list li .destroy:after { + content: '✖'; +} + +#todo-list li:hover .destroy { + display: block; +} + +#todo-list li .edit { + display: none; +} + +#todo-list li.editing:last-child { + margin-bottom: -1px; +} + +#footer { + color: #777; + padding: 0 15px; + position: absolute; + right: 0; + bottom: -31px; + left: 0; + height: 20px; + z-index: 1; + text-align: center; +} + +#footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 31px; + left: 0; + height: 50px; + z-index: -1; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), + 0 6px 0 -3px rgba(255, 255, 255, 0.8), + 0 7px 1px -3px rgba(0, 0, 0, 0.3), + 0 43px 0 -6px rgba(255, 255, 255, 0.8), + 0 44px 2px -6px rgba(0, 0, 0, 0.2); +} + +#todo-count { + float: left; + text-align: left; +} + +#filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +#filters li { + display: inline; +} + +#filters li a { + color: #83756f; + margin: 2px; + text-decoration: none; +} + +#filters li a.selected { + font-weight: bold; +} + +#clear-completed { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + font-size: 11px; + padding: 0 10px; + border-radius: 3px; + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); +} + +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3); +} + +#info { + margin: 65px auto 0; + color: #a6a6a6; + font-size: 12px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); + text-align: center; +} + +#info a { + color: inherit; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox and Opera +*/ +@media screen and (-webkit-min-device-pixel-ratio:0) { + #toggle-all, + #todo-list li .toggle { + background: none; + } + + #todo-list li .toggle { + height: 40px; + } + + #toggle-all { + top: -56px; + left: -15px; + width: 65px; + height: 41px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +.hidden{ + display:none; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/architecture-examples/yui/bower_components/todomvc-common/base.js b/architecture-examples/yui/bower_components/todomvc-common/base.js new file mode 100644 index 0000000000..5ca690ece1 --- /dev/null +++ b/architecture-examples/yui/bower_components/todomvc-common/base.js @@ -0,0 +1,182 @@ +(function () { + 'use strict'; + + if (location.hostname === 'todomvc.com') { + window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); + } + + function getSourcePath() { + // If accessed via tastejs.github.io/todomvc/, strip the project path. + if (location.hostname.indexOf('github.io') > 0) { + return location.pathname.replace(/todomvc\//, ''); + } + return location.pathname; + } + + function appendSourceLink() { + var sourceLink = document.createElement('a'); + var paragraph = document.createElement('p'); + var footer = document.getElementById('info'); + var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; + + if (footer) { + sourceLink.href = urlBase + getSourcePath(); + sourceLink.appendChild(document.createTextNode('Check out the source')); + paragraph.appendChild(sourceLink); + footer.appendChild(paragraph); + } + } + + function redirect() { + if (location.hostname === 'tastejs.github.io') { + location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); + } + } + + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
      ' + example.name + '
      ' + + '

      ' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

      '; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

      ' + linkGroup.heading + '

      ' + + '
        ' + + linkGroup.links.map(function (link) { + return '' + + '
      • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
      • '; + }).join('') + + '
      '; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + + appendSourceLink(); + redirect(); + getFile('learn.json', Learn); +})(); diff --git a/architecture-examples/yui/bower_components/todomvc-common/bg.png b/architecture-examples/yui/bower_components/todomvc-common/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a7600825ee11f21849ed475499c7d1ecbcc870 GIT binary patch literal 2126 zcmV-U2(kBxP)+9y`=HK7nt=~3t000O5Nklm=04hVa_lXl_bm=+M;=eI<%$rO2ta`suh*Sr#POw*?adq!O!CV z*0&b)rkCCEV)1nIuiLBntUH-MJI;&qYgz|d@Nhnn_abi2g`pu4NAMVid3hS%?quz~ zjlJf(x8cj{VS zUVEP1msg9`^OFUhSO5rtXHhRlyU2i>6$BT=glG`{JlctGHrwRIm)6Buu65jLQn^H8 zvl9lZqUBA+%qvM5XC+yY@mfA(YB~XP=e|6<{%$^eU8nrK?v2ccb@Jom5CG>rKAL7J zplHEIavVp|0p1&m!G`Ti?<7iZ;}@G7#Z)}Km%2!FHnQ0*&?PLR)G!HAaHgU#c|$dz zpj#0HmeadIe>`#)=Jjkb{B=FKnU3pc-&Y@j_j6(h4Y~+Uq!^J=LHunx1xi4QXK-Y{&MoT8ky6Vb9c|WhnOwF~c=3zOy8agktliS6# z`#8F`9H)D=bmk9B5MnW&_r#)f$c+;$LSr-@^An8dhc~Iquuv>jOK7pw7LJ;&X0i1C zGMsHdP1Os@ny$$j!>XAii%7bp5k>`pyNA!~epb)()p9zR4Yl6z=U}{CIdh1z(FpAo zQIW!;0zpCyC4*7YLkZCO@cul0R_&zghsA8Ek)z%jNpKa92{@NH+SstX%@}xB*Jk!l}PZ1cClIns~}5^!RncUk*rmA z%SIVgt58EQxLJ+OiFqKkBuwquyZLUp|gr zPUbUbFbBrPd1xO`^C*r-i3p9*F#(OBh!4Wy@aC&*!|O|GXcjDA&YhF{;cD7*o(GS^ z@pQSE7)x_81=Qyje6*LQ#TXu-7(o;S8u3tpDA0_ddj%hmCspeXdhYR}-i9A=C`EoChUYuH~^x!9+|&(Pgb*>Ck<=9j|)*@xyfT zpP#+Kt<}39b|3Wl4fxT(+G?aH>gG^d@MEaUOJRfy55TtFI7^Y)VuMU=7Pp0y55jS~ z+TJ)igMyrqkX;wU8j68iIDtqJYhS_D3_Oem-@g6me_RfiQ}uT_K-A-9qG%}gk3E9c z!8`KgsMNXm)beloPfMql*|&$M>1q`i!cY)RFYnjNYu*gSv@8XebV7%}xYL>6)GJPJ zJpA7K31lcJuIFKSw-{x4FX0K2Az)~Xg<`sOu$4|^-(^XJX4YzoiNRvL zyuY7~26w-P^Zw%6F}shBwV2$02c8RsSUy6dM92diCAxiX3IUqsq5ig6>U_!Vy*q5$ zjm}16tJr+QZ&T?HkkpeIwVX-r1EI=@%Zlt;6g*mj&E!A))%gXJ=x6u#l zcKEP>bx4rqV*k`BBrZ$Mqjt{TsHcxUH>;)iAK}B(Kila&VD%b?6m&^0WK4^&EZNAI z8AMYs_%$D%|M+@+cQqL-hi4yG>h*jwdii!W1{}p>ZhwFYt_4Su1kjY9<-5`!$VNOI1y(EDSH4WpCijE_>al!Nt=^eVER#uJ1=b z;BWF2IgyF5LexV+yec$Kin;Ai@myo;G>zJ&jrdW#ecXhIZph5OYqw_PEfcF56Z5Zu_ZZE#q3Mc+N&1O^7hoh9QR7`+L$cBP5pqG=fqA0uh zUBukaxTFmH)<|Xbvp2c=HSbNkpXw73a5lv7V$jb92#yZ141@$X?F}Jt8gIU7Wm6m9 z?e_;;zsnm6`LZeP>T=$)Kr>Z?kr*UmFqR7zx0C6^bmcsc@1AGtw_rNH>-Xm$d*|Q< zn&1Ln0u7=l&ILs>%CkJp`DiG9F18x4Ne+lg<#i?e7jL%x;4ZnRkN^Mx07*qoM6N<$ Ef(>0N!2kdN literal 0 HcmV?d00001 diff --git a/architecture-examples/yui/index.html b/architecture-examples/yui/index.html index 6008e63517..829ef63060 100644 --- a/architecture-examples/yui/index.html +++ b/architecture-examples/yui/index.html @@ -1,13 +1,10 @@ - + YUI • TodoMVC - - +
      @@ -30,6 +27,7 @@

      todos

      Part of TodoMVC

      + - - +
      +
      + + + + diff --git a/dependency-examples/flight/readme.md b/dependency-examples/flight/readme.md new file mode 100644 index 0000000000..4dbf76bcd9 --- /dev/null +++ b/dependency-examples/flight/readme.md @@ -0,0 +1,19 @@ +# Flight TodoMVC Example + +> Flight is a lightweight, component-based JavaScript framework that maps behavior to DOM nodes. + +> _[Flight - twitter.github.io/flight](http://twitter.github.io/flight)_ + + +## Learning Flight + +The [Flight website](http://twitter.github.io/flight) is a great resource for getting started. + +Here are some links you may find helpful: + +* [GitHub](https://github.com/twitter/flight) +* [Demo Application](http://twitter.github.com/flight/demo) +* [Installation](https://github.com/twitter/flight/blob/master/README.md#installation) +* [Flight on Twitter](http://twitter.com/flight) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/labs/architecture-examples/ariatemplates/bower.json b/labs/architecture-examples/ariatemplates/bower.json new file mode 100644 index 0000000000..e43423491b --- /dev/null +++ b/labs/architecture-examples/ariatemplates/bower.json @@ -0,0 +1,7 @@ +{ + "name": "todomvc-ariatemplates", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6" + } +} diff --git a/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.css b/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.css new file mode 100644 index 0000000000..a726662053 --- /dev/null +++ b/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.css @@ -0,0 +1,555 @@ +html, +body { + margin: 0; + padding: 0; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + color: inherit; + -webkit-appearance: none; + /*-moz-appearance: none;*/ + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eaeaea url('bg.png'); + color: #4d4d4d; + width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +#todoapp { + background: #fff; + background: rgba(255, 255, 255, 0.9); + margin: 130px 0 40px 0; + border: 1px solid #ccc; + position: relative; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.15); +} + +#todoapp:before { + content: ''; + border-left: 1px solid #f5d6d6; + border-right: 1px solid #f5d6d6; + width: 2px; + position: absolute; + top: 0; + left: 40px; + height: 100%; +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todoapp input:-moz-placeholder { + font-style: italic; + color: #a9a9a9; +} + +#todoapp h1 { + position: absolute; + top: -120px; + width: 100%; + font-size: 70px; + font-weight: bold; + text-align: center; + color: #b3b3b3; + color: rgba(255, 255, 255, 0.3); + text-shadow: -1px -1px rgba(0, 0, 0, 0.2); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + -ms-text-rendering: optimizeLegibility; + -o-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +#header { + padding-top: 15px; + border-radius: inherit; +} + +#header:before { + content: ''; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 15px; + z-index: 2; + border-bottom: 1px solid #6c615c; + background: #8d7d77; + background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8))); + background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); + border-top-left-radius: 1px; + border-top-right-radius: 1px; +} + +#new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + color: inherit; + padding: 6px; + border: 1px solid #999; + box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +#new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.02); + z-index: 2; + box-shadow: none; +} + +#main { + position: relative; + z-index: 2; + border-top: 1px dotted #adadad; +} + +label[for='toggle-all'] { + display: none; +} + +#toggle-all { + position: absolute; + top: -42px; + left: -4px; + width: 40px; + text-align: center; + border: none; /* Mobile Safari */ +} + +#toggle-all:before { + content: '»'; + font-size: 28px; + color: #d9d9d9; + padding: 0 25px 7px; +} + +#toggle-all:checked:before { + color: #737373; +} + +#todo-list { + margin: 0; + padding: 0; + list-style: none; +} + +#todo-list li { + position: relative; + font-size: 24px; + border-bottom: 1px dotted #ccc; +} + +#todo-list li:last-child { + border-bottom: none; +} + +#todo-list li.editing { + border-bottom: none; + padding: 0; +} + +#todo-list li.editing .edit { + display: block; + width: 506px; + padding: 13px 17px 12px 17px; + margin: 0 0 0 43px; +} + +#todo-list li.editing .view { + display: none; +} + +#todo-list li .toggle { + text-align: center; + width: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; + position: absolute; + top: 0; + bottom: 0; + margin: auto 0; + border: none; /* Mobile Safari */ + -webkit-appearance: none; + /*-moz-appearance: none;*/ + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} + +#todo-list li .toggle:after { + content: '✔'; + line-height: 43px; /* 40 + a couple of pixels visual adjustment */ + font-size: 20px; + color: #d9d9d9; + text-shadow: 0 -1px 0 #bfbfbf; +} + +#todo-list li .toggle:checked:after { + color: #85ada7; + text-shadow: 0 1px 0 #669991; + bottom: 1px; + position: relative; +} + +#todo-list li label { + word-break: break-word; + padding: 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + -webkit-transition: color 0.4s; + -moz-transition: color 0.4s; + -ms-transition: color 0.4s; + -o-transition: color 0.4s; + transition: color 0.4s; +} + +#todo-list li.completed label { + color: #a9a9a9; + text-decoration: line-through; +} + +#todo-list li .destroy { + display: none; + position: absolute; + top: 0; + right: 10px; + bottom: 0; + width: 40px; + height: 40px; + margin: auto 0; + font-size: 22px; + color: #a88a8a; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + -ms-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; +} + +#todo-list li .destroy:hover { + text-shadow: 0 0 1px #000, + 0 0 10px rgba(199, 107, 107, 0.8); + -webkit-transform: scale(1.3); + -moz-transform: scale(1.3); + -ms-transform: scale(1.3); + -o-transform: scale(1.3); + transform: scale(1.3); +} + +#todo-list li .destroy:after { + content: '✖'; +} + +#todo-list li:hover .destroy { + display: block; +} + +#todo-list li .edit { + display: none; +} + +#todo-list li.editing:last-child { + margin-bottom: -1px; +} + +#footer { + color: #777; + padding: 0 15px; + position: absolute; + right: 0; + bottom: -31px; + left: 0; + height: 20px; + z-index: 1; + text-align: center; +} + +#footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 31px; + left: 0; + height: 50px; + z-index: -1; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), + 0 6px 0 -3px rgba(255, 255, 255, 0.8), + 0 7px 1px -3px rgba(0, 0, 0, 0.3), + 0 43px 0 -6px rgba(255, 255, 255, 0.8), + 0 44px 2px -6px rgba(0, 0, 0, 0.2); +} + +#todo-count { + float: left; + text-align: left; +} + +#filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +#filters li { + display: inline; +} + +#filters li a { + color: #83756f; + margin: 2px; + text-decoration: none; +} + +#filters li a.selected { + font-weight: bold; +} + +#clear-completed { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + font-size: 11px; + padding: 0 10px; + border-radius: 3px; + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); +} + +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3); +} + +#info { + margin: 65px auto 0; + color: #a6a6a6; + font-size: 12px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); + text-align: center; +} + +#info a { + color: inherit; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox and Opera +*/ +@media screen and (-webkit-min-device-pixel-ratio:0) { + #toggle-all, + #todo-list li .toggle { + background: none; + } + + #todo-list li .toggle { + height: 40px; + } + + #toggle-all { + top: -56px; + left: -15px; + width: 65px; + height: 41px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +.hidden{ + display:none; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px dashed #C5C5C5; + border-bottom: 1px dashed #F7F7F7; +} + +.learn a { + font-weight: normal; + text-decoration: none; + color: #b83f45; +} + +.learn a:hover { + text-decoration: underline; + color: #787e7e; +} + +.learn h3, +.learn h4, +.learn h5 { + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + color: #000; +} + +.learn h3 { + font-size: 24px; +} + +.learn h4 { + font-size: 18px; +} + +.learn h5 { + margin-bottom: 0; + font-size: 14px; +} + +.learn ul { + padding: 0; + margin: 0 0 30px 25px; +} + +.learn li { + line-height: 20px; +} + +.learn p { + font-size: 15px; + font-weight: 300; + line-height: 1.3; + margin-top: 0; + margin-bottom: 0; +} + +.quote { + border: none; + margin: 20px 0 60px 0; +} + +.quote p { + font-style: italic; +} + +.quote p:before { + content: '“'; + font-size: 50px; + opacity: .15; + position: absolute; + top: -20px; + left: 3px; +} + +.quote p:after { + content: '”'; + font-size: 50px; + opacity: .15; + position: absolute; + bottom: -42px; + right: 3px; +} + +.quote footer { + position: absolute; + bottom: -40px; + right: 0; +} + +.quote footer img { + border-radius: 3px; +} + +.quote footer a { + margin-left: 5px; + vertical-align: middle; +} + +.speech-bubble { + position: relative; + padding: 10px; + background: rgba(0, 0, 0, .04); + border-radius: 5px; +} + +.speech-bubble:after { + content: ''; + position: absolute; + top: 100%; + right: 30px; + border: 13px solid transparent; + border-top-color: rgba(0, 0, 0, .04); +} + +/**body*/.learn-bar > .learn { + position: absolute; + width: 272px; + top: 8px; + left: -300px; + padding: 10px; + border-radius: 5px; + background-color: rgba(255, 255, 255, .6); + transition-property: left; + transition-duration: 500ms; +} + +@media (min-width: 899px) { + /**body*/.learn-bar { + width: auto; + margin: 0 0 0 300px; + } + /**body*/.learn-bar > .learn { + left: 8px; + } + /**body*/.learn-bar #todoapp { + width: 550px; + margin: 130px auto 40px auto; + } +} diff --git a/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.js b/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.js new file mode 100644 index 0000000000..5ca690ece1 --- /dev/null +++ b/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/base.js @@ -0,0 +1,182 @@ +(function () { + 'use strict'; + + if (location.hostname === 'todomvc.com') { + window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); + } + + function getSourcePath() { + // If accessed via tastejs.github.io/todomvc/, strip the project path. + if (location.hostname.indexOf('github.io') > 0) { + return location.pathname.replace(/todomvc\//, ''); + } + return location.pathname; + } + + function appendSourceLink() { + var sourceLink = document.createElement('a'); + var paragraph = document.createElement('p'); + var footer = document.getElementById('info'); + var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages'; + + if (footer) { + sourceLink.href = urlBase + getSourcePath(); + sourceLink.appendChild(document.createTextNode('Check out the source')); + paragraph.appendChild(sourceLink); + footer.appendChild(paragraph); + } + } + + function redirect() { + if (location.hostname === 'tastejs.github.io') { + location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); + } + } + + function findRoot() { + var base; + + [/labs/, /\w*-examples/].forEach(function (href) { + var match = location.href.match(href); + + if (!base && match) { + base = location.href.indexOf(match); + } + }); + + return location.href.substr(0, base); + } + + function getFile(file, callback) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', findRoot() + file, true); + xhr.send(); + + xhr.onload = function () { + if (xhr.status === 200 && callback) { + callback(xhr.responseText); + } + }; + } + + function Learn(learnJSON, config) { + if (!(this instanceof Learn)) { + return new Learn(learnJSON, config); + } + + var template, framework; + + if (typeof learnJSON !== 'object') { + try { + learnJSON = JSON.parse(learnJSON); + } catch (e) { + return; + } + } + + if (config) { + template = config.template; + framework = config.framework; + } + + if (!template && learnJSON.templates) { + template = learnJSON.templates.todomvc; + } + + if (!framework && document.querySelector('[data-framework]')) { + framework = document.querySelector('[data-framework]').getAttribute('data-framework'); + } + + if (template && learnJSON[framework]) { + this.frameworkJSON = learnJSON[framework]; + this.template = template; + + this.append(); + } + } + + Learn.prototype._prepareTemplate = function () { + var aside = document.createElement('aside'); + aside.innerHTML = this.template; + + var header = aside.cloneNode(true); + header.removeChild(header.querySelector('ul')); + header.removeChild(header.querySelectorAll('footer')[1]); + + return { + header: header, + links: aside.cloneNode(true).querySelector('ul a'), + footer: aside.cloneNode(true).querySelectorAll('footer')[1] + }; + }; + + Learn.prototype._parseTemplate = function () { + if (!this.template) { + return; + } + + var frameworkJSON = this.frameworkJSON; + var template = this._prepareTemplate(); + + var aside = document.createElement('aside'); + var linksTemplate = template.links.outerHTML; + var parser = /\{\{([^}]*)\}\}/g; + + var header, examples, links; + + header = template.header.innerHTML.replace(parser, function (match, key) { + return frameworkJSON[key]; + }); + + aside.innerHTML = header; + + if (frameworkJSON.examples) { + examples = frameworkJSON.examples.map(function (example) { + return '' + + '
      ' + example.name + '
      ' + + '

      ' + + (location.href.match(example.url + '/') ? '' : ' Demo, ') + + ' Source' + + '

      '; + }).join(''); + + aside.querySelector('.source-links').innerHTML = examples; + } + + if (frameworkJSON.link_groups) { + links = frameworkJSON.link_groups.map(function (linkGroup) { + return '' + + '

      ' + linkGroup.heading + '

      ' + + '
        ' + + linkGroup.links.map(function (link) { + return '' + + '
      • ' + + linksTemplate.replace(parser, function (match, key) { + return link[key]; + }) + + '
      • '; + }).join('') + + '
      '; + }).join(''); + + aside.innerHTML += links; + aside.innerHTML += template.footer.outerHTML; + } + + return aside; + }; + + Learn.prototype.append = function () { + var aside = this._parseTemplate(); + + aside.className = 'learn'; + + document.body.className = (document.body.className + ' learn-bar').trim(); + document.body.insertAdjacentElement('afterBegin', aside); + }; + + appendSourceLink(); + redirect(); + getFile('learn.json', Learn); +})(); diff --git a/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/bg.png b/labs/architecture-examples/ariatemplates/bower_components/todomvc-common/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a7600825ee11f21849ed475499c7d1ecbcc870 GIT binary patch literal 2126 zcmV-U2(kBxP)+9y`=HK7nt=~3t000O5Nklm=04hVa_lXl_bm=+M;=eI<%$rO2ta`suh*Sr#POw*?adq!O!CV z*0&b)rkCCEV)1nIuiLBntUH-MJI;&qYgz|d@Nhnn_abi2g`pu4NAMVid3hS%?quz~ zjlJf(x8cj{VS zUVEP1msg9`^OFUhSO5rtXHhRlyU2i>6$BT=glG`{JlctGHrwRIm)6Buu65jLQn^H8 zvl9lZqUBA+%qvM5XC+yY@mfA(YB~XP=e|6<{%$^eU8nrK?v2ccb@Jom5CG>rKAL7J zplHEIavVp|0p1&m!G`Ti?<7iZ;}@G7#Z)}Km%2!FHnQ0*&?PLR)G!HAaHgU#c|$dz zpj#0HmeadIe>`#)=Jjkb{B=FKnU3pc-&Y@j_j6(h4Y~+Uq!^J=LHunx1xi4QXK-Y{&MoT8ky6Vb9c|WhnOwF~c=3zOy8agktliS6# z`#8F`9H)D=bmk9B5MnW&_r#)f$c+;$LSr-@^An8dhc~Iquuv>jOK7pw7LJ;&X0i1C zGMsHdP1Os@ny$$j!>XAii%7bp5k>`pyNA!~epb)()p9zR4Yl6z=U}{CIdh1z(FpAo zQIW!;0zpCyC4*7YLkZCO@cul0R_&zghsA8Ek)z%jNpKa92{@NH+SstX%@}xB*Jk!l}PZ1cClIns~}5^!RncUk*rmA z%SIVgt58EQxLJ+OiFqKkBuwquyZLUp|gr zPUbUbFbBrPd1xO`^C*r-i3p9*F#(OBh!4Wy@aC&*!|O|GXcjDA&YhF{;cD7*o(GS^ z@pQSE7)x_81=Qyje6*LQ#TXu-7(o;S8u3tpDA0_ddj%hmCspeXdhYR}-i9A=C`EoChUYuH~^x!9+|&(Pgb*>Ck<=9j|)*@xyfT zpP#+Kt<}39b|3Wl4fxT(+G?aH>gG^d@MEaUOJRfy55TtFI7^Y)VuMU=7Pp0y55jS~ z+TJ)igMyrqkX;wU8j68iIDtqJYhS_D3_Oem-@g6me_RfiQ}uT_K-A-9qG%}gk3E9c z!8`KgsMNXm)beloPfMql*|&$M>1q`i!cY)RFYnjNYu*gSv@8XebV7%}xYL>6)GJPJ zJpA7K31lcJuIFKSw-{x4FX0K2Az)~Xg<`sOu$4|^-(^XJX4YzoiNRvL zyuY7~26w-P^Zw%6F}shBwV2$02c8RsSUy6dM92diCAxiX3IUqsq5ig6>U_!Vy*q5$ zjm}16tJr+QZ&T?HkkpeIwVX-r1EI=@%Zlt;6g*mj&E!A))%gXJ=x6u#l zcKEP>bx4rqV*k`BBrZ$Mqjt{TsHcxUH>;)iAK}B(Kila&VD%b?6m&^0WK4^&EZNAI z8AMYs_%$D%|M+@+cQqL-hi4yG>h*jwdii!W1{}p>ZhwFYt_4Su1kjY9<-5`!$VNOI1y(EDSH4WpCijE_>al!Nt=^eVER#uJ1=b z;BWF2IgyF5LexV+yec$Kin;Ai@myo;G>zJ&jrdW#ecXhIZph5OYqw_PEfcF56Z5Zu_ZZE#q3Mc+N&1O^7hoh9QR7`+L$cBP5pqG=fqA0uh zUBukaxTFmH)<|Xbvp2c=HSbNkpXw73a5lv7V$jb92#yZ141@$X?F}Jt8gIU7Wm6m9 z?e_;;zsnm6`LZeP>T=$)Kr>Z?kr*UmFqR7zx0C6^bmcsc@1AGtw_rNH>-Xm$d*|Q< zn&1Ln0u7=l&ILs>%CkJp`DiG9F18x4Ne+lg<#i?e7jL%x;4ZnRkN^Mx07*qoM6N<$ Ef(>0N!2kdN literal 0 HcmV?d00001 diff --git a/labs/architecture-examples/ariatemplates/css/app.css b/labs/architecture-examples/ariatemplates/css/app.css deleted file mode 100644 index 532c9b83c7..0000000000 --- a/labs/architecture-examples/ariatemplates/css/app.css +++ /dev/null @@ -1,215 +0,0 @@ -html, -body { - margin: 0; - padding: 0; -} - -button { - margin: 0; - padding: 0; - border: 0; - background: none; - font-size: 100%; - vertical-align: baseline; - font-family: inherit; - color: inherit; - -webkit-appearance: none; - /*-moz-appearance: none;*/ - -ms-appearance: none; - -o-appearance: none; - appearance: none; -} - -body { - font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; - line-height: 1.4em; - background: #eaeaea url('../../../../assets/bg.png'); - color: #4d4d4d; - width: 550px; - margin: 0 auto; - -webkit-font-smoothing: antialiased; - -moz-font-smoothing: antialiased; - -ms-font-smoothing: antialiased; - -o-font-smoothing: antialiased; - font-smoothing: antialiased; -} - -#todoapp { - background: #fff; - background: rgba(255, 255, 255, 0.9); - margin: 130px 0 40px 0; - border: 1px solid #ccc; - position: relative; - border-top-left-radius: 2px; - border-top-right-radius: 2px; - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2), - 0 25px 50px 0 rgba(0, 0, 0, 0.15); -} - -#todoapp:before { - content: ''; - border-left: 1px solid #f5d6d6; - border-right: 1px solid #f5d6d6; - width: 2px; - position: absolute; - top: 0; - left: 40px; - height: 100%; -} - -#todoapp input::-webkit-input-placeholder { - font-style: italic; -} - -#todoapp input:-moz-placeholder { - font-style: italic; - color: #a9a9a9; -} - -#todoapp h1 { - position: absolute; - top: -120px; - width: 100%; - font-size: 70px; - font-weight: bold; - text-align: center; - color: #b3b3b3; - color: rgba(255, 255, 255, 0.3); - text-shadow: -1px -1px rgba(0, 0, 0, 0.2); - -webkit-text-rendering: optimizeLegibility; - -moz-text-rendering: optimizeLegibility; - -ms-text-rendering: optimizeLegibility; - -o-text-rendering: optimizeLegibility; - text-rendering: optimizeLegibility; -} - -#header { - padding-top: 15px; - border-radius: inherit; -} - -#header:before { - content: ''; - position: absolute; - top: 0; - right: 0; - left: 0; - height: 15px; - z-index: 2; - border-bottom: 1px solid #6c615c; - background: #8d7d77; - background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8))); - background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); - background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); - background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); - background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); - background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); - border-top-left-radius: 1px; - border-top-right-radius: 1px; -} - -#new-todo, -.edit { - position: relative; - margin: 0; - width: 100%; - font-size: 24px; - font-family: inherit; - line-height: 1.4em; - border: 0; - outline: none; - color: inherit; - padding: 6px; - border: 1px solid #999; - box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - -o-box-sizing: border-box; - box-sizing: border-box; - -webkit-font-smoothing: antialiased; - -moz-font-smoothing: antialiased; - -ms-font-smoothing: antialiased; - -o-font-smoothing: antialiased; - font-smoothing: antialiased; -} - -#new-todo { - padding: 16px 16px 16px 60px; - border: none; - background: rgba(0, 0, 0, 0.02); - z-index: 2; - box-shadow: none; -} - -#main { - position: relative; - z-index: 2; - border-top: 1px dotted #adadad; -} - -#footer { - color: #777; - padding: 0 15px; - position: absolute; - right: 0; - bottom: -31px; - left: 0; - height: 20px; - z-index: 1; - text-align: center; -} - -#footer:before { - content: ''; - position: absolute; - right: 0; - bottom: 31px; - left: 0; - height: 50px; - z-index: -1; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), - 0 6px 0 -3px rgba(255, 255, 255, 0.8), - 0 7px 1px -3px rgba(0, 0, 0, 0.3), - 0 43px 0 -6px rgba(255, 255, 255, 0.8), - 0 44px 2px -6px rgba(0, 0, 0, 0.2); -} - -#todo-count { - float: left; - text-align: left; -} - -#clear-completed { - float: right; - position: relative; - line-height: 20px; - text-decoration: none; - background: rgba(0, 0, 0, 0.1); - font-size: 11px; - padding: 0 10px; - border-radius: 3px; - box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); -} - -#clear-completed:hover { - background: rgba(0, 0, 0, 0.15); - box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3); -} - -#info { - margin: 65px auto 0; - color: #a6a6a6; - font-size: 12px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); - text-align: center; -} - -#info a { - color: inherit; -} - -.hidden{ - display:none; -} diff --git a/labs/architecture-examples/ariatemplates/index.html b/labs/architecture-examples/ariatemplates/index.html index 76e19072c3..8e11669ad8 100644 --- a/labs/architecture-examples/ariatemplates/index.html +++ b/labs/architecture-examples/ariatemplates/index.html @@ -1,19 +1,18 @@ - + Aria Templates • TodoMVC - + - - -
      +
      +
      + + diff --git a/labs/architecture-examples/ariatemplates/readme.md b/labs/architecture-examples/ariatemplates/readme.md new file mode 100644 index 0000000000..77883a1e20 --- /dev/null +++ b/labs/architecture-examples/ariatemplates/readme.md @@ -0,0 +1,27 @@ +# Aria Templates TodoMVC Example + +> Aria Templates (aka AT) is an application framework written in JavaScript for building rich and large-scaled enterprise web applications. + +> _[Aria Templates - ariatemplates.com](http://ariatemplates.com)_ + + +## Learning Aria Templates + +The [Aria Templates website](http://ariatemplates.com) is a great resource for getting started. + +Here are some links you may find helpful: + +* [Documentation](http://ariatemplates.com/usermanual) +* [API Reference](http://ariatemplates.com/aria/guide/apps/apidocs) +* [Guides](http://ariatemplates.com/guides) +* [Blog](http://ariatemplates.com/blog) +* [FAQ](http://ariatemplates.com/faq) +* [Aria Templates on GitHub](https://github.com/ariatemplates) + +Get help from other Aria Templates users: + +* [Aria Templates on StackOverflow](http://stackoverflow.com/questions/tagged/ariatemplates) +* [Forums](http://ariatemplates.com/forum) +* [Aria Templates on Twitter](http://twitter.com/ariatemplates) + +_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ diff --git a/labs/architecture-examples/backbone.xmpp/bower.json b/labs/architecture-examples/backbone.xmpp/bower.json new file mode 100644 index 0000000000..5d7e906296 --- /dev/null +++ b/labs/architecture-examples/backbone.xmpp/bower.json @@ -0,0 +1,11 @@ +{ + "name": "backbone.xmpp", + "version": "0.0.0", + "dependencies": { + "todomvc-common": "~0.1.6", + "jquery": "~2.0.0", + "lodash": "~1.2.1", + "backbone": "~1.0.0", + "Strophe.js": "~1.0.2" + } +} \ No newline at end of file diff --git a/labs/architecture-examples/backbone.xmpp/js/lib/strophe.js b/labs/architecture-examples/backbone.xmpp/bower_components/Strophe.js/strophe.js similarity index 84% rename from labs/architecture-examples/backbone.xmpp/js/lib/strophe.js rename to labs/architecture-examples/backbone.xmpp/bower_components/Strophe.js/strophe.js index c802b366d3..660d623e76 100644 --- a/labs/architecture-examples/backbone.xmpp/js/lib/strophe.js +++ b/labs/architecture-examples/backbone.xmpp/bower_components/Strophe.js/strophe.js @@ -78,213 +78,6 @@ var Base64 = (function () { return obj; })(); -/* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Version 2.1a Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */ - -/* - * Configurable variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ -var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ - -/* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ -function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} -function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} -function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} -function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} -function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} -function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} - -/* - * Perform a simple self-test to see if the VM is working - */ -function sha1_vm_test() -{ - return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; -} - -/* - * Calculate the SHA-1 of an array of big-endian words, and a bit length - */ -function core_sha1(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = new Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - var i, j, t, olda, oldb, oldc, oldd, olde; - for (i = 0; i < x.length; i += 16) - { - olda = a; - oldb = b; - oldc = c; - oldd = d; - olde = e; - - for (j = 0; j < 80; j++) - { - if (j < 16) { w[j] = x[i + j]; } - else { w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); } - t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return [a, b, c, d, e]; -} - -/* - * Perform the appropriate triplet combination function for the current - * iteration - */ -function sha1_ft(t, b, c, d) -{ - if (t < 20) { return (b & c) | ((~b) & d); } - if (t < 40) { return b ^ c ^ d; } - if (t < 60) { return (b & c) | (b & d) | (c & d); } - return b ^ c ^ d; -} - -/* - * Determine the appropriate additive constant for the current iteration - */ -function sha1_kt(t) -{ - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; -} - -/* - * Calculate the HMAC-SHA1 of a key and some data - */ -function core_hmac_sha1(key, data) -{ - var bkey = str2binb(key); - if (bkey.length > 16) { bkey = core_sha1(bkey, key.length * chrsz); } - - var ipad = new Array(16), opad = new Array(16); - for (var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); - return core_sha1(opad.concat(hash), 512 + 160); -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} - -/* - * Convert an 8-bit or 16-bit string to an array of big-endian words - * In 8-bit function, characters >255 have their hi-byte silently ignored. - */ -function str2binb(str) -{ - var bin = []; - var mask = (1 << chrsz) - 1; - for (var i = 0; i < str.length * chrsz; i += chrsz) - { - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); - } - return bin; -} - -/* - * Convert an array of big-endian words to a string - */ -function binb2str(bin) -{ - var str = ""; - var mask = (1 << chrsz) - 1; - for (var i = 0; i < bin.length * 32; i += chrsz) - { - str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); - } - return str; -} - -/* - * Convert an array of big-endian words to a hex string. - */ -function binb2hex(binarray) -{ - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var str = ""; - for (var i = 0; i < binarray.length * 4; i++) - { - str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + - hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); - } - return str; -} - -/* - * Convert an array of big-endian words to a base-64 string - */ -function binb2b64(binarray) -{ - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - var triplet, j; - for (var i = 0; i < binarray.length * 4; i += 3) - { - triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | - (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | - ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); - for (j = 0; j < 4; j++) - { - if (i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } - else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } - } - } - return str; -} /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. @@ -612,7 +405,7 @@ if (!Function.prototype.bind) { var _slice = Array.prototype.slice; var _concat = Array.prototype.concat; var _args = _slice.call(arguments, 1); - + return function () { return func.apply(obj ? obj : this, _concat.call(_args, @@ -721,7 +514,7 @@ Strophe = { * The version of the Strophe library. Unreleased builds will have * a version of head-HASH where HASH is a partial revision. */ - VERSION: "", + VERSION: "1.0.2", /** Constants: XMPP Namespace Constants * Common namespace constants from the XMPP RFCs and XEPs. @@ -739,8 +532,6 @@ Strophe = { * NS.STREAM - XMPP Streams namespace from RFC 3920. * NS.BIND - XMPP Binding namespace from RFC 3920. * NS.SESSION - XMPP Session namespace from RFC 3920. - * NS.XHTML_IM - XHTML-IM namespace from XEP 71. - * NS.XHTML - XHTML body namespace from XEP 71. */ NS: { HTTPBIND: "http://jabber.org/protocol/httpbind", @@ -757,68 +548,10 @@ Strophe = { BIND: "urn:ietf:params:xml:ns:xmpp-bind", SESSION: "urn:ietf:params:xml:ns:xmpp-session", VERSION: "jabber:iq:version", - STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas", - XHTML_IM: "http://jabber.org/protocol/xhtml-im", - XHTML: "http://www.w3.org/1999/xhtml" + STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas" }, - - /** Constants: XHTML_IM Namespace - * contains allowed tags, tag attributes, and css properties. - * Used in the createHtml function to filter incoming html into the allowed XHTML-IM subset. - * See http://xmpp.org/extensions/xep-0071.html#profile-summary for the list of recommended - * allowed tags and their attributes. - */ - XHTML: { - tags: ['a','blockquote','br','cite','em','img','li','ol','p','span','strong','ul','body'], - attributes: { - 'a': ['href'], - 'blockquote': ['style'], - 'br': [], - 'cite': ['style'], - 'em': [], - 'img': ['src', 'alt', 'style', 'height', 'width'], - 'li': ['style'], - 'ol': ['style'], - 'p': ['style'], - 'span': ['style'], - 'strong': [], - 'ul': ['style'], - 'body': [] - }, - css: ['background-color','color','font-family','font-size','font-style','font-weight','margin-left','margin-right','text-align','text-decoration'], - validTag: function(tag) - { - for(var i = 0; i < Strophe.XHTML.tags.length; i++) { - if(tag == Strophe.XHTML.tags[i]) { - return true; - } - } - return false; - }, - validAttribute: function(tag, attribute) - { - if(typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) { - for(var i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - if(attribute == Strophe.XHTML.attributes[tag][i]) { - return true; - } - } - } - return false; - }, - validCSS: function(style) - { - for(var i = 0; i < Strophe.XHTML.css.length; i++) { - if(style == Strophe.XHTML.css[i]) { - return true; - } - } - return false; - } - }, - - /** Function: addNamespace + /** Function: addNamespace * This function is used to extend the current namespaces in * Strophe.NS. It takes a key and a value with the key being the * name of the new namespace, with its actual value. @@ -832,7 +565,7 @@ Strophe = { */ addNamespace: function (name, value) { - Strophe.NS[name] = value; + Strophe.NS[name] = value; }, /** Constants: Connection Status Constants @@ -883,13 +616,11 @@ Strophe = { * * ElementType.NORMAL - Normal element. * ElementType.TEXT - Text data element. - * ElementType.FRAGMENT - XHTML fragment element. */ ElementType: { NORMAL: 1, TEXT: 3, - CDATA: 4, - FRAGMENT: 11 + CDATA: 4 }, /** PrivateConstants: Timeout Values @@ -967,11 +698,7 @@ Strophe = { _makeGenerator: function () { var doc; - // IE9 does implement createDocument(); however, using it will cause the browser to leak memory on page unload. - // Here, we test for presence of createDocument() plus IE's proprietary documentMode attribute, which would be - // less than 10 in the case of IE9 and below. - if (document.implementation.createDocument === undefined || - document.implementation.createDocument && document.documentMode && document.documentMode < 10) { + if (document.implementation.createDocument === undefined) { doc = this._getIEXmlDom(); doc.appendChild(doc.createElement('strophe')); } else { @@ -1115,30 +842,10 @@ Strophe = { */ xmlTextNode: function (text) { - return Strophe.xmlGenerator().createTextNode(text); - }, + //ensure text is escaped + text = Strophe.xmlescape(text); - /** Function: xmlHtmlNode - * Creates an XML DOM html node. - * - * Parameters: - * (String) html - The content of the html node. - * - * Returns: - * A new XML DOM text node. - */ - xmlHtmlNode: function (html) - { - //ensure text is escaped - if (window.DOMParser) { - parser = new DOMParser(); - node = parser.parseFromString(html, "text/xml"); - } else { - node = new ActiveXObject("Microsoft.XMLDOM"); - node.async="false"; - node.loadXML(html); - } - return node; + return Strophe.xmlGenerator().createTextNode(text); }, /** Function: getText @@ -1166,7 +873,7 @@ Strophe = { } } - return Strophe.xmlescape(str); + return str; }, /** Function: copyElement @@ -1202,83 +909,6 @@ Strophe = { return el; }, - - /** Function: createHtml - * Copy an HTML DOM element into an XML DOM. - * - * This function copies a DOM element and all its descendants and returns - * the new copy. - * - * Parameters: - * (HTMLElement) elem - A DOM element. - * - * Returns: - * A new, copied DOM element tree. - */ - createHtml: function (elem) - { - var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue, children, child; - if (elem.nodeType == Strophe.ElementType.NORMAL) { - tag = elem.nodeName.toLowerCase(); - if(Strophe.XHTML.validTag(tag)) { - try { - el = Strophe.xmlElement(tag); - for(i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - attribute = Strophe.XHTML.attributes[tag][i]; - value = elem.getAttribute(attribute); - if(typeof value == 'undefined' || value === null || value === '' || value === false || value === 0) { - continue; - } - if(attribute == 'style' && typeof value == 'object') { - if(typeof value.cssText != 'undefined') { - value = value.cssText; // we're dealing with IE, need to get CSS out - } - } - // filter out invalid css styles - if(attribute == 'style') { - css = []; - cssAttrs = value.split(';'); - for(j = 0; j < cssAttrs.length; j++) { - attr = cssAttrs[j].split(':'); - cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase(); - if(Strophe.XHTML.validCSS(cssName)) { - cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, ""); - css.push(cssName + ': ' + cssValue); - } - } - if(css.length > 0) { - value = css.join('; '); - el.setAttribute(attribute, value); - } - } else { - el.setAttribute(attribute, value); - } - } - - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } catch(e) { // invalid elements - el = Strophe.xmlTextNode(''); - } - } else { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } - } else if (elem.nodeType == Strophe.ElementType.FRAGMENT) { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } else if (elem.nodeType == Strophe.ElementType.TEXT) { - el = Strophe.xmlTextNode(elem.nodeValue); - } - - return el; - }, - /** Function: escapeNode * Escape the node part (also called local part) of a JID. * @@ -1515,7 +1145,6 @@ Strophe = { "='" + elem.attributes[i].value .replace(/&/g, "&") .replace(/\'/g, "'") - .replace(/>/g, ">") .replace(/ 0) { - this.node.appendChild(xhtml.childNodes[0]); - } - return this; } }; + /** PrivateClass: Strophe.Handler * _Private_ helper class for managing stanza handlers. * @@ -1839,7 +1442,7 @@ Strophe.Handler = function (handler, ns, name, type, id, from, options) this.type = type; this.id = id; this.options = options || {matchbare: false}; - + // default matchBare to false if undefined if (!this.options.matchBare) { this.options.matchBare = false; @@ -1869,7 +1472,7 @@ Strophe.Handler.prototype = { { var nsMatch; var from = null; - + if (this.options.matchBare) { from = Strophe.getBareJidFromJid(elem.getAttribute('from')); } else { @@ -1930,7 +1533,7 @@ Strophe.Handler.prototype = { e.fileName + ":" + e.lineNumber + " - " + e.name + ": " + e.message); } else { - Strophe.fatal("error: " + e.message + "\n" + e.stack); + Strophe.fatal("error: " + this.handler); } throw e; @@ -2131,7 +1734,7 @@ Strophe.Request.prototype = { /** Class: Strophe.Connection * XMPP Connection manager. * - * This class is the main part of Strophe. It manages a BOSH connection + * Thie class is the main part of Strophe. It manages a BOSH connection * to an XMPP server and dispatches events to the user callbacks as * data arrives. It supports SASL PLAIN, SASL DIGEST-MD5, and legacy * authentication. @@ -2165,8 +1768,6 @@ Strophe.Connection = function (service) this.service = service; /* The connected JID. */ this.jid = ""; - /* the JIDs domain */ - this.domain = null; /* request id for body tags */ this.rid = Math.floor(Math.random() * 4294967295); /* The current session ID. */ @@ -2176,7 +1777,6 @@ Strophe.Connection = function (service) this.features = null; // SASL - this._sasl_data = []; this.do_session = false; this.do_bind = false; @@ -2188,11 +1788,9 @@ Strophe.Connection = function (service) this.addTimeds = []; this.addHandlers = []; - this._authentication = {}; this._idleTimeout = null; this._disconnectTimeout = null; - this.do_authentication = true; this.authenticated = false; this.disconnecting = false; this.connected = false; @@ -2214,9 +1812,6 @@ Strophe.Connection = function (service) this._sasl_failure_handler = null; this._sasl_challenge_handler = null; - // Max retries before disconnecting - this.maxRetries = 5; - // setup onIdle callback every 1/10th of a second this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); @@ -2258,7 +1853,6 @@ Strophe.Connection.prototype = { this.removeHandlers = []; this.addTimeds = []; this.addHandlers = []; - this._authentication = {}; this.authenticated = false; this.disconnecting = false; @@ -2347,12 +1941,12 @@ Strophe.Connection.prototype = { * (Integer) wait - The optional HTTPBIND wait value. This is the * time the server will wait before returning an empty result for * a request. The default setting of 60 seconds is recommended. + * Other settings will require tweaks to the Strophe.TIMEOUT value. * (Integer) hold - The optional HTTPBIND hold value. This is the * number of connections the server will hold at one time. This * should almost always be set to 1 (the default). - * (String) route */ - connect: function (jid, pass, callback, wait, hold, route) + connect: function (jid, pass, callback, wait, hold) { this.jid = jid; this.pass = pass; @@ -2366,7 +1960,7 @@ Strophe.Connection.prototype = { this.hold = hold || this.hold; // parse jid for domain and resource - this.domain = this.domain || Strophe.getDomainFromJid(this.jid); + this.domain = Strophe.getDomainFromJid(this.jid); // build the body tag var body = this._buildBody().attrs({ @@ -2380,21 +1974,12 @@ Strophe.Connection.prototype = { "xmlns:xmpp": Strophe.NS.BOSH }); - if(route){ - body.attrs({ - route: route - }); - } - this._changeConnectStatus(Strophe.Status.CONNECTING, null); - var _connect_cb = this._connect_callback || this._connect_cb; - this._connect_callback = null; - this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind( - this, _connect_cb.bind(this)), + this, this._connect_cb.bind(this)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); }, @@ -2640,7 +2225,7 @@ Strophe.Connection.prototype = { message: "Cannot queue non-DOMElement." }; } - + this._data.push(element); }, @@ -2915,7 +2500,7 @@ Strophe.Connection.prototype = { } // make sure we limit the number of retries - if (req.sends > this.maxRetries) { + if (req.sends > 5) { this._onDisconnectTimeout(); return; } @@ -3319,11 +2904,8 @@ Strophe.Connection.prototype = { * * Parameters: * (Strophe.Request) req - The current request. - * (Function) _callback - low level (xmpp) connect callback function. - * Useful for plugins with their own xmpp connect callback (when their) - * want to do something special). */ - _connect_cb: function (req, _callback) + _connect_cb: function (req) { Strophe.info("_connect_cb was called"); @@ -3370,74 +2952,39 @@ Strophe.Connection.prototype = { var wait = bodyWrap.getAttribute('wait'); if (wait) { this.wait = parseInt(wait, 10); } - this._authentication.sasl_scram_sha1 = false; - this._authentication.sasl_plain = false; - this._authentication.sasl_digest_md5 = false; - this._authentication.sasl_anonymous = false; - this._authentication.legacy_auth = false; + var do_sasl_plain = false; + var do_sasl_digest_md5 = false; + var do_sasl_anonymous = false; - // Check for the stream:features tag - var hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0; - if (!hasFeatures) { - hasFeatures = bodyWrap.getElementsByTagName("features").length > 0; - } var mechanisms = bodyWrap.getElementsByTagName("mechanism"); - var i, mech, auth_str, hashed_auth_str, - found_authentication = false; - if (hasFeatures && mechanisms.length > 0) { - var missmatchedmechs = 0; + var i, mech, auth_str, hashed_auth_str; + if (mechanisms.length > 0) { for (i = 0; i < mechanisms.length; i++) { mech = Strophe.getText(mechanisms[i]); - if (mech == 'SCRAM-SHA-1') { - this._authentication.sasl_scram_sha1 = true; - } else if (mech == 'DIGEST-MD5') { - this._authentication.sasl_digest_md5 = true; + if (mech == 'DIGEST-MD5') { + do_sasl_digest_md5 = true; } else if (mech == 'PLAIN') { - this._authentication.sasl_plain = true; + do_sasl_plain = true; } else if (mech == 'ANONYMOUS') { - this._authentication.sasl_anonymous = true; - } else missmatchedmechs++; + do_sasl_anonymous = true; + } } - - this._authentication.legacy_auth = - bodyWrap.getElementsByTagName("auth").length > 0; - - found_authentication = - this._authentication.legacy_auth || - missmatchedmechs < mechanisms.length; - } - if (!found_authentication) { - _callback = _callback || this._connect_cb; + } else { // we didn't get stream:features yet, so we need wait for it // by sending a blank poll request var body = this._buildBody(); this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind( - this, _callback.bind(this)), + this, this._connect_cb.bind(this)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); return; } - if (this.do_authentication !== false) - this.authenticate(); - }, - /** Function: authenticate - * Set up authentication - * - * Contiunues the initial connection request by setting up authentication - * handlers and start the authentication process. - * - * SASL authentication will be attempted if available, otherwise - * the code will fall back to legacy authentication. - * - */ - authenticate: function () - { if (Strophe.getNodeFromJid(this.jid) === null && - this._authentication.sasl_anonymous) { + do_sasl_anonymous) { this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); this._sasl_success_handler = this._addSysHandler( this._sasl_success_cb.bind(this), null, @@ -3456,34 +3003,10 @@ Strophe.Connection.prototype = { this._changeConnectStatus(Strophe.Status.CONNFAIL, 'x-strophe-bad-non-anon-jid'); this.disconnect(); - } else if (this._authentication.sasl_scram_sha1) { - var cnonce = MD5.hexdigest(Math.random() * 1234567890); - - var auth_str = "n=" + Strophe.getNodeFromJid(this.jid); - auth_str += ",r="; - auth_str += cnonce; - - this._sasl_data["cnonce"] = cnonce; - this._sasl_data["client-first-message-bare"] = auth_str; - - auth_str = "n,," + auth_str; - - this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); - this._sasl_challenge_handler = this._addSysHandler( - this._sasl_scram_challenge_cb.bind(this), null, - "challenge", null, null); - this._sasl_failure_handler = this._addSysHandler( - this._sasl_failure_cb.bind(this), null, - "failure", null, null); - - this.send($build("auth", { - xmlns: Strophe.NS.SASL, - mechanism: "SCRAM-SHA-1" - }).t(Base64.encode(auth_str)).tree()); - } else if (this._authentication.sasl_digest_md5) { + } else if (do_sasl_digest_md5) { this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); this._sasl_challenge_handler = this._addSysHandler( - this._sasl_digest_challenge1_cb.bind(this), null, + this._sasl_challenge1_cb.bind(this), null, "challenge", null, null); this._sasl_failure_handler = this._addSysHandler( this._sasl_failure_cb.bind(this), null, @@ -3493,7 +3016,7 @@ Strophe.Connection.prototype = { xmlns: Strophe.NS.SASL, mechanism: "DIGEST-MD5" }).tree()); - } else if (this._authentication.sasl_plain) { + } else if (do_sasl_plain) { // Build the plain auth string (barejid null // username null password) and base 64 encoded. auth_str = Strophe.getBareJidFromJid(this.jid); @@ -3530,7 +3053,7 @@ Strophe.Connection.prototype = { } }, - /** PrivateFunction: _sasl_digest_challenge1_cb + /** PrivateFunction: _sasl_challenge1_cb * _Private_ handler for DIGEST-MD5 SASL authentication. * * Parameters: @@ -3539,7 +3062,7 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_digest_challenge1_cb: function (elem) + _sasl_challenge1_cb: function (elem) { var attribMatch = /([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/; @@ -3601,7 +3124,7 @@ Strophe.Connection.prototype = { responseText += 'charset="utf-8"'; this._sasl_challenge_handler = this._addSysHandler( - this._sasl_digest_challenge2_cb.bind(this), null, + this._sasl_challenge2_cb.bind(this), null, "challenge", null, null); this._sasl_success_handler = this._addSysHandler( this._sasl_success_cb.bind(this), null, @@ -3633,7 +3156,7 @@ Strophe.Connection.prototype = { }, - /** PrivateFunction: _sasl_digest_challenge2_cb + /** PrivateFunction: _sasl_challenge2_cb * _Private_ handler for second step of DIGEST-MD5 SASL authentication. * * Parameters: @@ -3642,7 +3165,7 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_digest_challenge2_cb: function (elem) + _sasl_challenge2_cb: function (elem) { // remove unneeded handlers this.deleteHandler(this._sasl_success_handler); @@ -3658,91 +3181,6 @@ Strophe.Connection.prototype = { return false; }, - /** PrivateFunction: _sasl_scram_challenge_cb - * _Private_ handler for SCRAM-SHA-1 SASL authentication. - * - * Parameters: - * (XMLElement) elem - The challenge stanza. - * - * Returns: - * false to remove the handler. - */ - _sasl_scram_challenge_cb: function (elem) - { - var nonce, salt, iter, Hi, U, U_old; - var clientKey, serverKey, clientSignature; - var responseText = "c=biws,"; - var challenge = Base64.decode(Strophe.getText(elem)); - var authMessage = this._sasl_data["client-first-message-bare"] + "," + - challenge + ","; - var cnonce = this._sasl_data["cnonce"] - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - - // remove unneeded handlers - this.deleteHandler(this._sasl_failure_handler); - - while (challenge.match(attribMatch)) { - matches = challenge.match(attribMatch); - challenge = challenge.replace(matches[0], ""); - switch (matches[1]) { - case "r": - nonce = matches[2]; - break; - case "s": - salt = matches[2]; - break; - case "i": - iter = matches[2]; - break; - } - } - - if (!(nonce.substr(0, cnonce.length) === cnonce)) { - this._sasl_data = []; - return this._sasl_failure_cb(null); - } - - responseText += "r=" + nonce; - authMessage += responseText; - - salt = Base64.decode(salt); - salt += "\0\0\0\1"; - - Hi = U_old = core_hmac_sha1(this.pass, salt); - for (i = 1; i < iter; i++) { - U = core_hmac_sha1(this.pass, binb2str(U_old)); - for (k = 0; k < 5; k++) { - Hi[k] ^= U[k]; - } - U_old = U; - } - Hi = binb2str(Hi); - - clientKey = core_hmac_sha1(Hi, "Client Key"); - serverKey = str_hmac_sha1(Hi, "Server Key"); - clientSignature = core_hmac_sha1(str_sha1(binb2str(clientKey)), authMessage); - this._sasl_data["server-signature"] = b64_hmac_sha1(serverKey, authMessage); - - for (k = 0; k < 5; k++) { - clientKey[k] ^= clientSignature[k]; - } - - responseText += ",p=" + Base64.encode(binb2str(clientKey)); - - this._sasl_success_handler = this._addSysHandler( - this._sasl_success_cb.bind(this), null, - "success", null, null); - this._sasl_failure_handler = this._addSysHandler( - this._sasl_failure_cb.bind(this), null, - "failure", null, null); - - this.send($build('response', { - xmlns: Strophe.NS.SASL - }).t(Base64.encode(responseText)).tree()); - - return false; - }, - /** PrivateFunction: _auth1_cb * _Private_ handler for legacy authentication. * @@ -3793,29 +3231,7 @@ Strophe.Connection.prototype = { */ _sasl_success_cb: function (elem) { - if (this._sasl_data["server-signature"]) { - var serverSignature; - var success = Base64.decode(Strophe.getText(elem)); - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - matches = success.match(attribMatch); - if (matches[1] == "v") { - serverSignature = matches[2]; - } - if (serverSignature != this._sasl_data["server-signature"]) { - // remove old handlers - this.deleteHandler(this._sasl_failure_handler); - this._sasl_failure_handler = null; - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - this._sasl_data = []; - return this._sasl_failure_cb(null); - } - } - - Strophe.info("SASL authentication succeeded."); + Strophe.info("SASL authentication succeeded."); // remove old handlers this.deleteHandler(this._sasl_failure_handler); @@ -3896,11 +3312,7 @@ Strophe.Connection.prototype = { { if (elem.getAttribute("type") == "error") { Strophe.info("SASL binding failed."); - var conflict = elem.getElementsByTagName("conflict"), condition; - if (conflict.length > 0) { - condition = 'conflict'; - } - this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition); + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); return false; } diff --git a/labs/architecture-examples/backbone.xmpp/bower_components/backbone/backbone.js b/labs/architecture-examples/backbone.xmpp/bower_components/backbone/backbone.js new file mode 100644 index 0000000000..3512d42fb4 --- /dev/null +++ b/labs/architecture-examples/backbone.xmpp/bower_components/backbone/backbone.js @@ -0,0 +1,1571 @@ +// Backbone.js 1.0.0 + +// (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org + +(function(){ + + // Initial Setup + // ------------- + + // Save a reference to the global object (`window` in the browser, `exports` + // on the server). + var root = this; + + // Save the previous value of the `Backbone` variable, so that it can be + // restored later on, if `noConflict` is used. + var previousBackbone = root.Backbone; + + // Create local references to array methods we'll want to use later. + var array = []; + var push = array.push; + var slice = array.slice; + var splice = array.splice; + + // The top-level namespace. All public Backbone classes and modules will + // be attached to this. Exported for both the browser and the server. + var Backbone; + if (typeof exports !== 'undefined') { + Backbone = exports; + } else { + Backbone = root.Backbone = {}; + } + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '1.0.0'; + + // Require Underscore, if we're on the server, and it's not already present. + var _ = root._; + if (!_ && (typeof require !== 'undefined')) _ = require('underscore'); + + // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns + // the `$` variable. + Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function() { + root.Backbone = previousBackbone; + return this; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option + // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and + // set a `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Backbone.Events + // --------------- + + // A module that can be mixed in to *any object* in order to provide it with + // custom events. You may bind with `on` or remove with `off` callback + // functions to an event; `trigger`-ing an event fires all callbacks in + // succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.on('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + var Events = Backbone.Events = { + + // Bind an event to a `callback` function. Passing `"all"` will bind + // the callback to all events fired. + on: function(name, callback, context) { + if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; + this._events || (this._events = {}); + var events = this._events[name] || (this._events[name] = []); + events.push({callback: callback, context: context, ctx: context || this}); + return this; + }, + + // Bind an event to only be triggered a single time. After the first time + // the callback is invoked, it will be removed. + once: function(name, callback, context) { + if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; + var self = this; + var once = _.once(function() { + self.off(name, once); + callback.apply(this, arguments); + }); + once._callback = callback; + return this.on(name, once, context); + }, + + // Remove one or many callbacks. If `context` is null, removes all + // callbacks with that function. If `callback` is null, removes all + // callbacks for the event. If `name` is null, removes all bound + // callbacks for all events. + off: function(name, callback, context) { + var retain, ev, events, names, i, l, j, k; + if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; + if (!name && !callback && !context) { + this._events = {}; + return this; + } + + names = name ? [name] : _.keys(this._events); + for (i = 0, l = names.length; i < l; i++) { + name = names[i]; + if (events = this._events[name]) { + this._events[name] = retain = []; + if (callback || context) { + for (j = 0, k = events.length; j < k; j++) { + ev = events[j]; + if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || + (context && context !== ev.context)) { + retain.push(ev); + } + } + } + if (!retain.length) delete this._events[name]; + } + } + + return this; + }, + + // Trigger one or many events, firing all bound callbacks. Callbacks are + // passed the same arguments as `trigger` is, apart from the event name + // (unless you're listening on `"all"`, which will cause your callback to + // receive the true name of the event as the first argument). + trigger: function(name) { + if (!this._events) return this; + var args = slice.call(arguments, 1); + if (!eventsApi(this, 'trigger', name, args)) return this; + var events = this._events[name]; + var allEvents = this._events.all; + if (events) triggerEvents(events, args); + if (allEvents) triggerEvents(allEvents, arguments); + return this; + }, + + // Tell this object to stop listening to either specific events ... or + // to every object it's currently listening to. + stopListening: function(obj, name, callback) { + var listeners = this._listeners; + if (!listeners) return this; + var deleteListener = !name && !callback; + if (typeof name === 'object') callback = this; + if (obj) (listeners = {})[obj._listenerId] = obj; + for (var id in listeners) { + listeners[id].off(name, callback, this); + if (deleteListener) delete this._listeners[id]; + } + return this; + } + + }; + + // Regular expression used to split event strings. + var eventSplitter = /\s+/; + + // Implement fancy features of the Events API such as multiple event + // names `"change blur"` and jQuery-style event maps `{change: action}` + // in terms of the existing API. + var eventsApi = function(obj, action, name, rest) { + if (!name) return true; + + // Handle event maps. + if (typeof name === 'object') { + for (var key in name) { + obj[action].apply(obj, [key, name[key]].concat(rest)); + } + return false; + } + + // Handle space separated event names. + if (eventSplitter.test(name)) { + var names = name.split(eventSplitter); + for (var i = 0, l = names.length; i < l; i++) { + obj[action].apply(obj, [names[i]].concat(rest)); + } + return false; + } + + return true; + }; + + // A difficult-to-believe, but optimized internal dispatch function for + // triggering events. Tries to keep the usual cases speedy (most internal + // Backbone events have 3 arguments). + var triggerEvents = function(events, args) { + var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; + switch (args.length) { + case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; + case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; + case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; + case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; + default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); + } + }; + + var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; + + // Inversion-of-control versions of `on` and `once`. Tell *this* object to + // listen to an event in another object ... keeping track of what it's + // listening to. + _.each(listenMethods, function(implementation, method) { + Events[method] = function(obj, name, callback) { + var listeners = this._listeners || (this._listeners = {}); + var id = obj._listenerId || (obj._listenerId = _.uniqueId('l')); + listeners[id] = obj; + if (typeof name === 'object') callback = this; + obj[implementation](name, callback, this); + return this; + }; + }); + + // Aliases for backwards compatibility. + Events.bind = Events.on; + Events.unbind = Events.off; + + // Allow the `Backbone` object to serve as a global event bus, for folks who + // want global "pubsub" in a convenient place. + _.extend(Backbone, Events); + + // Backbone.Model + // -------------- + + // Backbone **Models** are the basic data object in the framework -- + // frequently representing a row in a table in a database on your server. + // A discrete chunk of data and a bunch of useful, related methods for + // performing computations and transformations on that data. + + // Create a new model with the specified attributes. A client id (`cid`) + // is automatically generated and assigned for you. + var Model = Backbone.Model = function(attributes, options) { + var defaults; + var attrs = attributes || {}; + options || (options = {}); + this.cid = _.uniqueId('c'); + this.attributes = {}; + _.extend(this, _.pick(options, modelOptions)); + if (options.parse) attrs = this.parse(attrs, options) || {}; + if (defaults = _.result(this, 'defaults')) { + attrs = _.defaults({}, attrs, defaults); + } + this.set(attrs, options); + this.changed = {}; + this.initialize.apply(this, arguments); + }; + + // A list of options to be attached directly to the model, if provided. + var modelOptions = ['url', 'urlRoot', 'collection']; + + // Attach all inheritable methods to the Model prototype. + _.extend(Model.prototype, Events, { + + // A hash of attributes whose current and previous value differ. + changed: null, + + // The value returned during the last failed validation. + validationError: null, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute: 'id', + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Return a copy of the model's `attributes` object. + toJSON: function(options) { + return _.clone(this.attributes); + }, + + // Proxy `Backbone.sync` by default -- but override this if you need + // custom syncing semantics for *this* particular model. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Get the value of an attribute. + get: function(attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape: function(attr) { + return _.escape(this.get(attr)); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has: function(attr) { + return this.get(attr) != null; + }, + + // Set a hash of model attributes on the object, firing `"change"`. This is + // the core primitive operation of a model, updating the data and notifying + // anyone who needs to know about the change in state. The heart of the beast. + set: function(key, val, options) { + var attr, attrs, unset, changes, silent, changing, prev, current; + if (key == null) return this; + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options || (options = {}); + + // Run validation. + if (!this._validate(attrs, options)) return false; + + // Extract attributes and options. + unset = options.unset; + silent = options.silent; + changes = []; + changing = this._changing; + this._changing = true; + + if (!changing) { + this._previousAttributes = _.clone(this.attributes); + this.changed = {}; + } + current = this.attributes, prev = this._previousAttributes; + + // Check for changes of `id`. + if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; + + // For each `set` attribute, update or delete the current value. + for (attr in attrs) { + val = attrs[attr]; + if (!_.isEqual(current[attr], val)) changes.push(attr); + if (!_.isEqual(prev[attr], val)) { + this.changed[attr] = val; + } else { + delete this.changed[attr]; + } + unset ? delete current[attr] : current[attr] = val; + } + + // Trigger all relevant attribute changes. + if (!silent) { + if (changes.length) this._pending = true; + for (var i = 0, l = changes.length; i < l; i++) { + this.trigger('change:' + changes[i], this, current[changes[i]], options); + } + } + + // You might be wondering why there's a `while` loop here. Changes can + // be recursively nested within `"change"` events. + if (changing) return this; + if (!silent) { + while (this._pending) { + this._pending = false; + this.trigger('change', this, options); + } + } + this._pending = false; + this._changing = false; + return this; + }, + + // Remove an attribute from the model, firing `"change"`. `unset` is a noop + // if the attribute doesn't exist. + unset: function(attr, options) { + return this.set(attr, void 0, _.extend({}, options, {unset: true})); + }, + + // Clear all attributes on the model, firing `"change"`. + clear: function(options) { + var attrs = {}; + for (var key in this.attributes) attrs[key] = void 0; + return this.set(attrs, _.extend({}, options, {unset: true})); + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged: function(attr) { + if (attr == null) return !_.isEmpty(this.changed); + return _.has(this.changed, attr); + }, + + // Return an object containing all the attributes that have changed, or + // false if there are no changed attributes. Useful for determining what + // parts of a view need to be updated and/or what attributes need to be + // persisted to the server. Unset attributes will be set to undefined. + // You can also pass an attributes object to diff against the model, + // determining if there *would be* a change. + changedAttributes: function(diff) { + if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; + var val, changed = false; + var old = this._changing ? this._previousAttributes : this.attributes; + for (var attr in diff) { + if (_.isEqual(old[attr], (val = diff[attr]))) continue; + (changed || (changed = {}))[attr] = val; + } + return changed; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous: function(attr) { + if (attr == null || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes: function() { + return _.clone(this._previousAttributes); + }, + + // Fetch the model from the server. If the server's representation of the + // model differs from its current attributes, they will be overridden, + // triggering a `"change"` event. + fetch: function(options) { + options = options ? _.clone(options) : {}; + if (options.parse === void 0) options.parse = true; + var model = this; + var success = options.success; + options.success = function(resp) { + if (!model.set(model.parse(resp, options), options)) return false; + if (success) success(model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save: function(key, val, options) { + var attrs, method, xhr, attributes = this.attributes; + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (key == null || typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + // If we're not waiting and attributes exist, save acts as `set(attr).save(null, opts)`. + if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false; + + options = _.extend({validate: true}, options); + + // Do not persist invalid models. + if (!this._validate(attrs, options)) return false; + + // Set temporary attributes if `{wait: true}`. + if (attrs && options.wait) { + this.attributes = _.extend({}, attributes, attrs); + } + + // After a successful server-side save, the client is (optionally) + // updated with the server-side state. + if (options.parse === void 0) options.parse = true; + var model = this; + var success = options.success; + options.success = function(resp) { + // Ensure attributes are restored during synchronous saves. + model.attributes = attributes; + var serverAttrs = model.parse(resp, options); + if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs); + if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { + return false; + } + if (success) success(model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + + method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); + if (method === 'patch') options.attrs = attrs; + xhr = this.sync(method, this, options); + + // Restore attributes. + if (attrs && options.wait) this.attributes = attributes; + + return xhr; + }, + + // Destroy this model on the server if it was already persisted. + // Optimistically removes the model from its collection, if it has one. + // If `wait: true` is passed, waits for the server to respond before removal. + destroy: function(options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + + var destroy = function() { + model.trigger('destroy', model, model.collection, options); + }; + + options.success = function(resp) { + if (options.wait || model.isNew()) destroy(); + if (success) success(model, resp, options); + if (!model.isNew()) model.trigger('sync', model, resp, options); + }; + + if (this.isNew()) { + options.success(); + return false; + } + wrapError(this, options); + + var xhr = this.sync('delete', this, options); + if (!options.wait) destroy(); + return xhr; + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url: function() { + var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError(); + if (this.isNew()) return base; + return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse: function(resp, options) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone: function() { + return new this.constructor(this.attributes); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew: function() { + return this.id == null; + }, + + // Check if the model is currently in a valid state. + isValid: function(options) { + return this._validate({}, _.extend(options || {}, { validate: true })); + }, + + // Run validation against the next complete set of model attributes, + // returning `true` if all is well. Otherwise, fire an `"invalid"` event. + _validate: function(attrs, options) { + if (!options.validate || !this.validate) return true; + attrs = _.extend({}, this.attributes, attrs); + var error = this.validationError = this.validate(attrs, options) || null; + if (!error) return true; + this.trigger('invalid', this, error, _.extend(options || {}, {validationError: error})); + return false; + } + + }); + + // Underscore methods that we want to implement on the Model. + var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; + + // Mix in each Underscore method as a proxy to `Model#attributes`. + _.each(modelMethods, function(method) { + Model.prototype[method] = function() { + var args = slice.call(arguments); + args.unshift(this.attributes); + return _[method].apply(_, args); + }; + }); + + // Backbone.Collection + // ------------------- + + // If models tend to represent a single row of data, a Backbone Collection is + // more analagous to a table full of data ... or a small slice or page of that + // table, or a collection of rows that belong together for a particular reason + // -- all of the messages in this particular folder, all of the documents + // belonging to this particular author, and so on. Collections maintain + // indexes of their models, both in order, and for lookup by `id`. + + // Create a new **Collection**, perhaps to contain a specific type of `model`. + // If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + var Collection = Backbone.Collection = function(models, options) { + options || (options = {}); + if (options.url) this.url = options.url; + if (options.model) this.model = options.model; + if (options.comparator !== void 0) this.comparator = options.comparator; + this._reset(); + this.initialize.apply(this, arguments); + if (models) this.reset(models, _.extend({silent: true}, options)); + }; + + // Default options for `Collection#set`. + var setOptions = {add: true, remove: true, merge: true}; + var addOptions = {add: true, merge: false, remove: false}; + + // Define the Collection's inheritable methods. + _.extend(Collection.prototype, Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model: Model, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON: function(options) { + return this.map(function(model){ return model.toJSON(options); }); + }, + + // Proxy `Backbone.sync` by default. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Add a model, or list of models to the set. + add: function(models, options) { + return this.set(models, _.defaults(options || {}, addOptions)); + }, + + // Remove a model, or a list of models from the set. + remove: function(models, options) { + models = _.isArray(models) ? models.slice() : [models]; + options || (options = {}); + var i, l, index, model; + for (i = 0, l = models.length; i < l; i++) { + model = this.get(models[i]); + if (!model) continue; + delete this._byId[model.id]; + delete this._byId[model.cid]; + index = this.indexOf(model); + this.models.splice(index, 1); + this.length--; + if (!options.silent) { + options.index = index; + model.trigger('remove', model, this, options); + } + this._removeReference(model); + } + return this; + }, + + // Update a collection by `set`-ing a new list of models, adding new ones, + // removing models that are no longer present, and merging models that + // already exist in the collection, as necessary. Similar to **Model#set**, + // the core operation for updating the data contained by the collection. + set: function(models, options) { + options = _.defaults(options || {}, setOptions); + if (options.parse) models = this.parse(models, options); + if (!_.isArray(models)) models = models ? [models] : []; + var i, l, model, attrs, existing, sort; + var at = options.at; + var sortable = this.comparator && (at == null) && options.sort !== false; + var sortAttr = _.isString(this.comparator) ? this.comparator : null; + var toAdd = [], toRemove = [], modelMap = {}; + + // Turn bare objects into model references, and prevent invalid models + // from being added. + for (i = 0, l = models.length; i < l; i++) { + if (!(model = this._prepareModel(models[i], options))) continue; + + // If a duplicate is found, prevent it from being added and + // optionally merge it into the existing model. + if (existing = this.get(model)) { + if (options.remove) modelMap[existing.cid] = true; + if (options.merge) { + existing.set(model.attributes, options); + if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; + } + + // This is a new model, push it to the `toAdd` list. + } else if (options.add) { + toAdd.push(model); + + // Listen to added models' events, and index models for lookup by + // `id` and by `cid`. + model.on('all', this._onModelEvent, this); + this._byId[model.cid] = model; + if (model.id != null) this._byId[model.id] = model; + } + } + + // Remove nonexistent models if appropriate. + if (options.remove) { + for (i = 0, l = this.length; i < l; ++i) { + if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); + } + if (toRemove.length) this.remove(toRemove, options); + } + + // See if sorting is needed, update `length` and splice in new models. + if (toAdd.length) { + if (sortable) sort = true; + this.length += toAdd.length; + if (at != null) { + splice.apply(this.models, [at, 0].concat(toAdd)); + } else { + push.apply(this.models, toAdd); + } + } + + // Silently sort the collection if appropriate. + if (sort) this.sort({silent: true}); + + if (options.silent) return this; + + // Trigger `add` events. + for (i = 0, l = toAdd.length; i < l; i++) { + (model = toAdd[i]).trigger('add', model, this, options); + } + + // Trigger `sort` if the collection was sorted. + if (sort) this.trigger('sort', this, options); + return this; + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any granular `add` or `remove` events. Fires `reset` when finished. + // Useful for bulk operations and optimizations. + reset: function(models, options) { + options || (options = {}); + for (var i = 0, l = this.models.length; i < l; i++) { + this._removeReference(this.models[i]); + } + options.previousModels = this.models; + this._reset(); + this.add(models, _.extend({silent: true}, options)); + if (!options.silent) this.trigger('reset', this, options); + return this; + }, + + // Add a model to the end of the collection. + push: function(model, options) { + model = this._prepareModel(model, options); + this.add(model, _.extend({at: this.length}, options)); + return model; + }, + + // Remove a model from the end of the collection. + pop: function(options) { + var model = this.at(this.length - 1); + this.remove(model, options); + return model; + }, + + // Add a model to the beginning of the collection. + unshift: function(model, options) { + model = this._prepareModel(model, options); + this.add(model, _.extend({at: 0}, options)); + return model; + }, + + // Remove a model from the beginning of the collection. + shift: function(options) { + var model = this.at(0); + this.remove(model, options); + return model; + }, + + // Slice out a sub-array of models from the collection. + slice: function(begin, end) { + return this.models.slice(begin, end); + }, + + // Get a model from the set by id. + get: function(obj) { + if (obj == null) return void 0; + return this._byId[obj.id != null ? obj.id : obj.cid || obj]; + }, + + // Get the model at the given index. + at: function(index) { + return this.models[index]; + }, + + // Return models with matching attributes. Useful for simple cases of + // `filter`. + where: function(attrs, first) { + if (_.isEmpty(attrs)) return first ? void 0 : []; + return this[first ? 'find' : 'filter'](function(model) { + for (var key in attrs) { + if (attrs[key] !== model.get(key)) return false; + } + return true; + }); + }, + + // Return the first model with matching attributes. Useful for simple cases + // of `find`. + findWhere: function(attrs) { + return this.where(attrs, true); + }, + + // Force the collection to re-sort itself. You don't need to call this under + // normal circumstances, as the set will maintain sort order as each item + // is added. + sort: function(options) { + if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); + options || (options = {}); + + // Run sort based on type of `comparator`. + if (_.isString(this.comparator) || this.comparator.length === 1) { + this.models = this.sortBy(this.comparator, this); + } else { + this.models.sort(_.bind(this.comparator, this)); + } + + if (!options.silent) this.trigger('sort', this, options); + return this; + }, + + // Figure out the smallest index at which a model should be inserted so as + // to maintain order. + sortedIndex: function(model, value, context) { + value || (value = this.comparator); + var iterator = _.isFunction(value) ? value : function(model) { + return model.get(value); + }; + return _.sortedIndex(this.models, model, iterator, context); + }, + + // Pluck an attribute from each model in the collection. + pluck: function(attr) { + return _.invoke(this.models, 'get', attr); + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `reset: true` is passed, the response + // data will be passed through the `reset` method instead of `set`. + fetch: function(options) { + options = options ? _.clone(options) : {}; + if (options.parse === void 0) options.parse = true; + var success = options.success; + var collection = this; + options.success = function(resp) { + var method = options.reset ? 'reset' : 'set'; + collection[method](resp, options); + if (success) success(collection, resp, options); + collection.trigger('sync', collection, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Create a new instance of a model in this collection. Add the model to the + // collection immediately, unless `wait: true` is passed, in which case we + // wait for the server to agree. + create: function(model, options) { + options = options ? _.clone(options) : {}; + if (!(model = this._prepareModel(model, options))) return false; + if (!options.wait) this.add(model, options); + var collection = this; + var success = options.success; + options.success = function(resp) { + if (options.wait) collection.add(model, options); + if (success) success(model, resp, options); + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse: function(resp, options) { + return resp; + }, + + // Create a new collection with an identical list of models as this one. + clone: function() { + return new this.constructor(this.models); + }, + + // Private method to reset all internal state. Called when the collection + // is first initialized or reset. + _reset: function() { + this.length = 0; + this.models = []; + this._byId = {}; + }, + + // Prepare a hash of attributes (or other model) to be added to this + // collection. + _prepareModel: function(attrs, options) { + if (attrs instanceof Model) { + if (!attrs.collection) attrs.collection = this; + return attrs; + } + options || (options = {}); + options.collection = this; + var model = new this.model(attrs, options); + if (!model._validate(attrs, options)) { + this.trigger('invalid', this, attrs, options); + return false; + } + return model; + }, + + // Internal method to sever a model's ties to a collection. + _removeReference: function(model) { + if (this === model.collection) delete model.collection; + model.off('all', this._onModelEvent, this); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent: function(event, model, collection, options) { + if ((event === 'add' || event === 'remove') && collection !== this) return; + if (event === 'destroy') this.remove(model, options); + if (model && event === 'change:' + model.idAttribute) { + delete this._byId[model.previous(model.idAttribute)]; + if (model.id != null) this._byId[model.id] = model; + } + this.trigger.apply(this, arguments); + } + + }); + + // Underscore methods that we want to implement on the Collection. + // 90% of the core usefulness of Backbone Collections is actually implemented + // right here: + var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', + 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', + 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', + 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', + 'tail', 'drop', 'last', 'without', 'indexOf', 'shuffle', 'lastIndexOf', + 'isEmpty', 'chain']; + + // Mix in each Underscore method as a proxy to `Collection#models`. + _.each(methods, function(method) { + Collection.prototype[method] = function() { + var args = slice.call(arguments); + args.unshift(this.models); + return _[method].apply(_, args); + }; + }); + + // Underscore methods that take a property name as an argument. + var attributeMethods = ['groupBy', 'countBy', 'sortBy']; + + // Use attributes instead of properties. + _.each(attributeMethods, function(method) { + Collection.prototype[method] = function(value, context) { + var iterator = _.isFunction(value) ? value : function(model) { + return model.get(value); + }; + return _[method](this.models, iterator, context); + }; + }); + + // Backbone.View + // ------------- + + // Backbone Views are almost more convention than they are actual code. A View + // is simply a JavaScript object that represents a logical chunk of UI in the + // DOM. This might be a single item, an entire list, a sidebar or panel, or + // even the surrounding frame which wraps your whole app. Defining a chunk of + // UI as a **View** allows you to define your DOM events declaratively, without + // having to worry about render order ... and makes it easy for the view to + // react to specific changes in the state of your models. + + // Creating a Backbone.View creates its initial element outside of the DOM, + // if an existing element is not provided... + var View = Backbone.View = function(options) { + this.cid = _.uniqueId('view'); + this._configure(options || {}); + this._ensureElement(); + this.initialize.apply(this, arguments); + this.delegateEvents(); + }; + + // Cached regex to split keys for `delegate`. + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + // List of view options to be merged as properties. + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + // Set up all inheritable **Backbone.View** properties and methods. + _.extend(View.prototype, Events, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + // jQuery delegate for element lookup, scoped to DOM elements within the + // current view. This should be prefered to global lookups where possible. + $: function(selector) { + return this.$el.find(selector); + }, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // **render** is the core function that your view should override, in order + // to populate its element (`this.el`), with the appropriate HTML. The + // convention is for **render** to always return `this`. + render: function() { + return this; + }, + + // Remove this view by taking the element out of the DOM, and removing any + // applicable Backbone.Events listeners. + remove: function() { + this.$el.remove(); + this.stopListening(); + return this; + }, + + // Change the view's element (`this.el` property), including event + // re-delegation. + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save' + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) continue; + + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this.cid; + if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + return this; + }, + + // Clears all callbacks previously bound to the view with `delegateEvents`. + // You usually don't need to use this, but may wish to if you have multiple + // Backbone views attached to the same DOM element. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this.cid); + return this; + }, + + // Performs the initial configuration of a View with a set of options. + // Keys with special meaning *(e.g. model, collection, id, className)* are + // attached directly to the view. See `viewOptions` for an exhaustive + // list. + _configure: function(options) { + if (this.options) options = _.extend({}, _.result(this, 'options'), options); + _.extend(this, _.pick(options, viewOptions)); + this.options = options; + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + if (!this.el) { + var attrs = _.extend({}, _.result(this, 'attributes')); + if (this.id) attrs.id = _.result(this, 'id'); + if (this.className) attrs['class'] = _.result(this, 'className'); + var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs); + this.setElement($el, false); + } else { + this.setElement(_.result(this, 'el'), false); + } + } + + }); + + // Backbone.sync + // ------------- + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + // If we're sending a `PATCH` request, and we're in an old Internet Explorer + // that still has ActiveX enabled by default, override jQuery to use that + // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. + if (params.type === 'PATCH' && window.ActiveXObject && + !(window.external && window.external.msActiveXFilteringEnabled)) { + params.xhr = function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }; + } + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + 'create': 'POST', + 'update': 'PUT', + 'patch': 'PATCH', + 'delete': 'DELETE', + 'read': 'GET' + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + // Override this if you'd like to use a different library. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Backbone.Router + // --------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function(options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route: function(route, name, callback) { + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (_.isFunction(name)) { + callback = name; + name = ''; + } + if (!callback) callback = this[name]; + var router = this; + Backbone.history.route(route, function(fragment) { + var args = router._extractParameters(route, fragment); + callback && callback.apply(router, args); + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); + }); + return this; + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate: function(fragment, options) { + Backbone.history.navigate(fragment, options); + return this; + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes: function() { + if (!this.routes) return; + this.routes = _.result(this, 'routes'); + var route, routes = _.keys(this.routes); + while ((route = routes.pop()) != null) { + this.route(route, this.routes[route]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional){ + return optional ? match : '([^\/]+)'; + }) + .replace(splatParam, '(.*?)'); + return new RegExp('^' + route + '$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + return _.map(params, function(param) { + return param ? decodeURIComponent(param) : null; + }); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on either + // [pushState](http://diveintohtml5.info/history.html) and real URLs, or + // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) + // and URL fragments. If the browser supports neither (old IE, natch), + // falls back to polling. + var History = Backbone.History = function() { + this.handlers = []; + _.bindAll(this, 'checkUrl'); + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } + }; + + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Cached regex for removing a trailing slash. + var trailingSlash = /\/$/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(window) { + var match = (window || this).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment: function(fragment, forcePushState) { + if (fragment == null) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + fragment = this.location.pathname; + var root = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); + } else { + fragment = this.getHash(); + } + } + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start: function(options) { + if (History.started) throw new Error("Backbone.history has already been started"); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({}, {root: '/'}, this.options, options); + this.root = this.options.root; + this._wantsHashChange = this.options.hashChange !== false; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + + // Normalize root to always include a leading and trailing slash. + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); + + if (oldIE && this._wantsHashChange) { + this.iframe = Backbone.$('